summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile1
-rw-r--r--Makefile2
-rw-r--r--README.md4
-rw-r--r--_config.yml4
-rw-r--r--source/_includes/footer.html5
-rw-r--r--source/_includes/preamble.html6
-rw-r--r--source/index.md3
-rw-r--r--source/infra/css/katex.css1236
-rw-r--r--source/infra/css/katex.min.css1
-rw-r--r--source/infra/js/cgit.js68
-rw-r--r--source/infra/js/count.js274
-rw-r--r--source/infra/js/katex.js17701
-rw-r--r--source/infra/js/katex.min.js1
-rw-r--r--source/know/concept/bb84-protocol/index.md23
-rw-r--r--source/know/concept/bell-state/index.md20
-rw-r--r--source/know/concept/bernstein-vazirani-algorithm/index.md4
-rw-r--r--source/know/concept/blochs-theorem/index.md25
-rw-r--r--source/know/concept/boltzmann-equation/index.md20
-rw-r--r--source/know/concept/bose-einstein-distribution/index.md36
-rw-r--r--source/know/concept/boussinesq-wave-theory/index.md2
-rw-r--r--source/know/concept/canonical-ensemble/index.md2
-rw-r--r--source/know/concept/clausius-mossotti-relation/index.md6
-rw-r--r--source/know/concept/convolution-theorem/index.md8
-rw-r--r--source/know/concept/coupled-mode-theory/index.md4
-rw-r--r--source/know/concept/debye-length/index.md30
-rw-r--r--source/know/concept/deutsch-jozsa-algorithm/index.md22
-rw-r--r--source/know/concept/diffie-hellman-key-exchange/index.md16
-rw-r--r--source/know/concept/dirac-notation/index.md16
-rw-r--r--source/know/concept/discrete-spectrum-summation/index.md77
-rw-r--r--source/know/concept/dyson-equation/index.md38
-rw-r--r--source/know/concept/electric-dipole-approximation/index.md6
-rw-r--r--source/know/concept/electromagnetic-wave-equation/index.md345
-rw-r--r--source/know/concept/equation-of-motion-theory/index.md7
-rw-r--r--source/know/concept/euler-equations/index.md2
-rw-r--r--source/know/concept/fabry-perot-cavity/index.md24
-rw-r--r--source/know/concept/fermi-dirac-distribution/index.md38
-rw-r--r--source/know/concept/fermi-gas/index.md219
-rw-r--r--source/know/concept/fundamental-relation-of-thermodynamics/index.md326
-rw-r--r--source/know/concept/fundamental-solution/index.md34
-rw-r--r--source/know/concept/fundamental-thermodynamic-relation/index.md54
-rw-r--r--source/know/concept/heaviside-step-function/index.md18
-rw-r--r--source/know/concept/heisenberg-picture/index.md107
-rw-r--r--source/know/concept/hellmann-feynman-theorem/index.md2
-rw-r--r--source/know/concept/hilbert-space/index.md162
-rw-r--r--source/know/concept/interaction-picture/index.md200
-rw-r--r--source/know/concept/ito-integral/index.md57
-rw-r--r--source/know/concept/jellium/index.md265
-rw-r--r--source/know/concept/korteweg-de-vries-equation/index.md33
-rw-r--r--source/know/concept/kramers-kronig-relations/index.md133
-rw-r--r--source/know/concept/kubo-formula/index.md23
-rw-r--r--source/know/concept/lagrange-multiplier/index.md2
-rw-r--r--source/know/concept/langmuir-waves/index.md39
-rw-r--r--source/know/concept/larmor-precession/index.md24
-rw-r--r--source/know/concept/laser-rate-equations/index.md10
-rw-r--r--source/know/concept/laws-of-thermodynamics/index.md104
-rw-r--r--source/know/concept/legendre-transform/index.md16
-rw-r--r--source/know/concept/lindhard-function/index.md86
-rw-r--r--source/know/concept/lyddane-sachs-teller-relation/index.md250
-rw-r--r--source/know/concept/magnetohydrodynamics/index.md122
-rw-r--r--source/know/concept/martingale/index.md2
-rw-r--r--source/know/concept/material-derivative/index.md10
-rw-r--r--source/know/concept/matsubara-greens-function/index.md10
-rw-r--r--source/know/concept/matsubara-summation/index.md (renamed from source/know/concept/matsubara-sum/index.md)14
-rw-r--r--source/know/concept/maxwell-bloch-equations/index.md22
-rw-r--r--source/know/concept/maxwell-relations/index.md14
-rw-r--r--source/know/concept/multi-photon-absorption/index.md7
-rw-r--r--source/know/concept/no-cloning-theorem/index.md8
-rw-r--r--source/know/concept/nonlinear-schrodinger-equation/index.md708
-rw-r--r--source/know/concept/optical-soliton/bright-full.pngbin0 -> 85508 bytes
-rw-r--r--source/know/concept/optical-soliton/bright-half.avifbin0 -> 13232 bytes
-rw-r--r--source/know/concept/optical-soliton/bright-half.jpgbin0 -> 72712 bytes
-rw-r--r--source/know/concept/optical-soliton/bright-half.pngbin0 -> 72999 bytes
-rw-r--r--source/know/concept/optical-soliton/bright-half.webpbin0 -> 31602 bytes
-rw-r--r--source/know/concept/optical-soliton/dark-full.pngbin0 -> 164793 bytes
-rw-r--r--source/know/concept/optical-soliton/dark-half.avifbin0 -> 25523 bytes
-rw-r--r--source/know/concept/optical-soliton/dark-half.jpgbin0 -> 125295 bytes
-rw-r--r--source/know/concept/optical-soliton/dark-half.pngbin0 -> 125292 bytes
-rw-r--r--source/know/concept/optical-soliton/dark-half.webpbin0 -> 57198 bytes
-rw-r--r--source/know/concept/optical-soliton/index.md576
-rw-r--r--source/know/concept/optical-wave-breaking/frequency-full.pngbin66588 -> 0 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/frequency-half.avifbin12506 -> 0 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/frequency-half.jpgbin47933 -> 0 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/frequency-half.pngbin41392 -> 0 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/frequency-half.webpbin26742 -> 0 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-domegadt-full.pngbin0 -> 89136 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-domegadt-half.avifbin0 -> 16097 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-domegadt-half.jpgbin0 -> 73248 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-domegadt-half.pngbin0 -> 63786 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-domegadt-half.webpbin0 -> 35022 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-omega-full.pngbin0 -> 93001 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-omega-half.avifbin0 -> 15847 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-omega-half.jpgbin0 -> 67654 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-omega-half.pngbin0 -> 63868 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/gauss-omega-half.webpbin0 -> 32392 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/index.md542
-rw-r--r--source/know/concept/optical-wave-breaking/sech-omega-full.pngbin0 -> 67230 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/sech-omega-half.avifbin0 -> 10439 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/sech-omega-half.jpgbin0 -> 54589 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/sech-omega-half.pngbin0 -> 48904 bytes
-rw-r--r--source/know/concept/optical-wave-breaking/sech-omega-half.webpbin0 -> 23824 bytes
-rw-r--r--source/know/concept/path-integral-formulation/index.md239
-rw-r--r--source/know/concept/pauli-exclusion-principle/index.md119
-rw-r--r--source/know/concept/propagator/index.md79
-rw-r--r--source/know/concept/quantum-teleportation/index.md17
-rw-r--r--source/know/concept/random-phase-approximation/index.md2
-rw-r--r--source/know/concept/repetition-code/index.md9
-rw-r--r--source/know/concept/ritz-method/index.md201
-rw-r--r--source/know/concept/rotating-wave-approximation/index.md32
-rw-r--r--source/know/concept/runge-kutta-method/index.md4
-rw-r--r--source/know/concept/rutherford-scattering/index.md70
-rw-r--r--source/know/concept/salt-equation/index.md6
-rw-r--r--source/know/concept/second-quantization/index.md192
-rw-r--r--source/know/concept/self-steepening/index.md241
-rw-r--r--source/know/concept/shors-algorithm/index.md62
-rw-r--r--source/know/concept/simons-algorithm/index.md46
-rw-r--r--source/know/concept/sokhotski-plemelj-theorem/index.md4
-rw-r--r--source/know/concept/superdense-coding/index.md14
-rw-r--r--source/know/concept/thermodynamic-potential/index.md51
-rw-r--r--source/know/concept/time-evolution-operator/index.md184
-rw-r--r--source/know/concept/triple-product-rule/index.md97
-rw-r--r--source/know/concept/two-fluid-equations/index.md47
-rw-r--r--source/know/concept/wkb-approximation/index.md140
122 files changed, 23890 insertions, 2242 deletions
diff --git a/Gemfile b/Gemfile
index 46a8096..5190e36 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,6 +3,7 @@ source "https://rubygems.org"
gem "jekyll"
gem "webrick"
gem "json"
+gem "erb"
# https://github.com/rubyjs/mini_racer
gem "mini_racer"
diff --git a/Makefile b/Makefile
index 05af8fe..32cbc02 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ compress:
deploy:
- rsync --rsh="ssh -p $(PORT)" --stats --checksum --recursive public/ $(HOST):/srv/prefetch.eu/public/
+ rclone sync --verbose ./public/ server:/home/html/prefetch.eu/
clean:
diff --git a/README.md b/README.md
index 75bb8fc..e9c112d 100644
--- a/README.md
+++ b/README.md
@@ -14,9 +14,13 @@ all its extensions needed by this website as listed in the `Gemfile`:
```sh
$ bundle config set --local path .bundle
+$ bundle config build.posix-spawn --with-cflags="-Wno-incompatible-pointer-types"
$ bundle install
```
+First try to run `bundle install` without changing any `CFLAGS`,
+it used to work like that, but not anymore as of mid-2024.
+
Now you should be able to run a local development version with:
```sh
diff --git a/_config.yml b/_config.yml
index 5023f33..3b45039 100644
--- a/_config.yml
+++ b/_config.yml
@@ -11,12 +11,12 @@ plugins:
kramdown:
math_engine: sskatex
math_engine_opts:
- katex_js: "source/infra/js/katex.min.js"
+ katex_js: "source/infra/js/katex.js"
katex_opts:
macros:
"\\Real": "\\mathop{\\mathrm{Re}}"
"\\Imag": "\\mathop{\\mathrm{Im}}"
- "\\pv": "\\:\\mathop{\\mathcal{P}}"
+ "\\pv": "\\:\\mathcal{P}\\!"
"\\cross": "\\times"
"\\va": "\\vec{\\mathbf{#1}}"
"\\vb": "\\mathbf{#1}"
diff --git a/source/_includes/footer.html b/source/_includes/footer.html
index 5cba67d..910cf33 100644
--- a/source/_includes/footer.html
+++ b/source/_includes/footer.html
@@ -1,7 +1,6 @@
<div class="align-l">
- &copy; Marcus R.A. Newman,
- <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA</a>.
+ &copy; 2019-2026 Marcus R.A. Newman
</div>
<div class="align-r">
- <a href="https://prefetch.goatcounter.com/">Visitor statistics</a>
+ <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">Licensed under CC BY-NC-SA</a>
</div>
diff --git a/source/_includes/preamble.html b/source/_includes/preamble.html
index 11fcce6..680e222 100644
--- a/source/_includes/preamble.html
+++ b/source/_includes/preamble.html
@@ -17,10 +17,6 @@
<link rel="stylesheet" href="/infra/css/syntax.css?v=20221108"/>
{% endif %}
{% if page.layout == "concept" or page.maths %}
-<link rel="stylesheet" href="/infra/css/katex.min.css?v=20230709"/>
+<link rel="stylesheet" href="/infra/css/katex.css?v=20260830"/>
{% endif %}
<link rel="stylesheet" href="/infra/css/main.css?v=20230723"/>
-
-{% if jekyll.environment == "production" %}
-<script data-goatcounter="https://prefetch.goatcounter.com/count" async src="/infra/js/count.js?v=20230709"></script>
-{% endif %}
diff --git a/source/index.md b/source/index.md
index 359d6de..29b3d68 100644
--- a/source/index.md
+++ b/source/index.md
@@ -24,6 +24,3 @@ This website is made by me using [Jekyll](https://jekyllrb.com/),
and served to you by [nginx](https://nginx.org/).
I intend to keep it free of advertising and associated tracking,
and to maintain my A+ score for [TLS quality](https://www.ssllabs.com/ssltest/analyze.html?d=prefetch.eu).
-Note that I do use [GoatCounter](https://www.goatcounter.com/)
-to collect some privacy-friendly statistics,
-which you can see [here](https://prefetch.goatcounter.com/).
diff --git a/source/infra/css/katex.css b/source/infra/css/katex.css
new file mode 100644
index 0000000..c576efe
--- /dev/null
+++ b/source/infra/css/katex.css
@@ -0,0 +1,1236 @@
+/* stylelint-disable font-family-no-missing-generic-family-keyword */
+@font-face {
+ font-family: "KaTeX_AMS";
+ src: url(/infra/font/KaTeX_AMS-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_AMS-Regular.woff) format("woff"), url(/infra/font/KaTeX_AMS-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Caligraphic";
+ src: url(/infra/font/KaTeX_Caligraphic-Bold.woff2) format("woff2"), url(/infra/font/KaTeX_Caligraphic-Bold.woff) format("woff"), url(/infra/font/KaTeX_Caligraphic-Bold.ttf) format("truetype");
+ font-weight: bold;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Caligraphic";
+ src: url(/infra/font/KaTeX_Caligraphic-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Caligraphic-Regular.woff) format("woff"), url(/infra/font/KaTeX_Caligraphic-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Fraktur";
+ src: url(/infra/font/KaTeX_Fraktur-Bold.woff2) format("woff2"), url(/infra/font/KaTeX_Fraktur-Bold.woff) format("woff"), url(/infra/font/KaTeX_Fraktur-Bold.ttf) format("truetype");
+ font-weight: bold;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Fraktur";
+ src: url(/infra/font/KaTeX_Fraktur-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Fraktur-Regular.woff) format("woff"), url(/infra/font/KaTeX_Fraktur-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Main";
+ src: url(/infra/font/KaTeX_Main-Bold.woff2) format("woff2"), url(/infra/font/KaTeX_Main-Bold.woff) format("woff"), url(/infra/font/KaTeX_Main-Bold.ttf) format("truetype");
+ font-weight: bold;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Main";
+ src: url(/infra/font/KaTeX_Main-BoldItalic.woff2) format("woff2"), url(/infra/font/KaTeX_Main-BoldItalic.woff) format("woff"), url(/infra/font/KaTeX_Main-BoldItalic.ttf) format("truetype");
+ font-weight: bold;
+ font-style: italic;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Main";
+ src: url(/infra/font/KaTeX_Main-Italic.woff2) format("woff2"), url(/infra/font/KaTeX_Main-Italic.woff) format("woff"), url(/infra/font/KaTeX_Main-Italic.ttf) format("truetype");
+ font-weight: normal;
+ font-style: italic;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Main";
+ src: url(/infra/font/KaTeX_Main-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Main-Regular.woff) format("woff"), url(/infra/font/KaTeX_Main-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Math";
+ src: url(/infra/font/KaTeX_Math-BoldItalic.woff2) format("woff2"), url(/infra/font/KaTeX_Math-BoldItalic.woff) format("woff"), url(/infra/font/KaTeX_Math-BoldItalic.ttf) format("truetype");
+ font-weight: bold;
+ font-style: italic;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Math";
+ src: url(/infra/font/KaTeX_Math-Italic.woff2) format("woff2"), url(/infra/font/KaTeX_Math-Italic.woff) format("woff"), url(/infra/font/KaTeX_Math-Italic.ttf) format("truetype");
+ font-weight: normal;
+ font-style: italic;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_SansSerif";
+ src: url(/infra/font/KaTeX_SansSerif-Bold.woff2) format("woff2"), url(/infra/font/KaTeX_SansSerif-Bold.woff) format("woff"), url(/infra/font/KaTeX_SansSerif-Bold.ttf) format("truetype");
+ font-weight: bold;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_SansSerif";
+ src: url(/infra/font/KaTeX_SansSerif-Italic.woff2) format("woff2"), url(/infra/font/KaTeX_SansSerif-Italic.woff) format("woff"), url(/infra/font/KaTeX_SansSerif-Italic.ttf) format("truetype");
+ font-weight: normal;
+ font-style: italic;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_SansSerif";
+ src: url(/infra/font/KaTeX_SansSerif-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_SansSerif-Regular.woff) format("woff"), url(/infra/font/KaTeX_SansSerif-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Script";
+ src: url(/infra/font/KaTeX_Script-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Script-Regular.woff) format("woff"), url(/infra/font/KaTeX_Script-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Size1";
+ src: url(/infra/font/KaTeX_Size1-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Size1-Regular.woff) format("woff"), url(/infra/font/KaTeX_Size1-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Size2";
+ src: url(/infra/font/KaTeX_Size2-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Size2-Regular.woff) format("woff"), url(/infra/font/KaTeX_Size2-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Size3";
+ src: url(/infra/font/KaTeX_Size3-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Size3-Regular.woff) format("woff"), url(/infra/font/KaTeX_Size3-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Size4";
+ src: url(/infra/font/KaTeX_Size4-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Size4-Regular.woff) format("woff"), url(/infra/font/KaTeX_Size4-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+@font-face {
+ font-family: "KaTeX_Typewriter";
+ src: url(/infra/font/KaTeX_Typewriter-Regular.woff2) format("woff2"), url(/infra/font/KaTeX_Typewriter-Regular.woff) format("woff"), url(/infra/font/KaTeX_Typewriter-Regular.ttf) format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: block;
+}
+/* stylelint-disable font-family-no-missing-generic-family-keyword */
+.katex {
+ font: normal 1.21em KaTeX_Main, Times New Roman, serif;
+ line-height: 1.2;
+ position: relative;
+ text-indent: 0;
+ text-rendering: auto;
+}
+.katex * {
+ -ms-high-contrast-adjust: none !important;
+}
+.katex * {
+ border-color: currentColor;
+}
+.katex .katex-version::after {
+ content: "0.18.4";
+}
+.katex .katex-mathml {
+ /* Accessibility hack to only show to screen readers
+ Found at: http://a11yproject.com/posts/how-to-hide-content/ */
+ position: absolute;
+ -webkit-clip-path: inset(50%);
+ clip-path: inset(50%);
+ padding: 0;
+ border: 0;
+ height: 1px;
+ width: 1px;
+ overflow: hidden;
+}
+.katex .katex-html {
+ /* \newline is an empty block at top level, between .katex-base elements */
+}
+.katex .katex-html > .katex-newline {
+ display: block;
+}
+.katex .katex-base {
+ position: relative;
+ display: inline-block;
+ white-space: nowrap;
+ width: -webkit-min-content;
+ width: -moz-min-content;
+ width: min-content;
+}
+.katex .katex-strut {
+ display: inline-block;
+}
+.katex .textbf {
+ font-weight: bold;
+}
+.katex .textit {
+ font-style: italic;
+}
+.katex .textrm {
+ font-family: KaTeX_Main;
+}
+.katex .textsf {
+ font-family: KaTeX_SansSerif;
+}
+.katex .texttt {
+ font-family: KaTeX_Typewriter;
+}
+.katex .mathnormal {
+ font-family: KaTeX_Math;
+ font-style: italic;
+}
+.katex .mathit {
+ font-family: KaTeX_Main;
+ font-style: italic;
+}
+.katex .mathrm {
+ font-style: normal;
+}
+.katex .mathbf {
+ font-family: KaTeX_Main;
+ font-weight: bold;
+}
+.katex .boldsymbol {
+ font-family: KaTeX_Math;
+ font-weight: bold;
+ font-style: italic;
+}
+.katex .amsrm {
+ font-family: KaTeX_AMS;
+}
+.katex .mathbb,
+.katex .textbb {
+ font-family: KaTeX_AMS;
+}
+.katex .mathcal {
+ font-family: KaTeX_Caligraphic;
+}
+.katex .mathfrak,
+.katex .textfrak {
+ font-family: KaTeX_Fraktur;
+}
+.katex .mathboldfrak,
+.katex .textboldfrak {
+ font-family: KaTeX_Fraktur;
+ font-weight: bold;
+}
+.katex .mathtt {
+ font-family: KaTeX_Typewriter;
+}
+.katex .mathscr,
+.katex .textscr {
+ font-family: KaTeX_Script;
+}
+.katex .mathsf,
+.katex .textsf {
+ font-family: KaTeX_SansSerif;
+}
+.katex .mathboldsf,
+.katex .textboldsf {
+ font-family: KaTeX_SansSerif;
+ font-weight: bold;
+}
+.katex .mathsfit,
+.katex .mathitsf,
+.katex .textitsf {
+ font-family: KaTeX_SansSerif;
+ font-style: italic;
+}
+.katex .mainrm {
+ font-family: KaTeX_Main;
+ font-style: normal;
+}
+.katex .vlist-t {
+ display: inline-table;
+ table-layout: fixed;
+ border-collapse: collapse;
+}
+.katex .vlist-r {
+ display: table-row;
+}
+.katex .vlist {
+ display: table-cell;
+ vertical-align: bottom;
+ position: relative;
+}
+.katex .vlist > span {
+ display: block;
+ height: 0;
+ position: relative;
+}
+.katex .vlist > span > span {
+ display: inline-block;
+}
+.katex .vlist > span > .pstrut {
+ overflow: hidden;
+ width: 0;
+}
+.katex .vlist-t2 {
+ margin-right: -2px;
+}
+.katex .vlist-s {
+ display: table-cell;
+ vertical-align: bottom;
+ font-size: 1px;
+ width: 2px;
+ min-width: 2px;
+}
+.katex .katex-vbox {
+ display: inline-flex;
+ flex-direction: column;
+ align-items: baseline;
+}
+.katex .katex-thinbox {
+ display: inline-flex;
+ flex-direction: row;
+ width: 0;
+ max-width: 0;
+}
+.katex .msupsub {
+ text-align: left;
+}
+.katex .mfrac > span > span {
+ text-align: center;
+}
+.katex .mfrac .frac-line {
+ display: inline-block;
+ width: 100%;
+ border-bottom-style: solid;
+}
+.katex .mfrac .frac-line,
+.katex .katex-overline .overline-line,
+.katex .katex-underline .underline-line,
+.katex .katex-hline,
+.katex .katex-hdashline,
+.katex .katex-rule {
+ min-height: 1px;
+}
+.katex .mspace {
+ display: inline-block;
+}
+.katex .katex-smash {
+ display: inline;
+ line-height: 0;
+}
+.katex .llap,
+.katex .rlap,
+.katex .clap {
+ width: 0;
+ position: relative;
+}
+.katex .llap > .katex-inner,
+.katex .rlap > .katex-inner,
+.katex .clap > .katex-inner {
+ position: absolute;
+}
+.katex .llap > .katex-fix,
+.katex .rlap > .katex-fix,
+.katex .clap > .katex-fix {
+ display: inline-block;
+}
+.katex .llap > .katex-inner {
+ right: 0;
+}
+.katex .rlap > .katex-inner,
+.katex .clap > .katex-inner {
+ left: 0;
+}
+.katex .clap > .katex-inner > span {
+ margin-left: -50%;
+ margin-right: 50%;
+}
+.katex .katex-rule {
+ display: inline-block;
+ border: solid 0;
+ position: relative;
+}
+.katex .katex-overline .overline-line,
+.katex .katex-underline .underline-line,
+.katex .katex-hline {
+ display: inline-block;
+ width: 100%;
+ border-bottom-style: solid;
+}
+.katex .katex-hdashline {
+ display: inline-block;
+ width: 100%;
+ border-bottom-style: dashed;
+}
+.katex .sqrt > .katex-root {
+ /* These values are taken from the definition of `\r@@t`,
+ `\mkern 5mu` and `\mkern -10mu`. */
+ /* stylelint-disable-next-line declaration-property-value-no-unknown */
+ margin-left: 0.2777777778em;
+ /* stylelint-disable-next-line declaration-property-value-no-unknown */
+ margin-right: -0.5555555556em;
+}
+.katex .katex-sizing.reset-size1.size1,
+.katex .fontsize-ensurer.reset-size1.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size1.size2,
+.katex .fontsize-ensurer.reset-size1.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 1.2em;
+}
+.katex .katex-sizing.reset-size1.size3,
+.katex .fontsize-ensurer.reset-size1.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 1.4em;
+}
+.katex .katex-sizing.reset-size1.size4,
+.katex .fontsize-ensurer.reset-size1.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 1.6em;
+}
+.katex .katex-sizing.reset-size1.size5,
+.katex .fontsize-ensurer.reset-size1.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 1.8em;
+}
+.katex .katex-sizing.reset-size1.size6,
+.katex .fontsize-ensurer.reset-size1.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 2em;
+}
+.katex .katex-sizing.reset-size1.size7,
+.katex .fontsize-ensurer.reset-size1.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 2.4em;
+}
+.katex .katex-sizing.reset-size1.size8,
+.katex .fontsize-ensurer.reset-size1.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 2.88em;
+}
+.katex .katex-sizing.reset-size1.size9,
+.katex .fontsize-ensurer.reset-size1.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 3.456em;
+}
+.katex .katex-sizing.reset-size1.size10,
+.katex .fontsize-ensurer.reset-size1.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 4.148em;
+}
+.katex .katex-sizing.reset-size1.size11,
+.katex .fontsize-ensurer.reset-size1.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 4.976em;
+}
+.katex .katex-sizing.reset-size2.size1,
+.katex .fontsize-ensurer.reset-size2.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8333333333em;
+}
+.katex .katex-sizing.reset-size2.size2,
+.katex .fontsize-ensurer.reset-size2.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size2.size3,
+.katex .fontsize-ensurer.reset-size2.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 1.1666666667em;
+}
+.katex .katex-sizing.reset-size2.size4,
+.katex .fontsize-ensurer.reset-size2.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 1.3333333333em;
+}
+.katex .katex-sizing.reset-size2.size5,
+.katex .fontsize-ensurer.reset-size2.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 1.5em;
+}
+.katex .katex-sizing.reset-size2.size6,
+.katex .fontsize-ensurer.reset-size2.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 1.6666666667em;
+}
+.katex .katex-sizing.reset-size2.size7,
+.katex .fontsize-ensurer.reset-size2.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 2em;
+}
+.katex .katex-sizing.reset-size2.size8,
+.katex .fontsize-ensurer.reset-size2.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 2.4em;
+}
+.katex .katex-sizing.reset-size2.size9,
+.katex .fontsize-ensurer.reset-size2.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 2.88em;
+}
+.katex .katex-sizing.reset-size2.size10,
+.katex .fontsize-ensurer.reset-size2.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 3.4566666667em;
+}
+.katex .katex-sizing.reset-size2.size11,
+.katex .fontsize-ensurer.reset-size2.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 4.1466666667em;
+}
+.katex .katex-sizing.reset-size3.size1,
+.katex .fontsize-ensurer.reset-size3.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.7142857143em;
+}
+.katex .katex-sizing.reset-size3.size2,
+.katex .fontsize-ensurer.reset-size3.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8571428571em;
+}
+.katex .katex-sizing.reset-size3.size3,
+.katex .fontsize-ensurer.reset-size3.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size3.size4,
+.katex .fontsize-ensurer.reset-size3.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 1.1428571429em;
+}
+.katex .katex-sizing.reset-size3.size5,
+.katex .fontsize-ensurer.reset-size3.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 1.2857142857em;
+}
+.katex .katex-sizing.reset-size3.size6,
+.katex .fontsize-ensurer.reset-size3.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 1.4285714286em;
+}
+.katex .katex-sizing.reset-size3.size7,
+.katex .fontsize-ensurer.reset-size3.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 1.7142857143em;
+}
+.katex .katex-sizing.reset-size3.size8,
+.katex .fontsize-ensurer.reset-size3.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 2.0571428571em;
+}
+.katex .katex-sizing.reset-size3.size9,
+.katex .fontsize-ensurer.reset-size3.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 2.4685714286em;
+}
+.katex .katex-sizing.reset-size3.size10,
+.katex .fontsize-ensurer.reset-size3.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 2.9628571429em;
+}
+.katex .katex-sizing.reset-size3.size11,
+.katex .fontsize-ensurer.reset-size3.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 3.5542857143em;
+}
+.katex .katex-sizing.reset-size4.size1,
+.katex .fontsize-ensurer.reset-size4.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.625em;
+}
+.katex .katex-sizing.reset-size4.size2,
+.katex .fontsize-ensurer.reset-size4.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.75em;
+}
+.katex .katex-sizing.reset-size4.size3,
+.katex .fontsize-ensurer.reset-size4.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 0.875em;
+}
+.katex .katex-sizing.reset-size4.size4,
+.katex .fontsize-ensurer.reset-size4.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size4.size5,
+.katex .fontsize-ensurer.reset-size4.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 1.125em;
+}
+.katex .katex-sizing.reset-size4.size6,
+.katex .fontsize-ensurer.reset-size4.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 1.25em;
+}
+.katex .katex-sizing.reset-size4.size7,
+.katex .fontsize-ensurer.reset-size4.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 1.5em;
+}
+.katex .katex-sizing.reset-size4.size8,
+.katex .fontsize-ensurer.reset-size4.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 1.8em;
+}
+.katex .katex-sizing.reset-size4.size9,
+.katex .fontsize-ensurer.reset-size4.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 2.16em;
+}
+.katex .katex-sizing.reset-size4.size10,
+.katex .fontsize-ensurer.reset-size4.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 2.5925em;
+}
+.katex .katex-sizing.reset-size4.size11,
+.katex .fontsize-ensurer.reset-size4.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 3.11em;
+}
+.katex .katex-sizing.reset-size5.size1,
+.katex .fontsize-ensurer.reset-size5.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.5555555556em;
+}
+.katex .katex-sizing.reset-size5.size2,
+.katex .fontsize-ensurer.reset-size5.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.6666666667em;
+}
+.katex .katex-sizing.reset-size5.size3,
+.katex .fontsize-ensurer.reset-size5.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 0.7777777778em;
+}
+.katex .katex-sizing.reset-size5.size4,
+.katex .fontsize-ensurer.reset-size5.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8888888889em;
+}
+.katex .katex-sizing.reset-size5.size5,
+.katex .fontsize-ensurer.reset-size5.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size5.size6,
+.katex .fontsize-ensurer.reset-size5.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 1.1111111111em;
+}
+.katex .katex-sizing.reset-size5.size7,
+.katex .fontsize-ensurer.reset-size5.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 1.3333333333em;
+}
+.katex .katex-sizing.reset-size5.size8,
+.katex .fontsize-ensurer.reset-size5.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 1.6em;
+}
+.katex .katex-sizing.reset-size5.size9,
+.katex .fontsize-ensurer.reset-size5.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 1.92em;
+}
+.katex .katex-sizing.reset-size5.size10,
+.katex .fontsize-ensurer.reset-size5.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 2.3044444444em;
+}
+.katex .katex-sizing.reset-size5.size11,
+.katex .fontsize-ensurer.reset-size5.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 2.7644444444em;
+}
+.katex .katex-sizing.reset-size6.size1,
+.katex .fontsize-ensurer.reset-size6.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.5em;
+}
+.katex .katex-sizing.reset-size6.size2,
+.katex .fontsize-ensurer.reset-size6.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.6em;
+}
+.katex .katex-sizing.reset-size6.size3,
+.katex .fontsize-ensurer.reset-size6.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 0.7em;
+}
+.katex .katex-sizing.reset-size6.size4,
+.katex .fontsize-ensurer.reset-size6.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8em;
+}
+.katex .katex-sizing.reset-size6.size5,
+.katex .fontsize-ensurer.reset-size6.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 0.9em;
+}
+.katex .katex-sizing.reset-size6.size6,
+.katex .fontsize-ensurer.reset-size6.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size6.size7,
+.katex .fontsize-ensurer.reset-size6.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 1.2em;
+}
+.katex .katex-sizing.reset-size6.size8,
+.katex .fontsize-ensurer.reset-size6.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 1.44em;
+}
+.katex .katex-sizing.reset-size6.size9,
+.katex .fontsize-ensurer.reset-size6.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 1.728em;
+}
+.katex .katex-sizing.reset-size6.size10,
+.katex .fontsize-ensurer.reset-size6.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 2.074em;
+}
+.katex .katex-sizing.reset-size6.size11,
+.katex .fontsize-ensurer.reset-size6.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 2.488em;
+}
+.katex .katex-sizing.reset-size7.size1,
+.katex .fontsize-ensurer.reset-size7.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.4166666667em;
+}
+.katex .katex-sizing.reset-size7.size2,
+.katex .fontsize-ensurer.reset-size7.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.5em;
+}
+.katex .katex-sizing.reset-size7.size3,
+.katex .fontsize-ensurer.reset-size7.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 0.5833333333em;
+}
+.katex .katex-sizing.reset-size7.size4,
+.katex .fontsize-ensurer.reset-size7.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 0.6666666667em;
+}
+.katex .katex-sizing.reset-size7.size5,
+.katex .fontsize-ensurer.reset-size7.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 0.75em;
+}
+.katex .katex-sizing.reset-size7.size6,
+.katex .fontsize-ensurer.reset-size7.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8333333333em;
+}
+.katex .katex-sizing.reset-size7.size7,
+.katex .fontsize-ensurer.reset-size7.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size7.size8,
+.katex .fontsize-ensurer.reset-size7.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 1.2em;
+}
+.katex .katex-sizing.reset-size7.size9,
+.katex .fontsize-ensurer.reset-size7.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 1.44em;
+}
+.katex .katex-sizing.reset-size7.size10,
+.katex .fontsize-ensurer.reset-size7.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 1.7283333333em;
+}
+.katex .katex-sizing.reset-size7.size11,
+.katex .fontsize-ensurer.reset-size7.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 2.0733333333em;
+}
+.katex .katex-sizing.reset-size8.size1,
+.katex .fontsize-ensurer.reset-size8.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.3472222222em;
+}
+.katex .katex-sizing.reset-size8.size2,
+.katex .fontsize-ensurer.reset-size8.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.4166666667em;
+}
+.katex .katex-sizing.reset-size8.size3,
+.katex .fontsize-ensurer.reset-size8.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 0.4861111111em;
+}
+.katex .katex-sizing.reset-size8.size4,
+.katex .fontsize-ensurer.reset-size8.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 0.5555555556em;
+}
+.katex .katex-sizing.reset-size8.size5,
+.katex .fontsize-ensurer.reset-size8.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 0.625em;
+}
+.katex .katex-sizing.reset-size8.size6,
+.katex .fontsize-ensurer.reset-size8.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 0.6944444444em;
+}
+.katex .katex-sizing.reset-size8.size7,
+.katex .fontsize-ensurer.reset-size8.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8333333333em;
+}
+.katex .katex-sizing.reset-size8.size8,
+.katex .fontsize-ensurer.reset-size8.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size8.size9,
+.katex .fontsize-ensurer.reset-size8.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 1.2em;
+}
+.katex .katex-sizing.reset-size8.size10,
+.katex .fontsize-ensurer.reset-size8.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 1.4402777778em;
+}
+.katex .katex-sizing.reset-size8.size11,
+.katex .fontsize-ensurer.reset-size8.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 1.7277777778em;
+}
+.katex .katex-sizing.reset-size9.size1,
+.katex .fontsize-ensurer.reset-size9.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.2893518519em;
+}
+.katex .katex-sizing.reset-size9.size2,
+.katex .fontsize-ensurer.reset-size9.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.3472222222em;
+}
+.katex .katex-sizing.reset-size9.size3,
+.katex .fontsize-ensurer.reset-size9.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 0.4050925926em;
+}
+.katex .katex-sizing.reset-size9.size4,
+.katex .fontsize-ensurer.reset-size9.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 0.462962963em;
+}
+.katex .katex-sizing.reset-size9.size5,
+.katex .fontsize-ensurer.reset-size9.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 0.5208333333em;
+}
+.katex .katex-sizing.reset-size9.size6,
+.katex .fontsize-ensurer.reset-size9.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 0.5787037037em;
+}
+.katex .katex-sizing.reset-size9.size7,
+.katex .fontsize-ensurer.reset-size9.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 0.6944444444em;
+}
+.katex .katex-sizing.reset-size9.size8,
+.katex .fontsize-ensurer.reset-size9.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8333333333em;
+}
+.katex .katex-sizing.reset-size9.size9,
+.katex .fontsize-ensurer.reset-size9.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size9.size10,
+.katex .fontsize-ensurer.reset-size9.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 1.2002314815em;
+}
+.katex .katex-sizing.reset-size9.size11,
+.katex .fontsize-ensurer.reset-size9.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 1.4398148148em;
+}
+.katex .katex-sizing.reset-size10.size1,
+.katex .fontsize-ensurer.reset-size10.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.2410800386em;
+}
+.katex .katex-sizing.reset-size10.size2,
+.katex .fontsize-ensurer.reset-size10.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.2892960463em;
+}
+.katex .katex-sizing.reset-size10.size3,
+.katex .fontsize-ensurer.reset-size10.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 0.337512054em;
+}
+.katex .katex-sizing.reset-size10.size4,
+.katex .fontsize-ensurer.reset-size10.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 0.3857280617em;
+}
+.katex .katex-sizing.reset-size10.size5,
+.katex .fontsize-ensurer.reset-size10.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 0.4339440694em;
+}
+.katex .katex-sizing.reset-size10.size6,
+.katex .fontsize-ensurer.reset-size10.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 0.4821600771em;
+}
+.katex .katex-sizing.reset-size10.size7,
+.katex .fontsize-ensurer.reset-size10.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 0.5785920926em;
+}
+.katex .katex-sizing.reset-size10.size8,
+.katex .fontsize-ensurer.reset-size10.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 0.6943105111em;
+}
+.katex .katex-sizing.reset-size10.size9,
+.katex .fontsize-ensurer.reset-size10.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8331726133em;
+}
+.katex .katex-sizing.reset-size10.size10,
+.katex .fontsize-ensurer.reset-size10.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .katex-sizing.reset-size10.size11,
+.katex .fontsize-ensurer.reset-size10.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 1.1996142719em;
+}
+.katex .katex-sizing.reset-size11.size1,
+.katex .fontsize-ensurer.reset-size11.size1 {
+ /* stylelint-disable-next-line */
+ font-size: 0.2009646302em;
+}
+.katex .katex-sizing.reset-size11.size2,
+.katex .fontsize-ensurer.reset-size11.size2 {
+ /* stylelint-disable-next-line */
+ font-size: 0.2411575563em;
+}
+.katex .katex-sizing.reset-size11.size3,
+.katex .fontsize-ensurer.reset-size11.size3 {
+ /* stylelint-disable-next-line */
+ font-size: 0.2813504823em;
+}
+.katex .katex-sizing.reset-size11.size4,
+.katex .fontsize-ensurer.reset-size11.size4 {
+ /* stylelint-disable-next-line */
+ font-size: 0.3215434084em;
+}
+.katex .katex-sizing.reset-size11.size5,
+.katex .fontsize-ensurer.reset-size11.size5 {
+ /* stylelint-disable-next-line */
+ font-size: 0.3617363344em;
+}
+.katex .katex-sizing.reset-size11.size6,
+.katex .fontsize-ensurer.reset-size11.size6 {
+ /* stylelint-disable-next-line */
+ font-size: 0.4019292605em;
+}
+.katex .katex-sizing.reset-size11.size7,
+.katex .fontsize-ensurer.reset-size11.size7 {
+ /* stylelint-disable-next-line */
+ font-size: 0.4823151125em;
+}
+.katex .katex-sizing.reset-size11.size8,
+.katex .fontsize-ensurer.reset-size11.size8 {
+ /* stylelint-disable-next-line */
+ font-size: 0.578778135em;
+}
+.katex .katex-sizing.reset-size11.size9,
+.katex .fontsize-ensurer.reset-size11.size9 {
+ /* stylelint-disable-next-line */
+ font-size: 0.6945337621em;
+}
+.katex .katex-sizing.reset-size11.size10,
+.katex .fontsize-ensurer.reset-size11.size10 {
+ /* stylelint-disable-next-line */
+ font-size: 0.8336012862em;
+}
+.katex .katex-sizing.reset-size11.size11,
+.katex .fontsize-ensurer.reset-size11.size11 {
+ /* stylelint-disable-next-line */
+ font-size: 1em;
+}
+.katex .delimsizing.size1 {
+ font-family: KaTeX_Size1;
+}
+.katex .delimsizing.size2 {
+ font-family: KaTeX_Size2;
+}
+.katex .delimsizing.size3 {
+ font-family: KaTeX_Size3;
+}
+.katex .delimsizing.size4 {
+ font-family: KaTeX_Size4;
+}
+.katex .delimsizing.mult .delim-size1 > span {
+ font-family: KaTeX_Size1;
+}
+.katex .delimsizing.mult .delim-size4 > span {
+ font-family: KaTeX_Size4;
+}
+.katex .nulldelimiter {
+ display: inline-block;
+ width: 0.12em;
+}
+.katex .delimcenter {
+ position: relative;
+}
+.katex .op-symbol {
+ position: relative;
+}
+.katex .op-symbol.small-op {
+ font-family: KaTeX_Size1;
+}
+.katex .op-symbol.large-op {
+ font-family: KaTeX_Size2;
+}
+.katex .op-limits > .vlist-t {
+ text-align: center;
+}
+.katex .katex-accent > .vlist-t {
+ text-align: center;
+}
+.katex .katex-accent .accent-body {
+ position: relative;
+}
+.katex .katex-accent .accent-body:not(.accent-full) {
+ width: 0;
+}
+.katex .katex-overlay {
+ display: block;
+}
+.katex .mtable .vertical-separator {
+ display: inline-block;
+ min-width: 1px;
+}
+.katex .mtable .arraycolsep {
+ display: inline-block;
+}
+.katex .mtable .col-align-c > .vlist-t {
+ text-align: center;
+}
+.katex .mtable .col-align-l > .vlist-t {
+ text-align: left;
+}
+.katex .mtable .col-align-r > .vlist-t {
+ text-align: right;
+}
+.katex .svg-align {
+ text-align: left;
+}
+.katex svg {
+ display: block;
+ position: absolute;
+ width: 100%;
+ height: inherit;
+ fill: currentColor;
+ stroke: currentColor;
+}
+.katex svg path {
+ stroke: none;
+}
+.katex svg {
+ fill-rule: nonzero;
+ fill-opacity: 1;
+ stroke-width: 1;
+ stroke-linecap: butt;
+ stroke-linejoin: miter;
+ stroke-miterlimit: 4;
+ stroke-dasharray: none;
+ stroke-dashoffset: 0;
+ stroke-opacity: 1;
+}
+.katex img {
+ border-style: none;
+ min-width: 0;
+ min-height: 0;
+ max-width: none;
+ max-height: none;
+}
+.katex .katex-stretchy {
+ width: 100%;
+ display: block;
+ position: relative;
+ overflow: hidden;
+}
+.katex .katex-stretchy::before, .katex .katex-stretchy::after {
+ content: "";
+}
+.katex .hide-tail {
+ width: 100%;
+ position: relative;
+ overflow: hidden;
+}
+.katex .halfarrow-left {
+ position: absolute;
+ left: 0;
+ width: 50.2%;
+ overflow: hidden;
+}
+.katex .halfarrow-right {
+ position: absolute;
+ right: 0;
+ width: 50.2%;
+ overflow: hidden;
+}
+.katex .brace-left {
+ position: absolute;
+ left: 0;
+ width: 25.1%;
+ overflow: hidden;
+}
+.katex .brace-center {
+ position: absolute;
+ left: 25%;
+ width: 50%;
+ overflow: hidden;
+}
+.katex .brace-right {
+ position: absolute;
+ right: 0;
+ width: 25.1%;
+ overflow: hidden;
+}
+.katex .x-arrow-pad {
+ padding: 0 0.5em;
+}
+.katex .cd-arrow-pad {
+ padding: 0 0.55556em 0 0.27778em;
+}
+.katex .x-arrow,
+.katex .mover,
+.katex .munder {
+ text-align: center;
+}
+.katex .boxpad {
+ padding: 0 0.3em;
+}
+.katex .fbox,
+.katex .fcolorbox {
+ box-sizing: border-box;
+ border: 0.04em solid;
+}
+.katex .cancel-pad {
+ padding: 0 0.2em;
+}
+.katex .cancel-lap {
+ margin-left: -0.2em;
+ margin-right: -0.2em;
+}
+.katex .katex-sout {
+ border-bottom-style: solid;
+ border-bottom-width: 0.08em;
+}
+.katex .angl {
+ box-sizing: border-box;
+ border-top: 0.049em solid;
+ border-right: 0.049em solid;
+ margin-right: 0.03889em;
+}
+.katex .anglpad {
+ padding: 0 0.03889em;
+}
+.katex .eqn-num::before {
+ counter-increment: katexEqnNo;
+ content: "(" counter(katexEqnNo) ")";
+}
+.katex .mml-eqn-num::before {
+ counter-increment: mmlEqnNo;
+ content: "(" counter(mmlEqnNo) ")";
+}
+.katex .mtr-glue {
+ width: 50%;
+}
+.katex .cd-vert-arrow {
+ display: inline-block;
+ position: relative;
+}
+.katex .cd-label-left {
+ display: inline-block;
+ position: absolute;
+ right: calc(50% + 0.3em);
+ text-align: left;
+}
+.katex .cd-label-right {
+ display: inline-block;
+ position: absolute;
+ left: calc(50% + 0.3em);
+ text-align: right;
+}
+
+.katex-display {
+ display: block;
+ margin: 1em 0;
+ text-align: center;
+}
+.katex-display > .katex {
+ display: block;
+ text-align: center;
+ white-space: nowrap;
+}
+.katex-display > .katex > .katex-html {
+ display: block;
+ position: relative;
+}
+.katex-display > .katex > .katex-html > .katex-tag {
+ position: absolute;
+ right: 0;
+}
+
+.katex-display.leqno > .katex > .katex-html > .katex-tag {
+ left: 0;
+ right: auto;
+}
+
+.katex-display.fleqn > .katex {
+ text-align: left;
+ padding-left: 2em;
+}
+
+body {
+ counter-reset: katexEqnNo mmlEqnNo;
+}
diff --git a/source/infra/css/katex.min.css b/source/infra/css/katex.min.css
deleted file mode 100644
index f11a882..0000000
--- a/source/infra/css/katex.min.css
+++ /dev/null
@@ -1 +0,0 @@
-@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_AMS-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_AMS-Regular.woff) format("woff"),url(/infra/font/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(/infra/font/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(/infra/font/KaTeX_Caligraphic-Bold.woff) format("woff"),url(/infra/font/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Caligraphic-Regular.woff) format("woff"),url(/infra/font/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(/infra/font/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(/infra/font/KaTeX_Fraktur-Bold.woff) format("woff"),url(/infra/font/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Fraktur-Regular.woff) format("woff"),url(/infra/font/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(/infra/font/KaTeX_Main-Bold.woff2) format("woff2"),url(/infra/font/KaTeX_Main-Bold.woff) format("woff"),url(/infra/font/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(/infra/font/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(/infra/font/KaTeX_Main-BoldItalic.woff) format("woff"),url(/infra/font/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(/infra/font/KaTeX_Main-Italic.woff2) format("woff2"),url(/infra/font/KaTeX_Main-Italic.woff) format("woff"),url(/infra/font/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Main-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Main-Regular.woff) format("woff"),url(/infra/font/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(/infra/font/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(/infra/font/KaTeX_Math-BoldItalic.woff) format("woff"),url(/infra/font/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(/infra/font/KaTeX_Math-Italic.woff2) format("woff2"),url(/infra/font/KaTeX_Math-Italic.woff) format("woff"),url(/infra/font/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(/infra/font/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(/infra/font/KaTeX_SansSerif-Bold.woff) format("woff"),url(/infra/font/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(/infra/font/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(/infra/font/KaTeX_SansSerif-Italic.woff) format("woff"),url(/infra/font/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_SansSerif-Regular.woff) format("woff"),url(/infra/font/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Script-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Script-Regular.woff) format("woff"),url(/infra/font/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Size1-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Size1-Regular.woff) format("woff"),url(/infra/font/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Size2-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Size2-Regular.woff) format("woff"),url(/infra/font/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Size3-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Size3-Regular.woff) format("woff"),url(/infra/font/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Size4-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Size4-Regular.woff) format("woff"),url(/infra/font/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(/infra/font/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(/infra/font/KaTeX_Typewriter-Regular.woff) format("woff"),url(/infra/font/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{text-rendering:auto;font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.16.8"}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo}
diff --git a/source/infra/js/cgit.js b/source/infra/js/cgit.js
new file mode 100644
index 0000000..df3ad4e
--- /dev/null
+++ b/source/infra/js/cgit.js
@@ -0,0 +1,68 @@
+/* cgit.js: javacript functions for cgit
+ *
+ * Copyright (C) 2006-2018 cgit Development Team <cgit@lists.zx2c4.com>
+ *
+ * Licensed under GNU General Public License v2
+ * (see COPYING for full license text)
+ */
+
+(function () {
+
+/* This follows the logic and suffixes used in ui-shared.c */
+
+var age_classes = [ "age-mins", "age-hours", "age-days", "age-weeks", "age-months", "age-years" ];
+var age_suffix = [ "min.", "hours", "days", "weeks", "months", "years", "years" ];
+var age_next = [ 60, 3600, 24 * 3600, 7 * 24 * 3600, 30 * 24 * 3600, 365 * 24 * 3600, 365 * 24 * 3600 ];
+var age_limit = [ 7200, 24 * 7200, 7 * 24 * 7200, 30 * 24 * 7200, 365 * 25 * 7200, 365 * 25 * 7200 ];
+var update_next = [ 10, 5 * 60, 1800, 24 * 3600, 24 * 3600, 24 * 3600, 24 * 3600 ];
+
+function render_age(e, age) {
+ var t, n;
+
+ for (n = 0; n < age_classes.length; n++)
+ if (age < age_limit[n])
+ break;
+
+ t = Math.round(age / age_next[n]) + " " + age_suffix[n];
+
+ if (e.textContent != t) {
+ e.textContent = t;
+ if (n == age_classes.length)
+ n--;
+ if (e.className != age_classes[n])
+ e.className = age_classes[n];
+ }
+}
+
+function aging() {
+ var n, next = 24 * 3600,
+ now_ut = Math.round((new Date().getTime() / 1000));
+
+ for (n = 0; n < age_classes.length; n++) {
+ var m, elems = document.getElementsByClassName(age_classes[n]);
+
+ if (elems.length && update_next[n] < next)
+ next = update_next[n];
+
+ for (m = 0; m < elems.length; m++) {
+ var age = now_ut - elems[m].getAttribute("data-ut");
+
+ render_age(elems[m], age);
+ }
+ }
+
+ /*
+ * We only need to come back when the age might have changed.
+ * Eg, if everything is counted in hours already, once per
+ * 5 minutes is accurate enough.
+ */
+
+ window.setTimeout(aging, next * 1000);
+}
+
+document.addEventListener("DOMContentLoaded", function() {
+ /* we can do the aging on DOM content load since no layout dependency */
+ aging();
+}, false);
+
+})();
diff --git a/source/infra/js/count.js b/source/infra/js/count.js
deleted file mode 100644
index 0271445..0000000
--- a/source/infra/js/count.js
+++ /dev/null
@@ -1,274 +0,0 @@
-// GoatCounter: https://www.goatcounter.com
-// This file (and *only* this file) is released under the ISC license:
-// https://opensource.org/licenses/ISC
-;(function() {
- 'use strict';
-
- if (window.goatcounter && window.goatcounter.vars) // Compatibility with very old version; do not use.
- window.goatcounter = window.goatcounter.vars
- else
- window.goatcounter = window.goatcounter || {}
-
- // Load settings from data-goatcounter-settings.
- var s = document.querySelector('script[data-goatcounter]')
- if (s && s.dataset.goatcounterSettings) {
- try { var set = JSON.parse(s.dataset.goatcounterSettings) }
- catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) }
- for (var k in set)
- if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1)
- window.goatcounter[k] = set[k]
- }
-
- var enc = encodeURIComponent
-
- // Get all data we're going to send off to the counter endpoint.
- var get_data = function(vars) {
- var data = {
- p: (vars.path === undefined ? goatcounter.path : vars.path),
- r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer),
- t: (vars.title === undefined ? goatcounter.title : vars.title),
- e: !!(vars.event || goatcounter.event),
- s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)],
- b: is_bot(),
- q: location.search,
- }
-
- var rcb, pcb, tcb // Save callbacks to apply later.
- if (typeof(data.r) === 'function') rcb = data.r
- if (typeof(data.t) === 'function') tcb = data.t
- if (typeof(data.p) === 'function') pcb = data.p
-
- if (is_empty(data.r)) data.r = document.referrer
- if (is_empty(data.t)) data.t = document.title
- if (is_empty(data.p)) data.p = get_path()
-
- if (rcb) data.r = rcb(data.r)
- if (tcb) data.t = tcb(data.t)
- if (pcb) data.p = pcb(data.p)
- return data
- }
-
- // Check if a value is "empty" for the purpose of get_data().
- var is_empty = function(v) { return v === null || v === undefined || typeof(v) === 'function' }
-
- // See if this looks like a bot; there is some additional filtering on the
- // backend, but these properties can't be fetched from there.
- var is_bot = function() {
- // Headless browsers are probably a bot.
- var w = window, d = document
- if (w.callPhantom || w._phantom || w.phantom)
- return 150
- if (w.__nightmare)
- return 151
- if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate)
- return 152
- if (navigator.webdriver)
- return 153
- return 0
- }
-
- // Object to urlencoded string, starting with a ?.
- var urlencode = function(obj) {
- var p = []
- for (var k in obj)
- if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false)
- p.push(enc(k) + '=' + enc(obj[k]))
- return '?' + p.join('&')
- }
-
- // Show a warning in the console.
- var warn = function(msg) {
- if (console && 'warn' in console)
- console.warn('goatcounter: ' + msg)
- }
-
- // Get the endpoint to send requests to.
- var get_endpoint = function() {
- var s = document.querySelector('script[data-goatcounter]')
- if (s && s.dataset.goatcounter)
- return s.dataset.goatcounter
- return (goatcounter.endpoint || window.counter) // counter is for compat; don't use.
- }
-
- // Get current path.
- var get_path = function() {
- var loc = location,
- c = document.querySelector('link[rel="canonical"][href]')
- if (c) { // May be relative or point to different domain.
- var a = document.createElement('a')
- a.href = c.href
- if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, ''))
- loc = a
- }
- return (loc.pathname + loc.search) || '/'
- }
-
- // Run function after DOM is loaded.
- var on_load = function(f) {
- if (document.body === null)
- document.addEventListener('DOMContentLoaded', function() { f() }, false)
- else
- f()
- }
-
- // Filter some requests that we (probably) don't want to count.
- goatcounter.filter = function() {
- if ('visibilityState' in document && document.visibilityState === 'prerender')
- return 'visibilityState'
- if (!goatcounter.allow_frame && location !== parent.location)
- return 'frame'
- if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/))
- return 'localhost'
- if (!goatcounter.allow_local && location.protocol === 'file:')
- return 'localfile'
- if (localStorage && localStorage.getItem('skipgc') === 't')
- return 'disabled with #toggle-goatcounter'
- return false
- }
-
- // Get URL to send to GoatCounter.
- window.goatcounter.url = function(vars) {
- var data = get_data(vars || {})
- if (data.p === null) // null from user callback.
- return
- data.rnd = Math.random().toString(36).substr(2, 5) // Browsers don't always listen to Cache-Control.
-
- var endpoint = get_endpoint()
- if (!endpoint)
- return warn('no endpoint found')
-
- return endpoint + urlencode(data)
- }
-
- // Count a hit.
- window.goatcounter.count = function(vars) {
- var f = goatcounter.filter()
- if (f)
- return warn('not counting because of: ' + f)
-
- var url = goatcounter.url(vars)
- if (!url)
- return warn('not counting because path callback returned null')
-
- if (navigator.sendBeacon)
- navigator.sendBeacon(url)
- else { // Fallback for (very) old browsers.
- var img = document.createElement('img')
- img.src = url
- img.style.position = 'absolute' // Affect layout less.
- img.style.bottom = '0px'
- img.style.width = '1px'
- img.style.height = '1px'
- img.loading = 'eager'
- img.setAttribute('alt', '')
- img.setAttribute('aria-hidden', 'true')
-
- var rm = function() { if (img && img.parentNode) img.parentNode.removeChild(img) }
- img.addEventListener('load', rm, false)
- document.body.appendChild(img)
- }
- }
-
- // Get a query parameter.
- window.goatcounter.get_query = function(name) {
- var s = location.search.substr(1).split('&')
- for (var i = 0; i < s.length; i++)
- if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0)
- return s[i].substr(name.length + 1)
- }
-
- // Track click events.
- window.goatcounter.bind_events = function() {
- if (!document.querySelectorAll) // Just in case someone uses an ancient browser.
- return
-
- var send = function(elem) {
- return function() {
- goatcounter.count({
- event: true,
- path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''),
- title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''),
- referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''),
- })
- }
- }
-
- Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function(elem) {
- if (elem.dataset.goatcounterBound)
- return
- var f = send(elem)
- elem.addEventListener('click', f, false)
- elem.addEventListener('auxclick', f, false) // Middle click.
- elem.dataset.goatcounterBound = 'true'
- })
- }
-
- // Add a "visitor counter" frame or image.
- window.goatcounter.visit_count = function(opt) {
- on_load(function() {
- opt = opt || {}
- opt.type = opt.type || 'html'
- opt.append = opt.append || 'body'
- opt.path = opt.path || get_path()
- opt.attr = opt.attr || {width: '200', height: (opt.no_branding ? '60' : '80')}
-
- opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?'
- if (opt.no_branding) opt.attr['src'] += '&no_branding=1'
- if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style)
- if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start)
- if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end)
-
- var tag = {png: 'img', svg: 'img', html: 'iframe'}[opt.type]
- if (!tag)
- return warn('visit_count: unknown type: ' + opt.type)
-
- if (opt.type === 'html') {
- opt.attr['frameborder'] = '0'
- opt.attr['scrolling'] = 'no'
- }
-
- var d = document.createElement(tag)
- for (var k in opt.attr)
- d.setAttribute(k, opt.attr[k])
-
- var p = document.querySelector(opt.append)
- if (!p)
- return warn('visit_count: append not found: ' + opt.append)
- p.appendChild(d)
- })
- }
-
- // Make it easy to skip your own views.
- if (location.hash === '#toggle-goatcounter') {
- if (localStorage.getItem('skipgc') === 't') {
- localStorage.removeItem('skipgc', 't')
- alert('GoatCounter tracking is now ENABLED in this browser.')
- }
- else {
- localStorage.setItem('skipgc', 't')
- alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.')
- }
- }
-
- if (!goatcounter.no_onload)
- on_load(function() {
- // 1. Page is visible, count request.
- // 2. Page is not yet visible; wait until it switches to 'visible' and count.
- // See #487
- if (!('visibilityState' in document) || document.visibilityState === 'visible')
- goatcounter.count()
- else {
- var f = function(e) {
- if (document.visibilityState !== 'visible')
- return
- document.removeEventListener('visibilitychange', f)
- goatcounter.count()
- }
- document.addEventListener('visibilitychange', f)
- }
-
- if (!goatcounter.no_events)
- goatcounter.bind_events()
- })
-})();
-
diff --git a/source/infra/js/katex.js b/source/infra/js/katex.js
new file mode 100644
index 0000000..795ae73
--- /dev/null
+++ b/source/infra/js/katex.js
@@ -0,0 +1,17701 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define([], factory);
+ else if(typeof exports === 'object')
+ exports["katex"] = factory();
+ else
+ root["katex"] = factory();
+})((typeof self !== 'undefined' ? self : this), function() {
+return /******/ (function() { // webpackBootstrap
+/******/ "use strict";
+/******/ // The require scope
+/******/ var __webpack_require__ = {};
+/******/
+/************************************************************************/
+/******/ /* webpack/runtime/define property getters */
+/******/ !function() {
+/******/ // define getter functions for harmony exports
+/******/ __webpack_require__.d = function(exports, definition) {
+/******/ for(var key in definition) {
+/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ }
+/******/ }
+/******/ };
+/******/ }();
+/******/
+/******/ /* webpack/runtime/hasOwnProperty shorthand */
+/******/ !function() {
+/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
+/******/ }();
+/******/
+/************************************************************************/
+var __webpack_exports__ = {};
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, {
+ "default": function() { return /* binding */ katex_webpack; }
+});
+
+;// ./src/ParseError.ts
+/**
+ * This is the ParseError class, which is the main error thrown by KaTeX
+ * functions when something has gone wrong. This is used to distinguish internal
+ * errors from errors in the expression that the user provided.
+ *
+ * If possible, a caller should provide a Token or ParseNode with information
+ * about where in the source string the problem occurred.
+ */
+class ParseError extends Error {
+ // The underlying error message without any context added.
+
+ constructor(message,
+ // The error message
+ token) {
+ let error = "KaTeX parse error: " + message;
+ let start;
+ let end;
+ const loc = token && token.loc;
+ if (loc && loc.start <= loc.end) {
+ // If we have the input and a position, make the error a bit fancier
+
+ // Get the input
+ const input = loc.lexer.input;
+
+ // Prepend some information
+ start = loc.start;
+ end = loc.end;
+ if (start === input.length) {
+ error += " at end of input: ";
+ } else {
+ error += " at position " + (start + 1) + ": ";
+ }
+
+ // Underline token in question using combining underscores
+ const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332");
+
+ // Extract some context from the input and add it to the error
+ let left;
+ if (start > 15) {
+ left = "…" + input.slice(start - 15, start);
+ } else {
+ left = input.slice(0, start);
+ }
+ let right;
+ if (end + 15 < input.length) {
+ right = input.slice(end, end + 15) + "…";
+ } else {
+ right = input.slice(end);
+ }
+ error += left + underlined + right;
+ }
+ super(error);
+ this.name = "ParseError";
+ this.position = void 0;
+ // Error start position based on passed-in Token or ParseNode.
+ this.length = void 0;
+ // Length of affected text based on passed-in Token or ParseNode.
+ this.rawMessage = void 0;
+ Object.setPrototypeOf(this, ParseError.prototype);
+ this.position = start;
+ if (start != null && end != null) {
+ this.length = end - start;
+ }
+ this.rawMessage = message;
+ }
+}
+/* harmony default export */ var src_ParseError = (ParseError);
+;// ./src/utils.ts
+/**
+ * This file contains a list of utility functions which are useful in other
+ * files.
+ */
+
+// hyphenate and escape adapted from Facebook's React under Apache 2 license
+const uppercase = /([A-Z])/g;
+const hyphenate = str => str.replace(uppercase, "-$1").toLowerCase();
+const ESCAPE_LOOKUP = {
+ "&": "&amp;",
+ ">": "&gt;",
+ "<": "&lt;",
+ "\"": "&quot;",
+ "'": "&#x27;"
+};
+const ESCAPE_REGEX = /[&><"']/g;
+
+/**
+ * Escapes text to prevent scripting attacks.
+ */
+const utils_escape = text => String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]);
+
+/**
+ * Sometimes we want to pull out the innermost element of a group. In most
+ * cases, this will just be the group itself, but when ordgroups and colors have
+ * a single element, we want to pull that out.
+ */
+const getBaseElem = group => {
+ if (group.type === "ordgroup") {
+ if (group.body.length === 1) {
+ return getBaseElem(group.body[0]);
+ } else {
+ return group;
+ }
+ } else if (group.type === "color") {
+ if (group.body.length === 1) {
+ return getBaseElem(group.body[0]);
+ } else {
+ return group;
+ }
+ } else if (group.type === "font") {
+ return getBaseElem(group.body);
+ } else {
+ return group;
+ }
+};
+const characterNodesTypes = new Set(["mathord", "textord", "atom"]);
+
+/**
+ * TeXbook algorithms often reference "character boxes", which are simply groups
+ * with a single character in them. To decide if something is a character box,
+ * we find its innermost group, and see if it is a single character.
+ */
+const isCharacterBox = group => characterNodesTypes.has(getBaseElem(group).type);
+
+/**
+ * Return the protocol of a URL, or "_relative" if the URL does not specify a
+ * protocol (and thus is relative), or `null` if URL has invalid protocol
+ * (so should be outright rejected).
+ */
+const protocolFromUrl = url => {
+ // Check for possible leading protocol.
+ // https://url.spec.whatwg.org/#url-parsing strips leading whitespace
+ // (U+20) or C0 control (U+00-U+1F) characters.
+ const protocol = /^[\x00-\x20]*([^\\/#?]*?)(:|&#0*58|&#x0*3a|&colon)/i.exec(url);
+ if (!protocol) {
+ return "_relative";
+ }
+ // Reject weird colons
+ if (protocol[2] !== ":") {
+ return null;
+ }
+ // Reject invalid characters in scheme according to
+ // https://datatracker.ietf.org/doc/html/rfc3986#section-3.1
+ if (!/^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(protocol[1])) {
+ return null;
+ }
+ // Lowercase the protocol
+ return protocol[1].toLowerCase();
+};
+;// ./src/Settings.ts
+/* eslint no-console:0 */
+/**
+ * This is a module for storing settings passed into KaTeX. It correctly handles
+ * default settings.
+ */
+
+
+
+
+/**
+ * Union of all values that appear as schema defaults, cliDefaults, or
+ * cliProcessor return values. StrictFunction / TrustFunction are
+ * option-value types, not default/schema values, so they are excluded.
+ */
+
+// TODO: automatically generate documentation
+// TODO: check all properties on Settings exist
+// TODO: check the type of a property on Settings matches
+const SETTINGS_SCHEMA = {
+ displayMode: {
+ type: "boolean",
+ description: "Render math in display mode, which puts the math in " + "display style (so \\int and \\sum are large, for example), and " + "centers the math on the page on its own line.",
+ cli: "-d, --display-mode"
+ },
+ output: {
+ type: {
+ enum: ["htmlAndMathml", "html", "mathml"]
+ },
+ description: "Determines the markup language of the output.",
+ cli: "-F, --format <type>"
+ },
+ leqno: {
+ type: "boolean",
+ description: "Render display math in leqno style (left-justified tags)."
+ },
+ fleqn: {
+ type: "boolean",
+ description: "Render display math flush left."
+ },
+ throwOnError: {
+ type: "boolean",
+ default: true,
+ cli: "-t, --no-throw-on-error",
+ cliDescription: "Render errors (in the color given by --error-color) ins" + "tead of throwing a ParseError exception when encountering an error."
+ },
+ errorColor: {
+ type: "string",
+ default: "#cc0000",
+ cli: "-c, --error-color <color>",
+ cliDescription: "A color string given in the format 'rgb' or 'rrggbb' " + "(no #). This option determines the color of errors rendered by the " + "-t option.",
+ cliProcessor: color => "#" + color
+ },
+ macros: {
+ type: "object",
+ cli: "-m, --macro <def>",
+ cliDescription: "Define custom macro of the form '\\foo:expansion' (use " + "multiple -m arguments for multiple macros).",
+ cliDefault: [],
+ cliProcessor: (def, defs) => {
+ defs.push(def);
+ return defs;
+ }
+ },
+ minRuleThickness: {
+ type: "number",
+ description: "Specifies a minimum thickness, in ems, for fraction lines," + " `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, " + "`\\hdashline`, `\\underline`, `\\overline`, and the borders of " + "`\\fbox`, `\\boxed`, and `\\fcolorbox`.",
+ processor: t => Math.max(0, t),
+ cli: "--min-rule-thickness <size>",
+ cliProcessor: parseFloat
+ },
+ colorIsTextColor: {
+ type: "boolean",
+ description: "Makes \\color behave like LaTeX's 2-argument \\textcolor, " + "instead of LaTeX's one-argument \\color mode change.",
+ cli: "-b, --color-is-text-color"
+ },
+ strict: {
+ type: [{
+ enum: ["warn", "ignore", "error"]
+ }, "boolean", "function"],
+ description: "Turn on strict / LaTeX faithfulness mode, which throws an " + "error if the input uses features that are not supported by LaTeX.",
+ cli: "-S, --strict",
+ cliDefault: false
+ },
+ trust: {
+ type: ["boolean", "function"],
+ description: "Trust the input, enabling all HTML features such as \\url.",
+ cli: "-T, --trust"
+ },
+ maxSize: {
+ type: "number",
+ default: Infinity,
+ description: "If non-zero, all user-specified sizes, e.g. in " + "\\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, " + "elements and spaces can be arbitrarily large",
+ processor: s => Math.max(0, s),
+ cli: "-s, --max-size <n>",
+ cliProcessor: parseInt
+ },
+ maxExpand: {
+ type: "number",
+ default: 1000,
+ description: "Limit the number of macro expansions to the specified " + "number, to prevent e.g. infinite macro loops. If set to Infinity, " + "the macro expander will try to fully expand as in LaTeX.",
+ processor: n => Math.max(0, n),
+ cli: "-e, --max-expand <n>",
+ cliProcessor: n => n === "Infinity" ? Infinity : parseInt(n)
+ },
+ globalGroup: {
+ type: "boolean",
+ cli: false
+ }
+};
+function getImplicitDefault(type) {
+ if (typeof type !== 'string') {
+ return type.enum[0];
+ }
+ switch (type) {
+ case 'boolean':
+ return false;
+ case 'string':
+ return '';
+ case 'number':
+ return 0;
+ case 'object':
+ return {};
+ default:
+ throw new Error("Unexpected schema type; settings must declare an explicit default.");
+ }
+}
+function getDefaultValue(schema) {
+ if (Object.prototype.hasOwnProperty.call(schema, "default") && schema.default !== undefined) {
+ return schema.default;
+ }
+ const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
+ return getImplicitDefault(type);
+}
+function applySetting(target, prop, options, schema) {
+ const optionValue = Object.prototype.hasOwnProperty.call(options, prop) ? options[prop] : undefined;
+ const processor = Object.prototype.hasOwnProperty.call(schema, "processor") ? schema.processor : undefined;
+ target[prop] = optionValue !== undefined ? processor ? processor(optionValue) : optionValue : getDefaultValue(schema);
+}
+
+/**
+ * The main Settings object
+ *
+ * The current options stored are:
+ * - displayMode: Whether the expression should be typeset as inline math
+ * (false, the default), meaning that the math starts in
+ * \textstyle and is placed in an inline-block); or as display
+ * math (true), meaning that the math starts in \displaystyle
+ * and is placed in a block with vertical margin.
+ */
+class Settings {
+ constructor(options) {
+ if (options === void 0) {
+ options = {};
+ }
+ this.displayMode = void 0;
+ this.output = void 0;
+ this.leqno = void 0;
+ this.fleqn = void 0;
+ this.throwOnError = void 0;
+ this.errorColor = void 0;
+ this.macros = void 0;
+ this.minRuleThickness = void 0;
+ this.colorIsTextColor = void 0;
+ this.strict = void 0;
+ this.trust = void 0;
+ this.maxSize = void 0;
+ this.maxExpand = void 0;
+ this.globalGroup = void 0;
+ // allow null options
+ options = options || {};
+ for (const prop of Object.keys(SETTINGS_SCHEMA)) {
+ const schema = SETTINGS_SCHEMA[prop];
+ if (schema) {
+ // TODO: validate options
+ applySetting(this, prop, options, schema);
+ }
+ }
+ }
+
+ /**
+ * Report nonstrict (non-LaTeX-compatible) input.
+ * Can safely not be called if `this.strict` is false in JavaScript.
+ */
+ reportNonstrict(errorCode, errorMsg, token) {
+ let strict = this.strict;
+ if (typeof strict === "function") {
+ // Allow return value of strict function to be boolean or string
+ // (or null/undefined, meaning no further processing).
+ strict = strict(errorCode, errorMsg, token);
+ }
+ if (!strict || strict === "ignore") {
+ return;
+ } else if (strict === true || strict === "error") {
+ throw new src_ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + (errorMsg + " [" + errorCode + "]"), token);
+ } else if (strict === "warn") {
+ typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]"));
+ } else {
+ // won't happen in type-safe code
+ typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]"));
+ }
+ }
+
+ /**
+ * Check whether to apply strict (LaTeX-adhering) behavior for unusual
+ * input (like `\\`). Unlike `nonstrict`, will not throw an error;
+ * instead, "error" translates to a return value of `true`, while "ignore"
+ * translates to a return value of `false`. May still print a warning:
+ * "warn" prints a warning and returns `false`.
+ * This is for the second category of `errorCode`s listed in the README.
+ */
+ useStrictBehavior(errorCode, errorMsg, token) {
+ let strict = this.strict;
+ if (typeof strict === "function") {
+ // Allow return value of strict function to be boolean or string
+ // (or null/undefined, meaning no further processing).
+ // But catch any exceptions thrown by function, treating them
+ // like "error".
+ try {
+ strict = strict(errorCode, errorMsg, token);
+ } catch (error) {
+ strict = "error";
+ }
+ }
+ if (!strict || strict === "ignore") {
+ return false;
+ } else if (strict === true || strict === "error") {
+ return true;
+ } else if (strict === "warn") {
+ typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]"));
+ return false;
+ } else {
+ // won't happen in type-safe code
+ typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]"));
+ return false;
+ }
+ }
+
+ /**
+ * Check whether to test potentially dangerous input, and return
+ * `true` (trusted) or `false` (untrusted). The sole argument `context`
+ * should be an object with `command` field specifying the relevant LaTeX
+ * command (as a string starting with `\`), and any other arguments, etc.
+ * If `context` has a `url` field, a `protocol` field will automatically
+ * get added by this function (changing the specified object).
+ */
+ isTrusted(context) {
+ if ("url" in context && context.url && !context.protocol) {
+ const protocol = protocolFromUrl(context.url);
+ if (protocol == null) {
+ return false;
+ }
+ context.protocol = protocol;
+ }
+ const trust = typeof this.trust === "function" ? this.trust(context) : this.trust;
+ return Boolean(trust);
+ }
+}
+;// ./src/Style.ts
+/**
+ * This file contains information and classes for the various kinds of styles
+ * used in TeX. It provides a generic `Style` class, which holds information
+ * about a specific style. It then provides instances of all the different kinds
+ * of styles possible, and provides functions to move between them and get
+ * information about them.
+ */
+
+/**
+ * The main style class. Contains a unique id for the style, a size (which is
+ * the same for cramped and uncramped version of a style), and a cramped flag.
+ */
+class Style {
+ constructor(id, size, cramped) {
+ this.id = void 0;
+ this.size = void 0;
+ this.cramped = void 0;
+ this.id = id;
+ this.size = size;
+ this.cramped = cramped;
+ }
+
+ /**
+ * Get the style of a superscript given a base in the current style.
+ */
+ sup() {
+ return styles[sup[this.id]];
+ }
+
+ /**
+ * Get the style of a subscript given a base in the current style.
+ */
+ sub() {
+ return styles[sub[this.id]];
+ }
+
+ /**
+ * Get the style of a fraction numerator given the fraction in the current
+ * style.
+ */
+ fracNum() {
+ return styles[fracNum[this.id]];
+ }
+
+ /**
+ * Get the style of a fraction denominator given the fraction in the current
+ * style.
+ */
+ fracDen() {
+ return styles[fracDen[this.id]];
+ }
+
+ /**
+ * Get the cramped version of a style (in particular, cramping a cramped style
+ * doesn't change the style).
+ */
+ cramp() {
+ return styles[cramp[this.id]];
+ }
+
+ /**
+ * Get a text or display version of this style.
+ */
+ text() {
+ return styles[Style_text[this.id]];
+ }
+
+ /**
+ * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle)
+ */
+ isTight() {
+ return this.size >= 2;
+ }
+}
+
+// Export an interface for type checking, but don't expose the implementation.
+// This way, no more styles can be generated.
+
+// IDs of the different styles
+const D = 0;
+const Dc = 1;
+const T = 2;
+const Tc = 3;
+const S = 4;
+const Sc = 5;
+const SS = 6;
+const SSc = 7;
+
+// Instances of the different styles
+const styles = [new Style(D, 0, false), new Style(Dc, 0, true), new Style(T, 1, false), new Style(Tc, 1, true), new Style(S, 2, false), new Style(Sc, 2, true), new Style(SS, 3, false), new Style(SSc, 3, true)];
+
+// Lookup tables for switching from one style to another
+const sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
+const sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
+const fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
+const fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
+const cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
+const Style_text = [D, Dc, T, Tc, T, Tc, T, Tc];
+
+// We only export some of the styles.
+/* harmony default export */ var src_Style = ({
+ DISPLAY: styles[D],
+ TEXT: styles[T],
+ SCRIPT: styles[S],
+ SCRIPTSCRIPT: styles[SS]
+});
+;// ./src/unicodeScripts.ts
+/*
+ * This file defines the Unicode scripts and script families that we
+ * support. To add new scripts or families, just add a new entry to the
+ * scriptData array below. Adding scripts to the scriptData array allows
+ * characters from that script to appear in \text{} environments.
+ */
+
+/**
+ * Each script or script family has a name and an array of blocks.
+ * Each block is an array of two numbers which specify the start and
+ * end points (inclusive) of a block of Unicode codepoints.
+ */
+
+/**
+ * Unicode block data for the families of scripts we support in \text{}.
+ * Scripts only need to appear here if they do not have font metrics.
+ */
+const scriptData = [{
+ // Latin characters beyond the Latin-1 characters we have metrics for.
+ // Needed for Czech, Hungarian and Turkish text, for example.
+ name: 'latin',
+ blocks: [[0x0100, 0x024f],
+ // Latin Extended-A and Latin Extended-B
+ [0x0300, 0x036f] // Combining Diacritical marks
+ ]
+}, {
+ // The Cyrillic script used by Russian and related languages.
+ // A Cyrillic subset used to be supported as explicitly defined
+ // symbols in symbols.js
+ name: 'cyrillic',
+ blocks: [[0x0400, 0x04ff]]
+}, {
+ // Armenian
+ name: 'armenian',
+ blocks: [[0x0530, 0x058F]]
+}, {
+ // The Brahmic scripts of South and Southeast Asia
+ // Devanagari (0900–097F)
+ // Bengali (0980–09FF)
+ // Gurmukhi (0A00–0A7F)
+ // Gujarati (0A80–0AFF)
+ // Oriya (0B00–0B7F)
+ // Tamil (0B80–0BFF)
+ // Telugu (0C00–0C7F)
+ // Kannada (0C80–0CFF)
+ // Malayalam (0D00–0D7F)
+ // Sinhala (0D80–0DFF)
+ // Thai (0E00–0E7F)
+ // Lao (0E80–0EFF)
+ // Tibetan (0F00–0FFF)
+ // Myanmar (1000–109F)
+ name: 'brahmic',
+ blocks: [[0x0900, 0x109F]]
+}, {
+ name: 'georgian',
+ blocks: [[0x10A0, 0x10ff]]
+}, {
+ // Chinese and Japanese.
+ // The "k" in cjk is for Korean, but we've separated Korean out
+ name: "cjk",
+ blocks: [[0x3000, 0x30FF],
+ // CJK symbols and punctuation, Hiragana, Katakana
+ [0x4E00, 0x9FAF],
+ // CJK ideograms
+ [0xFF00, 0xFF60] // Fullwidth punctuation
+ // TODO: add halfwidth Katakana and Romanji glyphs
+ ]
+}, {
+ // Korean
+ name: 'hangul',
+ blocks: [[0xAC00, 0xD7AF]]
+}];
+
+/**
+ * Given a codepoint, return the name of the script or script family
+ * it is from, or null if it is not part of a known block
+ */
+function scriptFromCodepoint(codepoint) {
+ for (let i = 0; i < scriptData.length; i++) {
+ const script = scriptData[i];
+ for (let i = 0; i < script.blocks.length; i++) {
+ const block = script.blocks[i];
+ if (codepoint >= block[0] && codepoint <= block[1]) {
+ return script.name;
+ }
+ }
+ }
+ return null;
+}
+
+/**
+ * A flattened version of all the supported blocks in a single array.
+ * This is an optimization to make supportedCodepoint() fast.
+ */
+const allBlocks = [];
+scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b)));
+
+/**
+ * Given a codepoint, return true if it falls within one of the
+ * scripts or script families defined above and false otherwise.
+ *
+ * Micro benchmarks shows that this is faster than
+ * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test()
+ * in Firefox, Chrome and Node.
+ */
+function supportedCodepoint(codepoint) {
+ for (let i = 0; i < allBlocks.length; i += 2) {
+ if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) {
+ return true;
+ }
+ }
+ return false;
+}
+;// ./src/svgGeometry.ts
+/**
+ * This file provides support to domTree.js and delimiter.js.
+ * It's a storehouse of path geometry for SVG images.
+ */
+
+// In all paths below, the viewBox-to-em scale is 1000:1.
+
+// Second Brush Stroke
+// Low resolution monitors struggle to display images in fine detail.
+// So browsers apply anti-aliasing. A long straight arrow shaft therefore
+// will sometimes appear as if it has a blurred edge.
+
+// To mitigate this, these SVG files contain a second "brush-stroke" on the
+// arrow shafts. That is, a second long thin rectangular SVG path has been
+// written directly on top of each arrow shaft. This reinforcement causes
+// some of the screen pixels to display as black instead of the anti-aliased
+// gray pixel that a single path would generate. So we get arrow shafts
+// whose edges appear to be sharper.
+const doubleBrushStroke = svgPath => svgPath + " " + svgPath;
+const hLinePad = 80; // padding above a sqrt vinculum. Prevents image cropping.
+
+// The vinculum of a \sqrt can be made thicker by a KaTeX rendering option.
+// Think of variable extraVinculum as two detours in the SVG path.
+// The detour begins at the lower left of the area labeled extraVinculum below.
+// The detour proceeds one extraVinculum distance up and slightly to the right,
+// displacing the radiused corner between surd and vinculum. The radius is
+// traversed as usual, then the detour resumes. It goes right, to the end of
+// the very long vinculum, then down one extraVinculum distance,
+// after which it resumes regular path geometry for the radical.
+/* vinculum
+ /
+ /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraVinculum
+ / █████████████████████←0.04em (40 unit) std vinculum thickness
+ / /
+ / /
+ / /\
+ / / surd
+*/
+
+const sqrtMain = function (extraVinculum, hLinePad) {
+ // sqrtMain path geometry is from glyph U221A in the font KaTeX Main
+ return "M95," + (622 + extraVinculum + hLinePad) + "\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl" + extraVinculum / 2.075 + " -" + extraVinculum + "\nc5.3,-9.3,12,-14,20,-14\nH400000v" + (40 + extraVinculum) + "H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM" + (834 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z";
+};
+const sqrtSize1 = function (extraVinculum, hLinePad) {
+ // size1 is from glyph U221A in the font KaTeX_Size1-Regular
+ return "M263," + (601 + extraVinculum + hLinePad) + "c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl" + extraVinculum / 2.084 + " -" + extraVinculum + "\nc4.7,-7.3,11,-11,19,-11\nH40000v" + (40 + extraVinculum) + "H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z";
+};
+const sqrtSize2 = function (extraVinculum, hLinePad) {
+ // size2 is from glyph U221A in the font KaTeX_Size2-Regular
+ return "M983 " + (10 + extraVinculum + hLinePad) + "\nl" + extraVinculum / 3.13 + " -" + extraVinculum + "\nc4,-6.7,10,-10,18,-10 H400000v" + (40 + extraVinculum) + "\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "h-400000z";
+};
+const sqrtSize3 = function (extraVinculum, hLinePad) {
+ // size3 is from glyph U221A in the font KaTeX_Size3-Regular
+ return "M424," + (2398 + extraVinculum + hLinePad) + "\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl" + extraVinculum / 4.223 + " -" + extraVinculum + "c4,-6.7,10,-10,18,-10 H400000\nv" + (40 + extraVinculum) + "H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M" + (1001 + extraVinculum) + " " + hLinePad + "\nh400000v" + (40 + extraVinculum) + "h-400000z";
+};
+const sqrtSize4 = function (extraVinculum, hLinePad) {
+ // size4 is from glyph U221A in the font KaTeX_Size4-Regular
+ return "M473," + (2713 + extraVinculum + hLinePad) + "\nc339.3,-1799.3,509.3,-2700,510,-2702 l" + extraVinculum / 5.298 + " -" + extraVinculum + "\nc3.3,-7.3,9.3,-11,18,-11 H400000v" + (40 + extraVinculum) + "H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM" + (1001 + extraVinculum) + " " + hLinePad + "h400000v" + (40 + extraVinculum) + "H1017.7z";
+};
+const phasePath = function (y) {
+ const x = y / 2; // x coordinate at top of angle
+ return "M400000 " + y + " H0 L" + x + " 0 l65 45 L145 " + (y - 80) + " H400000z";
+};
+const sqrtTall = function (extraVinculum, hLinePad, viewBoxHeight) {
+ // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular
+ // One path edge has a variable length. It runs vertically from the vinculum
+ // to a point near (14 units) the bottom of the surd. The vinculum
+ // is normally 40 units thick. So the length of the line in question is:
+ const vertSegment = viewBoxHeight - 54 - hLinePad - extraVinculum;
+ return "M702 " + (extraVinculum + hLinePad) + "H400000" + (40 + extraVinculum) + "\nH742v" + vertSegment + "l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 " + hLinePad + "H400000v" + (40 + extraVinculum) + "H742z";
+};
+const sqrtPath = function (size, extraVinculum, viewBoxHeight) {
+ extraVinculum = 1000 * extraVinculum; // Convert from document ems to viewBox.
+ let path = "";
+ switch (size) {
+ case "sqrtMain":
+ path = sqrtMain(extraVinculum, hLinePad);
+ break;
+ case "sqrtSize1":
+ path = sqrtSize1(extraVinculum, hLinePad);
+ break;
+ case "sqrtSize2":
+ path = sqrtSize2(extraVinculum, hLinePad);
+ break;
+ case "sqrtSize3":
+ path = sqrtSize3(extraVinculum, hLinePad);
+ break;
+ case "sqrtSize4":
+ path = sqrtSize4(extraVinculum, hLinePad);
+ break;
+ case "sqrtTall":
+ path = sqrtTall(extraVinculum, hLinePad, viewBoxHeight);
+ }
+ return path;
+};
+const innerPath = function (name, height) {
+ // The inner part of stretchy tall delimiters
+ switch (name) {
+ case "\u239c":
+ return doubleBrushStroke("M291 0 H417 V" + height + " H291z");
+ case "\u2223":
+ return doubleBrushStroke("M145 0 H188 V" + height + " H145z");
+ case "\u2225":
+ return doubleBrushStroke("M145 0 H188 V" + height + " H145z") + doubleBrushStroke("M367 0 H410 V" + height + " H367z");
+ case "\u239f":
+ return doubleBrushStroke("M457 0 H583 V" + height + " H457z");
+ case "\u23a2":
+ return doubleBrushStroke("M319 0 H403 V" + height + " H319z");
+ case "\u23a5":
+ return doubleBrushStroke("M263 0 H347 V" + height + " H263z");
+ case "\u23aa":
+ return doubleBrushStroke("M384 0 H504 V" + height + " H384z");
+ case "\u23d0":
+ return doubleBrushStroke("M312 0 H355 V" + height + " H312z");
+ case "\u2016":
+ return doubleBrushStroke("M257 0 H300 V" + height + " H257z") + doubleBrushStroke("M478 0 H521 V" + height + " H478z");
+ default:
+ return "";
+ }
+};
+const path = {
+ // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main
+ doubleleftarrow: "M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",
+ // doublerightarrow is from glyph U+21D2 in font KaTeX Main
+ doublerightarrow: "M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",
+ // leftarrow is from glyph U+2190 in font KaTeX Main
+ leftarrow: "M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",
+ // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular
+ leftbrace: "M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",
+ leftbraceunder: "M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",
+ // overgroup is from the MnSymbol package (public domain)
+ leftgroup: "M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",
+ leftgroupunder: "M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",
+ // Harpoons are from glyph U+21BD in font KaTeX Main
+ leftharpoon: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",
+ leftharpoonplus: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",
+ leftharpoondown: "M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",
+ leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",
+ // hook is from glyph U+21A9 in font KaTeX Main
+ lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",
+ leftlinesegment: doubleBrushStroke("M40 281 V428 H0 V94 H40 V241 H400000 v40z"),
+ leftbracketunder: doubleBrushStroke("M0 0 h120 V290 H399995 v120 H0z"),
+ leftbracketover: doubleBrushStroke("M0 440 h120 V150 H399995 v-120 H0z"),
+ leftmapsto: doubleBrushStroke("M40 281 V448H0V74H40V241H400000v40z"),
+ // tofrom is from glyph U+21C4 in font KaTeX AMS Regular
+ leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",
+ longequal: doubleBrushStroke("M0 50 h400000 v40H0z m0 194h40000v40H0z"),
+ midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",
+ midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",
+ oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",
+ oiintSize2: "M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",
+ oiiintSize1: "M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",
+ oiiintSize2: "M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",
+ rightarrow: "M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",
+ rightbrace: "M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",
+ rightbraceunder: "M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",
+ rightgroup: "M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",
+ rightgroupunder: "M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",
+ rightharpoon: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",
+ rightharpoonplus: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",
+ rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",
+ rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",
+ righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",
+ rightlinesegment: doubleBrushStroke("M399960 241 V94 h40 V428 h-40 V281 H0 v-40z"),
+ rightbracketunder: doubleBrushStroke("M399995 0 h-120 V290 H0 v120 H400000z"),
+ rightbracketover: doubleBrushStroke("M399995 440 h-120 V150 H0 v-120 H399995z"),
+ rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",
+ // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular
+ twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",
+ twoheadrightarrow: "M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",
+ // tilde1 is a modified version of a glyph from the MnSymbol package
+ tilde1: "M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",
+ // ditto tilde2, tilde3, & tilde4
+ tilde2: "M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",
+ tilde3: "M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",
+ tilde4: "M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",
+ // vec is from glyph U+20D7 in font KaTeX Main
+ vec: "M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",
+ // widehat1 is a modified version of a glyph from the MnSymbol package
+ widehat1: "M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",
+ // ditto widehat2, widehat3, & widehat4
+ widehat2: "M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
+ widehat3: "M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
+ widehat4: "M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
+ // widecheck paths are all inverted versions of widehat
+ widecheck1: "M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",
+ widecheck2: "M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
+ widecheck3: "M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
+ widecheck4: "M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
+ // The next ten paths support reaction arrows from the mhchem package.
+
+ // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX
+ // baraboveleftarrow is mostly from glyph U+2190 in font KaTeX Main
+ baraboveleftarrow: "M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",
+ // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main
+ rightarrowabovebar: "M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",
+ // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end.
+ // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em
+ baraboveshortleftharpoon: "M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",
+ rightharpoonaboveshortbar: "M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",
+ shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",
+ shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"
+};
+const tallDelim = function (label, midHeight) {
+ switch (label) {
+ case "lbrack":
+ return "M403 1759 V84 H666 V0 H319 V1759 v" + midHeight + " v1759 v84 h347 v-84\nH403z M403 1759 V0 H319 V1759 v" + midHeight + " v1759 v84 h84z";
+ case "rbrack":
+ return "M347 1759 V0 H0 V84 H263 V1759 v" + midHeight + " v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v" + midHeight + " v1759 h84z";
+ case "vert":
+ return "M145 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + midHeight + " v585 h43z";
+ case "doublevert":
+ return "M145 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v" + midHeight + " v585 h43z\nM367 15 v585 v" + midHeight + " v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v" + -midHeight + " v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M410 15 H367 v585 v" + midHeight + " v585 h43z";
+ case "lfloor":
+ return "M319 602 V0 H403 V602 v" + midHeight + " v1715 h263 v84 H319z\nMM319 602 V0 H403 V602 v" + midHeight + " v1715 H319z";
+ case "rfloor":
+ return "M319 602 V0 H403 V602 v" + midHeight + " v1799 H0 v-84 H319z\nMM319 602 V0 H403 V602 v" + midHeight + " v1715 H319z";
+ case "lceil":
+ return "M403 1759 V84 H666 V0 H319 V1759 v" + midHeight + " v602 h84z\nM403 1759 V0 H319 V1759 v" + midHeight + " v602 h84z";
+ case "rceil":
+ return "M347 1759 V0 H0 V84 H263 V1759 v" + midHeight + " v602 h84z\nM347 1759 V0 h-84 V1759 v" + midHeight + " v602 h84z";
+ case "lparen":
+ return "M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1\nc-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,\n-36,557 l0," + (midHeight + 84) + "c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,\n949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9\nc0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,\n-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189\nl0,-" + (midHeight + 92) + "c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,\n-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z";
+ case "rparen":
+ return "M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,\n63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5\nc11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0," + (midHeight + 9) + "\nc-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664\nc-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11\nc0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17\nc242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558\nl0,-" + (midHeight + 144) + "c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,\n-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z";
+ default:
+ // We should not ever get here.
+ throw new Error("Unknown stretchy delimiter.");
+ }
+};
+;// ./src/tree.ts
+// To ensure that all nodes have compatible signatures for these methods.
+
+function isMathDomNode(node) {
+ return 'toText' in node;
+}
+
+/**
+ * This node represents a document fragment, which contains elements, but when
+ * placed into the DOM doesn't have any representation itself. It only contains
+ * children and doesn't have any DOM node properties.
+ */
+class DocumentFragment {
+ // Never used; needed for satisfying interface.
+
+ constructor(children) {
+ this.children = void 0;
+ this.classes = void 0;
+ this.height = void 0;
+ this.depth = void 0;
+ this.maxFontSize = void 0;
+ this.style = void 0;
+ this.children = children;
+ this.classes = [];
+ this.height = 0;
+ this.depth = 0;
+ this.maxFontSize = 0;
+ this.style = {};
+ }
+ hasClass(className) {
+ return this.classes.includes(className);
+ }
+
+ /** Convert the fragment into a node. */
+ toNode() {
+ const frag = document.createDocumentFragment();
+ for (let i = 0; i < this.children.length; i++) {
+ frag.appendChild(this.children[i].toNode());
+ }
+ return frag;
+ }
+
+ /** Convert the fragment into HTML markup. */
+ toMarkup() {
+ let markup = "";
+
+ // Simply concatenate the markup for the children together.
+ for (let i = 0; i < this.children.length; i++) {
+ markup += this.children[i].toMarkup();
+ }
+ return markup;
+ }
+
+ /**
+ * Converts the math node into a string, similar to innerText. Applies to
+ * MathDomNode's only.
+ */
+ toText() {
+ return this.children.map(child => {
+ if (isMathDomNode(child)) {
+ return child.toText();
+ }
+ throw new Error("Expected MathDomNode with toText, got " + child.constructor.name);
+ }).join("");
+ }
+}
+;// ./src/units.ts
+/**
+ * This file does conversion between units. In particular, it provides
+ * calculateSize to convert other units into ems.
+ */
+
+
+// This table gives the number of TeX pts in one of each *absolute* TeX unit.
+// Thus, multiplying a length by this number converts the length from units
+// into pts. Dividing the result by ptPerEm gives the number of ems
+// *assuming* a font size of ptPerEm (normal size, normal style).
+const ptPerUnit = {
+ // https://en.wikibooks.org/wiki/LaTeX/Lengths and
+ // https://tex.stackexchange.com/a/8263
+ "pt": 1,
+ // TeX point
+ "mm": 7227 / 2540,
+ // millimeter
+ "cm": 7227 / 254,
+ // centimeter
+ "in": 72.27,
+ // inch
+ "bp": 803 / 800,
+ // big (PostScript) points
+ "pc": 12,
+ // pica
+ "dd": 1238 / 1157,
+ // didot
+ "cc": 14856 / 1157,
+ // cicero (12 didot)
+ "nd": 685 / 642,
+ // new didot
+ "nc": 1370 / 107,
+ // new cicero (12 new didot)
+ "sp": 1 / 65536,
+ // scaled point (TeX's internal smallest unit)
+ // https://tex.stackexchange.com/a/41371
+ "px": 803 / 800 // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX
+};
+
+// Dictionary of relative units, for fast validity testing.
+const relativeUnit = {
+ "ex": true,
+ "em": true,
+ "mu": true
+};
+
+/**
+ * Determine whether the specified unit (either a string defining the unit
+ * or a "size" parse node containing a unit field) is valid.
+ */
+const validUnit = function (unit) {
+ if (typeof unit !== "string") {
+ unit = unit.unit;
+ }
+ return unit in ptPerUnit || unit in relativeUnit || unit === "ex";
+};
+
+/*
+ * Convert a "size" parse node (with numeric "number" and string "unit" fields,
+ * as parsed by functions.js argType "size") into a CSS em value for the
+ * current style/scale. `options` gives the current options.
+ */
+const calculateSize = function (sizeValue, options) {
+ let scale;
+ if (sizeValue.unit in ptPerUnit) {
+ // Absolute units
+ scale = ptPerUnit[sizeValue.unit] // Convert unit to pt
+ / options.fontMetrics().ptPerEm // Convert pt to CSS em
+ / options.sizeMultiplier; // Unscale to make absolute units
+ } else if (sizeValue.unit === "mu") {
+ // `mu` units scale with scriptstyle/scriptscriptstyle.
+ scale = options.fontMetrics().cssEmPerMu;
+ } else {
+ // Other relative units always refer to the *textstyle* font
+ // in the current size.
+ let unitOptions;
+ if (options.style.isTight()) {
+ // isTight() means current style is script/scriptscript.
+ unitOptions = options.havingStyle(options.style.text());
+ } else {
+ unitOptions = options;
+ }
+ // TODO: In TeX these units are relative to the quad of the current
+ // *text* font, e.g. cmr10. KaTeX instead uses values from the
+ // comparably-sized *Computer Modern symbol* font. At 10pt, these
+ // match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641;
+ // cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$.
+ // TeX \showlists shows a kern of 1.13889 * fontsize;
+ // KaTeX shows a kern of 1.171 * fontsize.
+ if (sizeValue.unit === "ex") {
+ scale = unitOptions.fontMetrics().xHeight;
+ } else if (sizeValue.unit === "em") {
+ scale = unitOptions.fontMetrics().quad;
+ } else {
+ throw new src_ParseError("Invalid unit: '" + sizeValue.unit + "'");
+ }
+ if (unitOptions !== options) {
+ scale *= unitOptions.sizeMultiplier / options.sizeMultiplier;
+ }
+ }
+ return Math.min(sizeValue.number * scale, options.maxSize);
+};
+
+/**
+ * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. See
+ * https://github.com/KaTeX/KaTeX/pull/2460.
+ */
+const makeEm = function (n) {
+ return +n.toFixed(4) + "em";
+};
+;// ./src/domTree.ts
+/**
+ * These objects store the data about the DOM nodes we create, as well as some
+ * extra data. They can then be transformed into real DOM nodes with the
+ * `toNode` function or HTML markup using `toMarkup`. They are useful for both
+ * storing extra properties on the nodes, as well as providing a way to easily
+ * work with the DOM.
+ *
+ * Similar functions for working with MathML nodes exist in mathMLTree.js.
+ *
+ * TODO: refactor `span` and `anchor` into common superclass when
+ * target environments support class inheritance
+ */
+
+
+
+
+
+
+/**
+ * Create an HTML className based on a list of classes. In addition to joining
+ * with spaces, we also remove empty classes.
+ */
+const createClass = function (classes) {
+ return classes.filter(cls => cls).join(" ");
+};
+
+/**
+ * Serialize a CssStyle object into a semicolon-delimited inline-style string
+ * (hyphenating camelCase property names). Returns "" when no property is set.
+ */
+const cssStyleToString = function (style) {
+ let styles = "";
+ for (const key of Object.keys(style)) {
+ const value = style[key];
+ if (value !== undefined) {
+ styles += hyphenate(key) + ":" + value + ";";
+ }
+ }
+ return styles;
+};
+const initNode = function (classes, options, style) {
+ this.classes = classes || [];
+ this.attributes = {};
+ this.height = 0;
+ this.depth = 0;
+ this.maxFontSize = 0;
+ this.style = style || {};
+ if (options) {
+ if (options.style.isTight()) {
+ this.classes.push("mtight");
+ }
+ const color = options.getColor();
+ if (color) {
+ this.style.color = color;
+ }
+ }
+};
+
+/**
+ * Convert into an HTML node
+ */
+const toNode = function (tagName) {
+ const node = document.createElement(tagName);
+
+ // Apply the class
+ node.className = createClass(this.classes);
+
+ // Apply inline styles
+ Object.assign(node.style, this.style);
+
+ // Apply attributes
+ for (const attr of Object.keys(this.attributes)) {
+ node.setAttribute(attr, this.attributes[attr]);
+ }
+
+ // Append the children, also as HTML nodes
+ for (let i = 0; i < this.children.length; i++) {
+ node.appendChild(this.children[i].toNode());
+ }
+ return node;
+};
+
+/**
+ * https://w3c.github.io/html-reference/syntax.html#syntax-attributes
+ *
+ * > Attribute Names must consist of one or more characters
+ * other than the space characters, U+0000 NULL,
+ * '"', "'", ">", "/", "=", the control characters,
+ * and any characters that are not defined by Unicode.
+ */
+const invalidAttributeNameRegex = /[\s"'>/=\x00-\x1f]/;
+
+/**
+ * Convert into an HTML markup string
+ */
+const toMarkup = function (tagName) {
+ let markup = "<" + tagName;
+
+ // Add the class
+ if (this.classes.length) {
+ markup += " class=\"" + utils_escape(createClass(this.classes)) + "\"";
+ }
+ const styles = cssStyleToString(this.style);
+ if (styles) {
+ markup += " style=\"" + utils_escape(styles) + "\"";
+ }
+
+ // Add the attributes
+ for (const attr of Object.keys(this.attributes)) {
+ if (invalidAttributeNameRegex.test(attr)) {
+ throw new src_ParseError("Invalid attribute name '" + attr + "'");
+ }
+ markup += " " + attr + "=\"" + utils_escape(this.attributes[attr]) + "\"";
+ }
+ markup += ">";
+
+ // Add the markup of the children, also as markup
+ for (let i = 0; i < this.children.length; i++) {
+ markup += this.children[i].toMarkup();
+ }
+ markup += "</" + tagName + ">";
+ return markup;
+};
+
+// Making the type below exact with all optional fields doesn't work due to
+// - https://github.com/facebook/flow/issues/4582
+// - https://github.com/facebook/flow/issues/5688
+// However, since *all* fields are optional, $Shape<> works as suggested in 5688
+// above.
+// This type does not include all CSS properties. Additional properties should
+// be added as needed.
+
+// Span wrapping other DOM nodes.
+
+// Span wrapping an SVG node.
+
+/**
+ * This node represents a span node, with a className, a list of children, and
+ * an inline style. It also contains information about its height, depth, and
+ * maxFontSize.
+ *
+ * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan
+ * otherwise. This typesafety is important when HTML builders access a span's
+ * children.
+ */
+class Span {
+ constructor(classes, children, options, style) {
+ this.children = void 0;
+ this.attributes = void 0;
+ this.classes = void 0;
+ this.height = void 0;
+ this.depth = void 0;
+ this.width = void 0;
+ this.maxFontSize = void 0;
+ this.style = void 0;
+ /**
+ * Italic correction carried over from a SymbolNode when the symbol is
+ * wrapped in a vlist (e.g. \oiint / \oiiint). Read by supsub to adjust
+ * subscript positioning. Only set when nonzero; use `?? 0` at read sites.
+ */
+ this.italic = void 0;
+ initNode.call(this, classes, options, style);
+ this.children = children || [];
+ }
+
+ /**
+ * Sets an arbitrary attribute on the span. Warning: use this wisely. Not
+ * all browsers support attributes the same, and having too many custom
+ * attributes is probably bad.
+ */
+ setAttribute(attribute, value) {
+ this.attributes[attribute] = value;
+ }
+ hasClass(className) {
+ return this.classes.includes(className);
+ }
+ toNode() {
+ return toNode.call(this, "span");
+ }
+ toMarkup() {
+ return toMarkup.call(this, "span");
+ }
+}
+
+/**
+ * This node represents an anchor (<a>) element with a hyperlink. See `span`
+ * for further details.
+ */
+class Anchor {
+ constructor(href, classes, children, options) {
+ this.children = void 0;
+ this.attributes = void 0;
+ this.classes = void 0;
+ this.height = void 0;
+ this.depth = void 0;
+ this.maxFontSize = void 0;
+ this.style = void 0;
+ initNode.call(this, classes, options);
+ this.children = children || [];
+ this.setAttribute('href', href);
+ }
+ setAttribute(attribute, value) {
+ this.attributes[attribute] = value;
+ }
+ hasClass(className) {
+ return this.classes.includes(className);
+ }
+ toNode() {
+ return toNode.call(this, "a");
+ }
+ toMarkup() {
+ return toMarkup.call(this, "a");
+ }
+}
+
+/**
+ * This node represents an image embed (<img>) element.
+ */
+class Img {
+ constructor(src, alt, style) {
+ this.src = void 0;
+ this.alt = void 0;
+ this.classes = void 0;
+ this.height = void 0;
+ this.depth = void 0;
+ this.maxFontSize = void 0;
+ this.style = void 0;
+ this.alt = alt;
+ this.src = src;
+ this.classes = ["mord"];
+ this.height = 0;
+ this.depth = 0;
+ this.maxFontSize = 0;
+ this.style = style;
+ }
+ hasClass(className) {
+ return this.classes.includes(className);
+ }
+ toNode() {
+ const node = document.createElement("img");
+ node.src = this.src;
+ node.alt = this.alt;
+ node.className = "mord";
+
+ // Apply inline styles
+ Object.assign(node.style, this.style);
+ return node;
+ }
+ toMarkup() {
+ let markup = "<img src=\"" + utils_escape(this.src) + "\"" + (" alt=\"" + utils_escape(this.alt) + "\"");
+ const styles = cssStyleToString(this.style);
+ if (styles) {
+ markup += " style=\"" + utils_escape(styles) + "\"";
+ }
+ markup += "'/>";
+ return markup;
+ }
+}
+const iCombinations = {
+ 'î': '\u0131\u0302',
+ 'ï': '\u0131\u0308',
+ 'í': '\u0131\u0301',
+ // 'ī': '\u0131\u0304', // enable when we add Extended Latin
+ 'ì': '\u0131\u0300'
+};
+
+/**
+ * A symbol node contains information about a single symbol. It either renders
+ * to a single text node, or a span with a single text node in it, depending on
+ * whether it has CSS classes, styles, or needs italic correction.
+ */
+class SymbolNode {
+ constructor(text, height, depth, italic, skew, width, classes, style) {
+ this.text = void 0;
+ this.height = void 0;
+ this.depth = void 0;
+ this.italic = void 0;
+ this.skew = void 0;
+ this.width = void 0;
+ this.maxFontSize = void 0;
+ this.classes = void 0;
+ this.style = void 0;
+ this.text = text;
+ this.height = height || 0;
+ this.depth = depth || 0;
+ this.italic = italic || 0;
+ this.skew = skew || 0;
+ this.width = width || 0;
+ this.classes = classes || [];
+ this.style = style || {};
+ this.maxFontSize = 0;
+
+ // Mark text from non-Latin scripts with specific classes so that we
+ // can specify which fonts to use. This allows us to render these
+ // characters with a serif font in situations where the browser would
+ // either default to a sans serif or render a placeholder character.
+ // We use CSS class names like cjk_fallback, hangul_fallback and
+ // brahmic_fallback. See ./unicodeScripts.js for the set of possible
+ // script names
+ const script = scriptFromCodepoint(this.text.charCodeAt(0));
+ if (script) {
+ this.classes.push(script + "_fallback");
+ }
+ if (/[îïíì]/.test(this.text)) {
+ // add ī when we add Extended Latin
+ this.text = iCombinations[this.text];
+ }
+ }
+ hasClass(className) {
+ return this.classes.includes(className);
+ }
+
+ /**
+ * Creates a text node or span from a symbol node. Note that a span is only
+ * created if it is needed.
+ */
+ toNode() {
+ const node = document.createTextNode(this.text);
+ let span = null;
+ if (this.italic > 0) {
+ span = document.createElement("span");
+ span.style.marginRight = makeEm(this.italic);
+ }
+ if (this.classes.length > 0) {
+ span = span || document.createElement("span");
+ span.className = createClass(this.classes);
+ }
+ if (Object.keys(this.style).length > 0) {
+ span = span || document.createElement("span");
+ Object.assign(span.style, this.style);
+ }
+ if (span) {
+ span.appendChild(node);
+ return span;
+ } else {
+ return node;
+ }
+ }
+
+ /**
+ * Creates markup for a symbol node.
+ */
+ toMarkup() {
+ // TODO(alpert): More duplication than I'd like from
+ // span.prototype.toMarkup and symbolNode.prototype.toNode...
+ let needsSpan = false;
+ let markup = "<span";
+ if (this.classes.length) {
+ needsSpan = true;
+ markup += " class=\"";
+ markup += utils_escape(createClass(this.classes));
+ markup += "\"";
+ }
+ let styles = "";
+ if (this.italic > 0) {
+ styles += "margin-right:" + makeEm(this.italic) + ";";
+ }
+ styles += cssStyleToString(this.style);
+ if (styles) {
+ needsSpan = true;
+ markup += " style=\"" + utils_escape(styles) + "\"";
+ }
+ const escaped = utils_escape(this.text);
+ if (needsSpan) {
+ markup += ">";
+ markup += escaped;
+ markup += "</span>";
+ return markup;
+ } else {
+ return escaped;
+ }
+ }
+}
+
+/**
+ * SVG nodes are used to render stretchy wide elements.
+ */
+class SvgNode {
+ constructor(children, attributes) {
+ this.children = void 0;
+ this.attributes = void 0;
+ this.children = children || [];
+ this.attributes = attributes || {};
+ }
+ toNode() {
+ const svgNS = "http://www.w3.org/2000/svg";
+ const node = document.createElementNS(svgNS, "svg");
+
+ // Apply attributes
+ for (const attr of Object.keys(this.attributes)) {
+ node.setAttribute(attr, this.attributes[attr]);
+ }
+ for (let i = 0; i < this.children.length; i++) {
+ node.appendChild(this.children[i].toNode());
+ }
+ return node;
+ }
+ toMarkup() {
+ let markup = "<svg xmlns=\"http://www.w3.org/2000/svg\"";
+
+ // Apply attributes
+ for (const attr of Object.keys(this.attributes)) {
+ markup += " " + attr + "=\"" + utils_escape(this.attributes[attr]) + "\"";
+ }
+ markup += ">";
+ for (let i = 0; i < this.children.length; i++) {
+ markup += this.children[i].toMarkup();
+ }
+ markup += "</svg>";
+ return markup;
+ }
+}
+class PathNode {
+ constructor(pathName, alternate) {
+ this.pathName = void 0;
+ this.alternate = void 0;
+ this.pathName = pathName;
+ this.alternate = alternate; // Used only for \sqrt, \phase, & tall delims
+ }
+ toNode() {
+ const svgNS = "http://www.w3.org/2000/svg";
+ const node = document.createElementNS(svgNS, "path");
+ if (this.alternate) {
+ node.setAttribute("d", this.alternate);
+ } else {
+ node.setAttribute("d", path[this.pathName]);
+ }
+ return node;
+ }
+ toMarkup() {
+ if (this.alternate) {
+ return "<path d=\"" + utils_escape(this.alternate) + "\"/>";
+ } else {
+ return "<path d=\"" + utils_escape(path[this.pathName]) + "\"/>";
+ }
+ }
+}
+class LineNode {
+ constructor(attributes) {
+ this.attributes = void 0;
+ this.attributes = attributes || {};
+ }
+ toNode() {
+ const svgNS = "http://www.w3.org/2000/svg";
+ const node = document.createElementNS(svgNS, "line");
+
+ // Apply attributes
+ for (const attr of Object.keys(this.attributes)) {
+ node.setAttribute(attr, this.attributes[attr]);
+ }
+ return node;
+ }
+ toMarkup() {
+ let markup = "<line";
+ for (const attr of Object.keys(this.attributes)) {
+ markup += " " + attr + "=\"" + utils_escape(this.attributes[attr]) + "\"";
+ }
+ markup += "/>";
+ return markup;
+ }
+}
+function assertSymbolDomNode(group) {
+ if (group instanceof SymbolNode) {
+ return group;
+ } else {
+ throw new Error("Expected symbolNode but got " + String(group) + ".");
+ }
+}
+function assertSpan(group) {
+ if (group instanceof Span) {
+ return group;
+ } else {
+ throw new Error("Expected span<HtmlDomNode> but got " + String(group) + ".");
+ }
+}
+
+/**
+ * Whether an HtmlDomNode has HtmlDomNode children.
+ * HtmlDomNode is a base type representing a union of
+ * SymbolNode, SvgSpan, DomSpan, Anchor, and documentFragment.
+ * In the last three cases, the children are HtmlDomNode[].
+ */
+const hasHtmlDomChildren = node => node instanceof Span || node instanceof Anchor || node instanceof DocumentFragment;
+;// ./src/fontMetricsData.js
+// This file is GENERATED by buildMetrics.sh. DO NOT MODIFY.
+/* harmony default export */ var fontMetricsData = ({
+ "AMS-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "65": [0, 0.68889, 0, 0, 0.72222],
+ "66": [0, 0.68889, 0, 0, 0.66667],
+ "67": [0, 0.68889, 0, 0, 0.72222],
+ "68": [0, 0.68889, 0, 0, 0.72222],
+ "69": [0, 0.68889, 0, 0, 0.66667],
+ "70": [0, 0.68889, 0, 0, 0.61111],
+ "71": [0, 0.68889, 0, 0, 0.77778],
+ "72": [0, 0.68889, 0, 0, 0.77778],
+ "73": [0, 0.68889, 0, 0, 0.38889],
+ "74": [0.16667, 0.68889, 0, 0, 0.5],
+ "75": [0, 0.68889, 0, 0, 0.77778],
+ "76": [0, 0.68889, 0, 0, 0.66667],
+ "77": [0, 0.68889, 0, 0, 0.94445],
+ "78": [0, 0.68889, 0, 0, 0.72222],
+ "79": [0.16667, 0.68889, 0, 0, 0.77778],
+ "80": [0, 0.68889, 0, 0, 0.61111],
+ "81": [0.16667, 0.68889, 0, 0, 0.77778],
+ "82": [0, 0.68889, 0, 0, 0.72222],
+ "83": [0, 0.68889, 0, 0, 0.55556],
+ "84": [0, 0.68889, 0, 0, 0.66667],
+ "85": [0, 0.68889, 0, 0, 0.72222],
+ "86": [0, 0.68889, 0, 0, 0.72222],
+ "87": [0, 0.68889, 0, 0, 1.0],
+ "88": [0, 0.68889, 0, 0, 0.72222],
+ "89": [0, 0.68889, 0, 0, 0.72222],
+ "90": [0, 0.68889, 0, 0, 0.66667],
+ "107": [0, 0.68889, 0, 0, 0.55556],
+ "160": [0, 0, 0, 0, 0.25],
+ "165": [0, 0.675, 0.025, 0, 0.75],
+ "174": [0.15559, 0.69224, 0, 0, 0.94666],
+ "240": [0, 0.68889, 0, 0, 0.55556],
+ "295": [0, 0.68889, 0, 0, 0.54028],
+ "710": [0, 0.825, 0, 0, 2.33334],
+ "732": [0, 0.9, 0, 0, 2.33334],
+ "770": [0, 0.825, 0, 0, 2.33334],
+ "771": [0, 0.9, 0, 0, 2.33334],
+ "989": [0.08167, 0.58167, 0, 0, 0.77778],
+ "1008": [0, 0.43056, 0.04028, 0, 0.66667],
+ "8245": [0, 0.54986, 0, 0, 0.275],
+ "8463": [0, 0.68889, 0, 0, 0.54028],
+ "8487": [0, 0.68889, 0, 0, 0.72222],
+ "8498": [0, 0.68889, 0, 0, 0.55556],
+ "8502": [0, 0.68889, 0, 0, 0.66667],
+ "8503": [0, 0.68889, 0, 0, 0.44445],
+ "8504": [0, 0.68889, 0, 0, 0.66667],
+ "8513": [0, 0.68889, 0, 0, 0.63889],
+ "8592": [-0.03598, 0.46402, 0, 0, 0.5],
+ "8594": [-0.03598, 0.46402, 0, 0, 0.5],
+ "8602": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8603": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8606": [0.01354, 0.52239, 0, 0, 1.0],
+ "8608": [0.01354, 0.52239, 0, 0, 1.0],
+ "8610": [0.01354, 0.52239, 0, 0, 1.11111],
+ "8611": [0.01354, 0.52239, 0, 0, 1.11111],
+ "8619": [0, 0.54986, 0, 0, 1.0],
+ "8620": [0, 0.54986, 0, 0, 1.0],
+ "8621": [-0.13313, 0.37788, 0, 0, 1.38889],
+ "8622": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8624": [0, 0.69224, 0, 0, 0.5],
+ "8625": [0, 0.69224, 0, 0, 0.5],
+ "8630": [0, 0.43056, 0, 0, 1.0],
+ "8631": [0, 0.43056, 0, 0, 1.0],
+ "8634": [0.08198, 0.58198, 0, 0, 0.77778],
+ "8635": [0.08198, 0.58198, 0, 0, 0.77778],
+ "8638": [0.19444, 0.69224, 0, 0, 0.41667],
+ "8639": [0.19444, 0.69224, 0, 0, 0.41667],
+ "8642": [0.19444, 0.69224, 0, 0, 0.41667],
+ "8643": [0.19444, 0.69224, 0, 0, 0.41667],
+ "8644": [0.1808, 0.675, 0, 0, 1.0],
+ "8646": [0.1808, 0.675, 0, 0, 1.0],
+ "8647": [0.1808, 0.675, 0, 0, 1.0],
+ "8648": [0.19444, 0.69224, 0, 0, 0.83334],
+ "8649": [0.1808, 0.675, 0, 0, 1.0],
+ "8650": [0.19444, 0.69224, 0, 0, 0.83334],
+ "8651": [0.01354, 0.52239, 0, 0, 1.0],
+ "8652": [0.01354, 0.52239, 0, 0, 1.0],
+ "8653": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8654": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8655": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8666": [0.13667, 0.63667, 0, 0, 1.0],
+ "8667": [0.13667, 0.63667, 0, 0, 1.0],
+ "8669": [-0.13313, 0.37788, 0, 0, 1.0],
+ "8672": [-0.064, 0.437, 0, 0, 1.334],
+ "8674": [-0.064, 0.437, 0, 0, 1.334],
+ "8705": [0, 0.825, 0, 0, 0.5],
+ "8708": [0, 0.68889, 0, 0, 0.55556],
+ "8709": [0.08167, 0.58167, 0, 0, 0.77778],
+ "8717": [0, 0.43056, 0, 0, 0.42917],
+ "8722": [-0.03598, 0.46402, 0, 0, 0.5],
+ "8724": [0.08198, 0.69224, 0, 0, 0.77778],
+ "8726": [0.08167, 0.58167, 0, 0, 0.77778],
+ "8733": [0, 0.69224, 0, 0, 0.77778],
+ "8736": [0, 0.69224, 0, 0, 0.72222],
+ "8737": [0, 0.69224, 0, 0, 0.72222],
+ "8738": [0.03517, 0.52239, 0, 0, 0.72222],
+ "8739": [0.08167, 0.58167, 0, 0, 0.22222],
+ "8740": [0.25142, 0.74111, 0, 0, 0.27778],
+ "8741": [0.08167, 0.58167, 0, 0, 0.38889],
+ "8742": [0.25142, 0.74111, 0, 0, 0.5],
+ "8756": [0, 0.69224, 0, 0, 0.66667],
+ "8757": [0, 0.69224, 0, 0, 0.66667],
+ "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
+ "8765": [-0.13313, 0.37788, 0, 0, 0.77778],
+ "8769": [-0.13313, 0.36687, 0, 0, 0.77778],
+ "8770": [-0.03625, 0.46375, 0, 0, 0.77778],
+ "8774": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
+ "8778": [0.08167, 0.58167, 0, 0, 0.77778],
+ "8782": [0.06062, 0.54986, 0, 0, 0.77778],
+ "8783": [0.06062, 0.54986, 0, 0, 0.77778],
+ "8785": [0.08198, 0.58198, 0, 0, 0.77778],
+ "8786": [0.08198, 0.58198, 0, 0, 0.77778],
+ "8787": [0.08198, 0.58198, 0, 0, 0.77778],
+ "8790": [0, 0.69224, 0, 0, 0.77778],
+ "8791": [0.22958, 0.72958, 0, 0, 0.77778],
+ "8796": [0.08198, 0.91667, 0, 0, 0.77778],
+ "8806": [0.25583, 0.75583, 0, 0, 0.77778],
+ "8807": [0.25583, 0.75583, 0, 0, 0.77778],
+ "8808": [0.25142, 0.75726, 0, 0, 0.77778],
+ "8809": [0.25142, 0.75726, 0, 0, 0.77778],
+ "8812": [0.25583, 0.75583, 0, 0, 0.5],
+ "8814": [0.20576, 0.70576, 0, 0, 0.77778],
+ "8815": [0.20576, 0.70576, 0, 0, 0.77778],
+ "8816": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8817": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8818": [0.22958, 0.72958, 0, 0, 0.77778],
+ "8819": [0.22958, 0.72958, 0, 0, 0.77778],
+ "8822": [0.1808, 0.675, 0, 0, 0.77778],
+ "8823": [0.1808, 0.675, 0, 0, 0.77778],
+ "8828": [0.13667, 0.63667, 0, 0, 0.77778],
+ "8829": [0.13667, 0.63667, 0, 0, 0.77778],
+ "8830": [0.22958, 0.72958, 0, 0, 0.77778],
+ "8831": [0.22958, 0.72958, 0, 0, 0.77778],
+ "8832": [0.20576, 0.70576, 0, 0, 0.77778],
+ "8833": [0.20576, 0.70576, 0, 0, 0.77778],
+ "8840": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8841": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8842": [0.13597, 0.63597, 0, 0, 0.77778],
+ "8843": [0.13597, 0.63597, 0, 0, 0.77778],
+ "8847": [0.03517, 0.54986, 0, 0, 0.77778],
+ "8848": [0.03517, 0.54986, 0, 0, 0.77778],
+ "8858": [0.08198, 0.58198, 0, 0, 0.77778],
+ "8859": [0.08198, 0.58198, 0, 0, 0.77778],
+ "8861": [0.08198, 0.58198, 0, 0, 0.77778],
+ "8862": [0, 0.675, 0, 0, 0.77778],
+ "8863": [0, 0.675, 0, 0, 0.77778],
+ "8864": [0, 0.675, 0, 0, 0.77778],
+ "8865": [0, 0.675, 0, 0, 0.77778],
+ "8872": [0, 0.69224, 0, 0, 0.61111],
+ "8873": [0, 0.69224, 0, 0, 0.72222],
+ "8874": [0, 0.69224, 0, 0, 0.88889],
+ "8876": [0, 0.68889, 0, 0, 0.61111],
+ "8877": [0, 0.68889, 0, 0, 0.61111],
+ "8878": [0, 0.68889, 0, 0, 0.72222],
+ "8879": [0, 0.68889, 0, 0, 0.72222],
+ "8882": [0.03517, 0.54986, 0, 0, 0.77778],
+ "8883": [0.03517, 0.54986, 0, 0, 0.77778],
+ "8884": [0.13667, 0.63667, 0, 0, 0.77778],
+ "8885": [0.13667, 0.63667, 0, 0, 0.77778],
+ "8888": [0, 0.54986, 0, 0, 1.11111],
+ "8890": [0.19444, 0.43056, 0, 0, 0.55556],
+ "8891": [0.19444, 0.69224, 0, 0, 0.61111],
+ "8892": [0.19444, 0.69224, 0, 0, 0.61111],
+ "8901": [0, 0.54986, 0, 0, 0.27778],
+ "8903": [0.08167, 0.58167, 0, 0, 0.77778],
+ "8905": [0.08167, 0.58167, 0, 0, 0.77778],
+ "8906": [0.08167, 0.58167, 0, 0, 0.77778],
+ "8907": [0, 0.69224, 0, 0, 0.77778],
+ "8908": [0, 0.69224, 0, 0, 0.77778],
+ "8909": [-0.03598, 0.46402, 0, 0, 0.77778],
+ "8910": [0, 0.54986, 0, 0, 0.76042],
+ "8911": [0, 0.54986, 0, 0, 0.76042],
+ "8912": [0.03517, 0.54986, 0, 0, 0.77778],
+ "8913": [0.03517, 0.54986, 0, 0, 0.77778],
+ "8914": [0, 0.54986, 0, 0, 0.66667],
+ "8915": [0, 0.54986, 0, 0, 0.66667],
+ "8916": [0, 0.69224, 0, 0, 0.66667],
+ "8918": [0.0391, 0.5391, 0, 0, 0.77778],
+ "8919": [0.0391, 0.5391, 0, 0, 0.77778],
+ "8920": [0.03517, 0.54986, 0, 0, 1.33334],
+ "8921": [0.03517, 0.54986, 0, 0, 1.33334],
+ "8922": [0.38569, 0.88569, 0, 0, 0.77778],
+ "8923": [0.38569, 0.88569, 0, 0, 0.77778],
+ "8926": [0.13667, 0.63667, 0, 0, 0.77778],
+ "8927": [0.13667, 0.63667, 0, 0, 0.77778],
+ "8928": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8929": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8934": [0.23222, 0.74111, 0, 0, 0.77778],
+ "8935": [0.23222, 0.74111, 0, 0, 0.77778],
+ "8936": [0.23222, 0.74111, 0, 0, 0.77778],
+ "8937": [0.23222, 0.74111, 0, 0, 0.77778],
+ "8938": [0.20576, 0.70576, 0, 0, 0.77778],
+ "8939": [0.20576, 0.70576, 0, 0, 0.77778],
+ "8940": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8941": [0.30274, 0.79383, 0, 0, 0.77778],
+ "8994": [0.19444, 0.69224, 0, 0, 0.77778],
+ "8995": [0.19444, 0.69224, 0, 0, 0.77778],
+ "9416": [0.15559, 0.69224, 0, 0, 0.90222],
+ "9484": [0, 0.69224, 0, 0, 0.5],
+ "9488": [0, 0.69224, 0, 0, 0.5],
+ "9492": [0, 0.37788, 0, 0, 0.5],
+ "9496": [0, 0.37788, 0, 0, 0.5],
+ "9585": [0.19444, 0.68889, 0, 0, 0.88889],
+ "9586": [0.19444, 0.74111, 0, 0, 0.88889],
+ "9632": [0, 0.675, 0, 0, 0.77778],
+ "9633": [0, 0.675, 0, 0, 0.77778],
+ "9650": [0, 0.54986, 0, 0, 0.72222],
+ "9651": [0, 0.54986, 0, 0, 0.72222],
+ "9654": [0.03517, 0.54986, 0, 0, 0.77778],
+ "9660": [0, 0.54986, 0, 0, 0.72222],
+ "9661": [0, 0.54986, 0, 0, 0.72222],
+ "9664": [0.03517, 0.54986, 0, 0, 0.77778],
+ "9674": [0.11111, 0.69224, 0, 0, 0.66667],
+ "9733": [0.19444, 0.69224, 0, 0, 0.94445],
+ "10003": [0, 0.69224, 0, 0, 0.83334],
+ "10016": [0, 0.69224, 0, 0, 0.83334],
+ "10731": [0.11111, 0.69224, 0, 0, 0.66667],
+ "10846": [0.19444, 0.75583, 0, 0, 0.61111],
+ "10877": [0.13667, 0.63667, 0, 0, 0.77778],
+ "10878": [0.13667, 0.63667, 0, 0, 0.77778],
+ "10885": [0.25583, 0.75583, 0, 0, 0.77778],
+ "10886": [0.25583, 0.75583, 0, 0, 0.77778],
+ "10887": [0.13597, 0.63597, 0, 0, 0.77778],
+ "10888": [0.13597, 0.63597, 0, 0, 0.77778],
+ "10889": [0.26167, 0.75726, 0, 0, 0.77778],
+ "10890": [0.26167, 0.75726, 0, 0, 0.77778],
+ "10891": [0.48256, 0.98256, 0, 0, 0.77778],
+ "10892": [0.48256, 0.98256, 0, 0, 0.77778],
+ "10901": [0.13667, 0.63667, 0, 0, 0.77778],
+ "10902": [0.13667, 0.63667, 0, 0, 0.77778],
+ "10933": [0.25142, 0.75726, 0, 0, 0.77778],
+ "10934": [0.25142, 0.75726, 0, 0, 0.77778],
+ "10935": [0.26167, 0.75726, 0, 0, 0.77778],
+ "10936": [0.26167, 0.75726, 0, 0, 0.77778],
+ "10937": [0.26167, 0.75726, 0, 0, 0.77778],
+ "10938": [0.26167, 0.75726, 0, 0, 0.77778],
+ "10949": [0.25583, 0.75583, 0, 0, 0.77778],
+ "10950": [0.25583, 0.75583, 0, 0, 0.77778],
+ "10955": [0.28481, 0.79383, 0, 0, 0.77778],
+ "10956": [0.28481, 0.79383, 0, 0, 0.77778],
+ "57350": [0.08167, 0.58167, 0, 0, 0.22222],
+ "57351": [0.08167, 0.58167, 0, 0, 0.38889],
+ "57352": [0.08167, 0.58167, 0, 0, 0.77778],
+ "57353": [0, 0.43056, 0.04028, 0, 0.66667],
+ "57356": [0.25142, 0.75726, 0, 0, 0.77778],
+ "57357": [0.25142, 0.75726, 0, 0, 0.77778],
+ "57358": [0.41951, 0.91951, 0, 0, 0.77778],
+ "57359": [0.30274, 0.79383, 0, 0, 0.77778],
+ "57360": [0.30274, 0.79383, 0, 0, 0.77778],
+ "57361": [0.41951, 0.91951, 0, 0, 0.77778],
+ "57366": [0.25142, 0.75726, 0, 0, 0.77778],
+ "57367": [0.25142, 0.75726, 0, 0, 0.77778],
+ "57368": [0.25142, 0.75726, 0, 0, 0.77778],
+ "57369": [0.25142, 0.75726, 0, 0, 0.77778],
+ "57370": [0.13597, 0.63597, 0, 0, 0.77778],
+ "57371": [0.13597, 0.63597, 0, 0, 0.77778]
+ },
+ "Caligraphic-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "65": [0, 0.68333, 0, 0.19445, 0.79847],
+ "66": [0, 0.68333, 0.03041, 0.13889, 0.65681],
+ "67": [0, 0.68333, 0.05834, 0.13889, 0.52653],
+ "68": [0, 0.68333, 0.02778, 0.08334, 0.77139],
+ "69": [0, 0.68333, 0.08944, 0.11111, 0.52778],
+ "70": [0, 0.68333, 0.09931, 0.11111, 0.71875],
+ "71": [0.09722, 0.68333, 0.0593, 0.11111, 0.59487],
+ "72": [0, 0.68333, 0.00965, 0.11111, 0.84452],
+ "73": [0, 0.68333, 0.07382, 0, 0.54452],
+ "74": [0.09722, 0.68333, 0.18472, 0.16667, 0.67778],
+ "75": [0, 0.68333, 0.01445, 0.05556, 0.76195],
+ "76": [0, 0.68333, 0, 0.13889, 0.68972],
+ "77": [0, 0.68333, 0, 0.13889, 1.2009],
+ "78": [0, 0.68333, 0.14736, 0.08334, 0.82049],
+ "79": [0, 0.68333, 0.02778, 0.11111, 0.79611],
+ "80": [0, 0.68333, 0.08222, 0.08334, 0.69556],
+ "81": [0.09722, 0.68333, 0, 0.11111, 0.81667],
+ "82": [0, 0.68333, 0, 0.08334, 0.8475],
+ "83": [0, 0.68333, 0.075, 0.13889, 0.60556],
+ "84": [0, 0.68333, 0.25417, 0, 0.54464],
+ "85": [0, 0.68333, 0.09931, 0.08334, 0.62583],
+ "86": [0, 0.68333, 0.08222, 0, 0.61278],
+ "87": [0, 0.68333, 0.08222, 0.08334, 0.98778],
+ "88": [0, 0.68333, 0.14643, 0.13889, 0.7133],
+ "89": [0.09722, 0.68333, 0.08222, 0.08334, 0.66834],
+ "90": [0, 0.68333, 0.07944, 0.13889, 0.72473],
+ "160": [0, 0, 0, 0, 0.25]
+ },
+ "Fraktur-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "33": [0, 0.69141, 0, 0, 0.29574],
+ "34": [0, 0.69141, 0, 0, 0.21471],
+ "38": [0, 0.69141, 0, 0, 0.73786],
+ "39": [0, 0.69141, 0, 0, 0.21201],
+ "40": [0.24982, 0.74947, 0, 0, 0.38865],
+ "41": [0.24982, 0.74947, 0, 0, 0.38865],
+ "42": [0, 0.62119, 0, 0, 0.27764],
+ "43": [0.08319, 0.58283, 0, 0, 0.75623],
+ "44": [0, 0.10803, 0, 0, 0.27764],
+ "45": [0.08319, 0.58283, 0, 0, 0.75623],
+ "46": [0, 0.10803, 0, 0, 0.27764],
+ "47": [0.24982, 0.74947, 0, 0, 0.50181],
+ "48": [0, 0.47534, 0, 0, 0.50181],
+ "49": [0, 0.47534, 0, 0, 0.50181],
+ "50": [0, 0.47534, 0, 0, 0.50181],
+ "51": [0.18906, 0.47534, 0, 0, 0.50181],
+ "52": [0.18906, 0.47534, 0, 0, 0.50181],
+ "53": [0.18906, 0.47534, 0, 0, 0.50181],
+ "54": [0, 0.69141, 0, 0, 0.50181],
+ "55": [0.18906, 0.47534, 0, 0, 0.50181],
+ "56": [0, 0.69141, 0, 0, 0.50181],
+ "57": [0.18906, 0.47534, 0, 0, 0.50181],
+ "58": [0, 0.47534, 0, 0, 0.21606],
+ "59": [0.12604, 0.47534, 0, 0, 0.21606],
+ "61": [-0.13099, 0.36866, 0, 0, 0.75623],
+ "63": [0, 0.69141, 0, 0, 0.36245],
+ "65": [0, 0.69141, 0, 0, 0.7176],
+ "66": [0, 0.69141, 0, 0, 0.88397],
+ "67": [0, 0.69141, 0, 0, 0.61254],
+ "68": [0, 0.69141, 0, 0, 0.83158],
+ "69": [0, 0.69141, 0, 0, 0.66278],
+ "70": [0.12604, 0.69141, 0, 0, 0.61119],
+ "71": [0, 0.69141, 0, 0, 0.78539],
+ "72": [0.06302, 0.69141, 0, 0, 0.7203],
+ "73": [0, 0.69141, 0, 0, 0.55448],
+ "74": [0.12604, 0.69141, 0, 0, 0.55231],
+ "75": [0, 0.69141, 0, 0, 0.66845],
+ "76": [0, 0.69141, 0, 0, 0.66602],
+ "77": [0, 0.69141, 0, 0, 1.04953],
+ "78": [0, 0.69141, 0, 0, 0.83212],
+ "79": [0, 0.69141, 0, 0, 0.82699],
+ "80": [0.18906, 0.69141, 0, 0, 0.82753],
+ "81": [0.03781, 0.69141, 0, 0, 0.82699],
+ "82": [0, 0.69141, 0, 0, 0.82807],
+ "83": [0, 0.69141, 0, 0, 0.82861],
+ "84": [0, 0.69141, 0, 0, 0.66899],
+ "85": [0, 0.69141, 0, 0, 0.64576],
+ "86": [0, 0.69141, 0, 0, 0.83131],
+ "87": [0, 0.69141, 0, 0, 1.04602],
+ "88": [0, 0.69141, 0, 0, 0.71922],
+ "89": [0.18906, 0.69141, 0, 0, 0.83293],
+ "90": [0.12604, 0.69141, 0, 0, 0.60201],
+ "91": [0.24982, 0.74947, 0, 0, 0.27764],
+ "93": [0.24982, 0.74947, 0, 0, 0.27764],
+ "94": [0, 0.69141, 0, 0, 0.49965],
+ "97": [0, 0.47534, 0, 0, 0.50046],
+ "98": [0, 0.69141, 0, 0, 0.51315],
+ "99": [0, 0.47534, 0, 0, 0.38946],
+ "100": [0, 0.62119, 0, 0, 0.49857],
+ "101": [0, 0.47534, 0, 0, 0.40053],
+ "102": [0.18906, 0.69141, 0, 0, 0.32626],
+ "103": [0.18906, 0.47534, 0, 0, 0.5037],
+ "104": [0.18906, 0.69141, 0, 0, 0.52126],
+ "105": [0, 0.69141, 0, 0, 0.27899],
+ "106": [0, 0.69141, 0, 0, 0.28088],
+ "107": [0, 0.69141, 0, 0, 0.38946],
+ "108": [0, 0.69141, 0, 0, 0.27953],
+ "109": [0, 0.47534, 0, 0, 0.76676],
+ "110": [0, 0.47534, 0, 0, 0.52666],
+ "111": [0, 0.47534, 0, 0, 0.48885],
+ "112": [0.18906, 0.52396, 0, 0, 0.50046],
+ "113": [0.18906, 0.47534, 0, 0, 0.48912],
+ "114": [0, 0.47534, 0, 0, 0.38919],
+ "115": [0, 0.47534, 0, 0, 0.44266],
+ "116": [0, 0.62119, 0, 0, 0.33301],
+ "117": [0, 0.47534, 0, 0, 0.5172],
+ "118": [0, 0.52396, 0, 0, 0.5118],
+ "119": [0, 0.52396, 0, 0, 0.77351],
+ "120": [0.18906, 0.47534, 0, 0, 0.38865],
+ "121": [0.18906, 0.47534, 0, 0, 0.49884],
+ "122": [0.18906, 0.47534, 0, 0, 0.39054],
+ "160": [0, 0, 0, 0, 0.25],
+ "8216": [0, 0.69141, 0, 0, 0.21471],
+ "8217": [0, 0.69141, 0, 0, 0.21471],
+ "58112": [0, 0.62119, 0, 0, 0.49749],
+ "58113": [0, 0.62119, 0, 0, 0.4983],
+ "58114": [0.18906, 0.69141, 0, 0, 0.33328],
+ "58115": [0.18906, 0.69141, 0, 0, 0.32923],
+ "58116": [0.18906, 0.47534, 0, 0, 0.50343],
+ "58117": [0, 0.69141, 0, 0, 0.33301],
+ "58118": [0, 0.62119, 0, 0, 0.33409],
+ "58119": [0, 0.47534, 0, 0, 0.50073]
+ },
+ "Main-Bold": {
+ "32": [0, 0, 0, 0, 0.25],
+ "33": [0, 0.69444, 0, 0, 0.35],
+ "34": [0, 0.69444, 0, 0, 0.60278],
+ "35": [0.19444, 0.69444, 0, 0, 0.95833],
+ "36": [0.05556, 0.75, 0, 0, 0.575],
+ "37": [0.05556, 0.75, 0, 0, 0.95833],
+ "38": [0, 0.69444, 0, 0, 0.89444],
+ "39": [0, 0.69444, 0, 0, 0.31944],
+ "40": [0.25, 0.75, 0, 0, 0.44722],
+ "41": [0.25, 0.75, 0, 0, 0.44722],
+ "42": [0, 0.75, 0, 0, 0.575],
+ "43": [0.13333, 0.63333, 0, 0, 0.89444],
+ "44": [0.19444, 0.15556, 0, 0, 0.31944],
+ "45": [0, 0.44444, 0, 0, 0.38333],
+ "46": [0, 0.15556, 0, 0, 0.31944],
+ "47": [0.25, 0.75, 0, 0, 0.575],
+ "48": [0, 0.64444, 0, 0, 0.575],
+ "49": [0, 0.64444, 0, 0, 0.575],
+ "50": [0, 0.64444, 0, 0, 0.575],
+ "51": [0, 0.64444, 0, 0, 0.575],
+ "52": [0, 0.64444, 0, 0, 0.575],
+ "53": [0, 0.64444, 0, 0, 0.575],
+ "54": [0, 0.64444, 0, 0, 0.575],
+ "55": [0, 0.64444, 0, 0, 0.575],
+ "56": [0, 0.64444, 0, 0, 0.575],
+ "57": [0, 0.64444, 0, 0, 0.575],
+ "58": [0, 0.44444, 0, 0, 0.31944],
+ "59": [0.19444, 0.44444, 0, 0, 0.31944],
+ "60": [0.08556, 0.58556, 0, 0, 0.89444],
+ "61": [-0.10889, 0.39111, 0, 0, 0.89444],
+ "62": [0.08556, 0.58556, 0, 0, 0.89444],
+ "63": [0, 0.69444, 0, 0, 0.54305],
+ "64": [0, 0.69444, 0, 0, 0.89444],
+ "65": [0, 0.68611, 0, 0, 0.86944],
+ "66": [0, 0.68611, 0, 0, 0.81805],
+ "67": [0, 0.68611, 0, 0, 0.83055],
+ "68": [0, 0.68611, 0, 0, 0.88194],
+ "69": [0, 0.68611, 0, 0, 0.75555],
+ "70": [0, 0.68611, 0, 0, 0.72361],
+ "71": [0, 0.68611, 0, 0, 0.90416],
+ "72": [0, 0.68611, 0, 0, 0.9],
+ "73": [0, 0.68611, 0, 0, 0.43611],
+ "74": [0, 0.68611, 0, 0, 0.59444],
+ "75": [0, 0.68611, 0, 0, 0.90138],
+ "76": [0, 0.68611, 0, 0, 0.69166],
+ "77": [0, 0.68611, 0, 0, 1.09166],
+ "78": [0, 0.68611, 0, 0, 0.9],
+ "79": [0, 0.68611, 0, 0, 0.86388],
+ "80": [0, 0.68611, 0, 0, 0.78611],
+ "81": [0.19444, 0.68611, 0, 0, 0.86388],
+ "82": [0, 0.68611, 0, 0, 0.8625],
+ "83": [0, 0.68611, 0, 0, 0.63889],
+ "84": [0, 0.68611, 0, 0, 0.8],
+ "85": [0, 0.68611, 0, 0, 0.88472],
+ "86": [0, 0.68611, 0.01597, 0, 0.86944],
+ "87": [0, 0.68611, 0.01597, 0, 1.18888],
+ "88": [0, 0.68611, 0, 0, 0.86944],
+ "89": [0, 0.68611, 0.02875, 0, 0.86944],
+ "90": [0, 0.68611, 0, 0, 0.70277],
+ "91": [0.25, 0.75, 0, 0, 0.31944],
+ "92": [0.25, 0.75, 0, 0, 0.575],
+ "93": [0.25, 0.75, 0, 0, 0.31944],
+ "94": [0, 0.69444, 0, 0, 0.575],
+ "95": [0.31, 0.13444, 0.03194, 0, 0.575],
+ "97": [0, 0.44444, 0, 0, 0.55902],
+ "98": [0, 0.69444, 0, 0, 0.63889],
+ "99": [0, 0.44444, 0, 0, 0.51111],
+ "100": [0, 0.69444, 0, 0, 0.63889],
+ "101": [0, 0.44444, 0, 0, 0.52708],
+ "102": [0, 0.69444, 0.10903, 0, 0.35139],
+ "103": [0.19444, 0.44444, 0.01597, 0, 0.575],
+ "104": [0, 0.69444, 0, 0, 0.63889],
+ "105": [0, 0.69444, 0, 0, 0.31944],
+ "106": [0.19444, 0.69444, 0, 0, 0.35139],
+ "107": [0, 0.69444, 0, 0, 0.60694],
+ "108": [0, 0.69444, 0, 0, 0.31944],
+ "109": [0, 0.44444, 0, 0, 0.95833],
+ "110": [0, 0.44444, 0, 0, 0.63889],
+ "111": [0, 0.44444, 0, 0, 0.575],
+ "112": [0.19444, 0.44444, 0, 0, 0.63889],
+ "113": [0.19444, 0.44444, 0, 0, 0.60694],
+ "114": [0, 0.44444, 0, 0, 0.47361],
+ "115": [0, 0.44444, 0, 0, 0.45361],
+ "116": [0, 0.63492, 0, 0, 0.44722],
+ "117": [0, 0.44444, 0, 0, 0.63889],
+ "118": [0, 0.44444, 0.01597, 0, 0.60694],
+ "119": [0, 0.44444, 0.01597, 0, 0.83055],
+ "120": [0, 0.44444, 0, 0, 0.60694],
+ "121": [0.19444, 0.44444, 0.01597, 0, 0.60694],
+ "122": [0, 0.44444, 0, 0, 0.51111],
+ "123": [0.25, 0.75, 0, 0, 0.575],
+ "124": [0.25, 0.75, 0, 0, 0.31944],
+ "125": [0.25, 0.75, 0, 0, 0.575],
+ "126": [0.35, 0.34444, 0, 0, 0.575],
+ "160": [0, 0, 0, 0, 0.25],
+ "163": [0, 0.69444, 0, 0, 0.86853],
+ "168": [0, 0.69444, 0, 0, 0.575],
+ "172": [0, 0.44444, 0, 0, 0.76666],
+ "176": [0, 0.69444, 0, 0, 0.86944],
+ "177": [0.13333, 0.63333, 0, 0, 0.89444],
+ "184": [0.17014, 0, 0, 0, 0.51111],
+ "198": [0, 0.68611, 0, 0, 1.04166],
+ "215": [0.13333, 0.63333, 0, 0, 0.89444],
+ "216": [0.04861, 0.73472, 0, 0, 0.89444],
+ "223": [0, 0.69444, 0, 0, 0.59722],
+ "230": [0, 0.44444, 0, 0, 0.83055],
+ "247": [0.13333, 0.63333, 0, 0, 0.89444],
+ "248": [0.09722, 0.54167, 0, 0, 0.575],
+ "305": [0, 0.44444, 0, 0, 0.31944],
+ "338": [0, 0.68611, 0, 0, 1.16944],
+ "339": [0, 0.44444, 0, 0, 0.89444],
+ "567": [0.19444, 0.44444, 0, 0, 0.35139],
+ "710": [0, 0.69444, 0, 0, 0.575],
+ "711": [0, 0.63194, 0, 0, 0.575],
+ "713": [0, 0.59611, 0, 0, 0.575],
+ "714": [0, 0.69444, 0, 0, 0.575],
+ "715": [0, 0.69444, 0, 0, 0.575],
+ "728": [0, 0.69444, 0, 0, 0.575],
+ "729": [0, 0.69444, 0, 0, 0.31944],
+ "730": [0, 0.69444, 0, 0, 0.86944],
+ "732": [0, 0.69444, 0, 0, 0.575],
+ "733": [0, 0.69444, 0, 0, 0.575],
+ "915": [0, 0.68611, 0, 0, 0.69166],
+ "916": [0, 0.68611, 0, 0, 0.95833],
+ "920": [0, 0.68611, 0, 0, 0.89444],
+ "923": [0, 0.68611, 0, 0, 0.80555],
+ "926": [0, 0.68611, 0, 0, 0.76666],
+ "928": [0, 0.68611, 0, 0, 0.9],
+ "931": [0, 0.68611, 0, 0, 0.83055],
+ "933": [0, 0.68611, 0, 0, 0.89444],
+ "934": [0, 0.68611, 0, 0, 0.83055],
+ "936": [0, 0.68611, 0, 0, 0.89444],
+ "937": [0, 0.68611, 0, 0, 0.83055],
+ "8211": [0, 0.44444, 0.03194, 0, 0.575],
+ "8212": [0, 0.44444, 0.03194, 0, 1.14999],
+ "8216": [0, 0.69444, 0, 0, 0.31944],
+ "8217": [0, 0.69444, 0, 0, 0.31944],
+ "8220": [0, 0.69444, 0, 0, 0.60278],
+ "8221": [0, 0.69444, 0, 0, 0.60278],
+ "8224": [0.19444, 0.69444, 0, 0, 0.51111],
+ "8225": [0.19444, 0.69444, 0, 0, 0.51111],
+ "8242": [0, 0.55556, 0, 0, 0.34444],
+ "8407": [0, 0.72444, 0.15486, 0, 0.575],
+ "8463": [0, 0.69444, 0, 0, 0.66759],
+ "8465": [0, 0.69444, 0, 0, 0.83055],
+ "8467": [0, 0.69444, 0, 0, 0.47361],
+ "8472": [0.19444, 0.44444, 0, 0, 0.74027],
+ "8476": [0, 0.69444, 0, 0, 0.83055],
+ "8501": [0, 0.69444, 0, 0, 0.70277],
+ "8592": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8593": [0.19444, 0.69444, 0, 0, 0.575],
+ "8594": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8595": [0.19444, 0.69444, 0, 0, 0.575],
+ "8596": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8597": [0.25, 0.75, 0, 0, 0.575],
+ "8598": [0.19444, 0.69444, 0, 0, 1.14999],
+ "8599": [0.19444, 0.69444, 0, 0, 1.14999],
+ "8600": [0.19444, 0.69444, 0, 0, 1.14999],
+ "8601": [0.19444, 0.69444, 0, 0, 1.14999],
+ "8636": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8637": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8640": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8641": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8656": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8657": [0.19444, 0.69444, 0, 0, 0.70277],
+ "8658": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8659": [0.19444, 0.69444, 0, 0, 0.70277],
+ "8660": [-0.10889, 0.39111, 0, 0, 1.14999],
+ "8661": [0.25, 0.75, 0, 0, 0.70277],
+ "8704": [0, 0.69444, 0, 0, 0.63889],
+ "8706": [0, 0.69444, 0.06389, 0, 0.62847],
+ "8707": [0, 0.69444, 0, 0, 0.63889],
+ "8709": [0.05556, 0.75, 0, 0, 0.575],
+ "8711": [0, 0.68611, 0, 0, 0.95833],
+ "8712": [0.08556, 0.58556, 0, 0, 0.76666],
+ "8715": [0.08556, 0.58556, 0, 0, 0.76666],
+ "8722": [0.13333, 0.63333, 0, 0, 0.89444],
+ "8723": [0.13333, 0.63333, 0, 0, 0.89444],
+ "8725": [0.25, 0.75, 0, 0, 0.575],
+ "8726": [0.25, 0.75, 0, 0, 0.575],
+ "8727": [-0.02778, 0.47222, 0, 0, 0.575],
+ "8728": [-0.02639, 0.47361, 0, 0, 0.575],
+ "8729": [-0.02639, 0.47361, 0, 0, 0.575],
+ "8730": [0.18, 0.82, 0, 0, 0.95833],
+ "8733": [0, 0.44444, 0, 0, 0.89444],
+ "8734": [0, 0.44444, 0, 0, 1.14999],
+ "8736": [0, 0.69224, 0, 0, 0.72222],
+ "8739": [0.25, 0.75, 0, 0, 0.31944],
+ "8741": [0.25, 0.75, 0, 0, 0.575],
+ "8743": [0, 0.55556, 0, 0, 0.76666],
+ "8744": [0, 0.55556, 0, 0, 0.76666],
+ "8745": [0, 0.55556, 0, 0, 0.76666],
+ "8746": [0, 0.55556, 0, 0, 0.76666],
+ "8747": [0.19444, 0.69444, 0.12778, 0, 0.56875],
+ "8764": [-0.10889, 0.39111, 0, 0, 0.89444],
+ "8768": [0.19444, 0.69444, 0, 0, 0.31944],
+ "8771": [0.00222, 0.50222, 0, 0, 0.89444],
+ "8773": [0.027, 0.638, 0, 0, 0.894],
+ "8776": [0.02444, 0.52444, 0, 0, 0.89444],
+ "8781": [0.00222, 0.50222, 0, 0, 0.89444],
+ "8801": [0.00222, 0.50222, 0, 0, 0.89444],
+ "8804": [0.19667, 0.69667, 0, 0, 0.89444],
+ "8805": [0.19667, 0.69667, 0, 0, 0.89444],
+ "8810": [0.08556, 0.58556, 0, 0, 1.14999],
+ "8811": [0.08556, 0.58556, 0, 0, 1.14999],
+ "8826": [0.08556, 0.58556, 0, 0, 0.89444],
+ "8827": [0.08556, 0.58556, 0, 0, 0.89444],
+ "8834": [0.08556, 0.58556, 0, 0, 0.89444],
+ "8835": [0.08556, 0.58556, 0, 0, 0.89444],
+ "8838": [0.19667, 0.69667, 0, 0, 0.89444],
+ "8839": [0.19667, 0.69667, 0, 0, 0.89444],
+ "8846": [0, 0.55556, 0, 0, 0.76666],
+ "8849": [0.19667, 0.69667, 0, 0, 0.89444],
+ "8850": [0.19667, 0.69667, 0, 0, 0.89444],
+ "8851": [0, 0.55556, 0, 0, 0.76666],
+ "8852": [0, 0.55556, 0, 0, 0.76666],
+ "8853": [0.13333, 0.63333, 0, 0, 0.89444],
+ "8854": [0.13333, 0.63333, 0, 0, 0.89444],
+ "8855": [0.13333, 0.63333, 0, 0, 0.89444],
+ "8856": [0.13333, 0.63333, 0, 0, 0.89444],
+ "8857": [0.13333, 0.63333, 0, 0, 0.89444],
+ "8866": [0, 0.69444, 0, 0, 0.70277],
+ "8867": [0, 0.69444, 0, 0, 0.70277],
+ "8868": [0, 0.69444, 0, 0, 0.89444],
+ "8869": [0, 0.69444, 0, 0, 0.89444],
+ "8900": [-0.02639, 0.47361, 0, 0, 0.575],
+ "8901": [-0.02639, 0.47361, 0, 0, 0.31944],
+ "8902": [-0.02778, 0.47222, 0, 0, 0.575],
+ "8968": [0.25, 0.75, 0, 0, 0.51111],
+ "8969": [0.25, 0.75, 0, 0, 0.51111],
+ "8970": [0.25, 0.75, 0, 0, 0.51111],
+ "8971": [0.25, 0.75, 0, 0, 0.51111],
+ "8994": [-0.13889, 0.36111, 0, 0, 1.14999],
+ "8995": [-0.13889, 0.36111, 0, 0, 1.14999],
+ "9651": [0.19444, 0.69444, 0, 0, 1.02222],
+ "9657": [-0.02778, 0.47222, 0, 0, 0.575],
+ "9661": [0.19444, 0.69444, 0, 0, 1.02222],
+ "9667": [-0.02778, 0.47222, 0, 0, 0.575],
+ "9711": [0.19444, 0.69444, 0, 0, 1.14999],
+ "9824": [0.12963, 0.69444, 0, 0, 0.89444],
+ "9825": [0.12963, 0.69444, 0, 0, 0.89444],
+ "9826": [0.12963, 0.69444, 0, 0, 0.89444],
+ "9827": [0.12963, 0.69444, 0, 0, 0.89444],
+ "9837": [0, 0.75, 0, 0, 0.44722],
+ "9838": [0.19444, 0.69444, 0, 0, 0.44722],
+ "9839": [0.19444, 0.69444, 0, 0, 0.44722],
+ "10216": [0.25, 0.75, 0, 0, 0.44722],
+ "10217": [0.25, 0.75, 0, 0, 0.44722],
+ "10815": [0, 0.68611, 0, 0, 0.9],
+ "10927": [0.19667, 0.69667, 0, 0, 0.89444],
+ "10928": [0.19667, 0.69667, 0, 0, 0.89444],
+ "57376": [0.19444, 0.69444, 0, 0, 0]
+ },
+ "Main-BoldItalic": {
+ "32": [0, 0, 0, 0, 0.25],
+ "33": [0, 0.69444, 0.11417, 0, 0.38611],
+ "34": [0, 0.69444, 0.07939, 0, 0.62055],
+ "35": [0.19444, 0.69444, 0.06833, 0, 0.94444],
+ "37": [0.05556, 0.75, 0.12861, 0, 0.94444],
+ "38": [0, 0.69444, 0.08528, 0, 0.88555],
+ "39": [0, 0.69444, 0.12945, 0, 0.35555],
+ "40": [0.25, 0.75, 0.15806, 0, 0.47333],
+ "41": [0.25, 0.75, 0.03306, 0, 0.47333],
+ "42": [0, 0.75, 0.14333, 0, 0.59111],
+ "43": [0.10333, 0.60333, 0.03306, 0, 0.88555],
+ "44": [0.19444, 0.14722, 0, 0, 0.35555],
+ "45": [0, 0.44444, 0.02611, 0, 0.41444],
+ "46": [0, 0.14722, 0, 0, 0.35555],
+ "47": [0.25, 0.75, 0.15806, 0, 0.59111],
+ "48": [0, 0.64444, 0.13167, 0, 0.59111],
+ "49": [0, 0.64444, 0.13167, 0, 0.59111],
+ "50": [0, 0.64444, 0.13167, 0, 0.59111],
+ "51": [0, 0.64444, 0.13167, 0, 0.59111],
+ "52": [0.19444, 0.64444, 0.13167, 0, 0.59111],
+ "53": [0, 0.64444, 0.13167, 0, 0.59111],
+ "54": [0, 0.64444, 0.13167, 0, 0.59111],
+ "55": [0.19444, 0.64444, 0.13167, 0, 0.59111],
+ "56": [0, 0.64444, 0.13167, 0, 0.59111],
+ "57": [0, 0.64444, 0.13167, 0, 0.59111],
+ "58": [0, 0.44444, 0.06695, 0, 0.35555],
+ "59": [0.19444, 0.44444, 0.06695, 0, 0.35555],
+ "61": [-0.10889, 0.39111, 0.06833, 0, 0.88555],
+ "63": [0, 0.69444, 0.11472, 0, 0.59111],
+ "64": [0, 0.69444, 0.09208, 0, 0.88555],
+ "65": [0, 0.68611, 0, 0, 0.86555],
+ "66": [0, 0.68611, 0.0992, 0, 0.81666],
+ "67": [0, 0.68611, 0.14208, 0, 0.82666],
+ "68": [0, 0.68611, 0.09062, 0, 0.87555],
+ "69": [0, 0.68611, 0.11431, 0, 0.75666],
+ "70": [0, 0.68611, 0.12903, 0, 0.72722],
+ "71": [0, 0.68611, 0.07347, 0, 0.89527],
+ "72": [0, 0.68611, 0.17208, 0, 0.8961],
+ "73": [0, 0.68611, 0.15681, 0, 0.47166],
+ "74": [0, 0.68611, 0.145, 0, 0.61055],
+ "75": [0, 0.68611, 0.14208, 0, 0.89499],
+ "76": [0, 0.68611, 0, 0, 0.69777],
+ "77": [0, 0.68611, 0.17208, 0, 1.07277],
+ "78": [0, 0.68611, 0.17208, 0, 0.8961],
+ "79": [0, 0.68611, 0.09062, 0, 0.85499],
+ "80": [0, 0.68611, 0.0992, 0, 0.78721],
+ "81": [0.19444, 0.68611, 0.09062, 0, 0.85499],
+ "82": [0, 0.68611, 0.02559, 0, 0.85944],
+ "83": [0, 0.68611, 0.11264, 0, 0.64999],
+ "84": [0, 0.68611, 0.12903, 0, 0.7961],
+ "85": [0, 0.68611, 0.17208, 0, 0.88083],
+ "86": [0, 0.68611, 0.18625, 0, 0.86555],
+ "87": [0, 0.68611, 0.18625, 0, 1.15999],
+ "88": [0, 0.68611, 0.15681, 0, 0.86555],
+ "89": [0, 0.68611, 0.19803, 0, 0.86555],
+ "90": [0, 0.68611, 0.14208, 0, 0.70888],
+ "91": [0.25, 0.75, 0.1875, 0, 0.35611],
+ "93": [0.25, 0.75, 0.09972, 0, 0.35611],
+ "94": [0, 0.69444, 0.06709, 0, 0.59111],
+ "95": [0.31, 0.13444, 0.09811, 0, 0.59111],
+ "97": [0, 0.44444, 0.09426, 0, 0.59111],
+ "98": [0, 0.69444, 0.07861, 0, 0.53222],
+ "99": [0, 0.44444, 0.05222, 0, 0.53222],
+ "100": [0, 0.69444, 0.10861, 0, 0.59111],
+ "101": [0, 0.44444, 0.085, 0, 0.53222],
+ "102": [0.19444, 0.69444, 0.21778, 0, 0.4],
+ "103": [0.19444, 0.44444, 0.105, 0, 0.53222],
+ "104": [0, 0.69444, 0.09426, 0, 0.59111],
+ "105": [0, 0.69326, 0.11387, 0, 0.35555],
+ "106": [0.19444, 0.69326, 0.1672, 0, 0.35555],
+ "107": [0, 0.69444, 0.11111, 0, 0.53222],
+ "108": [0, 0.69444, 0.10861, 0, 0.29666],
+ "109": [0, 0.44444, 0.09426, 0, 0.94444],
+ "110": [0, 0.44444, 0.09426, 0, 0.64999],
+ "111": [0, 0.44444, 0.07861, 0, 0.59111],
+ "112": [0.19444, 0.44444, 0.07861, 0, 0.59111],
+ "113": [0.19444, 0.44444, 0.105, 0, 0.53222],
+ "114": [0, 0.44444, 0.11111, 0, 0.50167],
+ "115": [0, 0.44444, 0.08167, 0, 0.48694],
+ "116": [0, 0.63492, 0.09639, 0, 0.385],
+ "117": [0, 0.44444, 0.09426, 0, 0.62055],
+ "118": [0, 0.44444, 0.11111, 0, 0.53222],
+ "119": [0, 0.44444, 0.11111, 0, 0.76777],
+ "120": [0, 0.44444, 0.12583, 0, 0.56055],
+ "121": [0.19444, 0.44444, 0.105, 0, 0.56166],
+ "122": [0, 0.44444, 0.13889, 0, 0.49055],
+ "126": [0.35, 0.34444, 0.11472, 0, 0.59111],
+ "160": [0, 0, 0, 0, 0.25],
+ "168": [0, 0.69444, 0.11473, 0, 0.59111],
+ "176": [0, 0.69444, 0, 0, 0.94888],
+ "184": [0.17014, 0, 0, 0, 0.53222],
+ "198": [0, 0.68611, 0.11431, 0, 1.02277],
+ "216": [0.04861, 0.73472, 0.09062, 0, 0.88555],
+ "223": [0.19444, 0.69444, 0.09736, 0, 0.665],
+ "230": [0, 0.44444, 0.085, 0, 0.82666],
+ "248": [0.09722, 0.54167, 0.09458, 0, 0.59111],
+ "305": [0, 0.44444, 0.09426, 0, 0.35555],
+ "338": [0, 0.68611, 0.11431, 0, 1.14054],
+ "339": [0, 0.44444, 0.085, 0, 0.82666],
+ "567": [0.19444, 0.44444, 0.04611, 0, 0.385],
+ "710": [0, 0.69444, 0.06709, 0, 0.59111],
+ "711": [0, 0.63194, 0.08271, 0, 0.59111],
+ "713": [0, 0.59444, 0.10444, 0, 0.59111],
+ "714": [0, 0.69444, 0.08528, 0, 0.59111],
+ "715": [0, 0.69444, 0, 0, 0.59111],
+ "728": [0, 0.69444, 0.10333, 0, 0.59111],
+ "729": [0, 0.69444, 0.12945, 0, 0.35555],
+ "730": [0, 0.69444, 0, 0, 0.94888],
+ "732": [0, 0.69444, 0.11472, 0, 0.59111],
+ "733": [0, 0.69444, 0.11472, 0, 0.59111],
+ "915": [0, 0.68611, 0.12903, 0, 0.69777],
+ "916": [0, 0.68611, 0, 0, 0.94444],
+ "920": [0, 0.68611, 0.09062, 0, 0.88555],
+ "923": [0, 0.68611, 0, 0, 0.80666],
+ "926": [0, 0.68611, 0.15092, 0, 0.76777],
+ "928": [0, 0.68611, 0.17208, 0, 0.8961],
+ "931": [0, 0.68611, 0.11431, 0, 0.82666],
+ "933": [0, 0.68611, 0.10778, 0, 0.88555],
+ "934": [0, 0.68611, 0.05632, 0, 0.82666],
+ "936": [0, 0.68611, 0.10778, 0, 0.88555],
+ "937": [0, 0.68611, 0.0992, 0, 0.82666],
+ "8211": [0, 0.44444, 0.09811, 0, 0.59111],
+ "8212": [0, 0.44444, 0.09811, 0, 1.18221],
+ "8216": [0, 0.69444, 0.12945, 0, 0.35555],
+ "8217": [0, 0.69444, 0.12945, 0, 0.35555],
+ "8220": [0, 0.69444, 0.16772, 0, 0.62055],
+ "8221": [0, 0.69444, 0.07939, 0, 0.62055]
+ },
+ "Main-Italic": {
+ "32": [0, 0, 0, 0, 0.25],
+ "33": [0, 0.69444, 0.12417, 0, 0.30667],
+ "34": [0, 0.69444, 0.06961, 0, 0.51444],
+ "35": [0.19444, 0.69444, 0.06616, 0, 0.81777],
+ "37": [0.05556, 0.75, 0.13639, 0, 0.81777],
+ "38": [0, 0.69444, 0.09694, 0, 0.76666],
+ "39": [0, 0.69444, 0.12417, 0, 0.30667],
+ "40": [0.25, 0.75, 0.16194, 0, 0.40889],
+ "41": [0.25, 0.75, 0.03694, 0, 0.40889],
+ "42": [0, 0.75, 0.14917, 0, 0.51111],
+ "43": [0.05667, 0.56167, 0.03694, 0, 0.76666],
+ "44": [0.19444, 0.10556, 0, 0, 0.30667],
+ "45": [0, 0.43056, 0.02826, 0, 0.35778],
+ "46": [0, 0.10556, 0, 0, 0.30667],
+ "47": [0.25, 0.75, 0.16194, 0, 0.51111],
+ "48": [0, 0.64444, 0.13556, 0, 0.51111],
+ "49": [0, 0.64444, 0.13556, 0, 0.51111],
+ "50": [0, 0.64444, 0.13556, 0, 0.51111],
+ "51": [0, 0.64444, 0.13556, 0, 0.51111],
+ "52": [0.19444, 0.64444, 0.13556, 0, 0.51111],
+ "53": [0, 0.64444, 0.13556, 0, 0.51111],
+ "54": [0, 0.64444, 0.13556, 0, 0.51111],
+ "55": [0.19444, 0.64444, 0.13556, 0, 0.51111],
+ "56": [0, 0.64444, 0.13556, 0, 0.51111],
+ "57": [0, 0.64444, 0.13556, 0, 0.51111],
+ "58": [0, 0.43056, 0.0582, 0, 0.30667],
+ "59": [0.19444, 0.43056, 0.0582, 0, 0.30667],
+ "61": [-0.13313, 0.36687, 0.06616, 0, 0.76666],
+ "63": [0, 0.69444, 0.1225, 0, 0.51111],
+ "64": [0, 0.69444, 0.09597, 0, 0.76666],
+ "65": [0, 0.68333, 0, 0, 0.74333],
+ "66": [0, 0.68333, 0.10257, 0, 0.70389],
+ "67": [0, 0.68333, 0.14528, 0, 0.71555],
+ "68": [0, 0.68333, 0.09403, 0, 0.755],
+ "69": [0, 0.68333, 0.12028, 0, 0.67833],
+ "70": [0, 0.68333, 0.13305, 0, 0.65277],
+ "71": [0, 0.68333, 0.08722, 0, 0.77361],
+ "72": [0, 0.68333, 0.16389, 0, 0.74333],
+ "73": [0, 0.68333, 0.15806, 0, 0.38555],
+ "74": [0, 0.68333, 0.14028, 0, 0.525],
+ "75": [0, 0.68333, 0.14528, 0, 0.76888],
+ "76": [0, 0.68333, 0, 0, 0.62722],
+ "77": [0, 0.68333, 0.16389, 0, 0.89666],
+ "78": [0, 0.68333, 0.16389, 0, 0.74333],
+ "79": [0, 0.68333, 0.09403, 0, 0.76666],
+ "80": [0, 0.68333, 0.10257, 0, 0.67833],
+ "81": [0.19444, 0.68333, 0.09403, 0, 0.76666],
+ "82": [0, 0.68333, 0.03868, 0, 0.72944],
+ "83": [0, 0.68333, 0.11972, 0, 0.56222],
+ "84": [0, 0.68333, 0.13305, 0, 0.71555],
+ "85": [0, 0.68333, 0.16389, 0, 0.74333],
+ "86": [0, 0.68333, 0.18361, 0, 0.74333],
+ "87": [0, 0.68333, 0.18361, 0, 0.99888],
+ "88": [0, 0.68333, 0.15806, 0, 0.74333],
+ "89": [0, 0.68333, 0.19383, 0, 0.74333],
+ "90": [0, 0.68333, 0.14528, 0, 0.61333],
+ "91": [0.25, 0.75, 0.1875, 0, 0.30667],
+ "93": [0.25, 0.75, 0.10528, 0, 0.30667],
+ "94": [0, 0.69444, 0.06646, 0, 0.51111],
+ "95": [0.31, 0.12056, 0.09208, 0, 0.51111],
+ "97": [0, 0.43056, 0.07671, 0, 0.51111],
+ "98": [0, 0.69444, 0.06312, 0, 0.46],
+ "99": [0, 0.43056, 0.05653, 0, 0.46],
+ "100": [0, 0.69444, 0.10333, 0, 0.51111],
+ "101": [0, 0.43056, 0.07514, 0, 0.46],
+ "102": [0.19444, 0.69444, 0.21194, 0, 0.30667],
+ "103": [0.19444, 0.43056, 0.08847, 0, 0.46],
+ "104": [0, 0.69444, 0.07671, 0, 0.51111],
+ "105": [0, 0.65536, 0.1019, 0, 0.30667],
+ "106": [0.19444, 0.65536, 0.14467, 0, 0.30667],
+ "107": [0, 0.69444, 0.10764, 0, 0.46],
+ "108": [0, 0.69444, 0.10333, 0, 0.25555],
+ "109": [0, 0.43056, 0.07671, 0, 0.81777],
+ "110": [0, 0.43056, 0.07671, 0, 0.56222],
+ "111": [0, 0.43056, 0.06312, 0, 0.51111],
+ "112": [0.19444, 0.43056, 0.06312, 0, 0.51111],
+ "113": [0.19444, 0.43056, 0.08847, 0, 0.46],
+ "114": [0, 0.43056, 0.10764, 0, 0.42166],
+ "115": [0, 0.43056, 0.08208, 0, 0.40889],
+ "116": [0, 0.61508, 0.09486, 0, 0.33222],
+ "117": [0, 0.43056, 0.07671, 0, 0.53666],
+ "118": [0, 0.43056, 0.10764, 0, 0.46],
+ "119": [0, 0.43056, 0.10764, 0, 0.66444],
+ "120": [0, 0.43056, 0.12042, 0, 0.46389],
+ "121": [0.19444, 0.43056, 0.08847, 0, 0.48555],
+ "122": [0, 0.43056, 0.12292, 0, 0.40889],
+ "126": [0.35, 0.31786, 0.11585, 0, 0.51111],
+ "160": [0, 0, 0, 0, 0.25],
+ "168": [0, 0.66786, 0.10474, 0, 0.51111],
+ "176": [0, 0.69444, 0, 0, 0.83129],
+ "184": [0.17014, 0, 0, 0, 0.46],
+ "198": [0, 0.68333, 0.12028, 0, 0.88277],
+ "216": [0.04861, 0.73194, 0.09403, 0, 0.76666],
+ "223": [0.19444, 0.69444, 0.10514, 0, 0.53666],
+ "230": [0, 0.43056, 0.07514, 0, 0.71555],
+ "248": [0.09722, 0.52778, 0.09194, 0, 0.51111],
+ "338": [0, 0.68333, 0.12028, 0, 0.98499],
+ "339": [0, 0.43056, 0.07514, 0, 0.71555],
+ "710": [0, 0.69444, 0.06646, 0, 0.51111],
+ "711": [0, 0.62847, 0.08295, 0, 0.51111],
+ "713": [0, 0.56167, 0.10333, 0, 0.51111],
+ "714": [0, 0.69444, 0.09694, 0, 0.51111],
+ "715": [0, 0.69444, 0, 0, 0.51111],
+ "728": [0, 0.69444, 0.10806, 0, 0.51111],
+ "729": [0, 0.66786, 0.11752, 0, 0.30667],
+ "730": [0, 0.69444, 0, 0, 0.83129],
+ "732": [0, 0.66786, 0.11585, 0, 0.51111],
+ "733": [0, 0.69444, 0.1225, 0, 0.51111],
+ "915": [0, 0.68333, 0.13305, 0, 0.62722],
+ "916": [0, 0.68333, 0, 0, 0.81777],
+ "920": [0, 0.68333, 0.09403, 0, 0.76666],
+ "923": [0, 0.68333, 0, 0, 0.69222],
+ "926": [0, 0.68333, 0.15294, 0, 0.66444],
+ "928": [0, 0.68333, 0.16389, 0, 0.74333],
+ "931": [0, 0.68333, 0.12028, 0, 0.71555],
+ "933": [0, 0.68333, 0.11111, 0, 0.76666],
+ "934": [0, 0.68333, 0.05986, 0, 0.71555],
+ "936": [0, 0.68333, 0.11111, 0, 0.76666],
+ "937": [0, 0.68333, 0.10257, 0, 0.71555],
+ "8211": [0, 0.43056, 0.09208, 0, 0.51111],
+ "8212": [0, 0.43056, 0.09208, 0, 1.02222],
+ "8216": [0, 0.69444, 0.12417, 0, 0.30667],
+ "8217": [0, 0.69444, 0.12417, 0, 0.30667],
+ "8220": [0, 0.69444, 0.1685, 0, 0.51444],
+ "8221": [0, 0.69444, 0.06961, 0, 0.51444],
+ "8463": [0, 0.68889, 0, 0, 0.54028]
+ },
+ "Main-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "33": [0, 0.69444, 0, 0, 0.27778],
+ "34": [0, 0.69444, 0, 0, 0.5],
+ "35": [0.19444, 0.69444, 0, 0, 0.83334],
+ "36": [0.05556, 0.75, 0, 0, 0.5],
+ "37": [0.05556, 0.75, 0, 0, 0.83334],
+ "38": [0, 0.69444, 0, 0, 0.77778],
+ "39": [0, 0.69444, 0, 0, 0.27778],
+ "40": [0.25, 0.75, 0, 0, 0.38889],
+ "41": [0.25, 0.75, 0, 0, 0.38889],
+ "42": [0, 0.75, 0, 0, 0.5],
+ "43": [0.08333, 0.58333, 0, 0, 0.77778],
+ "44": [0.19444, 0.10556, 0, 0, 0.27778],
+ "45": [0, 0.43056, 0, 0, 0.33333],
+ "46": [0, 0.10556, 0, 0, 0.27778],
+ "47": [0.25, 0.75, 0, 0, 0.5],
+ "48": [0, 0.64444, 0, 0, 0.5],
+ "49": [0, 0.64444, 0, 0, 0.5],
+ "50": [0, 0.64444, 0, 0, 0.5],
+ "51": [0, 0.64444, 0, 0, 0.5],
+ "52": [0, 0.64444, 0, 0, 0.5],
+ "53": [0, 0.64444, 0, 0, 0.5],
+ "54": [0, 0.64444, 0, 0, 0.5],
+ "55": [0, 0.64444, 0, 0, 0.5],
+ "56": [0, 0.64444, 0, 0, 0.5],
+ "57": [0, 0.64444, 0, 0, 0.5],
+ "58": [0, 0.43056, 0, 0, 0.27778],
+ "59": [0.19444, 0.43056, 0, 0, 0.27778],
+ "60": [0.0391, 0.5391, 0, 0, 0.77778],
+ "61": [-0.13313, 0.36687, 0, 0, 0.77778],
+ "62": [0.0391, 0.5391, 0, 0, 0.77778],
+ "63": [0, 0.69444, 0, 0, 0.47222],
+ "64": [0, 0.69444, 0, 0, 0.77778],
+ "65": [0, 0.68333, 0, 0, 0.75],
+ "66": [0, 0.68333, 0, 0, 0.70834],
+ "67": [0, 0.68333, 0, 0, 0.72222],
+ "68": [0, 0.68333, 0, 0, 0.76389],
+ "69": [0, 0.68333, 0, 0, 0.68056],
+ "70": [0, 0.68333, 0, 0, 0.65278],
+ "71": [0, 0.68333, 0, 0, 0.78472],
+ "72": [0, 0.68333, 0, 0, 0.75],
+ "73": [0, 0.68333, 0, 0, 0.36111],
+ "74": [0, 0.68333, 0, 0, 0.51389],
+ "75": [0, 0.68333, 0, 0, 0.77778],
+ "76": [0, 0.68333, 0, 0, 0.625],
+ "77": [0, 0.68333, 0, 0, 0.91667],
+ "78": [0, 0.68333, 0, 0, 0.75],
+ "79": [0, 0.68333, 0, 0, 0.77778],
+ "80": [0, 0.68333, 0, 0, 0.68056],
+ "81": [0.19444, 0.68333, 0, 0, 0.77778],
+ "82": [0, 0.68333, 0, 0, 0.73611],
+ "83": [0, 0.68333, 0, 0, 0.55556],
+ "84": [0, 0.68333, 0, 0, 0.72222],
+ "85": [0, 0.68333, 0, 0, 0.75],
+ "86": [0, 0.68333, 0.01389, 0, 0.75],
+ "87": [0, 0.68333, 0.01389, 0, 1.02778],
+ "88": [0, 0.68333, 0, 0, 0.75],
+ "89": [0, 0.68333, 0.025, 0, 0.75],
+ "90": [0, 0.68333, 0, 0, 0.61111],
+ "91": [0.25, 0.75, 0, 0, 0.27778],
+ "92": [0.25, 0.75, 0, 0, 0.5],
+ "93": [0.25, 0.75, 0, 0, 0.27778],
+ "94": [0, 0.69444, 0, 0, 0.5],
+ "95": [0.31, 0.12056, 0.02778, 0, 0.5],
+ "97": [0, 0.43056, 0, 0, 0.5],
+ "98": [0, 0.69444, 0, 0, 0.55556],
+ "99": [0, 0.43056, 0, 0, 0.44445],
+ "100": [0, 0.69444, 0, 0, 0.55556],
+ "101": [0, 0.43056, 0, 0, 0.44445],
+ "102": [0, 0.69444, 0.07778, 0, 0.30556],
+ "103": [0.19444, 0.43056, 0.01389, 0, 0.5],
+ "104": [0, 0.69444, 0, 0, 0.55556],
+ "105": [0, 0.66786, 0, 0, 0.27778],
+ "106": [0.19444, 0.66786, 0, 0, 0.30556],
+ "107": [0, 0.69444, 0, 0, 0.52778],
+ "108": [0, 0.69444, 0, 0, 0.27778],
+ "109": [0, 0.43056, 0, 0, 0.83334],
+ "110": [0, 0.43056, 0, 0, 0.55556],
+ "111": [0, 0.43056, 0, 0, 0.5],
+ "112": [0.19444, 0.43056, 0, 0, 0.55556],
+ "113": [0.19444, 0.43056, 0, 0, 0.52778],
+ "114": [0, 0.43056, 0, 0, 0.39167],
+ "115": [0, 0.43056, 0, 0, 0.39445],
+ "116": [0, 0.61508, 0, 0, 0.38889],
+ "117": [0, 0.43056, 0, 0, 0.55556],
+ "118": [0, 0.43056, 0.01389, 0, 0.52778],
+ "119": [0, 0.43056, 0.01389, 0, 0.72222],
+ "120": [0, 0.43056, 0, 0, 0.52778],
+ "121": [0.19444, 0.43056, 0.01389, 0, 0.52778],
+ "122": [0, 0.43056, 0, 0, 0.44445],
+ "123": [0.25, 0.75, 0, 0, 0.5],
+ "124": [0.25, 0.75, 0, 0, 0.27778],
+ "125": [0.25, 0.75, 0, 0, 0.5],
+ "126": [0.35, 0.31786, 0, 0, 0.5],
+ "160": [0, 0, 0, 0, 0.25],
+ "163": [0, 0.69444, 0, 0, 0.76909],
+ "167": [0.19444, 0.69444, 0, 0, 0.44445],
+ "168": [0, 0.66786, 0, 0, 0.5],
+ "172": [0, 0.43056, 0, 0, 0.66667],
+ "176": [0, 0.69444, 0, 0, 0.75],
+ "177": [0.08333, 0.58333, 0, 0, 0.77778],
+ "182": [0.19444, 0.69444, 0, 0, 0.61111],
+ "184": [0.17014, 0, 0, 0, 0.44445],
+ "198": [0, 0.68333, 0, 0, 0.90278],
+ "215": [0.08333, 0.58333, 0, 0, 0.77778],
+ "216": [0.04861, 0.73194, 0, 0, 0.77778],
+ "223": [0, 0.69444, 0, 0, 0.5],
+ "230": [0, 0.43056, 0, 0, 0.72222],
+ "247": [0.08333, 0.58333, 0, 0, 0.77778],
+ "248": [0.09722, 0.52778, 0, 0, 0.5],
+ "305": [0, 0.43056, 0, 0, 0.27778],
+ "338": [0, 0.68333, 0, 0, 1.01389],
+ "339": [0, 0.43056, 0, 0, 0.77778],
+ "567": [0.19444, 0.43056, 0, 0, 0.30556],
+ "710": [0, 0.69444, 0, 0, 0.5],
+ "711": [0, 0.62847, 0, 0, 0.5],
+ "713": [0, 0.56778, 0, 0, 0.5],
+ "714": [0, 0.69444, 0, 0, 0.5],
+ "715": [0, 0.69444, 0, 0, 0.5],
+ "728": [0, 0.69444, 0, 0, 0.5],
+ "729": [0, 0.66786, 0, 0, 0.27778],
+ "730": [0, 0.69444, 0, 0, 0.75],
+ "732": [0, 0.66786, 0, 0, 0.5],
+ "733": [0, 0.69444, 0, 0, 0.5],
+ "915": [0, 0.68333, 0, 0, 0.625],
+ "916": [0, 0.68333, 0, 0, 0.83334],
+ "920": [0, 0.68333, 0, 0, 0.77778],
+ "923": [0, 0.68333, 0, 0, 0.69445],
+ "926": [0, 0.68333, 0, 0, 0.66667],
+ "928": [0, 0.68333, 0, 0, 0.75],
+ "931": [0, 0.68333, 0, 0, 0.72222],
+ "933": [0, 0.68333, 0, 0, 0.77778],
+ "934": [0, 0.68333, 0, 0, 0.72222],
+ "936": [0, 0.68333, 0, 0, 0.77778],
+ "937": [0, 0.68333, 0, 0, 0.72222],
+ "8211": [0, 0.43056, 0.02778, 0, 0.5],
+ "8212": [0, 0.43056, 0.02778, 0, 1.0],
+ "8216": [0, 0.69444, 0, 0, 0.27778],
+ "8217": [0, 0.69444, 0, 0, 0.27778],
+ "8220": [0, 0.69444, 0, 0, 0.5],
+ "8221": [0, 0.69444, 0, 0, 0.5],
+ "8224": [0.19444, 0.69444, 0, 0, 0.44445],
+ "8225": [0.19444, 0.69444, 0, 0, 0.44445],
+ "8230": [0, 0.123, 0, 0, 1.172],
+ "8242": [0, 0.55556, 0, 0, 0.275],
+ "8407": [0, 0.71444, 0.15382, 0, 0.5],
+ "8463": [0, 0.68889, 0, 0, 0.54028],
+ "8465": [0, 0.69444, 0, 0, 0.72222],
+ "8467": [0, 0.69444, 0, 0.11111, 0.41667],
+ "8472": [0.19444, 0.43056, 0, 0.11111, 0.63646],
+ "8476": [0, 0.69444, 0, 0, 0.72222],
+ "8501": [0, 0.69444, 0, 0, 0.61111],
+ "8592": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8593": [0.19444, 0.69444, 0, 0, 0.5],
+ "8594": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8595": [0.19444, 0.69444, 0, 0, 0.5],
+ "8596": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8597": [0.25, 0.75, 0, 0, 0.5],
+ "8598": [0.19444, 0.69444, 0, 0, 1.0],
+ "8599": [0.19444, 0.69444, 0, 0, 1.0],
+ "8600": [0.19444, 0.69444, 0, 0, 1.0],
+ "8601": [0.19444, 0.69444, 0, 0, 1.0],
+ "8614": [0.011, 0.511, 0, 0, 1.0],
+ "8617": [0.011, 0.511, 0, 0, 1.126],
+ "8618": [0.011, 0.511, 0, 0, 1.126],
+ "8636": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8637": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8640": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8641": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8652": [0.011, 0.671, 0, 0, 1.0],
+ "8656": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8657": [0.19444, 0.69444, 0, 0, 0.61111],
+ "8658": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8659": [0.19444, 0.69444, 0, 0, 0.61111],
+ "8660": [-0.13313, 0.36687, 0, 0, 1.0],
+ "8661": [0.25, 0.75, 0, 0, 0.61111],
+ "8704": [0, 0.69444, 0, 0, 0.55556],
+ "8706": [0, 0.69444, 0.05556, 0.08334, 0.5309],
+ "8707": [0, 0.69444, 0, 0, 0.55556],
+ "8709": [0.05556, 0.75, 0, 0, 0.5],
+ "8711": [0, 0.68333, 0, 0, 0.83334],
+ "8712": [0.0391, 0.5391, 0, 0, 0.66667],
+ "8715": [0.0391, 0.5391, 0, 0, 0.66667],
+ "8722": [0.08333, 0.58333, 0, 0, 0.77778],
+ "8723": [0.08333, 0.58333, 0, 0, 0.77778],
+ "8725": [0.25, 0.75, 0, 0, 0.5],
+ "8726": [0.25, 0.75, 0, 0, 0.5],
+ "8727": [-0.03472, 0.46528, 0, 0, 0.5],
+ "8728": [-0.05555, 0.44445, 0, 0, 0.5],
+ "8729": [-0.05555, 0.44445, 0, 0, 0.5],
+ "8730": [0.2, 0.8, 0, 0, 0.83334],
+ "8733": [0, 0.43056, 0, 0, 0.77778],
+ "8734": [0, 0.43056, 0, 0, 1.0],
+ "8736": [0, 0.69224, 0, 0, 0.72222],
+ "8739": [0.25, 0.75, 0, 0, 0.27778],
+ "8741": [0.25, 0.75, 0, 0, 0.5],
+ "8743": [0, 0.55556, 0, 0, 0.66667],
+ "8744": [0, 0.55556, 0, 0, 0.66667],
+ "8745": [0, 0.55556, 0, 0, 0.66667],
+ "8746": [0, 0.55556, 0, 0, 0.66667],
+ "8747": [0.19444, 0.69444, 0.11111, 0, 0.41667],
+ "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
+ "8768": [0.19444, 0.69444, 0, 0, 0.27778],
+ "8771": [-0.03625, 0.46375, 0, 0, 0.77778],
+ "8773": [-0.022, 0.589, 0, 0, 0.778],
+ "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
+ "8781": [-0.03625, 0.46375, 0, 0, 0.77778],
+ "8784": [-0.133, 0.673, 0, 0, 0.778],
+ "8801": [-0.03625, 0.46375, 0, 0, 0.77778],
+ "8804": [0.13597, 0.63597, 0, 0, 0.77778],
+ "8805": [0.13597, 0.63597, 0, 0, 0.77778],
+ "8810": [0.0391, 0.5391, 0, 0, 1.0],
+ "8811": [0.0391, 0.5391, 0, 0, 1.0],
+ "8826": [0.0391, 0.5391, 0, 0, 0.77778],
+ "8827": [0.0391, 0.5391, 0, 0, 0.77778],
+ "8834": [0.0391, 0.5391, 0, 0, 0.77778],
+ "8835": [0.0391, 0.5391, 0, 0, 0.77778],
+ "8838": [0.13597, 0.63597, 0, 0, 0.77778],
+ "8839": [0.13597, 0.63597, 0, 0, 0.77778],
+ "8846": [0, 0.55556, 0, 0, 0.66667],
+ "8849": [0.13597, 0.63597, 0, 0, 0.77778],
+ "8850": [0.13597, 0.63597, 0, 0, 0.77778],
+ "8851": [0, 0.55556, 0, 0, 0.66667],
+ "8852": [0, 0.55556, 0, 0, 0.66667],
+ "8853": [0.08333, 0.58333, 0, 0, 0.77778],
+ "8854": [0.08333, 0.58333, 0, 0, 0.77778],
+ "8855": [0.08333, 0.58333, 0, 0, 0.77778],
+ "8856": [0.08333, 0.58333, 0, 0, 0.77778],
+ "8857": [0.08333, 0.58333, 0, 0, 0.77778],
+ "8866": [0, 0.69444, 0, 0, 0.61111],
+ "8867": [0, 0.69444, 0, 0, 0.61111],
+ "8868": [0, 0.69444, 0, 0, 0.77778],
+ "8869": [0, 0.69444, 0, 0, 0.77778],
+ "8872": [0.249, 0.75, 0, 0, 0.867],
+ "8900": [-0.05555, 0.44445, 0, 0, 0.5],
+ "8901": [-0.05555, 0.44445, 0, 0, 0.27778],
+ "8902": [-0.03472, 0.46528, 0, 0, 0.5],
+ "8904": [0.005, 0.505, 0, 0, 0.9],
+ "8942": [0.03, 0.903, 0, 0, 0.278],
+ "8943": [-0.19, 0.313, 0, 0, 1.172],
+ "8945": [-0.1, 0.823, 0, 0, 1.282],
+ "8968": [0.25, 0.75, 0, 0, 0.44445],
+ "8969": [0.25, 0.75, 0, 0, 0.44445],
+ "8970": [0.25, 0.75, 0, 0, 0.44445],
+ "8971": [0.25, 0.75, 0, 0, 0.44445],
+ "8994": [-0.14236, 0.35764, 0, 0, 1.0],
+ "8995": [-0.14236, 0.35764, 0, 0, 1.0],
+ "9136": [0.244, 0.744, 0, 0, 0.412],
+ "9137": [0.244, 0.745, 0, 0, 0.412],
+ "9651": [0.19444, 0.69444, 0, 0, 0.88889],
+ "9657": [-0.03472, 0.46528, 0, 0, 0.5],
+ "9661": [0.19444, 0.69444, 0, 0, 0.88889],
+ "9667": [-0.03472, 0.46528, 0, 0, 0.5],
+ "9711": [0.19444, 0.69444, 0, 0, 1.0],
+ "9824": [0.12963, 0.69444, 0, 0, 0.77778],
+ "9825": [0.12963, 0.69444, 0, 0, 0.77778],
+ "9826": [0.12963, 0.69444, 0, 0, 0.77778],
+ "9827": [0.12963, 0.69444, 0, 0, 0.77778],
+ "9837": [0, 0.75, 0, 0, 0.38889],
+ "9838": [0.19444, 0.69444, 0, 0, 0.38889],
+ "9839": [0.19444, 0.69444, 0, 0, 0.38889],
+ "10216": [0.25, 0.75, 0, 0, 0.38889],
+ "10217": [0.25, 0.75, 0, 0, 0.38889],
+ "10222": [0.244, 0.744, 0, 0, 0.412],
+ "10223": [0.244, 0.745, 0, 0, 0.412],
+ "10229": [0.011, 0.511, 0, 0, 1.609],
+ "10230": [0.011, 0.511, 0, 0, 1.638],
+ "10231": [0.011, 0.511, 0, 0, 1.859],
+ "10232": [0.024, 0.525, 0, 0, 1.609],
+ "10233": [0.024, 0.525, 0, 0, 1.638],
+ "10234": [0.024, 0.525, 0, 0, 1.858],
+ "10236": [0.011, 0.511, 0, 0, 1.638],
+ "10815": [0, 0.68333, 0, 0, 0.75],
+ "10927": [0.13597, 0.63597, 0, 0, 0.77778],
+ "10928": [0.13597, 0.63597, 0, 0, 0.77778],
+ "57376": [0.19444, 0.69444, 0, 0, 0]
+ },
+ "Math-BoldItalic": {
+ "32": [0, 0, 0, 0, 0.25],
+ "48": [0, 0.44444, 0, 0, 0.575],
+ "49": [0, 0.44444, 0, 0, 0.575],
+ "50": [0, 0.44444, 0, 0, 0.575],
+ "51": [0.19444, 0.44444, 0, 0, 0.575],
+ "52": [0.19444, 0.44444, 0, 0, 0.575],
+ "53": [0.19444, 0.44444, 0, 0, 0.575],
+ "54": [0, 0.64444, 0, 0, 0.575],
+ "55": [0.19444, 0.44444, 0, 0, 0.575],
+ "56": [0, 0.64444, 0, 0, 0.575],
+ "57": [0.19444, 0.44444, 0, 0, 0.575],
+ "65": [0, 0.68611, 0, 0, 0.86944],
+ "66": [0, 0.68611, 0.04835, 0, 0.8664],
+ "67": [0, 0.68611, 0.06979, 0, 0.81694],
+ "68": [0, 0.68611, 0.03194, 0, 0.93812],
+ "69": [0, 0.68611, 0.05451, 0, 0.81007],
+ "70": [0, 0.68611, 0.15972, 0, 0.68889],
+ "71": [0, 0.68611, 0, 0, 0.88673],
+ "72": [0, 0.68611, 0.08229, 0, 0.98229],
+ "73": [0, 0.68611, 0.07778, 0, 0.51111],
+ "74": [0, 0.68611, 0.10069, 0, 0.63125],
+ "75": [0, 0.68611, 0.06979, 0, 0.97118],
+ "76": [0, 0.68611, 0, 0, 0.75555],
+ "77": [0, 0.68611, 0.11424, 0, 1.14201],
+ "78": [0, 0.68611, 0.11424, 0, 0.95034],
+ "79": [0, 0.68611, 0.03194, 0, 0.83666],
+ "80": [0, 0.68611, 0.15972, 0, 0.72309],
+ "81": [0.19444, 0.68611, 0, 0, 0.86861],
+ "82": [0, 0.68611, 0.00421, 0, 0.87235],
+ "83": [0, 0.68611, 0.05382, 0, 0.69271],
+ "84": [0, 0.68611, 0.15972, 0, 0.63663],
+ "85": [0, 0.68611, 0.11424, 0, 0.80027],
+ "86": [0, 0.68611, 0.25555, 0, 0.67778],
+ "87": [0, 0.68611, 0.15972, 0, 1.09305],
+ "88": [0, 0.68611, 0.07778, 0, 0.94722],
+ "89": [0, 0.68611, 0.25555, 0, 0.67458],
+ "90": [0, 0.68611, 0.06979, 0, 0.77257],
+ "97": [0, 0.44444, 0, 0, 0.63287],
+ "98": [0, 0.69444, 0, 0, 0.52083],
+ "99": [0, 0.44444, 0, 0, 0.51342],
+ "100": [0, 0.69444, 0, 0, 0.60972],
+ "101": [0, 0.44444, 0, 0, 0.55361],
+ "102": [0.19444, 0.69444, 0.11042, 0, 0.56806],
+ "103": [0.19444, 0.44444, 0.03704, 0, 0.5449],
+ "104": [0, 0.69444, 0, 0, 0.66759],
+ "105": [0, 0.69326, 0, 0, 0.4048],
+ "106": [0.19444, 0.69326, 0.0622, 0, 0.47083],
+ "107": [0, 0.69444, 0.01852, 0, 0.6037],
+ "108": [0, 0.69444, 0.0088, 0, 0.34815],
+ "109": [0, 0.44444, 0, 0, 1.0324],
+ "110": [0, 0.44444, 0, 0, 0.71296],
+ "111": [0, 0.44444, 0, 0, 0.58472],
+ "112": [0.19444, 0.44444, 0, 0, 0.60092],
+ "113": [0.19444, 0.44444, 0.03704, 0, 0.54213],
+ "114": [0, 0.44444, 0.03194, 0, 0.5287],
+ "115": [0, 0.44444, 0, 0, 0.53125],
+ "116": [0, 0.63492, 0, 0, 0.41528],
+ "117": [0, 0.44444, 0, 0, 0.68102],
+ "118": [0, 0.44444, 0.03704, 0, 0.56666],
+ "119": [0, 0.44444, 0.02778, 0, 0.83148],
+ "120": [0, 0.44444, 0, 0, 0.65903],
+ "121": [0.19444, 0.44444, 0.03704, 0, 0.59028],
+ "122": [0, 0.44444, 0.04213, 0, 0.55509],
+ "160": [0, 0, 0, 0, 0.25],
+ "915": [0, 0.68611, 0.15972, 0, 0.65694],
+ "916": [0, 0.68611, 0, 0, 0.95833],
+ "920": [0, 0.68611, 0.03194, 0, 0.86722],
+ "923": [0, 0.68611, 0, 0, 0.80555],
+ "926": [0, 0.68611, 0.07458, 0, 0.84125],
+ "928": [0, 0.68611, 0.08229, 0, 0.98229],
+ "931": [0, 0.68611, 0.05451, 0, 0.88507],
+ "933": [0, 0.68611, 0.15972, 0, 0.67083],
+ "934": [0, 0.68611, 0, 0, 0.76666],
+ "936": [0, 0.68611, 0.11653, 0, 0.71402],
+ "937": [0, 0.68611, 0.04835, 0, 0.8789],
+ "945": [0, 0.44444, 0, 0, 0.76064],
+ "946": [0.19444, 0.69444, 0.03403, 0, 0.65972],
+ "947": [0.19444, 0.44444, 0.06389, 0, 0.59003],
+ "948": [0, 0.69444, 0.03819, 0, 0.52222],
+ "949": [0, 0.44444, 0, 0, 0.52882],
+ "950": [0.19444, 0.69444, 0.06215, 0, 0.50833],
+ "951": [0.19444, 0.44444, 0.03704, 0, 0.6],
+ "952": [0, 0.69444, 0.03194, 0, 0.5618],
+ "953": [0, 0.44444, 0, 0, 0.41204],
+ "954": [0, 0.44444, 0, 0, 0.66759],
+ "955": [0, 0.69444, 0, 0, 0.67083],
+ "956": [0.19444, 0.44444, 0, 0, 0.70787],
+ "957": [0, 0.44444, 0.06898, 0, 0.57685],
+ "958": [0.19444, 0.69444, 0.03021, 0, 0.50833],
+ "959": [0, 0.44444, 0, 0, 0.58472],
+ "960": [0, 0.44444, 0.03704, 0, 0.68241],
+ "961": [0.19444, 0.44444, 0, 0, 0.6118],
+ "962": [0.09722, 0.44444, 0.07917, 0, 0.42361],
+ "963": [0, 0.44444, 0.03704, 0, 0.68588],
+ "964": [0, 0.44444, 0.13472, 0, 0.52083],
+ "965": [0, 0.44444, 0.03704, 0, 0.63055],
+ "966": [0.19444, 0.44444, 0, 0, 0.74722],
+ "967": [0.19444, 0.44444, 0, 0, 0.71805],
+ "968": [0.19444, 0.69444, 0.03704, 0, 0.75833],
+ "969": [0, 0.44444, 0.03704, 0, 0.71782],
+ "977": [0, 0.69444, 0, 0, 0.69155],
+ "981": [0.19444, 0.69444, 0, 0, 0.7125],
+ "982": [0, 0.44444, 0.03194, 0, 0.975],
+ "1009": [0.19444, 0.44444, 0, 0, 0.6118],
+ "1013": [0, 0.44444, 0, 0, 0.48333],
+ "57649": [0, 0.44444, 0, 0, 0.39352],
+ "57911": [0.19444, 0.44444, 0, 0, 0.43889]
+ },
+ "Math-Italic": {
+ "32": [0, 0, 0, 0, 0.25],
+ "48": [0, 0.43056, 0, 0, 0.5],
+ "49": [0, 0.43056, 0, 0, 0.5],
+ "50": [0, 0.43056, 0, 0, 0.5],
+ "51": [0.19444, 0.43056, 0, 0, 0.5],
+ "52": [0.19444, 0.43056, 0, 0, 0.5],
+ "53": [0.19444, 0.43056, 0, 0, 0.5],
+ "54": [0, 0.64444, 0, 0, 0.5],
+ "55": [0.19444, 0.43056, 0, 0, 0.5],
+ "56": [0, 0.64444, 0, 0, 0.5],
+ "57": [0.19444, 0.43056, 0, 0, 0.5],
+ "65": [0, 0.68333, 0, 0.13889, 0.75],
+ "66": [0, 0.68333, 0.05017, 0.08334, 0.75851],
+ "67": [0, 0.68333, 0.07153, 0.08334, 0.71472],
+ "68": [0, 0.68333, 0.02778, 0.05556, 0.82792],
+ "69": [0, 0.68333, 0.05764, 0.08334, 0.7382],
+ "70": [0, 0.68333, 0.13889, 0.08334, 0.64306],
+ "71": [0, 0.68333, 0, 0.08334, 0.78625],
+ "72": [0, 0.68333, 0.08125, 0.05556, 0.83125],
+ "73": [0, 0.68333, 0.07847, 0.11111, 0.43958],
+ "74": [0, 0.68333, 0.09618, 0.16667, 0.55451],
+ "75": [0, 0.68333, 0.07153, 0.05556, 0.84931],
+ "76": [0, 0.68333, 0, 0.02778, 0.68056],
+ "77": [0, 0.68333, 0.10903, 0.08334, 0.97014],
+ "78": [0, 0.68333, 0.10903, 0.08334, 0.80347],
+ "79": [0, 0.68333, 0.02778, 0.08334, 0.76278],
+ "80": [0, 0.68333, 0.13889, 0.08334, 0.64201],
+ "81": [0.19444, 0.68333, 0, 0.08334, 0.79056],
+ "82": [0, 0.68333, 0.00773, 0.08334, 0.75929],
+ "83": [0, 0.68333, 0.05764, 0.08334, 0.6132],
+ "84": [0, 0.68333, 0.13889, 0.08334, 0.58438],
+ "85": [0, 0.68333, 0.10903, 0.02778, 0.68278],
+ "86": [0, 0.68333, 0.22222, 0, 0.58333],
+ "87": [0, 0.68333, 0.13889, 0, 0.94445],
+ "88": [0, 0.68333, 0.07847, 0.08334, 0.82847],
+ "89": [0, 0.68333, 0.22222, 0, 0.58056],
+ "90": [0, 0.68333, 0.07153, 0.08334, 0.68264],
+ "97": [0, 0.43056, 0, 0, 0.52859],
+ "98": [0, 0.69444, 0, 0, 0.42917],
+ "99": [0, 0.43056, 0, 0.05556, 0.43276],
+ "100": [0, 0.69444, 0, 0.16667, 0.52049],
+ "101": [0, 0.43056, 0, 0.05556, 0.46563],
+ "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959],
+ "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697],
+ "104": [0, 0.69444, 0, 0, 0.57616],
+ "105": [0, 0.65952, 0, 0, 0.34451],
+ "106": [0.19444, 0.65952, 0.05724, 0, 0.41181],
+ "107": [0, 0.69444, 0.03148, 0, 0.5206],
+ "108": [0, 0.69444, 0.01968, 0.08334, 0.29838],
+ "109": [0, 0.43056, 0, 0, 0.87801],
+ "110": [0, 0.43056, 0, 0, 0.60023],
+ "111": [0, 0.43056, 0, 0.05556, 0.48472],
+ "112": [0.19444, 0.43056, 0, 0.08334, 0.50313],
+ "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641],
+ "114": [0, 0.43056, 0.02778, 0.05556, 0.45116],
+ "115": [0, 0.43056, 0, 0.05556, 0.46875],
+ "116": [0, 0.61508, 0, 0.08334, 0.36111],
+ "117": [0, 0.43056, 0, 0.02778, 0.57246],
+ "118": [0, 0.43056, 0.03588, 0.02778, 0.48472],
+ "119": [0, 0.43056, 0.02691, 0.08334, 0.71592],
+ "120": [0, 0.43056, 0, 0.02778, 0.57153],
+ "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028],
+ "122": [0, 0.43056, 0.04398, 0.05556, 0.46505],
+ "160": [0, 0, 0, 0, 0.25],
+ "915": [0, 0.68333, 0.13889, 0.08334, 0.61528],
+ "916": [0, 0.68333, 0, 0.16667, 0.83334],
+ "920": [0, 0.68333, 0.02778, 0.08334, 0.76278],
+ "923": [0, 0.68333, 0, 0.16667, 0.69445],
+ "926": [0, 0.68333, 0.07569, 0.08334, 0.74236],
+ "928": [0, 0.68333, 0.08125, 0.05556, 0.83125],
+ "931": [0, 0.68333, 0.05764, 0.08334, 0.77986],
+ "933": [0, 0.68333, 0.13889, 0.05556, 0.58333],
+ "934": [0, 0.68333, 0, 0.08334, 0.66667],
+ "936": [0, 0.68333, 0.11, 0.05556, 0.61222],
+ "937": [0, 0.68333, 0.05017, 0.08334, 0.7724],
+ "945": [0, 0.43056, 0.0037, 0.02778, 0.6397],
+ "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563],
+ "947": [0.19444, 0.43056, 0.05556, 0, 0.51773],
+ "948": [0, 0.69444, 0.03785, 0.05556, 0.44444],
+ "949": [0, 0.43056, 0, 0.08334, 0.46632],
+ "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375],
+ "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653],
+ "952": [0, 0.69444, 0.02778, 0.08334, 0.46944],
+ "953": [0, 0.43056, 0, 0.05556, 0.35394],
+ "954": [0, 0.43056, 0, 0, 0.57616],
+ "955": [0, 0.69444, 0, 0, 0.58334],
+ "956": [0.19444, 0.43056, 0, 0.02778, 0.60255],
+ "957": [0, 0.43056, 0.06366, 0.02778, 0.49398],
+ "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375],
+ "959": [0, 0.43056, 0, 0.05556, 0.48472],
+ "960": [0, 0.43056, 0.03588, 0, 0.57003],
+ "961": [0.19444, 0.43056, 0, 0.08334, 0.51702],
+ "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285],
+ "963": [0, 0.43056, 0.03588, 0, 0.57141],
+ "964": [0, 0.43056, 0.1132, 0.02778, 0.43715],
+ "965": [0, 0.43056, 0.03588, 0.02778, 0.54028],
+ "966": [0.19444, 0.43056, 0, 0.08334, 0.65417],
+ "967": [0.19444, 0.43056, 0, 0.05556, 0.62569],
+ "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139],
+ "969": [0, 0.43056, 0.03588, 0, 0.62245],
+ "977": [0, 0.69444, 0, 0.08334, 0.59144],
+ "981": [0.19444, 0.69444, 0, 0.08334, 0.59583],
+ "982": [0, 0.43056, 0.02778, 0, 0.82813],
+ "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702],
+ "1013": [0, 0.43056, 0, 0.05556, 0.4059],
+ "57649": [0, 0.43056, 0, 0.02778, 0.32246],
+ "57911": [0.19444, 0.43056, 0, 0.08334, 0.38403]
+ },
+ "SansSerif-Bold": {
+ "32": [0, 0, 0, 0, 0.25],
+ "33": [0, 0.69444, 0, 0, 0.36667],
+ "34": [0, 0.69444, 0, 0, 0.55834],
+ "35": [0.19444, 0.69444, 0, 0, 0.91667],
+ "36": [0.05556, 0.75, 0, 0, 0.55],
+ "37": [0.05556, 0.75, 0, 0, 1.02912],
+ "38": [0, 0.69444, 0, 0, 0.83056],
+ "39": [0, 0.69444, 0, 0, 0.30556],
+ "40": [0.25, 0.75, 0, 0, 0.42778],
+ "41": [0.25, 0.75, 0, 0, 0.42778],
+ "42": [0, 0.75, 0, 0, 0.55],
+ "43": [0.11667, 0.61667, 0, 0, 0.85556],
+ "44": [0.10556, 0.13056, 0, 0, 0.30556],
+ "45": [0, 0.45833, 0, 0, 0.36667],
+ "46": [0, 0.13056, 0, 0, 0.30556],
+ "47": [0.25, 0.75, 0, 0, 0.55],
+ "48": [0, 0.69444, 0, 0, 0.55],
+ "49": [0, 0.69444, 0, 0, 0.55],
+ "50": [0, 0.69444, 0, 0, 0.55],
+ "51": [0, 0.69444, 0, 0, 0.55],
+ "52": [0, 0.69444, 0, 0, 0.55],
+ "53": [0, 0.69444, 0, 0, 0.55],
+ "54": [0, 0.69444, 0, 0, 0.55],
+ "55": [0, 0.69444, 0, 0, 0.55],
+ "56": [0, 0.69444, 0, 0, 0.55],
+ "57": [0, 0.69444, 0, 0, 0.55],
+ "58": [0, 0.45833, 0, 0, 0.30556],
+ "59": [0.10556, 0.45833, 0, 0, 0.30556],
+ "61": [-0.09375, 0.40625, 0, 0, 0.85556],
+ "63": [0, 0.69444, 0, 0, 0.51945],
+ "64": [0, 0.69444, 0, 0, 0.73334],
+ "65": [0, 0.69444, 0, 0, 0.73334],
+ "66": [0, 0.69444, 0, 0, 0.73334],
+ "67": [0, 0.69444, 0, 0, 0.70278],
+ "68": [0, 0.69444, 0, 0, 0.79445],
+ "69": [0, 0.69444, 0, 0, 0.64167],
+ "70": [0, 0.69444, 0, 0, 0.61111],
+ "71": [0, 0.69444, 0, 0, 0.73334],
+ "72": [0, 0.69444, 0, 0, 0.79445],
+ "73": [0, 0.69444, 0, 0, 0.33056],
+ "74": [0, 0.69444, 0, 0, 0.51945],
+ "75": [0, 0.69444, 0, 0, 0.76389],
+ "76": [0, 0.69444, 0, 0, 0.58056],
+ "77": [0, 0.69444, 0, 0, 0.97778],
+ "78": [0, 0.69444, 0, 0, 0.79445],
+ "79": [0, 0.69444, 0, 0, 0.79445],
+ "80": [0, 0.69444, 0, 0, 0.70278],
+ "81": [0.10556, 0.69444, 0, 0, 0.79445],
+ "82": [0, 0.69444, 0, 0, 0.70278],
+ "83": [0, 0.69444, 0, 0, 0.61111],
+ "84": [0, 0.69444, 0, 0, 0.73334],
+ "85": [0, 0.69444, 0, 0, 0.76389],
+ "86": [0, 0.69444, 0.01528, 0, 0.73334],
+ "87": [0, 0.69444, 0.01528, 0, 1.03889],
+ "88": [0, 0.69444, 0, 0, 0.73334],
+ "89": [0, 0.69444, 0.0275, 0, 0.73334],
+ "90": [0, 0.69444, 0, 0, 0.67223],
+ "91": [0.25, 0.75, 0, 0, 0.34306],
+ "93": [0.25, 0.75, 0, 0, 0.34306],
+ "94": [0, 0.69444, 0, 0, 0.55],
+ "95": [0.35, 0.10833, 0.03056, 0, 0.55],
+ "97": [0, 0.45833, 0, 0, 0.525],
+ "98": [0, 0.69444, 0, 0, 0.56111],
+ "99": [0, 0.45833, 0, 0, 0.48889],
+ "100": [0, 0.69444, 0, 0, 0.56111],
+ "101": [0, 0.45833, 0, 0, 0.51111],
+ "102": [0, 0.69444, 0.07639, 0, 0.33611],
+ "103": [0.19444, 0.45833, 0.01528, 0, 0.55],
+ "104": [0, 0.69444, 0, 0, 0.56111],
+ "105": [0, 0.69444, 0, 0, 0.25556],
+ "106": [0.19444, 0.69444, 0, 0, 0.28611],
+ "107": [0, 0.69444, 0, 0, 0.53056],
+ "108": [0, 0.69444, 0, 0, 0.25556],
+ "109": [0, 0.45833, 0, 0, 0.86667],
+ "110": [0, 0.45833, 0, 0, 0.56111],
+ "111": [0, 0.45833, 0, 0, 0.55],
+ "112": [0.19444, 0.45833, 0, 0, 0.56111],
+ "113": [0.19444, 0.45833, 0, 0, 0.56111],
+ "114": [0, 0.45833, 0.01528, 0, 0.37222],
+ "115": [0, 0.45833, 0, 0, 0.42167],
+ "116": [0, 0.58929, 0, 0, 0.40417],
+ "117": [0, 0.45833, 0, 0, 0.56111],
+ "118": [0, 0.45833, 0.01528, 0, 0.5],
+ "119": [0, 0.45833, 0.01528, 0, 0.74445],
+ "120": [0, 0.45833, 0, 0, 0.5],
+ "121": [0.19444, 0.45833, 0.01528, 0, 0.5],
+ "122": [0, 0.45833, 0, 0, 0.47639],
+ "126": [0.35, 0.34444, 0, 0, 0.55],
+ "160": [0, 0, 0, 0, 0.25],
+ "168": [0, 0.69444, 0, 0, 0.55],
+ "176": [0, 0.69444, 0, 0, 0.73334],
+ "180": [0, 0.69444, 0, 0, 0.55],
+ "184": [0.17014, 0, 0, 0, 0.48889],
+ "305": [0, 0.45833, 0, 0, 0.25556],
+ "567": [0.19444, 0.45833, 0, 0, 0.28611],
+ "710": [0, 0.69444, 0, 0, 0.55],
+ "711": [0, 0.63542, 0, 0, 0.55],
+ "713": [0, 0.63778, 0, 0, 0.55],
+ "728": [0, 0.69444, 0, 0, 0.55],
+ "729": [0, 0.69444, 0, 0, 0.30556],
+ "730": [0, 0.69444, 0, 0, 0.73334],
+ "732": [0, 0.69444, 0, 0, 0.55],
+ "733": [0, 0.69444, 0, 0, 0.55],
+ "915": [0, 0.69444, 0, 0, 0.58056],
+ "916": [0, 0.69444, 0, 0, 0.91667],
+ "920": [0, 0.69444, 0, 0, 0.85556],
+ "923": [0, 0.69444, 0, 0, 0.67223],
+ "926": [0, 0.69444, 0, 0, 0.73334],
+ "928": [0, 0.69444, 0, 0, 0.79445],
+ "931": [0, 0.69444, 0, 0, 0.79445],
+ "933": [0, 0.69444, 0, 0, 0.85556],
+ "934": [0, 0.69444, 0, 0, 0.79445],
+ "936": [0, 0.69444, 0, 0, 0.85556],
+ "937": [0, 0.69444, 0, 0, 0.79445],
+ "8211": [0, 0.45833, 0.03056, 0, 0.55],
+ "8212": [0, 0.45833, 0.03056, 0, 1.10001],
+ "8216": [0, 0.69444, 0, 0, 0.30556],
+ "8217": [0, 0.69444, 0, 0, 0.30556],
+ "8220": [0, 0.69444, 0, 0, 0.55834],
+ "8221": [0, 0.69444, 0, 0, 0.55834]
+ },
+ "SansSerif-Italic": {
+ "32": [0, 0, 0, 0, 0.25],
+ "33": [0, 0.69444, 0.05733, 0, 0.31945],
+ "34": [0, 0.69444, 0.00316, 0, 0.5],
+ "35": [0.19444, 0.69444, 0.05087, 0, 0.83334],
+ "36": [0.05556, 0.75, 0.11156, 0, 0.5],
+ "37": [0.05556, 0.75, 0.03126, 0, 0.83334],
+ "38": [0, 0.69444, 0.03058, 0, 0.75834],
+ "39": [0, 0.69444, 0.07816, 0, 0.27778],
+ "40": [0.25, 0.75, 0.13164, 0, 0.38889],
+ "41": [0.25, 0.75, 0.02536, 0, 0.38889],
+ "42": [0, 0.75, 0.11775, 0, 0.5],
+ "43": [0.08333, 0.58333, 0.02536, 0, 0.77778],
+ "44": [0.125, 0.08333, 0, 0, 0.27778],
+ "45": [0, 0.44444, 0.01946, 0, 0.33333],
+ "46": [0, 0.08333, 0, 0, 0.27778],
+ "47": [0.25, 0.75, 0.13164, 0, 0.5],
+ "48": [0, 0.65556, 0.11156, 0, 0.5],
+ "49": [0, 0.65556, 0.11156, 0, 0.5],
+ "50": [0, 0.65556, 0.11156, 0, 0.5],
+ "51": [0, 0.65556, 0.11156, 0, 0.5],
+ "52": [0, 0.65556, 0.11156, 0, 0.5],
+ "53": [0, 0.65556, 0.11156, 0, 0.5],
+ "54": [0, 0.65556, 0.11156, 0, 0.5],
+ "55": [0, 0.65556, 0.11156, 0, 0.5],
+ "56": [0, 0.65556, 0.11156, 0, 0.5],
+ "57": [0, 0.65556, 0.11156, 0, 0.5],
+ "58": [0, 0.44444, 0.02502, 0, 0.27778],
+ "59": [0.125, 0.44444, 0.02502, 0, 0.27778],
+ "61": [-0.13, 0.37, 0.05087, 0, 0.77778],
+ "63": [0, 0.69444, 0.11809, 0, 0.47222],
+ "64": [0, 0.69444, 0.07555, 0, 0.66667],
+ "65": [0, 0.69444, 0, 0, 0.66667],
+ "66": [0, 0.69444, 0.08293, 0, 0.66667],
+ "67": [0, 0.69444, 0.11983, 0, 0.63889],
+ "68": [0, 0.69444, 0.07555, 0, 0.72223],
+ "69": [0, 0.69444, 0.11983, 0, 0.59722],
+ "70": [0, 0.69444, 0.13372, 0, 0.56945],
+ "71": [0, 0.69444, 0.11983, 0, 0.66667],
+ "72": [0, 0.69444, 0.08094, 0, 0.70834],
+ "73": [0, 0.69444, 0.13372, 0, 0.27778],
+ "74": [0, 0.69444, 0.08094, 0, 0.47222],
+ "75": [0, 0.69444, 0.11983, 0, 0.69445],
+ "76": [0, 0.69444, 0, 0, 0.54167],
+ "77": [0, 0.69444, 0.08094, 0, 0.875],
+ "78": [0, 0.69444, 0.08094, 0, 0.70834],
+ "79": [0, 0.69444, 0.07555, 0, 0.73611],
+ "80": [0, 0.69444, 0.08293, 0, 0.63889],
+ "81": [0.125, 0.69444, 0.07555, 0, 0.73611],
+ "82": [0, 0.69444, 0.08293, 0, 0.64584],
+ "83": [0, 0.69444, 0.09205, 0, 0.55556],
+ "84": [0, 0.69444, 0.13372, 0, 0.68056],
+ "85": [0, 0.69444, 0.08094, 0, 0.6875],
+ "86": [0, 0.69444, 0.1615, 0, 0.66667],
+ "87": [0, 0.69444, 0.1615, 0, 0.94445],
+ "88": [0, 0.69444, 0.13372, 0, 0.66667],
+ "89": [0, 0.69444, 0.17261, 0, 0.66667],
+ "90": [0, 0.69444, 0.11983, 0, 0.61111],
+ "91": [0.25, 0.75, 0.15942, 0, 0.28889],
+ "93": [0.25, 0.75, 0.08719, 0, 0.28889],
+ "94": [0, 0.69444, 0.0799, 0, 0.5],
+ "95": [0.35, 0.09444, 0.08616, 0, 0.5],
+ "97": [0, 0.44444, 0.00981, 0, 0.48056],
+ "98": [0, 0.69444, 0.03057, 0, 0.51667],
+ "99": [0, 0.44444, 0.08336, 0, 0.44445],
+ "100": [0, 0.69444, 0.09483, 0, 0.51667],
+ "101": [0, 0.44444, 0.06778, 0, 0.44445],
+ "102": [0, 0.69444, 0.21705, 0, 0.30556],
+ "103": [0.19444, 0.44444, 0.10836, 0, 0.5],
+ "104": [0, 0.69444, 0.01778, 0, 0.51667],
+ "105": [0, 0.67937, 0.09718, 0, 0.23889],
+ "106": [0.19444, 0.67937, 0.09162, 0, 0.26667],
+ "107": [0, 0.69444, 0.08336, 0, 0.48889],
+ "108": [0, 0.69444, 0.09483, 0, 0.23889],
+ "109": [0, 0.44444, 0.01778, 0, 0.79445],
+ "110": [0, 0.44444, 0.01778, 0, 0.51667],
+ "111": [0, 0.44444, 0.06613, 0, 0.5],
+ "112": [0.19444, 0.44444, 0.0389, 0, 0.51667],
+ "113": [0.19444, 0.44444, 0.04169, 0, 0.51667],
+ "114": [0, 0.44444, 0.10836, 0, 0.34167],
+ "115": [0, 0.44444, 0.0778, 0, 0.38333],
+ "116": [0, 0.57143, 0.07225, 0, 0.36111],
+ "117": [0, 0.44444, 0.04169, 0, 0.51667],
+ "118": [0, 0.44444, 0.10836, 0, 0.46111],
+ "119": [0, 0.44444, 0.10836, 0, 0.68334],
+ "120": [0, 0.44444, 0.09169, 0, 0.46111],
+ "121": [0.19444, 0.44444, 0.10836, 0, 0.46111],
+ "122": [0, 0.44444, 0.08752, 0, 0.43472],
+ "126": [0.35, 0.32659, 0.08826, 0, 0.5],
+ "160": [0, 0, 0, 0, 0.25],
+ "168": [0, 0.67937, 0.06385, 0, 0.5],
+ "176": [0, 0.69444, 0, 0, 0.73752],
+ "184": [0.17014, 0, 0, 0, 0.44445],
+ "305": [0, 0.44444, 0.04169, 0, 0.23889],
+ "567": [0.19444, 0.44444, 0.04169, 0, 0.26667],
+ "710": [0, 0.69444, 0.0799, 0, 0.5],
+ "711": [0, 0.63194, 0.08432, 0, 0.5],
+ "713": [0, 0.60889, 0.08776, 0, 0.5],
+ "714": [0, 0.69444, 0.09205, 0, 0.5],
+ "715": [0, 0.69444, 0, 0, 0.5],
+ "728": [0, 0.69444, 0.09483, 0, 0.5],
+ "729": [0, 0.67937, 0.07774, 0, 0.27778],
+ "730": [0, 0.69444, 0, 0, 0.73752],
+ "732": [0, 0.67659, 0.08826, 0, 0.5],
+ "733": [0, 0.69444, 0.09205, 0, 0.5],
+ "915": [0, 0.69444, 0.13372, 0, 0.54167],
+ "916": [0, 0.69444, 0, 0, 0.83334],
+ "920": [0, 0.69444, 0.07555, 0, 0.77778],
+ "923": [0, 0.69444, 0, 0, 0.61111],
+ "926": [0, 0.69444, 0.12816, 0, 0.66667],
+ "928": [0, 0.69444, 0.08094, 0, 0.70834],
+ "931": [0, 0.69444, 0.11983, 0, 0.72222],
+ "933": [0, 0.69444, 0.09031, 0, 0.77778],
+ "934": [0, 0.69444, 0.04603, 0, 0.72222],
+ "936": [0, 0.69444, 0.09031, 0, 0.77778],
+ "937": [0, 0.69444, 0.08293, 0, 0.72222],
+ "8211": [0, 0.44444, 0.08616, 0, 0.5],
+ "8212": [0, 0.44444, 0.08616, 0, 1.0],
+ "8216": [0, 0.69444, 0.07816, 0, 0.27778],
+ "8217": [0, 0.69444, 0.07816, 0, 0.27778],
+ "8220": [0, 0.69444, 0.14205, 0, 0.5],
+ "8221": [0, 0.69444, 0.00316, 0, 0.5]
+ },
+ "SansSerif-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "33": [0, 0.69444, 0, 0, 0.31945],
+ "34": [0, 0.69444, 0, 0, 0.5],
+ "35": [0.19444, 0.69444, 0, 0, 0.83334],
+ "36": [0.05556, 0.75, 0, 0, 0.5],
+ "37": [0.05556, 0.75, 0, 0, 0.83334],
+ "38": [0, 0.69444, 0, 0, 0.75834],
+ "39": [0, 0.69444, 0, 0, 0.27778],
+ "40": [0.25, 0.75, 0, 0, 0.38889],
+ "41": [0.25, 0.75, 0, 0, 0.38889],
+ "42": [0, 0.75, 0, 0, 0.5],
+ "43": [0.08333, 0.58333, 0, 0, 0.77778],
+ "44": [0.125, 0.08333, 0, 0, 0.27778],
+ "45": [0, 0.44444, 0, 0, 0.33333],
+ "46": [0, 0.08333, 0, 0, 0.27778],
+ "47": [0.25, 0.75, 0, 0, 0.5],
+ "48": [0, 0.65556, 0, 0, 0.5],
+ "49": [0, 0.65556, 0, 0, 0.5],
+ "50": [0, 0.65556, 0, 0, 0.5],
+ "51": [0, 0.65556, 0, 0, 0.5],
+ "52": [0, 0.65556, 0, 0, 0.5],
+ "53": [0, 0.65556, 0, 0, 0.5],
+ "54": [0, 0.65556, 0, 0, 0.5],
+ "55": [0, 0.65556, 0, 0, 0.5],
+ "56": [0, 0.65556, 0, 0, 0.5],
+ "57": [0, 0.65556, 0, 0, 0.5],
+ "58": [0, 0.44444, 0, 0, 0.27778],
+ "59": [0.125, 0.44444, 0, 0, 0.27778],
+ "61": [-0.13, 0.37, 0, 0, 0.77778],
+ "63": [0, 0.69444, 0, 0, 0.47222],
+ "64": [0, 0.69444, 0, 0, 0.66667],
+ "65": [0, 0.69444, 0, 0, 0.66667],
+ "66": [0, 0.69444, 0, 0, 0.66667],
+ "67": [0, 0.69444, 0, 0, 0.63889],
+ "68": [0, 0.69444, 0, 0, 0.72223],
+ "69": [0, 0.69444, 0, 0, 0.59722],
+ "70": [0, 0.69444, 0, 0, 0.56945],
+ "71": [0, 0.69444, 0, 0, 0.66667],
+ "72": [0, 0.69444, 0, 0, 0.70834],
+ "73": [0, 0.69444, 0, 0, 0.27778],
+ "74": [0, 0.69444, 0, 0, 0.47222],
+ "75": [0, 0.69444, 0, 0, 0.69445],
+ "76": [0, 0.69444, 0, 0, 0.54167],
+ "77": [0, 0.69444, 0, 0, 0.875],
+ "78": [0, 0.69444, 0, 0, 0.70834],
+ "79": [0, 0.69444, 0, 0, 0.73611],
+ "80": [0, 0.69444, 0, 0, 0.63889],
+ "81": [0.125, 0.69444, 0, 0, 0.73611],
+ "82": [0, 0.69444, 0, 0, 0.64584],
+ "83": [0, 0.69444, 0, 0, 0.55556],
+ "84": [0, 0.69444, 0, 0, 0.68056],
+ "85": [0, 0.69444, 0, 0, 0.6875],
+ "86": [0, 0.69444, 0.01389, 0, 0.66667],
+ "87": [0, 0.69444, 0.01389, 0, 0.94445],
+ "88": [0, 0.69444, 0, 0, 0.66667],
+ "89": [0, 0.69444, 0.025, 0, 0.66667],
+ "90": [0, 0.69444, 0, 0, 0.61111],
+ "91": [0.25, 0.75, 0, 0, 0.28889],
+ "93": [0.25, 0.75, 0, 0, 0.28889],
+ "94": [0, 0.69444, 0, 0, 0.5],
+ "95": [0.35, 0.09444, 0.02778, 0, 0.5],
+ "97": [0, 0.44444, 0, 0, 0.48056],
+ "98": [0, 0.69444, 0, 0, 0.51667],
+ "99": [0, 0.44444, 0, 0, 0.44445],
+ "100": [0, 0.69444, 0, 0, 0.51667],
+ "101": [0, 0.44444, 0, 0, 0.44445],
+ "102": [0, 0.69444, 0.06944, 0, 0.30556],
+ "103": [0.19444, 0.44444, 0.01389, 0, 0.5],
+ "104": [0, 0.69444, 0, 0, 0.51667],
+ "105": [0, 0.67937, 0, 0, 0.23889],
+ "106": [0.19444, 0.67937, 0, 0, 0.26667],
+ "107": [0, 0.69444, 0, 0, 0.48889],
+ "108": [0, 0.69444, 0, 0, 0.23889],
+ "109": [0, 0.44444, 0, 0, 0.79445],
+ "110": [0, 0.44444, 0, 0, 0.51667],
+ "111": [0, 0.44444, 0, 0, 0.5],
+ "112": [0.19444, 0.44444, 0, 0, 0.51667],
+ "113": [0.19444, 0.44444, 0, 0, 0.51667],
+ "114": [0, 0.44444, 0.01389, 0, 0.34167],
+ "115": [0, 0.44444, 0, 0, 0.38333],
+ "116": [0, 0.57143, 0, 0, 0.36111],
+ "117": [0, 0.44444, 0, 0, 0.51667],
+ "118": [0, 0.44444, 0.01389, 0, 0.46111],
+ "119": [0, 0.44444, 0.01389, 0, 0.68334],
+ "120": [0, 0.44444, 0, 0, 0.46111],
+ "121": [0.19444, 0.44444, 0.01389, 0, 0.46111],
+ "122": [0, 0.44444, 0, 0, 0.43472],
+ "126": [0.35, 0.32659, 0, 0, 0.5],
+ "160": [0, 0, 0, 0, 0.25],
+ "168": [0, 0.67937, 0, 0, 0.5],
+ "176": [0, 0.69444, 0, 0, 0.66667],
+ "184": [0.17014, 0, 0, 0, 0.44445],
+ "305": [0, 0.44444, 0, 0, 0.23889],
+ "567": [0.19444, 0.44444, 0, 0, 0.26667],
+ "710": [0, 0.69444, 0, 0, 0.5],
+ "711": [0, 0.63194, 0, 0, 0.5],
+ "713": [0, 0.60889, 0, 0, 0.5],
+ "714": [0, 0.69444, 0, 0, 0.5],
+ "715": [0, 0.69444, 0, 0, 0.5],
+ "728": [0, 0.69444, 0, 0, 0.5],
+ "729": [0, 0.67937, 0, 0, 0.27778],
+ "730": [0, 0.69444, 0, 0, 0.66667],
+ "732": [0, 0.67659, 0, 0, 0.5],
+ "733": [0, 0.69444, 0, 0, 0.5],
+ "915": [0, 0.69444, 0, 0, 0.54167],
+ "916": [0, 0.69444, 0, 0, 0.83334],
+ "920": [0, 0.69444, 0, 0, 0.77778],
+ "923": [0, 0.69444, 0, 0, 0.61111],
+ "926": [0, 0.69444, 0, 0, 0.66667],
+ "928": [0, 0.69444, 0, 0, 0.70834],
+ "931": [0, 0.69444, 0, 0, 0.72222],
+ "933": [0, 0.69444, 0, 0, 0.77778],
+ "934": [0, 0.69444, 0, 0, 0.72222],
+ "936": [0, 0.69444, 0, 0, 0.77778],
+ "937": [0, 0.69444, 0, 0, 0.72222],
+ "8211": [0, 0.44444, 0.02778, 0, 0.5],
+ "8212": [0, 0.44444, 0.02778, 0, 1.0],
+ "8216": [0, 0.69444, 0, 0, 0.27778],
+ "8217": [0, 0.69444, 0, 0, 0.27778],
+ "8220": [0, 0.69444, 0, 0, 0.5],
+ "8221": [0, 0.69444, 0, 0, 0.5]
+ },
+ "Script-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "65": [0, 0.7, 0.22925, 0, 0.80253],
+ "66": [0, 0.7, 0.04087, 0, 0.90757],
+ "67": [0, 0.7, 0.1689, 0, 0.66619],
+ "68": [0, 0.7, 0.09371, 0, 0.77443],
+ "69": [0, 0.7, 0.18583, 0, 0.56162],
+ "70": [0, 0.7, 0.13634, 0, 0.89544],
+ "71": [0, 0.7, 0.17322, 0, 0.60961],
+ "72": [0, 0.7, 0.29694, 0, 0.96919],
+ "73": [0, 0.7, 0.19189, 0, 0.80907],
+ "74": [0.27778, 0.7, 0.19189, 0, 1.05159],
+ "75": [0, 0.7, 0.31259, 0, 0.91364],
+ "76": [0, 0.7, 0.19189, 0, 0.87373],
+ "77": [0, 0.7, 0.15981, 0, 1.08031],
+ "78": [0, 0.7, 0.3525, 0, 0.9015],
+ "79": [0, 0.7, 0.08078, 0, 0.73787],
+ "80": [0, 0.7, 0.08078, 0, 1.01262],
+ "81": [0, 0.7, 0.03305, 0, 0.88282],
+ "82": [0, 0.7, 0.06259, 0, 0.85],
+ "83": [0, 0.7, 0.19189, 0, 0.86767],
+ "84": [0, 0.7, 0.29087, 0, 0.74697],
+ "85": [0, 0.7, 0.25815, 0, 0.79996],
+ "86": [0, 0.7, 0.27523, 0, 0.62204],
+ "87": [0, 0.7, 0.27523, 0, 0.80532],
+ "88": [0, 0.7, 0.26006, 0, 0.94445],
+ "89": [0, 0.7, 0.2939, 0, 0.70961],
+ "90": [0, 0.7, 0.24037, 0, 0.8212],
+ "160": [0, 0, 0, 0, 0.25]
+ },
+ "Size1-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "40": [0.35001, 0.85, 0, 0, 0.45834],
+ "41": [0.35001, 0.85, 0, 0, 0.45834],
+ "47": [0.35001, 0.85, 0, 0, 0.57778],
+ "91": [0.35001, 0.85, 0, 0, 0.41667],
+ "92": [0.35001, 0.85, 0, 0, 0.57778],
+ "93": [0.35001, 0.85, 0, 0, 0.41667],
+ "123": [0.35001, 0.85, 0, 0, 0.58334],
+ "125": [0.35001, 0.85, 0, 0, 0.58334],
+ "160": [0, 0, 0, 0, 0.25],
+ "710": [0, 0.72222, 0, 0, 0.55556],
+ "732": [0, 0.72222, 0, 0, 0.55556],
+ "770": [0, 0.72222, 0, 0, 0.55556],
+ "771": [0, 0.72222, 0, 0, 0.55556],
+ "8214": [-0.00099, 0.601, 0, 0, 0.77778],
+ "8593": [1e-05, 0.6, 0, 0, 0.66667],
+ "8595": [1e-05, 0.6, 0, 0, 0.66667],
+ "8657": [1e-05, 0.6, 0, 0, 0.77778],
+ "8659": [1e-05, 0.6, 0, 0, 0.77778],
+ "8719": [0.25001, 0.75, 0, 0, 0.94445],
+ "8720": [0.25001, 0.75, 0, 0, 0.94445],
+ "8721": [0.25001, 0.75, 0, 0, 1.05556],
+ "8730": [0.35001, 0.85, 0, 0, 1.0],
+ "8739": [-0.00599, 0.606, 0, 0, 0.33333],
+ "8741": [-0.00599, 0.606, 0, 0, 0.55556],
+ "8747": [0.30612, 0.805, 0.19445, 0, 0.47222],
+ "8748": [0.306, 0.805, 0.19445, 0, 0.47222],
+ "8749": [0.306, 0.805, 0.19445, 0, 0.47222],
+ "8750": [0.30612, 0.805, 0.19445, 0, 0.47222],
+ "8896": [0.25001, 0.75, 0, 0, 0.83334],
+ "8897": [0.25001, 0.75, 0, 0, 0.83334],
+ "8898": [0.25001, 0.75, 0, 0, 0.83334],
+ "8899": [0.25001, 0.75, 0, 0, 0.83334],
+ "8968": [0.35001, 0.85, 0, 0, 0.47222],
+ "8969": [0.35001, 0.85, 0, 0, 0.47222],
+ "8970": [0.35001, 0.85, 0, 0, 0.47222],
+ "8971": [0.35001, 0.85, 0, 0, 0.47222],
+ "9168": [-0.00099, 0.601, 0, 0, 0.66667],
+ "10216": [0.35001, 0.85, 0, 0, 0.47222],
+ "10217": [0.35001, 0.85, 0, 0, 0.47222],
+ "10752": [0.25001, 0.75, 0, 0, 1.11111],
+ "10753": [0.25001, 0.75, 0, 0, 1.11111],
+ "10754": [0.25001, 0.75, 0, 0, 1.11111],
+ "10756": [0.25001, 0.75, 0, 0, 0.83334],
+ "10758": [0.25001, 0.75, 0, 0, 0.83334]
+ },
+ "Size2-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "40": [0.65002, 1.15, 0, 0, 0.59722],
+ "41": [0.65002, 1.15, 0, 0, 0.59722],
+ "47": [0.65002, 1.15, 0, 0, 0.81111],
+ "91": [0.65002, 1.15, 0, 0, 0.47222],
+ "92": [0.65002, 1.15, 0, 0, 0.81111],
+ "93": [0.65002, 1.15, 0, 0, 0.47222],
+ "123": [0.65002, 1.15, 0, 0, 0.66667],
+ "125": [0.65002, 1.15, 0, 0, 0.66667],
+ "160": [0, 0, 0, 0, 0.25],
+ "710": [0, 0.75, 0, 0, 1.0],
+ "732": [0, 0.75, 0, 0, 1.0],
+ "770": [0, 0.75, 0, 0, 1.0],
+ "771": [0, 0.75, 0, 0, 1.0],
+ "8719": [0.55001, 1.05, 0, 0, 1.27778],
+ "8720": [0.55001, 1.05, 0, 0, 1.27778],
+ "8721": [0.55001, 1.05, 0, 0, 1.44445],
+ "8730": [0.65002, 1.15, 0, 0, 1.0],
+ "8747": [0.86225, 1.36, 0.44445, 0, 0.55556],
+ "8748": [0.862, 1.36, 0.44445, 0, 0.55556],
+ "8749": [0.862, 1.36, 0.44445, 0, 0.55556],
+ "8750": [0.86225, 1.36, 0.44445, 0, 0.55556],
+ "8896": [0.55001, 1.05, 0, 0, 1.11111],
+ "8897": [0.55001, 1.05, 0, 0, 1.11111],
+ "8898": [0.55001, 1.05, 0, 0, 1.11111],
+ "8899": [0.55001, 1.05, 0, 0, 1.11111],
+ "8968": [0.65002, 1.15, 0, 0, 0.52778],
+ "8969": [0.65002, 1.15, 0, 0, 0.52778],
+ "8970": [0.65002, 1.15, 0, 0, 0.52778],
+ "8971": [0.65002, 1.15, 0, 0, 0.52778],
+ "10216": [0.65002, 1.15, 0, 0, 0.61111],
+ "10217": [0.65002, 1.15, 0, 0, 0.61111],
+ "10752": [0.55001, 1.05, 0, 0, 1.51112],
+ "10753": [0.55001, 1.05, 0, 0, 1.51112],
+ "10754": [0.55001, 1.05, 0, 0, 1.51112],
+ "10756": [0.55001, 1.05, 0, 0, 1.11111],
+ "10758": [0.55001, 1.05, 0, 0, 1.11111]
+ },
+ "Size3-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "40": [0.95003, 1.45, 0, 0, 0.73611],
+ "41": [0.95003, 1.45, 0, 0, 0.73611],
+ "47": [0.95003, 1.45, 0, 0, 1.04445],
+ "91": [0.95003, 1.45, 0, 0, 0.52778],
+ "92": [0.95003, 1.45, 0, 0, 1.04445],
+ "93": [0.95003, 1.45, 0, 0, 0.52778],
+ "123": [0.95003, 1.45, 0, 0, 0.75],
+ "125": [0.95003, 1.45, 0, 0, 0.75],
+ "160": [0, 0, 0, 0, 0.25],
+ "710": [0, 0.75, 0, 0, 1.44445],
+ "732": [0, 0.75, 0, 0, 1.44445],
+ "770": [0, 0.75, 0, 0, 1.44445],
+ "771": [0, 0.75, 0, 0, 1.44445],
+ "8730": [0.95003, 1.45, 0, 0, 1.0],
+ "8968": [0.95003, 1.45, 0, 0, 0.58334],
+ "8969": [0.95003, 1.45, 0, 0, 0.58334],
+ "8970": [0.95003, 1.45, 0, 0, 0.58334],
+ "8971": [0.95003, 1.45, 0, 0, 0.58334],
+ "10216": [0.95003, 1.45, 0, 0, 0.75],
+ "10217": [0.95003, 1.45, 0, 0, 0.75]
+ },
+ "Size4-Regular": {
+ "32": [0, 0, 0, 0, 0.25],
+ "40": [1.25003, 1.75, 0, 0, 0.79167],
+ "41": [1.25003, 1.75, 0, 0, 0.79167],
+ "47": [1.25003, 1.75, 0, 0, 1.27778],
+ "91": [1.25003, 1.75, 0, 0, 0.58334],
+ "92": [1.25003, 1.75, 0, 0, 1.27778],
+ "93": [1.25003, 1.75, 0, 0, 0.58334],
+ "123": [1.25003, 1.75, 0, 0, 0.80556],
+ "125": [1.25003, 1.75, 0, 0, 0.80556],
+ "160": [0, 0, 0, 0, 0.25],
+ "710": [0, 0.825, 0, 0, 1.8889],
+ "732": [0, 0.825, 0, 0, 1.8889],
+ "770": [0, 0.825, 0, 0, 1.8889],
+ "771": [0, 0.825, 0, 0, 1.8889],
+ "8730": [1.25003, 1.75, 0, 0, 1.0],
+ "8968": [1.25003, 1.75, 0, 0, 0.63889],
+ "8969": [1.25003, 1.75, 0, 0, 0.63889],
+ "8970": [1.25003, 1.75, 0, 0, 0.63889],
+ "8971": [1.25003, 1.75, 0, 0, 0.63889],
+ "9115": [0.64502, 1.155, 0, 0, 0.875],
+ "9116": [1e-05, 0.6, 0, 0, 0.875],
+ "9117": [0.64502, 1.155, 0, 0, 0.875],
+ "9118": [0.64502, 1.155, 0, 0, 0.875],
+ "9119": [1e-05, 0.6, 0, 0, 0.875],
+ "9120": [0.64502, 1.155, 0, 0, 0.875],
+ "9121": [0.64502, 1.155, 0, 0, 0.66667],
+ "9122": [-0.00099, 0.601, 0, 0, 0.66667],
+ "9123": [0.64502, 1.155, 0, 0, 0.66667],
+ "9124": [0.64502, 1.155, 0, 0, 0.66667],
+ "9125": [-0.00099, 0.601, 0, 0, 0.66667],
+ "9126": [0.64502, 1.155, 0, 0, 0.66667],
+ "9127": [1e-05, 0.9, 0, 0, 0.88889],
+ "9128": [0.65002, 1.15, 0, 0, 0.88889],
+ "9129": [0.90001, 0, 0, 0, 0.88889],
+ "9130": [0, 0.3, 0, 0, 0.88889],
+ "9131": [1e-05, 0.9, 0, 0, 0.88889],
+ "9132": [0.65002, 1.15, 0, 0, 0.88889],
+ "9133": [0.90001, 0, 0, 0, 0.88889],
+ "9143": [0.88502, 0.915, 0, 0, 1.05556],
+ "10216": [1.25003, 1.75, 0, 0, 0.80556],
+ "10217": [1.25003, 1.75, 0, 0, 0.80556],
+ "57344": [-0.00499, 0.605, 0, 0, 1.05556],
+ "57345": [-0.00499, 0.605, 0, 0, 1.05556],
+ "57680": [0, 0.12, 0, 0, 0.45],
+ "57681": [0, 0.12, 0, 0, 0.45],
+ "57682": [0, 0.12, 0, 0, 0.45],
+ "57683": [0, 0.12, 0, 0, 0.45]
+ },
+ "Typewriter-Regular": {
+ "32": [0, 0, 0, 0, 0.525],
+ "33": [0, 0.61111, 0, 0, 0.525],
+ "34": [0, 0.61111, 0, 0, 0.525],
+ "35": [0, 0.61111, 0, 0, 0.525],
+ "36": [0.08333, 0.69444, 0, 0, 0.525],
+ "37": [0.08333, 0.69444, 0, 0, 0.525],
+ "38": [0, 0.61111, 0, 0, 0.525],
+ "39": [0, 0.61111, 0, 0, 0.525],
+ "40": [0.08333, 0.69444, 0, 0, 0.525],
+ "41": [0.08333, 0.69444, 0, 0, 0.525],
+ "42": [0, 0.52083, 0, 0, 0.525],
+ "43": [-0.08056, 0.53055, 0, 0, 0.525],
+ "44": [0.13889, 0.125, 0, 0, 0.525],
+ "45": [-0.08056, 0.53055, 0, 0, 0.525],
+ "46": [0, 0.125, 0, 0, 0.525],
+ "47": [0.08333, 0.69444, 0, 0, 0.525],
+ "48": [0, 0.61111, 0, 0, 0.525],
+ "49": [0, 0.61111, 0, 0, 0.525],
+ "50": [0, 0.61111, 0, 0, 0.525],
+ "51": [0, 0.61111, 0, 0, 0.525],
+ "52": [0, 0.61111, 0, 0, 0.525],
+ "53": [0, 0.61111, 0, 0, 0.525],
+ "54": [0, 0.61111, 0, 0, 0.525],
+ "55": [0, 0.61111, 0, 0, 0.525],
+ "56": [0, 0.61111, 0, 0, 0.525],
+ "57": [0, 0.61111, 0, 0, 0.525],
+ "58": [0, 0.43056, 0, 0, 0.525],
+ "59": [0.13889, 0.43056, 0, 0, 0.525],
+ "60": [-0.05556, 0.55556, 0, 0, 0.525],
+ "61": [-0.19549, 0.41562, 0, 0, 0.525],
+ "62": [-0.05556, 0.55556, 0, 0, 0.525],
+ "63": [0, 0.61111, 0, 0, 0.525],
+ "64": [0, 0.61111, 0, 0, 0.525],
+ "65": [0, 0.61111, 0, 0, 0.525],
+ "66": [0, 0.61111, 0, 0, 0.525],
+ "67": [0, 0.61111, 0, 0, 0.525],
+ "68": [0, 0.61111, 0, 0, 0.525],
+ "69": [0, 0.61111, 0, 0, 0.525],
+ "70": [0, 0.61111, 0, 0, 0.525],
+ "71": [0, 0.61111, 0, 0, 0.525],
+ "72": [0, 0.61111, 0, 0, 0.525],
+ "73": [0, 0.61111, 0, 0, 0.525],
+ "74": [0, 0.61111, 0, 0, 0.525],
+ "75": [0, 0.61111, 0, 0, 0.525],
+ "76": [0, 0.61111, 0, 0, 0.525],
+ "77": [0, 0.61111, 0, 0, 0.525],
+ "78": [0, 0.61111, 0, 0, 0.525],
+ "79": [0, 0.61111, 0, 0, 0.525],
+ "80": [0, 0.61111, 0, 0, 0.525],
+ "81": [0.13889, 0.61111, 0, 0, 0.525],
+ "82": [0, 0.61111, 0, 0, 0.525],
+ "83": [0, 0.61111, 0, 0, 0.525],
+ "84": [0, 0.61111, 0, 0, 0.525],
+ "85": [0, 0.61111, 0, 0, 0.525],
+ "86": [0, 0.61111, 0, 0, 0.525],
+ "87": [0, 0.61111, 0, 0, 0.525],
+ "88": [0, 0.61111, 0, 0, 0.525],
+ "89": [0, 0.61111, 0, 0, 0.525],
+ "90": [0, 0.61111, 0, 0, 0.525],
+ "91": [0.08333, 0.69444, 0, 0, 0.525],
+ "92": [0.08333, 0.69444, 0, 0, 0.525],
+ "93": [0.08333, 0.69444, 0, 0, 0.525],
+ "94": [0, 0.61111, 0, 0, 0.525],
+ "95": [0.09514, 0, 0, 0, 0.525],
+ "96": [0, 0.61111, 0, 0, 0.525],
+ "97": [0, 0.43056, 0, 0, 0.525],
+ "98": [0, 0.61111, 0, 0, 0.525],
+ "99": [0, 0.43056, 0, 0, 0.525],
+ "100": [0, 0.61111, 0, 0, 0.525],
+ "101": [0, 0.43056, 0, 0, 0.525],
+ "102": [0, 0.61111, 0, 0, 0.525],
+ "103": [0.22222, 0.43056, 0, 0, 0.525],
+ "104": [0, 0.61111, 0, 0, 0.525],
+ "105": [0, 0.61111, 0, 0, 0.525],
+ "106": [0.22222, 0.61111, 0, 0, 0.525],
+ "107": [0, 0.61111, 0, 0, 0.525],
+ "108": [0, 0.61111, 0, 0, 0.525],
+ "109": [0, 0.43056, 0, 0, 0.525],
+ "110": [0, 0.43056, 0, 0, 0.525],
+ "111": [0, 0.43056, 0, 0, 0.525],
+ "112": [0.22222, 0.43056, 0, 0, 0.525],
+ "113": [0.22222, 0.43056, 0, 0, 0.525],
+ "114": [0, 0.43056, 0, 0, 0.525],
+ "115": [0, 0.43056, 0, 0, 0.525],
+ "116": [0, 0.55358, 0, 0, 0.525],
+ "117": [0, 0.43056, 0, 0, 0.525],
+ "118": [0, 0.43056, 0, 0, 0.525],
+ "119": [0, 0.43056, 0, 0, 0.525],
+ "120": [0, 0.43056, 0, 0, 0.525],
+ "121": [0.22222, 0.43056, 0, 0, 0.525],
+ "122": [0, 0.43056, 0, 0, 0.525],
+ "123": [0.08333, 0.69444, 0, 0, 0.525],
+ "124": [0.08333, 0.69444, 0, 0, 0.525],
+ "125": [0.08333, 0.69444, 0, 0, 0.525],
+ "126": [0, 0.61111, 0, 0, 0.525],
+ "127": [0, 0.61111, 0, 0, 0.525],
+ "160": [0, 0, 0, 0, 0.525],
+ "176": [0, 0.61111, 0, 0, 0.525],
+ "184": [0.19445, 0, 0, 0, 0.525],
+ "305": [0, 0.43056, 0, 0, 0.525],
+ "567": [0.22222, 0.43056, 0, 0, 0.525],
+ "711": [0, 0.56597, 0, 0, 0.525],
+ "713": [0, 0.56555, 0, 0, 0.525],
+ "714": [0, 0.61111, 0, 0, 0.525],
+ "715": [0, 0.61111, 0, 0, 0.525],
+ "728": [0, 0.61111, 0, 0, 0.525],
+ "730": [0, 0.61111, 0, 0, 0.525],
+ "770": [0, 0.61111, 0, 0, 0.525],
+ "771": [0, 0.61111, 0, 0, 0.525],
+ "776": [0, 0.61111, 0, 0, 0.525],
+ "915": [0, 0.61111, 0, 0, 0.525],
+ "916": [0, 0.61111, 0, 0, 0.525],
+ "920": [0, 0.61111, 0, 0, 0.525],
+ "923": [0, 0.61111, 0, 0, 0.525],
+ "926": [0, 0.61111, 0, 0, 0.525],
+ "928": [0, 0.61111, 0, 0, 0.525],
+ "931": [0, 0.61111, 0, 0, 0.525],
+ "933": [0, 0.61111, 0, 0, 0.525],
+ "934": [0, 0.61111, 0, 0, 0.525],
+ "936": [0, 0.61111, 0, 0, 0.525],
+ "937": [0, 0.61111, 0, 0, 0.525],
+ "8216": [0, 0.61111, 0, 0, 0.525],
+ "8217": [0, 0.61111, 0, 0, 0.525],
+ "8242": [0, 0.61111, 0, 0, 0.525],
+ "9251": [0.11111, 0.21944, 0, 0, 0.525]
+ }
+});
+;// ./src/fontMetrics.ts
+
+// This map contains a mapping from font name and character code to character
+// metrics, including height, depth, italic correction, and skew (kern from the
+// character to the corresponding \skewchar)
+// This map is generated via `make metrics`. It should not be changed manually.
+
+
+/**
+ * This file contains metrics regarding fonts and individual symbols. The sigma
+ * and xi variables, as well as the metricMap map contain data extracted from
+ * TeX, TeX font metrics, and the TTF files. These data are then exposed via the
+ * `metrics` variable and the getCharacterMetrics function.
+ */
+
+// In TeX, there are actually three sets of dimensions, one for each of
+// textstyle (size index 5 and higher: >=9pt), scriptstyle (size index 3 and 4:
+// 7-8pt), and scriptscriptstyle (size index 1 and 2: 5-6pt). These are
+// provided in the arrays below, in that order.
+//
+// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respectively.
+// This was determined by running the following script:
+//
+// latex -interaction=nonstopmode \
+// '\documentclass{article}\usepackage{amsmath}\begin{document}' \
+// '$a$ \expandafter\show\the\textfont2' \
+// '\expandafter\show\the\scriptfont2' \
+// '\expandafter\show\the\scriptscriptfont2' \
+// '\stop'
+//
+// The metrics themselves were retrieved using the following commands:
+//
+// tftopl cmsy10
+// tftopl cmsy7
+// tftopl cmsy5
+//
+// The output of each of these commands is quite lengthy. The only part we
+// care about is the FONTDIMEN section. Each value is measured in EMs.
+const sigmasAndXis = {
+ slant: [0.250, 0.250, 0.250],
+ // sigma1
+ space: [0.000, 0.000, 0.000],
+ // sigma2
+ stretch: [0.000, 0.000, 0.000],
+ // sigma3
+ shrink: [0.000, 0.000, 0.000],
+ // sigma4
+ xHeight: [0.431, 0.431, 0.431],
+ // sigma5
+ quad: [1.000, 1.171, 1.472],
+ // sigma6
+ extraSpace: [0.000, 0.000, 0.000],
+ // sigma7
+ num1: [0.677, 0.732, 0.925],
+ // sigma8
+ num2: [0.394, 0.384, 0.387],
+ // sigma9
+ num3: [0.444, 0.471, 0.504],
+ // sigma10
+ denom1: [0.686, 0.752, 1.025],
+ // sigma11
+ denom2: [0.345, 0.344, 0.532],
+ // sigma12
+ sup1: [0.413, 0.503, 0.504],
+ // sigma13
+ sup2: [0.363, 0.431, 0.404],
+ // sigma14
+ sup3: [0.289, 0.286, 0.294],
+ // sigma15
+ sub1: [0.150, 0.143, 0.200],
+ // sigma16
+ sub2: [0.247, 0.286, 0.400],
+ // sigma17
+ supDrop: [0.386, 0.353, 0.494],
+ // sigma18
+ subDrop: [0.050, 0.071, 0.100],
+ // sigma19
+ delim1: [2.390, 1.700, 1.980],
+ // sigma20
+ delim2: [1.010, 1.157, 1.420],
+ // sigma21
+ axisHeight: [0.250, 0.250, 0.250],
+ // sigma22
+
+ // These font metrics are extracted from TeX by using tftopl on cmex10.tfm;
+ // they correspond to the font parameters of the extension fonts (family 3).
+ // See the TeXbook, page 441. In AMSTeX, the extension fonts scale; to
+ // match cmex7, we'd use cmex7.tfm values for script and scriptscript
+ // values.
+ defaultRuleThickness: [0.04, 0.049, 0.049],
+ // xi8; cmex7: 0.049
+ bigOpSpacing1: [0.111, 0.111, 0.111],
+ // xi9
+ bigOpSpacing2: [0.166, 0.166, 0.166],
+ // xi10
+ bigOpSpacing3: [0.2, 0.2, 0.2],
+ // xi11
+ bigOpSpacing4: [0.6, 0.611, 0.611],
+ // xi12; cmex7: 0.611
+ bigOpSpacing5: [0.1, 0.143, 0.143],
+ // xi13; cmex7: 0.143
+
+ // The \sqrt rule width is taken from the height of the surd character.
+ // Since we use the same font at all sizes, this thickness doesn't scale.
+ sqrtRuleThickness: [0.04, 0.04, 0.04],
+ // This value determines how large a pt is, for metrics which are defined
+ // in terms of pts.
+ // This value is also used in katex.scss; if you change it make sure the
+ // values match.
+ ptPerEm: [10.0, 10.0, 10.0],
+ // The space between adjacent `|` columns in an array definition. From
+ // `\showthe\doublerulesep` in LaTeX. Equals 2.0 / ptPerEm.
+ doubleRuleSep: [0.2, 0.2, 0.2],
+ // The width of separator lines in {array} environments. From
+ // `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm.
+ arrayRuleWidth: [0.04, 0.04, 0.04],
+ // Two values from LaTeX source2e:
+ fboxsep: [0.3, 0.3, 0.3],
+ // 3 pt / ptPerEm
+ fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm
+};
+
+// These are very rough approximations. We default to Times New Roman which
+// should have Latin-1 and Cyrillic characters, but may not depending on the
+// operating system. The metrics do not account for extra height from the
+// accents. In the case of Cyrillic characters which have both ascenders and
+// descenders we prefer approximations with ascenders, primarily to prevent
+// the fraction bar or root line from intersecting the glyph.
+// TODO(kevinb) allow union of multiple glyph metrics for better accuracy.
+const extraCharacterMap = {
+ // Latin-1
+ 'Å': 'A',
+ 'Ð': 'D',
+ 'Þ': 'o',
+ 'å': 'a',
+ 'ð': 'd',
+ 'þ': 'o',
+ // Cyrillic
+ 'А': 'A',
+ 'Б': 'B',
+ 'В': 'B',
+ 'Г': 'F',
+ 'Д': 'A',
+ 'Е': 'E',
+ 'Ж': 'K',
+ 'З': '3',
+ 'И': 'N',
+ 'Й': 'N',
+ 'К': 'K',
+ 'Л': 'N',
+ 'М': 'M',
+ 'Н': 'H',
+ 'О': 'O',
+ 'П': 'N',
+ 'Р': 'P',
+ 'С': 'C',
+ 'Т': 'T',
+ 'У': 'y',
+ 'Ф': 'O',
+ 'Х': 'X',
+ 'Ц': 'U',
+ 'Ч': 'h',
+ 'Ш': 'W',
+ 'Щ': 'W',
+ 'Ъ': 'B',
+ 'Ы': 'X',
+ 'Ь': 'B',
+ 'Э': '3',
+ 'Ю': 'X',
+ 'Я': 'R',
+ 'а': 'a',
+ 'б': 'b',
+ 'в': 'a',
+ 'г': 'r',
+ 'д': 'y',
+ 'е': 'e',
+ 'ж': 'm',
+ 'з': 'e',
+ 'и': 'n',
+ 'й': 'n',
+ 'к': 'n',
+ 'л': 'n',
+ 'м': 'm',
+ 'н': 'n',
+ 'о': 'o',
+ 'п': 'n',
+ 'р': 'p',
+ 'с': 'c',
+ 'т': 'o',
+ 'у': 'y',
+ 'ф': 'b',
+ 'х': 'x',
+ 'ц': 'n',
+ 'ч': 'n',
+ 'ш': 'w',
+ 'щ': 'w',
+ 'ъ': 'a',
+ 'ы': 'm',
+ 'ь': 'a',
+ 'э': 'e',
+ 'ю': 'm',
+ 'я': 'r'
+};
+
+/**
+ * This function adds new font metrics to default metricMap
+ * It can also override existing metrics
+ */
+function setFontMetrics(fontName, metrics) {
+ fontMetricsData[fontName] = metrics;
+}
+
+/**
+ * This function is a convenience function for looking up information in the
+ * metricMap table. It takes a character as a string, and a font.
+ *
+ * Note: the `width` property may be undefined if fontMetricsData.js wasn't
+ * built using `Make extended_metrics`.
+ */
+function getCharacterMetrics(character, font, mode) {
+ if (!fontMetricsData[font]) {
+ throw new Error("Font metrics not found for font: " + font + ".");
+ }
+ let ch = character.charCodeAt(0);
+ let metrics = fontMetricsData[font][ch];
+ if (!metrics && character[0] in extraCharacterMap) {
+ ch = extraCharacterMap[character[0]].charCodeAt(0);
+ metrics = fontMetricsData[font][ch];
+ }
+ if (!metrics && mode === 'text') {
+ // We don't typically have font metrics for Asian scripts.
+ // But since we support them in text mode, we need to return
+ // some sort of metrics.
+ // So if the character is in a script we support but we
+ // don't have metrics for it, just use the metrics for
+ // the Latin capital letter M. This is close enough because
+ // we (currently) only care about the height of the glyph
+ // not its width.
+ if (supportedCodepoint(ch)) {
+ metrics = fontMetricsData[font][77]; // 77 is the charcode for 'M'
+ }
+ }
+ if (metrics) {
+ return {
+ depth: metrics[0],
+ height: metrics[1],
+ italic: metrics[2],
+ skew: metrics[3],
+ width: metrics[4]
+ };
+ }
+}
+const fontMetricsBySizeIndex = {};
+
+/**
+ * Get the font metrics for a given size.
+ */
+function getGlobalMetrics(size) {
+ let sizeIndex;
+ if (size >= 5) {
+ sizeIndex = 0;
+ } else if (size >= 3) {
+ sizeIndex = 1;
+ } else {
+ sizeIndex = 2;
+ }
+ if (!fontMetricsBySizeIndex[sizeIndex]) {
+ const metrics = fontMetricsBySizeIndex[sizeIndex] = {
+ cssEmPerMu: sigmasAndXis.quad[sizeIndex] / 18
+ };
+ for (const key of Object.keys(sigmasAndXis)) {
+ metrics[key] = sigmasAndXis[key][sizeIndex];
+ }
+ }
+ return fontMetricsBySizeIndex[sizeIndex];
+}
+;// ./src/symbols.ts
+/**
+ * This file holds a list of all no-argument functions and single-character
+ * symbols (like 'a' or ';').
+ *
+ * For each of the symbols, there are three properties they can have:
+ * - font (required): the font to be used for this symbol. Either "main" (the
+ normal font), or "ams" (the ams fonts).
+ * - group (required): the ParseNode group type the symbol should have (i.e.
+ "textord", "mathord", etc).
+ See https://github.com/KaTeX/KaTeX/wiki/Examining-TeX#group-types
+ * - replace: the character that this symbol or function should be
+ * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi
+ * character in the main font).
+ *
+ * The outermost map in the table indicates what mode the symbols should be
+ * accepted in (e.g. "math" or "text").
+ */
+
+// Some of these have a "-token" suffix since these are also used as `ParseNode`
+// types for raw text tokens, and we want to avoid conflicts with higher-level
+// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
+// looking up the `symbols` map.
+
+const symbols = {
+ "math": {},
+ "text": {}
+};
+/* harmony default export */ var src_symbols = (symbols);
+
+/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */
+function defineSymbol(mode, font, group, replace, name, acceptUnicodeChar) {
+ symbols[mode][name] = {
+ font,
+ group,
+ replace
+ };
+ if (acceptUnicodeChar && replace) {
+ symbols[mode][replace] = symbols[mode][name];
+ }
+}
+
+// Some abbreviations for commonly used strings.
+// This helps minify the code, and also spotting typos using jshint.
+
+// modes:
+const math = "math";
+const symbols_text = "text";
+
+// fonts:
+const main = "main";
+const ams = "ams";
+
+// groups:
+const accent = "accent-token";
+const bin = "bin";
+const symbols_close = "close";
+const inner = "inner";
+const mathord = "mathord";
+const op = "op-token";
+const symbols_open = "open";
+const punct = "punct";
+const rel = "rel";
+const spacing = "spacing";
+const textord = "textord";
+
+// Now comes the symbol table
+
+// Relation Symbols
+defineSymbol(math, main, rel, "\u2261", "\\equiv", true);
+defineSymbol(math, main, rel, "\u227a", "\\prec", true);
+defineSymbol(math, main, rel, "\u227b", "\\succ", true);
+defineSymbol(math, main, rel, "\u223c", "\\sim", true);
+defineSymbol(math, main, rel, "\u22a5", "\\perp");
+defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true);
+defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true);
+defineSymbol(math, main, rel, "\u2243", "\\simeq", true);
+defineSymbol(math, main, rel, "\u2223", "\\mid", true);
+defineSymbol(math, main, rel, "\u226a", "\\ll", true);
+defineSymbol(math, main, rel, "\u226b", "\\gg", true);
+defineSymbol(math, main, rel, "\u224d", "\\asymp", true);
+defineSymbol(math, main, rel, "\u2225", "\\parallel");
+defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true);
+defineSymbol(math, main, rel, "\u2323", "\\smile", true);
+defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true);
+defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true);
+defineSymbol(math, main, rel, "\u2250", "\\doteq", true);
+defineSymbol(math, main, rel, "\u2322", "\\frown", true);
+defineSymbol(math, main, rel, "\u220b", "\\ni", true);
+defineSymbol(math, main, rel, "\u221d", "\\propto", true);
+defineSymbol(math, main, rel, "\u22a2", "\\vdash", true);
+defineSymbol(math, main, rel, "\u22a3", "\\dashv", true);
+defineSymbol(math, main, rel, "\u220b", "\\owns");
+
+// Punctuation
+defineSymbol(math, main, punct, "\u002e", "\\ldotp");
+defineSymbol(math, main, punct, "\u22c5", "\\cdotp");
+// The KaTeX fonts do not contain U+00B7. Use the centered dot glyph at U+22C5
+// in both modes, but keep math-mode punctuation spacing only in math mode.
+defineSymbol(math, main, punct, "\u22c5", "\u00b7");
+defineSymbol(symbols_text, main, textord, "\u22c5", "\u00b7");
+
+// Misc Symbols
+defineSymbol(math, main, textord, "\u0023", "\\#");
+defineSymbol(symbols_text, main, textord, "\u0023", "\\#");
+defineSymbol(math, main, textord, "\u0026", "\\&");
+defineSymbol(symbols_text, main, textord, "\u0026", "\\&");
+defineSymbol(math, main, textord, "\u2135", "\\aleph", true);
+defineSymbol(math, main, textord, "\u2200", "\\forall", true);
+defineSymbol(math, main, textord, "\u210f", "\\hbar", true);
+defineSymbol(math, main, textord, "\u2203", "\\exists", true);
+defineSymbol(math, main, textord, "\u2207", "\\nabla", true);
+defineSymbol(math, main, textord, "\u266d", "\\flat", true);
+defineSymbol(math, main, textord, "\u2113", "\\ell", true);
+defineSymbol(math, main, textord, "\u266e", "\\natural", true);
+defineSymbol(math, main, textord, "\u2663", "\\clubsuit", true);
+defineSymbol(math, main, textord, "\u2118", "\\wp", true);
+defineSymbol(math, main, textord, "\u266f", "\\sharp", true);
+defineSymbol(math, main, textord, "\u2662", "\\diamondsuit", true);
+defineSymbol(math, main, textord, "\u211c", "\\Re", true);
+defineSymbol(math, main, textord, "\u2661", "\\heartsuit", true);
+defineSymbol(math, main, textord, "\u2111", "\\Im", true);
+defineSymbol(math, main, textord, "\u2660", "\\spadesuit", true);
+defineSymbol(math, main, textord, "\u00a7", "\\S", true);
+defineSymbol(symbols_text, main, textord, "\u00a7", "\\S");
+defineSymbol(math, main, textord, "\u00b6", "\\P", true);
+defineSymbol(symbols_text, main, textord, "\u00b6", "\\P");
+
+// Math and Text
+defineSymbol(math, main, textord, "\u2020", "\\dag");
+defineSymbol(symbols_text, main, textord, "\u2020", "\\dag");
+defineSymbol(symbols_text, main, textord, "\u2020", "\\textdagger");
+defineSymbol(math, main, textord, "\u2021", "\\ddag");
+defineSymbol(symbols_text, main, textord, "\u2021", "\\ddag");
+defineSymbol(symbols_text, main, textord, "\u2021", "\\textdaggerdbl");
+
+// Large Delimiters
+defineSymbol(math, main, symbols_close, "\u23b1", "\\rmoustache", true);
+defineSymbol(math, main, symbols_open, "\u23b0", "\\lmoustache", true);
+defineSymbol(math, main, symbols_close, "\u27ef", "\\rgroup", true);
+defineSymbol(math, main, symbols_open, "\u27ee", "\\lgroup", true);
+
+// Binary Operators
+defineSymbol(math, main, bin, "\u2213", "\\mp", true);
+defineSymbol(math, main, bin, "\u2296", "\\ominus", true);
+defineSymbol(math, main, bin, "\u228e", "\\uplus", true);
+defineSymbol(math, main, bin, "\u2293", "\\sqcap", true);
+defineSymbol(math, main, bin, "\u2217", "\\ast");
+defineSymbol(math, main, bin, "\u2294", "\\sqcup", true);
+defineSymbol(math, main, bin, "\u25ef", "\\bigcirc", true);
+defineSymbol(math, main, bin, "\u2219", "\\bullet", true);
+defineSymbol(math, main, bin, "\u2021", "\\ddagger");
+defineSymbol(math, main, bin, "\u2240", "\\wr", true);
+defineSymbol(math, main, bin, "\u2a3f", "\\amalg");
+defineSymbol(math, main, bin, "\u0026", "\\And"); // from amsmath
+
+// Arrow Symbols
+defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow", true);
+defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow", true);
+defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow", true);
+defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow", true);
+defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow", true);
+defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow", true);
+defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow", true);
+defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow", true);
+defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow", true);
+defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow", true);
+defineSymbol(math, main, rel, "\u21a6", "\\mapsto", true);
+defineSymbol(math, main, rel, "\u27fc", "\\longmapsto", true);
+defineSymbol(math, main, rel, "\u2197", "\\nearrow", true);
+defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow", true);
+defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow", true);
+defineSymbol(math, main, rel, "\u2198", "\\searrow", true);
+defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup", true);
+defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup", true);
+defineSymbol(math, main, rel, "\u2199", "\\swarrow", true);
+defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown", true);
+defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown", true);
+defineSymbol(math, main, rel, "\u2196", "\\nwarrow", true);
+defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons", true);
+
+// AMS Negated Binary Relations
+defineSymbol(math, ams, rel, "\u226e", "\\nless", true);
+// Symbol names preceded by "@" each have a corresponding macro.
+defineSymbol(math, ams, rel, "\ue010", "\\@nleqslant");
+defineSymbol(math, ams, rel, "\ue011", "\\@nleqq");
+defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true);
+defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true);
+defineSymbol(math, ams, rel, "\ue00c", "\\@lvertneqq");
+defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true);
+defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true);
+defineSymbol(math, ams, rel, "\u2280", "\\nprec", true);
+// unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true);
+defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true);
+defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true);
+defineSymbol(math, ams, rel, "\u2241", "\\nsim", true);
+defineSymbol(math, ams, rel, "\ue006", "\\@nshortmid");
+defineSymbol(math, ams, rel, "\u2224", "\\nmid", true);
+defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true);
+defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true);
+defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft");
+defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true);
+defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true);
+defineSymbol(math, ams, rel, "\ue01a", "\\@varsubsetneq");
+defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true);
+defineSymbol(math, ams, rel, "\ue017", "\\@varsubsetneqq");
+defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true);
+defineSymbol(math, ams, rel, "\ue00f", "\\@ngeqslant");
+defineSymbol(math, ams, rel, "\ue00e", "\\@ngeqq");
+defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true);
+defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true);
+defineSymbol(math, ams, rel, "\ue00d", "\\@gvertneqq");
+defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true);
+defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true);
+defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true);
+// unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true);
+defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true);
+defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true);
+// unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u2246", "\\ncong", true);
+defineSymbol(math, ams, rel, "\ue007", "\\@nshortparallel");
+defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true);
+defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true);
+defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright");
+defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true);
+defineSymbol(math, ams, rel, "\ue018", "\\@nsupseteqq");
+defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true);
+defineSymbol(math, ams, rel, "\ue01b", "\\@varsupsetneq");
+defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true);
+defineSymbol(math, ams, rel, "\ue019", "\\@varsupsetneqq");
+defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true);
+defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true);
+defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true);
+defineSymbol(math, ams, rel, "\ue016", "\\@nsubseteqq");
+defineSymbol(math, ams, bin, "\u22b4", "\\unlhd");
+defineSymbol(math, ams, bin, "\u22b5", "\\unrhd");
+
+// AMS Negated Arrows
+defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow", true);
+defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow", true);
+defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow", true);
+defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow", true);
+defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow", true);
+defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow", true);
+
+// AMS Misc
+defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle");
+defineSymbol(math, ams, textord, "\u210f", "\\hslash");
+defineSymbol(math, ams, textord, "\u25bd", "\\triangledown");
+defineSymbol(math, ams, textord, "\u25ca", "\\lozenge");
+defineSymbol(math, ams, textord, "\u24c8", "\\circledS");
+defineSymbol(math, ams, textord, "\u00ae", "\\circledR");
+defineSymbol(symbols_text, ams, textord, "\u00ae", "\\circledR");
+defineSymbol(math, ams, textord, "\u2221", "\\measuredangle", true);
+defineSymbol(math, ams, textord, "\u2204", "\\nexists");
+defineSymbol(math, ams, textord, "\u2127", "\\mho");
+defineSymbol(math, ams, textord, "\u2132", "\\Finv", true);
+defineSymbol(math, ams, textord, "\u2141", "\\Game", true);
+defineSymbol(math, ams, textord, "\u2035", "\\backprime");
+defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle");
+defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown");
+defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare");
+defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge");
+defineSymbol(math, ams, textord, "\u2605", "\\bigstar");
+defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle", true);
+defineSymbol(math, ams, textord, "\u2201", "\\complement", true);
+// unicode-math maps U+F0 to \matheth. We map to AMS function \eth
+defineSymbol(math, ams, textord, "\u00f0", "\\eth", true);
+defineSymbol(symbols_text, main, textord, "\u00f0", "\u00f0");
+defineSymbol(math, ams, textord, "\u2571", "\\diagup");
+defineSymbol(math, ams, textord, "\u2572", "\\diagdown");
+defineSymbol(math, ams, textord, "\u25a1", "\\square");
+defineSymbol(math, ams, textord, "\u25a1", "\\Box");
+defineSymbol(math, ams, textord, "\u25ca", "\\Diamond");
+// unicode-math maps U+A5 to \mathyen. We map to AMS function \yen
+defineSymbol(math, ams, textord, "\u00a5", "\\yen", true);
+defineSymbol(symbols_text, ams, textord, "\u00a5", "\\yen", true);
+defineSymbol(math, ams, textord, "\u2713", "\\checkmark", true);
+defineSymbol(symbols_text, ams, textord, "\u2713", "\\checkmark");
+
+// AMS Hebrew
+defineSymbol(math, ams, textord, "\u2136", "\\beth", true);
+defineSymbol(math, ams, textord, "\u2138", "\\daleth", true);
+defineSymbol(math, ams, textord, "\u2137", "\\gimel", true);
+
+// AMS Greek
+defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true);
+defineSymbol(math, ams, textord, "\u03f0", "\\varkappa");
+
+// AMS Delimiters
+defineSymbol(math, ams, symbols_open, "\u250c", "\\@ulcorner", true);
+defineSymbol(math, ams, symbols_close, "\u2510", "\\@urcorner", true);
+defineSymbol(math, ams, symbols_open, "\u2514", "\\@llcorner", true);
+defineSymbol(math, ams, symbols_close, "\u2518", "\\@lrcorner", true);
+
+// AMS Binary Relations
+defineSymbol(math, ams, rel, "\u2266", "\\leqq", true);
+defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant", true);
+defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true);
+defineSymbol(math, ams, rel, "\u2272", "\\lesssim", true);
+defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox", true);
+defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true);
+defineSymbol(math, ams, bin, "\u22d6", "\\lessdot");
+defineSymbol(math, ams, rel, "\u22d8", "\\lll", true);
+defineSymbol(math, ams, rel, "\u2276", "\\lessgtr", true);
+defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr", true);
+defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr", true);
+defineSymbol(math, ams, rel, "\u2251", "\\doteqdot");
+defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true);
+defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true);
+defineSymbol(math, ams, rel, "\u223d", "\\backsim", true);
+defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true);
+defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true);
+defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true);
+defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true);
+defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true);
+defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true);
+defineSymbol(math, ams, rel, "\u227e", "\\precsim", true);
+defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true);
+defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft");
+defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq");
+defineSymbol(math, ams, rel, "\u22a8", "\\vDash", true);
+defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true);
+defineSymbol(math, ams, rel, "\u2323", "\\smallsmile");
+defineSymbol(math, ams, rel, "\u2322", "\\smallfrown");
+defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true);
+defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true);
+defineSymbol(math, ams, rel, "\u2267", "\\geqq", true);
+defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true);
+defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true);
+defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true);
+defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true);
+defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot");
+defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true);
+defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true);
+defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true);
+defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true);
+defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true);
+defineSymbol(math, ams, rel, "\u2257", "\\circeq", true);
+defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true);
+defineSymbol(math, ams, rel, "\u223c", "\\thicksim");
+defineSymbol(math, ams, rel, "\u2248", "\\thickapprox");
+defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true);
+defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true);
+defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true);
+defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true);
+defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true);
+defineSymbol(math, ams, rel, "\u227f", "\\succsim", true);
+defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true);
+defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright");
+defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq");
+defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true);
+defineSymbol(math, ams, rel, "\u2223", "\\shortmid");
+defineSymbol(math, ams, rel, "\u2225", "\\shortparallel");
+defineSymbol(math, ams, rel, "\u226c", "\\between", true);
+defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true);
+defineSymbol(math, ams, rel, "\u221d", "\\varpropto");
+defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft");
+// unicode-math says that \therefore is a mathord atom.
+// We kept the amssymb atom type, which is rel.
+defineSymbol(math, ams, rel, "\u2234", "\\therefore", true);
+defineSymbol(math, ams, rel, "\u220d", "\\backepsilon");
+defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright");
+// unicode-math says that \because is a mathord atom.
+// We kept the amssymb atom type, which is rel.
+defineSymbol(math, ams, rel, "\u2235", "\\because", true);
+defineSymbol(math, ams, rel, "\u22d8", "\\llless");
+defineSymbol(math, ams, rel, "\u22d9", "\\gggtr");
+defineSymbol(math, ams, bin, "\u22b2", "\\lhd");
+defineSymbol(math, ams, bin, "\u22b3", "\\rhd");
+defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true);
+defineSymbol(math, main, rel, "\u22c8", "\\Join");
+defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true);
+
+// AMS Binary Operators
+defineSymbol(math, ams, bin, "\u2214", "\\dotplus", true);
+defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus");
+defineSymbol(math, ams, bin, "\u22d2", "\\Cap", true);
+defineSymbol(math, ams, bin, "\u22d3", "\\Cup", true);
+defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge", true);
+defineSymbol(math, ams, bin, "\u229f", "\\boxminus", true);
+defineSymbol(math, ams, bin, "\u229e", "\\boxplus", true);
+defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes", true);
+defineSymbol(math, ams, bin, "\u22c9", "\\ltimes", true);
+defineSymbol(math, ams, bin, "\u22ca", "\\rtimes", true);
+defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes", true);
+defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes", true);
+defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge", true);
+defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee", true);
+defineSymbol(math, ams, bin, "\u229d", "\\circleddash", true);
+defineSymbol(math, ams, bin, "\u229b", "\\circledast", true);
+defineSymbol(math, ams, bin, "\u22c5", "\\centerdot");
+defineSymbol(math, ams, bin, "\u22ba", "\\intercal", true);
+defineSymbol(math, ams, bin, "\u22d2", "\\doublecap");
+defineSymbol(math, ams, bin, "\u22d3", "\\doublecup");
+defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes", true);
+
+// AMS Arrows
+// Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
+// We'll map it to AMS function \dashrightarrow. It produces the same atom.
+defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow", true);
+// unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow", true);
+defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows", true);
+defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows", true);
+defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow", true);
+defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow", true);
+defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail", true);
+defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft", true);
+defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons", true);
+defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft", true);
+// unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft", true);
+defineSymbol(math, ams, rel, "\u21b0", "\\Lsh", true);
+defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows", true);
+defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft", true);
+defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft", true);
+defineSymbol(math, main, rel, "\u22b6", "\\origof", true); // not in font
+defineSymbol(math, main, rel, "\u22b7", "\\imageof", true); // not in font
+defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true);
+defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow", true);
+defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows", true);
+defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows", true);
+defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow", true);
+defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail", true);
+defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright", true);
+defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright", true);
+// unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright", true);
+defineSymbol(math, ams, rel, "\u21b1", "\\Rsh", true);
+defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows", true);
+defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright", true);
+defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright", true);
+defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow", true);
+defineSymbol(math, ams, rel, "\u21dd", "\\leadsto");
+defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow", true);
+defineSymbol(math, ams, rel, "\u21be", "\\restriction");
+defineSymbol(math, main, textord, "\u2018", "`");
+defineSymbol(math, main, textord, "$", "\\$");
+defineSymbol(symbols_text, main, textord, "$", "\\$");
+defineSymbol(symbols_text, main, textord, "$", "\\textdollar");
+defineSymbol(math, main, textord, "%", "\\%");
+defineSymbol(symbols_text, main, textord, "%", "\\%");
+defineSymbol(math, main, textord, "_", "\\_");
+defineSymbol(symbols_text, main, textord, "_", "\\_");
+defineSymbol(symbols_text, main, textord, "_", "\\textunderscore");
+defineSymbol(math, main, textord, "\u2220", "\\angle", true);
+defineSymbol(math, main, textord, "\u221e", "\\infty", true);
+defineSymbol(math, main, textord, "\u2032", "\\prime");
+defineSymbol(math, main, textord, "\u25b3", "\\triangle");
+defineSymbol(math, main, textord, "\u0393", "\\Gamma", true);
+defineSymbol(math, main, textord, "\u0394", "\\Delta", true);
+defineSymbol(math, main, textord, "\u0398", "\\Theta", true);
+defineSymbol(math, main, textord, "\u039b", "\\Lambda", true);
+defineSymbol(math, main, textord, "\u039e", "\\Xi", true);
+defineSymbol(math, main, textord, "\u03a0", "\\Pi", true);
+defineSymbol(math, main, textord, "\u03a3", "\\Sigma", true);
+defineSymbol(math, main, textord, "\u03a5", "\\Upsilon", true);
+defineSymbol(math, main, textord, "\u03a6", "\\Phi", true);
+defineSymbol(math, main, textord, "\u03a8", "\\Psi", true);
+defineSymbol(math, main, textord, "\u03a9", "\\Omega", true);
+defineSymbol(math, main, textord, "A", "\u0391");
+defineSymbol(math, main, textord, "B", "\u0392");
+defineSymbol(math, main, textord, "E", "\u0395");
+defineSymbol(math, main, textord, "Z", "\u0396");
+defineSymbol(math, main, textord, "H", "\u0397");
+defineSymbol(math, main, textord, "I", "\u0399");
+defineSymbol(math, main, textord, "K", "\u039A");
+defineSymbol(math, main, textord, "M", "\u039C");
+defineSymbol(math, main, textord, "N", "\u039D");
+defineSymbol(math, main, textord, "O", "\u039F");
+defineSymbol(math, main, textord, "P", "\u03A1");
+defineSymbol(math, main, textord, "T", "\u03A4");
+defineSymbol(math, main, textord, "X", "\u03A7");
+defineSymbol(math, main, textord, "\u00ac", "\\neg", true);
+defineSymbol(math, main, textord, "\u00ac", "\\lnot");
+defineSymbol(math, main, textord, "\u22a4", "\\top");
+defineSymbol(math, main, textord, "\u22a5", "\\bot");
+defineSymbol(math, main, textord, "\u2205", "\\emptyset");
+defineSymbol(math, ams, textord, "\u2205", "\\varnothing");
+defineSymbol(math, main, mathord, "\u03b1", "\\alpha", true);
+defineSymbol(math, main, mathord, "\u03b2", "\\beta", true);
+defineSymbol(math, main, mathord, "\u03b3", "\\gamma", true);
+defineSymbol(math, main, mathord, "\u03b4", "\\delta", true);
+defineSymbol(math, main, mathord, "\u03f5", "\\epsilon", true);
+defineSymbol(math, main, mathord, "\u03b6", "\\zeta", true);
+defineSymbol(math, main, mathord, "\u03b7", "\\eta", true);
+defineSymbol(math, main, mathord, "\u03b8", "\\theta", true);
+defineSymbol(math, main, mathord, "\u03b9", "\\iota", true);
+defineSymbol(math, main, mathord, "\u03ba", "\\kappa", true);
+defineSymbol(math, main, mathord, "\u03bb", "\\lambda", true);
+defineSymbol(math, main, mathord, "\u03bc", "\\mu", true);
+defineSymbol(math, main, mathord, "\u03bd", "\\nu", true);
+defineSymbol(math, main, mathord, "\u03be", "\\xi", true);
+defineSymbol(math, main, mathord, "\u03bf", "\\omicron", true);
+defineSymbol(math, main, mathord, "\u03c0", "\\pi", true);
+defineSymbol(math, main, mathord, "\u03c1", "\\rho", true);
+defineSymbol(math, main, mathord, "\u03c3", "\\sigma", true);
+defineSymbol(math, main, mathord, "\u03c4", "\\tau", true);
+defineSymbol(math, main, mathord, "\u03c5", "\\upsilon", true);
+defineSymbol(math, main, mathord, "\u03d5", "\\phi", true);
+defineSymbol(math, main, mathord, "\u03c7", "\\chi", true);
+defineSymbol(math, main, mathord, "\u03c8", "\\psi", true);
+defineSymbol(math, main, mathord, "\u03c9", "\\omega", true);
+defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon", true);
+defineSymbol(math, main, mathord, "\u03d1", "\\vartheta", true);
+defineSymbol(math, main, mathord, "\u03d6", "\\varpi", true);
+defineSymbol(math, main, mathord, "\u03f1", "\\varrho", true);
+defineSymbol(math, main, mathord, "\u03c2", "\\varsigma", true);
+defineSymbol(math, main, mathord, "\u03c6", "\\varphi", true);
+defineSymbol(math, main, bin, "\u2217", "*", true);
+defineSymbol(math, main, bin, "+", "+");
+defineSymbol(math, main, bin, "\u2212", "-", true);
+defineSymbol(math, main, bin, "\u22c5", "\\cdot", true);
+defineSymbol(math, main, bin, "\u2218", "\\circ", true);
+defineSymbol(math, main, bin, "\u00f7", "\\div", true);
+defineSymbol(math, main, bin, "\u00b1", "\\pm", true);
+defineSymbol(math, main, bin, "\u00d7", "\\times", true);
+defineSymbol(math, main, bin, "\u2229", "\\cap", true);
+defineSymbol(math, main, bin, "\u222a", "\\cup", true);
+defineSymbol(math, main, bin, "\u2216", "\\setminus", true);
+defineSymbol(math, main, bin, "\u2227", "\\land");
+defineSymbol(math, main, bin, "\u2228", "\\lor");
+defineSymbol(math, main, bin, "\u2227", "\\wedge", true);
+defineSymbol(math, main, bin, "\u2228", "\\vee", true);
+defineSymbol(math, main, textord, "\u221a", "\\surd");
+defineSymbol(math, main, symbols_open, "\u27e8", "\\langle", true);
+defineSymbol(math, main, symbols_open, "\u2223", "\\lvert");
+defineSymbol(math, main, symbols_open, "\u2225", "\\lVert");
+defineSymbol(math, main, symbols_close, "?", "?");
+defineSymbol(math, main, symbols_close, "!", "!");
+defineSymbol(math, main, symbols_close, "\u27e9", "\\rangle", true);
+defineSymbol(math, main, symbols_close, "\u2223", "\\rvert");
+defineSymbol(math, main, symbols_close, "\u2225", "\\rVert");
+defineSymbol(math, main, rel, "=", "=");
+defineSymbol(math, main, rel, ":", ":");
+defineSymbol(math, main, rel, "\u2248", "\\approx", true);
+defineSymbol(math, main, rel, "\u2245", "\\cong", true);
+defineSymbol(math, main, rel, "\u2265", "\\ge");
+defineSymbol(math, main, rel, "\u2265", "\\geq", true);
+defineSymbol(math, main, rel, "\u2190", "\\gets");
+defineSymbol(math, main, rel, ">", "\\gt", true);
+defineSymbol(math, main, rel, "\u2208", "\\in", true);
+defineSymbol(math, main, rel, "\ue020", "\\@not");
+defineSymbol(math, main, rel, "\u2282", "\\subset", true);
+defineSymbol(math, main, rel, "\u2283", "\\supset", true);
+defineSymbol(math, main, rel, "\u2286", "\\subseteq", true);
+defineSymbol(math, main, rel, "\u2287", "\\supseteq", true);
+defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true);
+defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true);
+defineSymbol(math, main, rel, "\u22a8", "\\models");
+defineSymbol(math, main, rel, "\u2190", "\\leftarrow", true);
+defineSymbol(math, main, rel, "\u2264", "\\le");
+defineSymbol(math, main, rel, "\u2264", "\\leq", true);
+defineSymbol(math, main, rel, "<", "\\lt", true);
+defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true);
+defineSymbol(math, main, rel, "\u2192", "\\to");
+defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true);
+defineSymbol(math, ams, rel, "\u2270", "\\nleq", true);
+defineSymbol(math, main, spacing, "\u00a0", "\\ ");
+defineSymbol(math, main, spacing, "\u00a0", "\\space");
+// Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{%
+defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace");
+defineSymbol(symbols_text, main, spacing, "\u00a0", "\\ ");
+defineSymbol(symbols_text, main, spacing, "\u00a0", " ");
+defineSymbol(symbols_text, main, spacing, "\u00a0", "\\space");
+defineSymbol(symbols_text, main, spacing, "\u00a0", "\\nobreakspace");
+defineSymbol(math, main, spacing, "", "\\nobreak");
+defineSymbol(math, main, spacing, "", "\\allowbreak");
+defineSymbol(math, main, punct, ",", ",");
+defineSymbol(math, main, punct, ";", ";");
+defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true);
+defineSymbol(math, ams, bin, "\u22bb", "\\veebar", true);
+defineSymbol(math, main, bin, "\u2299", "\\odot", true);
+defineSymbol(math, main, bin, "\u2295", "\\oplus", true);
+defineSymbol(math, main, bin, "\u2297", "\\otimes", true);
+defineSymbol(math, main, textord, "\u2202", "\\partial", true);
+defineSymbol(math, main, bin, "\u2298", "\\oslash", true);
+defineSymbol(math, ams, bin, "\u229a", "\\circledcirc", true);
+defineSymbol(math, ams, bin, "\u22a1", "\\boxdot", true);
+defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup");
+defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown");
+defineSymbol(math, main, bin, "\u2020", "\\dagger");
+defineSymbol(math, main, bin, "\u22c4", "\\diamond");
+defineSymbol(math, main, bin, "\u22c6", "\\star");
+defineSymbol(math, main, bin, "\u25c3", "\\triangleleft");
+defineSymbol(math, main, bin, "\u25b9", "\\triangleright");
+defineSymbol(math, main, symbols_open, "{", "\\{");
+defineSymbol(symbols_text, main, textord, "{", "\\{");
+defineSymbol(symbols_text, main, textord, "{", "\\textbraceleft");
+defineSymbol(math, main, symbols_close, "}", "\\}");
+defineSymbol(symbols_text, main, textord, "}", "\\}");
+defineSymbol(symbols_text, main, textord, "}", "\\textbraceright");
+defineSymbol(math, main, symbols_open, "{", "\\lbrace");
+defineSymbol(math, main, symbols_close, "}", "\\rbrace");
+defineSymbol(math, main, symbols_open, "[", "\\lbrack", true);
+defineSymbol(symbols_text, main, textord, "[", "\\lbrack", true);
+defineSymbol(math, main, symbols_close, "]", "\\rbrack", true);
+defineSymbol(symbols_text, main, textord, "]", "\\rbrack", true);
+defineSymbol(math, main, symbols_open, "(", "\\lparen", true);
+defineSymbol(math, main, symbols_close, ")", "\\rparen", true);
+defineSymbol(symbols_text, main, textord, "<", "\\textless", true); // in T1 fontenc
+defineSymbol(symbols_text, main, textord, ">", "\\textgreater", true); // in T1 fontenc
+defineSymbol(math, main, symbols_open, "\u230a", "\\lfloor", true);
+defineSymbol(math, main, symbols_close, "\u230b", "\\rfloor", true);
+defineSymbol(math, main, symbols_open, "\u2308", "\\lceil", true);
+defineSymbol(math, main, symbols_close, "\u2309", "\\rceil", true);
+defineSymbol(math, main, textord, "\\", "\\backslash");
+defineSymbol(math, main, textord, "\u2223", "|");
+defineSymbol(math, main, textord, "\u2223", "\\vert");
+defineSymbol(symbols_text, main, textord, "|", "\\textbar", true); // in T1 fontenc
+defineSymbol(math, main, textord, "\u2225", "\\|");
+defineSymbol(math, main, textord, "\u2225", "\\Vert");
+defineSymbol(symbols_text, main, textord, "\u2225", "\\textbardbl");
+defineSymbol(symbols_text, main, textord, "~", "\\textasciitilde");
+defineSymbol(symbols_text, main, textord, "\\", "\\textbackslash");
+defineSymbol(symbols_text, main, textord, "^", "\\textasciicircum");
+defineSymbol(math, main, rel, "\u2191", "\\uparrow", true);
+defineSymbol(math, main, rel, "\u21d1", "\\Uparrow", true);
+defineSymbol(math, main, rel, "\u2193", "\\downarrow", true);
+defineSymbol(math, main, rel, "\u21d3", "\\Downarrow", true);
+defineSymbol(math, main, rel, "\u2195", "\\updownarrow", true);
+defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow", true);
+defineSymbol(math, main, op, "\u2210", "\\coprod");
+defineSymbol(math, main, op, "\u22c1", "\\bigvee");
+defineSymbol(math, main, op, "\u22c0", "\\bigwedge");
+defineSymbol(math, main, op, "\u2a04", "\\biguplus");
+defineSymbol(math, main, op, "\u22c2", "\\bigcap");
+defineSymbol(math, main, op, "\u22c3", "\\bigcup");
+defineSymbol(math, main, op, "\u222b", "\\int");
+defineSymbol(math, main, op, "\u222b", "\\intop");
+defineSymbol(math, main, op, "\u222c", "\\iint");
+defineSymbol(math, main, op, "\u222d", "\\iiint");
+defineSymbol(math, main, op, "\u220f", "\\prod");
+defineSymbol(math, main, op, "\u2211", "\\sum");
+defineSymbol(math, main, op, "\u2a02", "\\bigotimes");
+defineSymbol(math, main, op, "\u2a01", "\\bigoplus");
+defineSymbol(math, main, op, "\u2a00", "\\bigodot");
+defineSymbol(math, main, op, "\u222e", "\\oint");
+defineSymbol(math, main, op, "\u222f", "\\oiint");
+defineSymbol(math, main, op, "\u2230", "\\oiiint");
+defineSymbol(math, main, op, "\u2a06", "\\bigsqcup");
+defineSymbol(math, main, op, "\u222b", "\\smallint");
+defineSymbol(symbols_text, main, inner, "\u2026", "\\textellipsis");
+defineSymbol(math, main, inner, "\u2026", "\\mathellipsis");
+defineSymbol(symbols_text, main, inner, "\u2026", "\\ldots", true);
+defineSymbol(math, main, inner, "\u2026", "\\ldots", true);
+defineSymbol(math, main, inner, "\u22ef", "\\@cdots", true);
+defineSymbol(math, main, inner, "\u22f1", "\\ddots", true);
+// \vdots is a macro that uses one of these two symbols (with made-up names):
+defineSymbol(math, main, textord, "\u22ee", "\\varvdots");
+defineSymbol(symbols_text, main, textord, "\u22ee", "\\varvdots");
+defineSymbol(math, main, accent, "\u02ca", "\\acute");
+defineSymbol(math, main, accent, "\u02cb", "\\grave");
+defineSymbol(math, main, accent, "\u00a8", "\\ddot");
+defineSymbol(math, main, accent, "\u007e", "\\tilde");
+defineSymbol(math, main, accent, "\u02c9", "\\bar");
+defineSymbol(math, main, accent, "\u02d8", "\\breve");
+defineSymbol(math, main, accent, "\u02c7", "\\check");
+defineSymbol(math, main, accent, "\u005e", "\\hat");
+defineSymbol(math, main, accent, "\u20d7", "\\vec");
+defineSymbol(math, main, accent, "\u02d9", "\\dot");
+defineSymbol(math, main, accent, "\u02da", "\\mathring");
+// \imath and \jmath should be invariant to \mathrm, \mathbf, etc., so use PUA
+defineSymbol(math, main, mathord, "\ue131", "\\@imath");
+defineSymbol(math, main, mathord, "\ue237", "\\@jmath");
+defineSymbol(math, main, textord, "\u0131", "\u0131");
+defineSymbol(math, main, textord, "\u0237", "\u0237");
+defineSymbol(symbols_text, main, textord, "\u0131", "\\i", true);
+defineSymbol(symbols_text, main, textord, "\u0237", "\\j", true);
+defineSymbol(symbols_text, main, textord, "\u00df", "\\ss", true);
+defineSymbol(symbols_text, main, textord, "\u00e6", "\\ae", true);
+defineSymbol(symbols_text, main, textord, "\u0153", "\\oe", true);
+defineSymbol(symbols_text, main, textord, "\u00f8", "\\o", true);
+defineSymbol(symbols_text, main, textord, "\u00c6", "\\AE", true);
+defineSymbol(symbols_text, main, textord, "\u0152", "\\OE", true);
+defineSymbol(symbols_text, main, textord, "\u00d8", "\\O", true);
+defineSymbol(symbols_text, main, accent, "\u02ca", "\\'"); // acute
+defineSymbol(symbols_text, main, accent, "\u02cb", "\\`"); // grave
+defineSymbol(symbols_text, main, accent, "\u02c6", "\\^"); // circumflex
+defineSymbol(symbols_text, main, accent, "\u02dc", "\\~"); // tilde
+defineSymbol(symbols_text, main, accent, "\u02c9", "\\="); // macron
+defineSymbol(symbols_text, main, accent, "\u02d8", "\\u"); // breve
+defineSymbol(symbols_text, main, accent, "\u02d9", "\\."); // dot above
+defineSymbol(symbols_text, main, accent, "\u00b8", "\\c"); // cedilla
+defineSymbol(symbols_text, main, accent, "\u02da", "\\r"); // ring above
+defineSymbol(symbols_text, main, accent, "\u02c7", "\\v"); // caron
+defineSymbol(symbols_text, main, accent, "\u00a8", '\\"'); // diaeresis
+defineSymbol(symbols_text, main, accent, "\u02dd", "\\H"); // double acute
+defineSymbol(symbols_text, main, accent, "\u25ef", "\\textcircled"); // \bigcirc glyph
+
+// These ligatures are detected and created in Parser.js's `formLigatures`.
+const ligatures = {
+ "--": true,
+ "---": true,
+ "``": true,
+ "''": true
+};
+defineSymbol(symbols_text, main, textord, "\u2013", "--", true);
+defineSymbol(symbols_text, main, textord, "\u2013", "\\textendash");
+defineSymbol(symbols_text, main, textord, "\u2014", "---", true);
+defineSymbol(symbols_text, main, textord, "\u2014", "\\textemdash");
+defineSymbol(symbols_text, main, textord, "\u2018", "`", true);
+defineSymbol(symbols_text, main, textord, "\u2018", "\\textquoteleft");
+defineSymbol(symbols_text, main, textord, "\u2019", "'", true);
+defineSymbol(symbols_text, main, textord, "\u2019", "\\textquoteright");
+defineSymbol(symbols_text, main, textord, "\u201c", "``", true);
+defineSymbol(symbols_text, main, textord, "\u201c", "\\textquotedblleft");
+defineSymbol(symbols_text, main, textord, "\u201d", "''", true);
+defineSymbol(symbols_text, main, textord, "\u201d", "\\textquotedblright");
+// \degree from gensymb package
+defineSymbol(math, main, textord, "\u00b0", "\\degree", true);
+defineSymbol(symbols_text, main, textord, "\u00b0", "\\degree");
+// \textdegree from inputenc package
+defineSymbol(symbols_text, main, textord, "\u00b0", "\\textdegree", true);
+// TODO: In LaTeX, \pounds can generate a different character in text and math
+// mode, but among our fonts, only Main-Regular defines this character "163".
+defineSymbol(math, main, textord, "\u00a3", "\\pounds");
+defineSymbol(math, main, textord, "\u00a3", "\\mathsterling", true);
+defineSymbol(symbols_text, main, textord, "\u00a3", "\\pounds");
+defineSymbol(symbols_text, main, textord, "\u00a3", "\\textsterling", true);
+defineSymbol(math, ams, textord, "\u2720", "\\maltese");
+defineSymbol(symbols_text, ams, textord, "\u2720", "\\maltese");
+
+// There are lots of symbols which are the same, so we add them in afterwards.
+// All of these are textords in math mode
+const mathTextSymbols = "0123456789/@.\"";
+for (let i = 0; i < mathTextSymbols.length; i++) {
+ const ch = mathTextSymbols.charAt(i);
+ defineSymbol(math, main, textord, ch, ch);
+}
+
+// All of these are textords in text mode
+const textSymbols = "0123456789!@*()-=+\";:?/.,";
+for (let i = 0; i < textSymbols.length; i++) {
+ const ch = textSymbols.charAt(i);
+ defineSymbol(symbols_text, main, textord, ch, ch);
+}
+
+// All of these are textords in text mode, and mathords in math mode
+const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+for (let i = 0; i < letters.length; i++) {
+ const ch = letters.charAt(i);
+ defineSymbol(math, main, mathord, ch, ch);
+ defineSymbol(symbols_text, main, textord, ch, ch);
+}
+
+// Blackboard bold and script letters in Unicode range
+defineSymbol(math, ams, textord, "C", "\u2102"); // blackboard bold
+defineSymbol(symbols_text, ams, textord, "C", "\u2102");
+defineSymbol(math, ams, textord, "H", "\u210D");
+defineSymbol(symbols_text, ams, textord, "H", "\u210D");
+defineSymbol(math, ams, textord, "N", "\u2115");
+defineSymbol(symbols_text, ams, textord, "N", "\u2115");
+defineSymbol(math, ams, textord, "P", "\u2119");
+defineSymbol(symbols_text, ams, textord, "P", "\u2119");
+defineSymbol(math, ams, textord, "Q", "\u211A");
+defineSymbol(symbols_text, ams, textord, "Q", "\u211A");
+defineSymbol(math, ams, textord, "R", "\u211D");
+defineSymbol(symbols_text, ams, textord, "R", "\u211D");
+defineSymbol(math, ams, textord, "Z", "\u2124");
+defineSymbol(symbols_text, ams, textord, "Z", "\u2124");
+defineSymbol(math, main, mathord, "h", "\u210E"); // italic h, Planck constant
+defineSymbol(symbols_text, main, mathord, "h", "\u210E");
+
+// The next loop loads wide (surrogate pair) characters.
+// We support some letters in the Unicode range U+1D400 to U+1D7FF,
+// Mathematical Alphanumeric Symbols.
+// Some editors do not deal well with wide characters. So don't write the
+// string into this file. Instead, create the string from the surrogate pair.
+let wideChar;
+for (let i = 0; i < letters.length; i++) {
+ const ch = letters.charAt(i);
+
+ // The hex numbers in the next line are a surrogate pair.
+ // 0xD835 is the high surrogate for all letters in the range we support.
+ // 0xDC00 is the low surrogate for bold A.
+ wideChar = String.fromCharCode(0xD835, 0xDC00 + i); // A-Z a-z bold
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDC34 + i); // A-Z a-z italic
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDC68 + i); // A-Z a-z bold italic
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDD04 + i); // A-Z a-z Fraktur
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDD6C + i); // A-Z a-z bold Fraktur
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDDA0 + i); // A-Z a-z sans-serif
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDDD4 + i); // A-Z a-z sans bold
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDE08 + i); // A-Z a-z sans italic
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDE70 + i); // A-Z a-z monospace
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ if (i < 26) {
+ // KaTeX fonts have only capital letters for blackboard bold and script.
+ // See exception for k below.
+ wideChar = String.fromCharCode(0xD835, 0xDD38 + i); // A-Z double struck
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDC9C + i); // A-Z script
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ }
+
+ // TODO: Add bold script when it is supported by a KaTeX font.
+}
+// "k" is the only double struck lower case letter in the KaTeX fonts.
+wideChar = String.fromCharCode(0xD835, 0xDD5C); // k double struck
+defineSymbol(math, main, mathord, "k", wideChar);
+defineSymbol(symbols_text, main, textord, "k", wideChar);
+
+// Next, some wide character numerals
+for (let i = 0; i < 10; i++) {
+ const ch = i.toString();
+ wideChar = String.fromCharCode(0xD835, 0xDFCE + i); // 0-9 bold
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDFE2 + i); // 0-9 sans serif
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDFEC + i); // 0-9 bold sans
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+ wideChar = String.fromCharCode(0xD835, 0xDFF6 + i); // 0-9 monospace
+ defineSymbol(math, main, mathord, ch, wideChar);
+ defineSymbol(symbols_text, main, textord, ch, wideChar);
+}
+
+// We add these Latin-1 letters as symbols for backwards-compatibility,
+// but they are not actually in the font, nor are they supported by the
+// Unicode accent mechanism, so they fall back to Times font and look ugly.
+// TODO(edemaine): Fix this.
+const extraLatin = "\u00d0\u00de\u00fe";
+for (let i = 0; i < extraLatin.length; i++) {
+ const ch = extraLatin.charAt(i);
+ defineSymbol(math, main, mathord, ch, ch);
+ defineSymbol(symbols_text, main, textord, ch, ch);
+}
+;// ./src/wide-character.ts
+/**
+ * This file provides support for Unicode range U+1D400 to U+1D7FF,
+ * Mathematical Alphanumeric Symbols.
+ *
+ * Function wideCharacterFont takes a wide character as input and returns
+ * the font information necessary to render it properly.
+ */
+
+
+const boldUpright = {
+ mathClass: "mathbf",
+ textClass: "textbf",
+ font: "Main-Bold"
+};
+const italic = {
+ mathClass: "mathnormal",
+ textClass: "textit",
+ font: "Math-Italic"
+};
+const boldItalic = {
+ mathClass: "boldsymbol",
+ textClass: "boldsymbol",
+ font: "Main-BoldItalic"
+};
+const script = {
+ mathClass: "mathscr",
+ textClass: "textscr",
+ font: "Script-Regular"
+};
+const noFont = {
+ mathClass: "",
+ textClass: "",
+ font: ""
+};
+const fraktur = {
+ mathClass: "mathfrak",
+ textClass: "textfrak",
+ font: "Fraktur-Regular"
+};
+const doubleStruck = {
+ mathClass: "mathbb",
+ textClass: "textbb",
+ font: "AMS-Regular"
+};
+const boldFraktur = {
+ mathClass: "mathboldfrak",
+ textClass: "textboldfrak",
+ font: "Fraktur-Regular"
+};
+const sansSerif = {
+ mathClass: "mathsf",
+ textClass: "textsf",
+ font: "SansSerif-Regular"
+};
+const boldSansSerif = {
+ mathClass: "mathboldsf",
+ textClass: "textboldsf",
+ font: "SansSerif-Bold"
+};
+const italicSansSerif = {
+ mathClass: "mathitsf",
+ textClass: "textitsf",
+ font: "SansSerif-Italic"
+};
+const monospace = {
+ mathClass: "mathtt",
+ textClass: "texttt",
+ font: "Typewriter-Regular"
+};
+
+/**
+ * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf
+ * That document sorts characters into groups by font type, say bold or italic.
+ *
+ * In the arrays below, each object consists of three properties:
+ * * The CSS class of that group when in math mode.
+ * * The CSS class of that group when in text mode.
+ * * The font name, so that KaTeX can get font metrics.
+ */
+
+const wideLatinLetterData = [boldUpright, boldUpright,
+// A-Z, a-z
+italic, italic,
+// A-Z, a-z
+boldItalic, boldItalic,
+// A-Z, a-z
+// Map fancy A-Z letters to script, not calligraphic.
+// This aligns with unicode-math and math fonts (except Cambria Math).
+script, noFont,
+// A-Z script, a-z — no font
+noFont, noFont,
+// A-Z bold script, a-z bold script — no font
+fraktur, fraktur,
+// A-Z, a-z
+doubleStruck, doubleStruck,
+// A-Z double-struck, k double-struck
+// Note that we are using a bold font, but font metrics for regular Fraktur.
+boldFraktur, boldFraktur,
+// A-Z, a-z
+sansSerif, sansSerif,
+// A-Z, a-z
+boldSansSerif, boldSansSerif,
+// A-Z, a-z
+italicSansSerif, italicSansSerif,
+// A-Z, a-z
+noFont, noFont,
+// A-Z bold italic sans, a-z bold italic sans - no font
+monospace, monospace // A-Z, a-z
+];
+const wideNumeralData = [boldUpright,
+// 0-9
+noFont,
+// 0-9 double-struck. No KaTeX font.
+sansSerif,
+// 0-9
+boldSansSerif,
+// 0-9
+monospace // 0-9
+];
+const wideCharacterFont = wideChar => {
+ // IE doesn't support codePointAt(). So work with the surrogate pair.
+ const H = wideChar.charCodeAt(0); // high surrogate
+ const L = wideChar.charCodeAt(1); // low surrogate
+ const codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000;
+ if (0x1D400 <= codePoint && codePoint < 0x1D6A4) {
+ // wideLatinLetterData contains exactly 26 chars on each row.
+ // So we can calculate the relevant row. No traverse necessary.
+ const i = Math.floor((codePoint - 0x1D400) / 26);
+ return wideLatinLetterData[i];
+ } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) {
+ // Numerals, ten per row.
+ const i = Math.floor((codePoint - 0x1D7CE) / 10);
+ return wideNumeralData[i];
+ } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) {
+ // dotless i or j
+ return wideLatinLetterData[0];
+ } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) {
+ // Greek letters. Not supported, yet.
+ return noFont;
+ } else {
+ // We don't support any wide characters outside 1D400–1D7FF.
+ throw new src_ParseError("Unsupported character: " + wideChar);
+ }
+};
+;// ./src/buildCommon.ts
+/* eslint no-console:0 */
+/**
+ * This module contains general functions that can be used for building
+ * different kinds of domTree nodes in a consistent manner.
+ */
+
+
+
+
+
+
+
+/**
+ * Looks up the given symbol in fontMetrics, after applying any symbol
+ * replacements defined in symbol.js
+ */
+const lookupSymbol = function (value, fontName, mode) {
+ // Replace the value with its replaced value from symbol.js
+ if (src_symbols[mode][value]) {
+ const replacement = src_symbols[mode][value].replace;
+ if (replacement) {
+ value = replacement;
+ }
+ }
+ return {
+ value,
+ metrics: getCharacterMetrics(value, fontName, mode)
+ };
+};
+
+/**
+ * Makes a symbolNode after translation via the list of symbols in symbols.js.
+ * Correctly pulls out metrics for the character, and optionally takes a list of
+ * classes to be attached to the node.
+ *
+ * TODO: make argument order closer to makeSpan
+ * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
+ * should if present come first in `classes`.
+ * TODO(#953): Make `options` mandatory and always pass it in.
+ */
+const makeSymbol = function (value, fontName, mode, options, classes) {
+ const lookup = lookupSymbol(value, fontName, mode);
+ const metrics = lookup.metrics;
+ value = lookup.value;
+ let symbolNode;
+ if (metrics) {
+ let italic = metrics.italic;
+ if (mode === "text" || options && options.font === "mathit") {
+ italic = 0;
+ }
+ symbolNode = new SymbolNode(value, metrics.height, metrics.depth, italic, metrics.skew, metrics.width, classes);
+ } else {
+ // TODO(emily): Figure out a good way to only print this in development
+ typeof console !== "undefined" && console.warn("No character metrics " + ("for '" + value + "' in style '" + fontName + "' and mode '" + mode + "'"));
+ symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes);
+ }
+ if (options) {
+ symbolNode.maxFontSize = options.sizeMultiplier;
+ if (options.style.isTight()) {
+ symbolNode.classes.push("mtight");
+ }
+ const color = options.getColor();
+ if (color) {
+ symbolNode.style.color = color;
+ }
+ }
+ return symbolNode;
+};
+
+/**
+ * Makes a symbol in Main-Regular or AMS-Regular.
+ * Used for rel, bin, open, close, inner, and punct.
+ */
+const mathsym = function (value, mode, options, classes) {
+ if (classes === void 0) {
+ classes = [];
+ }
+ // Decide what font to render the symbol in by its entry in the symbols
+ // table.
+ // Have a special case for when the value = \ because the \ is used as a
+ // textord in unsupported command errors but cannot be parsed as a regular
+ // text ordinal and is therefore not present as a symbol in the symbols
+ // table for text, as well as a special case for boldsymbol because it
+ // can be used for bold + and -
+ if (options.font === "boldsymbol" && lookupSymbol(value, "Main-Bold", mode).metrics) {
+ return makeSymbol(value, "Main-Bold", mode, options, classes.concat(["mathbf"]));
+ } else if (value === "\\" || src_symbols[mode][value].font === "main") {
+ return makeSymbol(value, "Main-Regular", mode, options, classes);
+ } else {
+ return makeSymbol(value, "AMS-Regular", mode, options, classes.concat(["amsrm"]));
+ }
+};
+
+/**
+ * Determines which of the two font names (Main-Bold and Math-BoldItalic) and
+ * corresponding style tags (mathbf or boldsymbol) to use for font "boldsymbol",
+ * depending on the symbol. Use this function instead of fontMap for font
+ * "boldsymbol".
+ */
+const boldSymbol = function (value, mode, type) {
+ if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) {
+ return {
+ fontName: "Math-BoldItalic",
+ fontClass: "boldsymbol"
+ };
+ } else {
+ // Some glyphs do not exist in Math-BoldItalic so we need to use
+ // Main-Bold instead.
+ return {
+ fontName: "Main-Bold",
+ fontClass: "mathbf"
+ };
+ }
+};
+
+/**
+ * Makes either a mathord or textord in the correct font and color.
+ */
+const makeOrd = function (group, options) {
+ // Spacing nodes are rendered as textord.
+ const type = group.type === "mathord" ? "mathord" : "textord";
+ const mode = group.mode;
+ const text = group.text;
+ const classes = ["mord"];
+ const font = options.font,
+ fontFamily = options.fontFamily,
+ fontWeight = options.fontWeight,
+ fontShape = options.fontShape;
+
+ // Math mode or Old font (i.e. \rm)
+ const useFont = mode === "math" || mode === "text" && !!font;
+ const fontOrFamily = useFont ? font : fontFamily;
+ let wideFontName = "";
+ let wideFontClass = "";
+ if (text.charCodeAt(0) === 0xD835) {
+ const wideCharData = wideCharacterFont(text);
+ wideFontName = wideCharData.font;
+ wideFontClass = wideCharData[mode + "Class"];
+ }
+ if (wideFontName) {
+ // surrogate pairs get special treatment
+ return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass));
+ } else if (fontOrFamily) {
+ let fontName;
+ let fontClasses;
+ if (fontOrFamily === "boldsymbol") {
+ const fontData = boldSymbol(text, mode, type);
+ fontName = fontData.fontName;
+ fontClasses = [fontData.fontClass];
+ } else if (useFont) {
+ fontName = fontMap[font].fontName;
+ fontClasses = [font];
+ } else {
+ fontName = retrieveTextFontName(fontFamily, fontWeight, fontShape);
+ fontClasses = [fontFamily, fontWeight, fontShape];
+ }
+ if (lookupSymbol(text, fontName, mode).metrics) {
+ return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses));
+ } else if (Object.prototype.hasOwnProperty.call(ligatures, text) && fontName.slice(0, 10) === "Typewriter") {
+ // Deconstruct ligatures in monospace fonts (\texttt, \tt).
+ const parts = [];
+ for (let i = 0; i < text.length; i++) {
+ parts.push(makeSymbol(text[i], fontName, mode, options, classes.concat(fontClasses)));
+ }
+ return makeFragment(parts);
+ }
+ }
+
+ // Makes a symbol in the default font for mathords and textords.
+ if (type === "mathord") {
+ return makeSymbol(text, "Math-Italic", mode, options, classes.concat(["mathnormal"]));
+ } else if (type === "textord") {
+ const font = src_symbols[mode][text] && src_symbols[mode][text].font;
+ if (font === "ams") {
+ const fontName = retrieveTextFontName("amsrm", fontWeight, fontShape);
+ return makeSymbol(text, fontName, mode, options, classes.concat("amsrm", fontWeight, fontShape));
+ } else if (font === "main" || !font) {
+ const fontName = retrieveTextFontName("textrm", fontWeight, fontShape);
+ return makeSymbol(text, fontName, mode, options, classes.concat(fontWeight, fontShape));
+ } else {
+ // fonts added by plugins
+ const fontName = retrieveTextFontName(font, fontWeight, fontShape);
+ // We add font name as a css class
+ return makeSymbol(text, fontName, mode, options, classes.concat(fontName, fontWeight, fontShape));
+ }
+ } else {
+ throw new Error("unexpected type: " + type + " in makeOrd");
+ }
+};
+
+/**
+ * Returns true if subsequent symbolNodes have the same classes, skew, maxFont,
+ * and styles. For mathnormal text, the left node must also have zero italic
+ * correction so we don't lose spacing between combined glyphs.
+ */
+const canCombine = (prev, next) => {
+ if (createClass(prev.classes) !== createClass(next.classes) || prev.skew !== next.skew || prev.maxFontSize !== next.maxFontSize || prev.italic !== 0 && prev.hasClass("mathnormal")) {
+ return false;
+ }
+
+ // If prev and next both are just "mbin"s or "mord"s we don't combine them
+ // so that the proper spacing can be preserved.
+ if (prev.classes.length === 1) {
+ const cls = prev.classes[0];
+ if (cls === "mbin" || cls === "mord") {
+ return false;
+ }
+ }
+ for (const key of Object.keys(prev.style)) {
+ if (prev.style[key] !== next.style[key]) {
+ return false;
+ }
+ }
+ for (const key of Object.keys(next.style)) {
+ if (prev.style[key] !== next.style[key]) {
+ return false;
+ }
+ }
+ return true;
+};
+
+/**
+ * Combine consecutive domTree.symbolNodes into a single symbolNode.
+ * Note: this function mutates the argument.
+ */
+const tryCombineChars = chars => {
+ for (let i = 0; i < chars.length - 1; i++) {
+ const prev = chars[i];
+ const next = chars[i + 1];
+ if (prev instanceof SymbolNode && next instanceof SymbolNode && canCombine(prev, next)) {
+ prev.text += next.text;
+ prev.height = Math.max(prev.height, next.height);
+ prev.depth = Math.max(prev.depth, next.depth);
+ // Use the last character's italic correction since we use
+ // it to add padding to the right of the span created from
+ // the combined characters.
+ prev.italic = next.italic;
+ chars.splice(i + 1, 1);
+ i--;
+ }
+ }
+ return chars;
+};
+
+/**
+ * Calculate the height, depth, and maxFontSize of an element based on its
+ * children.
+ */
+const sizeElementFromChildren = function (elem) {
+ let height = 0;
+ let depth = 0;
+ let maxFontSize = 0;
+ for (let i = 0; i < elem.children.length; i++) {
+ const child = elem.children[i];
+ if (child.height > height) {
+ height = child.height;
+ }
+ if (child.depth > depth) {
+ depth = child.depth;
+ }
+ if (child.maxFontSize > maxFontSize) {
+ maxFontSize = child.maxFontSize;
+ }
+ }
+ elem.height = height;
+ elem.depth = depth;
+ elem.maxFontSize = maxFontSize;
+};
+
+/**
+ * Makes a span with the given list of classes, list of children, and options.
+ *
+ * TODO(#953): Ensure that `options` is always provided (currently some call
+ * sites don't pass it) and make the type below mandatory.
+ * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
+ * should if present come first in `classes`.
+ */
+const makeSpan = function (classes, children, options, style) {
+ const span = new Span(classes, children, options, style);
+ sizeElementFromChildren(span);
+ return span;
+};
+
+// SVG one is simpler -- doesn't require height, depth, max-font setting.
+// This is also a separate method for typesafety.
+const makeSvgSpan = (classes, children, options, style) => new Span(classes, children, options, style);
+const makeLineSpan = function (className, options, thickness) {
+ const line = makeSpan([className], [], options);
+ line.height = Math.max(thickness || options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
+ line.style.borderBottomWidth = makeEm(line.height);
+ line.maxFontSize = 1.0;
+ return line;
+};
+
+/**
+ * Makes an anchor with the given href, list of classes, list of children,
+ * and options.
+ */
+const makeAnchor = function (href, classes, children, options) {
+ const anchor = new Anchor(href, classes, children, options);
+ sizeElementFromChildren(anchor);
+ return anchor;
+};
+
+/**
+ * Makes a document fragment with the given list of children.
+ */
+const makeFragment = function (children) {
+ const fragment = new DocumentFragment(children);
+ sizeElementFromChildren(fragment);
+ return fragment;
+};
+
+/**
+ * Wraps group in a span if it's a document fragment, allowing to apply classes
+ * and styles
+ */
+const wrapFragment = function (group, options) {
+ if (group instanceof DocumentFragment) {
+ return makeSpan([], [group], options);
+ }
+ return group;
+};
+
+// A list of child or kern nodes to be stacked on top of each other (i.e. the
+// first element will be at the bottom, and the last at the top).
+
+// Computes the updated `children` list and the overall depth.
+//
+// This helper function for makeVList makes it easier to enforce type safety by
+// allowing early exits (returns) in the logic.
+const getVListChildrenAndDepth = function (params) {
+ if (params.positionType === "individualShift") {
+ const oldChildren = params.children;
+ const children = [oldChildren[0]];
+
+ // Add in kerns to the list of params.children to get each element to be
+ // shifted to the correct specified shift
+ const depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
+ let currPos = depth;
+ for (let i = 1; i < oldChildren.length; i++) {
+ const diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth;
+ const size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth);
+ currPos = currPos + diff;
+ children.push({
+ type: "kern",
+ size
+ });
+ children.push(oldChildren[i]);
+ }
+ return {
+ children,
+ depth
+ };
+ }
+ let depth;
+ if (params.positionType === "top") {
+ // We always start at the bottom, so calculate the bottom by adding up
+ // all the sizes
+ let bottom = params.positionData;
+ for (let i = 0; i < params.children.length; i++) {
+ const child = params.children[i];
+ bottom -= child.type === "kern" ? child.size : child.elem.height + child.elem.depth;
+ }
+ depth = bottom;
+ } else if (params.positionType === "bottom") {
+ depth = -params.positionData;
+ } else {
+ const firstChild = params.children[0];
+ if (firstChild.type !== "elem") {
+ throw new Error('First child must have type "elem".');
+ }
+ if (params.positionType === "shift") {
+ depth = -firstChild.elem.depth - params.positionData;
+ } else if (params.positionType === "firstBaseline") {
+ depth = -firstChild.elem.depth;
+ } else {
+ throw new Error("Invalid positionType " + params.positionType + ".");
+ }
+ }
+ return {
+ children: params.children,
+ depth
+ };
+};
+
+/**
+ * Makes a vertical list by stacking elements and kerns on top of each other.
+ * Allows for many different ways of specifying the positioning method.
+ *
+ * See VListParam documentation above.
+ */
+const makeVList = function (params, options) {
+ const _getVListChildrenAndD = getVListChildrenAndDepth(params),
+ children = _getVListChildrenAndD.children,
+ depth = _getVListChildrenAndD.depth;
+
+ // Create a strut that is taller than any list item. The strut is added to
+ // each item, where it will determine the item's baseline. Since it has
+ // `overflow:hidden`, the strut's top edge will sit on the item's line box's
+ // top edge and the strut's bottom edge will sit on the item's baseline,
+ // with no additional line-height spacing. This allows the item baseline to
+ // be positioned precisely without worrying about font ascent and
+ // line-height.
+ let pstrutSize = 0;
+ for (let i = 0; i < children.length; i++) {
+ const child = children[i];
+ if (child.type === "elem") {
+ const elem = child.elem;
+ pstrutSize = Math.max(pstrutSize, elem.maxFontSize, elem.height);
+ }
+ }
+ pstrutSize += 2;
+ const pstrut = makeSpan(["pstrut"], []);
+ pstrut.style.height = makeEm(pstrutSize);
+
+ // Create a new list of actual children at the correct offsets
+ const realChildren = [];
+ let minPos = depth;
+ let maxPos = depth;
+ let currPos = depth;
+ for (let i = 0; i < children.length; i++) {
+ const child = children[i];
+ if (child.type === "kern") {
+ currPos += child.size;
+ } else {
+ const elem = child.elem;
+ const classes = child.wrapperClasses || [];
+ const style = child.wrapperStyle || {};
+ const childWrap = makeSpan(classes, [pstrut, elem], undefined, style);
+ childWrap.style.top = makeEm(-pstrutSize - currPos - elem.depth);
+ if (child.marginLeft) {
+ childWrap.style.marginLeft = child.marginLeft;
+ }
+ if (child.marginRight) {
+ childWrap.style.marginRight = child.marginRight;
+ }
+ realChildren.push(childWrap);
+ currPos += elem.height + elem.depth;
+ }
+ minPos = Math.min(minPos, currPos);
+ maxPos = Math.max(maxPos, currPos);
+ }
+
+ // The vlist contents go in a table-cell with `vertical-align:bottom`.
+ // This cell's bottom edge will determine the containing table's baseline
+ // without overly expanding the containing line-box.
+ const vlist = makeSpan(["vlist"], realChildren);
+ vlist.style.height = makeEm(maxPos);
+
+ // A second row is used if necessary to represent the vlist's depth.
+ let rows;
+ if (minPos < 0) {
+ // We will define depth in an empty span with display: table-cell.
+ // It should render with the height that we define. But Chrome, in
+ // contenteditable mode only, treats that span as if it contains some
+ // text content. And that min-height over-rides our desired height.
+ // So we put another empty span inside the depth strut span.
+ const emptySpan = makeSpan([], []);
+ const depthStrut = makeSpan(["vlist"], [emptySpan]);
+ depthStrut.style.height = makeEm(-minPos);
+
+ // Safari wants the first row to have inline content; otherwise it
+ // puts the bottom of the *second* row on the baseline.
+ const topStrut = makeSpan(["vlist-s"], [new SymbolNode("\u200b")]);
+ rows = [makeSpan(["vlist-r"], [vlist, topStrut]), makeSpan(["vlist-r"], [depthStrut])];
+ } else {
+ rows = [makeSpan(["vlist-r"], [vlist])];
+ }
+ const vtable = makeSpan(["vlist-t"], rows);
+ if (rows.length === 2) {
+ vtable.classes.push("vlist-t2");
+ }
+ vtable.height = maxPos;
+ vtable.depth = -minPos;
+ return vtable;
+};
+
+// Glue is a concept from TeX which is a flexible space between elements in
+// either a vertical or horizontal list. In KaTeX, at least for now, it's
+// static space between elements in a horizontal layout.
+const makeGlue = (measurement, options) => {
+ // Make an empty span for the space
+ const rule = makeSpan(["mspace"], [], options);
+ const size = calculateSize(measurement, options);
+ rule.style.marginRight = makeEm(size);
+ return rule;
+};
+
+// Takes font options, and returns the appropriate fontLookup name
+const retrieveTextFontName = (fontFamily, fontWeight, fontShape) => {
+ let baseFontName;
+ let fontStylesName;
+ switch (fontFamily) {
+ case "amsrm":
+ baseFontName = "AMS";
+ break;
+ case "textrm":
+ baseFontName = "Main";
+ break;
+ case "textsf":
+ baseFontName = "SansSerif";
+ break;
+ case "texttt":
+ baseFontName = "Typewriter";
+ break;
+ default:
+ baseFontName = fontFamily;
+ // use fonts added by a plugin
+ }
+ if (fontWeight === "textbf" && fontShape === "textit") {
+ fontStylesName = "BoldItalic";
+ } else if (fontWeight === "textbf") {
+ fontStylesName = "Bold";
+ } else if (fontShape === "textit") {
+ fontStylesName = "Italic";
+ } else {
+ fontStylesName = "Regular";
+ }
+ return baseFontName + "-" + fontStylesName;
+};
+
+/**
+ * Maps TeX font commands to objects containing:
+ * - variant: string used for "mathvariant" attribute in buildMathML.js
+ * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics
+ */
+// A map between tex font commands an MathML mathvariant attribute values
+const fontMap = {
+ // styles
+ "mathbf": {
+ variant: "bold",
+ fontName: "Main-Bold"
+ },
+ "mathrm": {
+ variant: "normal",
+ fontName: "Main-Regular"
+ },
+ "textit": {
+ variant: "italic",
+ fontName: "Main-Italic"
+ },
+ "mathit": {
+ variant: "italic",
+ fontName: "Main-Italic"
+ },
+ "mathnormal": {
+ variant: "italic",
+ fontName: "Math-Italic"
+ },
+ "mathsfit": {
+ variant: "sans-serif-italic",
+ fontName: "SansSerif-Italic"
+ },
+ // "boldsymbol" is missing because they require the use of multiple fonts:
+ // Math-BoldItalic and Main-Bold. This is handled by a special case in
+ // makeOrd which ends up calling boldsymbol.
+
+ // families
+ "mathbb": {
+ variant: "double-struck",
+ fontName: "AMS-Regular"
+ },
+ "mathcal": {
+ variant: "script",
+ fontName: "Caligraphic-Regular"
+ },
+ "mathfrak": {
+ variant: "fraktur",
+ fontName: "Fraktur-Regular"
+ },
+ "mathscr": {
+ variant: "script",
+ fontName: "Script-Regular"
+ },
+ "mathsf": {
+ variant: "sans-serif",
+ fontName: "SansSerif-Regular"
+ },
+ "mathtt": {
+ variant: "monospace",
+ fontName: "Typewriter-Regular"
+ }
+};
+const svgData = {
+ // path, width, height
+ vec: ["vec", 0.471, 0.714],
+ // values from the font glyph
+ oiintSize1: ["oiintSize1", 0.957, 0.499],
+ // oval to overlay the integrand
+ oiintSize2: ["oiintSize2", 1.472, 0.659],
+ oiiintSize1: ["oiiintSize1", 1.304, 0.499],
+ oiiintSize2: ["oiiintSize2", 1.98, 0.659]
+};
+const staticSvg = function (value, options) {
+ // Create a span with inline SVG for the element.
+ const _svgData$value = svgData[value],
+ pathName = _svgData$value[0],
+ width = _svgData$value[1],
+ height = _svgData$value[2];
+ const path = new PathNode(pathName);
+ const svgNode = new SvgNode([path], {
+ "width": makeEm(width),
+ "height": makeEm(height),
+ // Override CSS rule `.katex svg { width: 100% }`
+ "style": "width:" + makeEm(width),
+ "viewBox": "0 0 " + 1000 * width + " " + 1000 * height,
+ "preserveAspectRatio": "xMinYMin"
+ });
+ const span = makeSvgSpan(["katex-overlay"], [svgNode], options);
+ span.height = height;
+ span.style.height = makeEm(height);
+ span.style.width = makeEm(width);
+ return span;
+};
+;// ./src/spacingData.ts
+/**
+ * Describes spaces between different classes of atoms.
+ */
+
+const thinspace = {
+ number: 3,
+ unit: "mu"
+};
+const mediumspace = {
+ number: 4,
+ unit: "mu"
+};
+const thickspace = {
+ number: 5,
+ unit: "mu"
+};
+
+// Making the type below exact with all optional fields doesn't work due to
+// - https://github.com/facebook/flow/issues/4582
+// - https://github.com/facebook/flow/issues/5688
+// However, since *all* fields are optional, $Shape<> works as suggested in 5688
+// above.
+
+// Spacing relationships for display and text styles
+const spacings = {
+ mord: {
+ mop: thinspace,
+ mbin: mediumspace,
+ mrel: thickspace,
+ minner: thinspace
+ },
+ mop: {
+ mord: thinspace,
+ mop: thinspace,
+ mrel: thickspace,
+ minner: thinspace
+ },
+ mbin: {
+ mord: mediumspace,
+ mop: mediumspace,
+ mopen: mediumspace,
+ minner: mediumspace
+ },
+ mrel: {
+ mord: thickspace,
+ mop: thickspace,
+ mopen: thickspace,
+ minner: thickspace
+ },
+ mopen: {},
+ mclose: {
+ mop: thinspace,
+ mbin: mediumspace,
+ mrel: thickspace,
+ minner: thinspace
+ },
+ mpunct: {
+ mord: thinspace,
+ mop: thinspace,
+ mrel: thickspace,
+ mopen: thinspace,
+ mclose: thinspace,
+ mpunct: thinspace,
+ minner: thinspace
+ },
+ minner: {
+ mord: thinspace,
+ mop: thinspace,
+ mbin: mediumspace,
+ mrel: thickspace,
+ mopen: thinspace,
+ mpunct: thinspace,
+ minner: thinspace
+ }
+};
+
+// Spacing relationships for script and scriptscript styles
+const tightSpacings = {
+ mord: {
+ mop: thinspace
+ },
+ mop: {
+ mord: thinspace,
+ mop: thinspace
+ },
+ mbin: {},
+ mrel: {},
+ mopen: {},
+ mclose: {
+ mop: thinspace
+ },
+ mpunct: {},
+ minner: {
+ mop: thinspace
+ }
+};
+;// ./src/defineFunction.ts
+/** Context provided to function handlers for error messages. */
+
+// Note: reverse the order of the return type union will cause a flow error.
+// See https://github.com/facebook/flow/issues/3663.
+
+// More general version of `HtmlBuilder` for nodes (e.g. \sum, accent types)
+// whose presence impacts super/subscripting. In this case, ParseNode<"supsub">
+// delegates its HTML building to the HtmlBuilder corresponding to these nodes.
+
+/**
+ * Parser-facing function spec. Optional properties should use the defaults
+ * documented below.
+ */
+
+/**
+ * Builder fields consumed during registration. These are stored separately in
+ * `_htmlGroupBuilders` and `_mathmlGroupBuilders`, and are not used by Parser.
+ */
+
+/**
+ * Full registration spec passed to `defineFunction`. It combines the
+ * parser-facing fields with optional builder fields and the names being
+ * registered.
+ */
+
+/**
+ * All registered functions.
+ * `functions.js` just exports this same dictionary again and makes it public.
+ * `Parser.js` requires this dictionary.
+ */
+const _functions = {};
+
+/**
+ * All HTML builders. Should be only used in the `define*` and the `build*ML`
+ * functions.
+ *
+ * Builders for different node types are stored side by side, but
+ * `HtmlBuilder<T>` is contravariant in `T`, so there is no single type
+ * argument that makes storing/retrieving them typecheck. `any` is used
+ * as an existential-quantifier escape hatch.
+ */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const _htmlGroupBuilders = {};
+
+/**
+ * All MathML builders. Should be only used in the `define*` and the `build*ML`
+ * functions. See `_htmlGroupBuilders` above for the rationale behind `any`.
+ */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const _mathmlGroupBuilders = {};
+function defineFunction(data) {
+ const type = data.type,
+ names = data.names,
+ htmlBuilder = data.htmlBuilder,
+ mathmlBuilder = data.mathmlBuilder;
+ for (let i = 0; i < names.length; ++i) {
+ // To avoid destructuring and rebuilding an object,
+ // we store the entire FunctionDefSpec object,
+ // even though Parser only needs the FunctionSpec fields.
+ _functions[names[i]] = data;
+ }
+ if (type) {
+ if (htmlBuilder) {
+ _htmlGroupBuilders[type] = htmlBuilder;
+ }
+ if (mathmlBuilder) {
+ _mathmlGroupBuilders[type] = mathmlBuilder;
+ }
+ }
+}
+
+/**
+ * Use this to register only the HTML and MathML builders for a function (e.g.
+ * if the function's ParseNode is generated in Parser.js rather than via a
+ * stand-alone handler provided to `defineFunction`).
+ */
+function defineFunctionBuilders(_ref) {
+ let type = _ref.type,
+ htmlBuilder = _ref.htmlBuilder,
+ mathmlBuilder = _ref.mathmlBuilder;
+ if (htmlBuilder) {
+ _htmlGroupBuilders[type] = htmlBuilder;
+ }
+ if (mathmlBuilder) {
+ _mathmlGroupBuilders[type] = mathmlBuilder;
+ }
+}
+const normalizeArgument = function (arg) {
+ return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg;
+};
+
+// Since the corresponding buildHTML/buildMathML function expects a
+// list of elements, we normalize for different kinds of arguments
+const ordargument = function (arg) {
+ return arg.type === "ordgroup" ? arg.body : [arg];
+};
+;// ./src/buildHTML.ts
+/**
+ * This file does the main work of building a domTree structure from a parse
+ * tree. The entry point is the `buildHTML` function, which takes a parse tree.
+ * Then, the buildExpression, buildGroup, and various groupBuilders functions
+ * are called, to produce a final HTML tree.
+ */
+
+
+
+
+
+
+
+
+
+// Binary atoms (first class `mbin`) change into ordinary atoms (`mord`)
+// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6,
+// and the text before Rule 19.
+const binLeftCanceller = new Set(["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"]);
+const binRightCanceller = new Set(["rightmost", "mrel", "mclose", "mpunct"]);
+const styleMap = {
+ "display": src_Style.DISPLAY,
+ "text": src_Style.TEXT,
+ "script": src_Style.SCRIPT,
+ "scriptscript": src_Style.SCRIPTSCRIPT
+};
+const DomEnum = {
+ mord: "mord",
+ mop: "mop",
+ mbin: "mbin",
+ mrel: "mrel",
+ mopen: "mopen",
+ mclose: "mclose",
+ mpunct: "mpunct",
+ minner: "minner"
+};
+/**
+ * Take a list of nodes, build them in order, and return a list of the built
+ * nodes. documentFragments are flattened into their contents, so the
+ * returned list contains no fragments. `isRealGroup` is true if `expression`
+ * is a real group (no atoms will be added on either side), as opposed to
+ * a partial group (e.g. one created by \color). `surrounding` is an array
+ * consisting type of nodes that will be added to the left and right.
+ */
+const buildExpression = function (expression, options, isRealGroup, surrounding) {
+ if (surrounding === void 0) {
+ surrounding = [null, null];
+ }
+ // Parse expressions into `groups`.
+ const groups = [];
+ for (let i = 0; i < expression.length; i++) {
+ const output = buildGroup(expression[i], options);
+ if (output instanceof DocumentFragment) {
+ const children = output.children;
+ groups.push(...children);
+ } else {
+ groups.push(output);
+ }
+ }
+
+ // Combine consecutive domTree.symbolNodes into a single symbolNode.
+ tryCombineChars(groups);
+
+ // If `expression` is a partial group, let the parent handle spacings
+ // to avoid processing groups multiple times.
+ if (!isRealGroup) {
+ return groups;
+ }
+ let glueOptions = options;
+ if (expression.length === 1) {
+ const node = expression[0];
+ if (node.type === "sizing") {
+ glueOptions = options.havingSize(node.size);
+ } else if (node.type === "styling") {
+ glueOptions = options.havingStyle(styleMap[node.style]);
+ }
+ }
+
+ // Dummy spans for determining spacings between surrounding atoms.
+ // If `expression` has no atoms on the left or right, class "leftmost"
+ // or "rightmost", respectively, is used to indicate it.
+ const dummyPrev = makeSpan([surrounding[0] || "leftmost"], [], options);
+ const dummyNext = makeSpan([surrounding[1] || "rightmost"], [], options);
+
+ // TODO: These code assumes that a node's math class is the first element
+ // of its `classes` array. A later cleanup should ensure this, for
+ // instance by changing the signature of `makeSpan`.
+
+ // Before determining what spaces to insert, perform bin cancellation.
+ // Binary operators change to ordinary symbols in some contexts.
+ const isRoot = isRealGroup === "root";
+ traverseNonSpaceNodes(groups, (node, prev) => {
+ const prevType = prev.classes[0];
+ const type = node.classes[0];
+ if (prevType === "mbin" && binRightCanceller.has(type)) {
+ prev.classes[0] = "mord";
+ } else if (type === "mbin" && binLeftCanceller.has(prevType)) {
+ node.classes[0] = "mord";
+ }
+ }, {
+ node: dummyPrev
+ }, dummyNext, isRoot);
+ traverseNonSpaceNodes(groups, (node, prev) => {
+ var _tightSpacings$prevTy, _spacings$prevType;
+ const prevType = getTypeOfDomTree(prev);
+ const type = getTypeOfDomTree(node);
+
+ // 'mtight' indicates that the node is script or scriptscript style.
+ const space = prevType && type ? node.hasClass("mtight") ? (_tightSpacings$prevTy = tightSpacings[prevType]) == null ? void 0 : _tightSpacings$prevTy[type] : (_spacings$prevType = spacings[prevType]) == null ? void 0 : _spacings$prevType[type] : null;
+ if (space) {
+ // Insert glue (spacing) after the `prev`.
+ return makeGlue(space, glueOptions);
+ }
+ }, {
+ node: dummyPrev
+ }, dummyNext, isRoot);
+ return groups;
+};
+
+// Depth-first traverse non-space `nodes`, calling `callback` with the current and
+// previous node as arguments, optionally returning a node to insert after the
+// previous node. `prev` is an object with the previous node and `insertAfter`
+// function to insert after it. `next` is a node that will be added to the right.
+// Used for bin cancellation and inserting spacings.
+const traverseNonSpaceNodes = function (nodes, callback, prev, next, isRoot) {
+ if (next) {
+ // temporarily append the right node, if exists
+ nodes.push(next);
+ }
+ let i = 0;
+ for (; i < nodes.length; i++) {
+ const node = nodes[i];
+ const partialGroup = checkPartialGroup(node);
+ if (partialGroup) {
+ // Recursive DFS
+ // TODO(ts): partialGroup.children is ReadonlyArray but this
+ // function mutates the array (insertAfter splices into it).
+ traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot);
+ continue;
+ }
+
+ // Ignore explicit spaces (e.g., \;, \,) when determining what implicit
+ // spacing should go between atoms of different classes
+ const nonspace = !node.hasClass("mspace");
+ if (nonspace) {
+ const result = callback(node, prev.node);
+ if (result) {
+ if (prev.insertAfter) {
+ prev.insertAfter(result);
+ } else {
+ // insert at front
+ nodes.unshift(result);
+ i++;
+ }
+ }
+ }
+ if (nonspace) {
+ prev.node = node;
+ } else if (isRoot && node.hasClass("katex-newline")) {
+ prev.node = makeSpan(["leftmost"]); // treat like beginning of line
+ }
+ prev.insertAfter = (index => n => {
+ nodes.splice(index + 1, 0, n);
+ i++;
+ })(i);
+ }
+ if (next) {
+ nodes.pop();
+ }
+};
+
+// Check if given node is a partial group, i.e., does not affect spacing around.
+const checkPartialGroup = function (node) {
+ if (node instanceof DocumentFragment || node instanceof Anchor || node instanceof Span && node.hasClass("enclosing")) {
+ return node;
+ }
+ return null;
+};
+
+// Return the outermost node of a domTree.
+const getOutermostNode = function (node, side) {
+ const partialGroup = checkPartialGroup(node);
+ if (partialGroup) {
+ const children = partialGroup.children;
+ if (children.length) {
+ if (side === "right") {
+ return getOutermostNode(children[children.length - 1], "right");
+ } else if (side === "left") {
+ return getOutermostNode(children[0], "left");
+ }
+ }
+ }
+ return node;
+};
+
+// Return math atom class (mclass) of a domTree.
+// If `side` is given, it will get the type of the outermost node at given side.
+const getTypeOfDomTree = function (node, side) {
+ if (!node) {
+ return null;
+ }
+ if (side) {
+ node = getOutermostNode(node, side);
+ }
+ // This makes a lot of assumptions as to where the type of atom
+ // appears. We should do a better job of enforcing this.
+ const className = node.classes[0];
+ return DomEnum[className] || null;
+};
+const makeNullDelimiter = function (options, classes) {
+ const moreClasses = ["nulldelimiter"].concat(options.baseSizingClasses());
+ return makeSpan(classes.concat(moreClasses));
+};
+
+/**
+ * buildGroup is the function that takes a group and calls the correct groupType
+ * function for it. It also handles the interaction of size and style changes
+ * between parents and children.
+ */
+const buildGroup = function (group, options, baseOptions) {
+ if (!group) {
+ return makeSpan();
+ }
+ if (_htmlGroupBuilders[group.type]) {
+ // TODO(ts): groupBuilders is Record<string, HtmlBuilder<any>>;
+ // a type-safe registry would need a mapped type keyed by NodeType.
+ let groupNode = _htmlGroupBuilders[group.type](group, options);
+
+ // If the size changed between the parent and the current group, account
+ // for that size difference.
+ if (baseOptions && options.size !== baseOptions.size) {
+ groupNode = makeSpan(options.sizingClasses(baseOptions), [groupNode], options);
+ const multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier;
+ groupNode.height *= multiplier;
+ groupNode.depth *= multiplier;
+ }
+ return groupNode;
+ } else {
+ throw new src_ParseError("Got group of unknown type: '" + group.type + "'");
+ }
+};
+
+/**
+ * Combine an array of HTML DOM nodes (e.g., the output of `buildExpression`)
+ * into an unbreakable HTML node of class .katex-base, with proper struts to
+ * guarantee correct vertical extent. `buildHTML` calls this repeatedly to
+ * make up the entire expression as a sequence of unbreakable units.
+ */
+function buildHTMLUnbreakable(children, options) {
+ // Compute height and depth of this chunk.
+ const body = makeSpan(["katex-base"], children, options);
+
+ // Add strut, which ensures that the top of the HTML element falls at
+ // the height of the expression, and the bottom of the HTML element
+ // falls at the depth of the expression.
+ const strut = makeSpan(["katex-strut"]);
+ strut.style.height = makeEm(body.height + body.depth);
+ if (body.depth) {
+ strut.style.verticalAlign = makeEm(-body.depth);
+ }
+ body.children.unshift(strut);
+ return body;
+}
+
+/**
+ * Take an entire parse tree, and build it into an appropriate set of HTML
+ * nodes.
+ */
+function buildHTML(tree, options) {
+ // Strip off outer tag wrapper for processing below.
+ let tag = null;
+ if (tree.length === 1 && tree[0].type === "tag") {
+ tag = tree[0].tag;
+ tree = tree[0].body;
+ }
+
+ // Build the expression contained in the tree
+ const expression = buildExpression(tree, options, "root");
+ let eqnNum;
+ if (expression.length === 2 && expression[1].hasClass("katex-tag")) {
+ // An environment with automatic equation numbers, e.g. {gather}.
+ eqnNum = expression.pop();
+ }
+ const children = [];
+
+ // Create one base node for each chunk between potential line breaks.
+ // The TeXBook [p.173] says "A formula will be broken only after a
+ // relation symbol like $=$ or $<$ or $\rightarrow$, or after a binary
+ // operation symbol like $+$ or $-$ or $\times$, where the relation or
+ // binary operation is on the ``outer level'' of the formula (i.e., not
+ // enclosed in {...} and not part of an \over construction)."
+
+ let parts = [];
+ for (let i = 0; i < expression.length; i++) {
+ parts.push(expression[i]);
+ if (expression[i].hasClass("mbin") || expression[i].hasClass("mrel") || expression[i].hasClass("allowbreak")) {
+ // Put any post-operator glue on same line as operator.
+ // Watch for \nobreak along the way, and stop at \newline.
+ let nobreak = false;
+ while (i < expression.length - 1 && expression[i + 1].hasClass("mspace") && !expression[i + 1].hasClass("katex-newline")) {
+ i++;
+ parts.push(expression[i]);
+ if (expression[i].hasClass("nobreak")) {
+ nobreak = true;
+ }
+ }
+ // Don't allow break if \nobreak among the post-operator glue.
+ if (!nobreak) {
+ children.push(buildHTMLUnbreakable(parts, options));
+ parts = [];
+ }
+ } else if (expression[i].hasClass("katex-newline")) {
+ // Write the line except the newline
+ parts.pop();
+ if (parts.length > 0) {
+ children.push(buildHTMLUnbreakable(parts, options));
+ parts = [];
+ }
+ // Put the newline at the top level
+ children.push(expression[i]);
+ }
+ }
+ if (parts.length > 0) {
+ children.push(buildHTMLUnbreakable(parts, options));
+ }
+
+ // Now, if there was a tag, build it too and append it as a final child.
+ let tagChild;
+ if (tag) {
+ tagChild = buildHTMLUnbreakable(buildExpression(tag, options, true), options);
+ tagChild.classes = ["katex-tag"];
+ children.push(tagChild);
+ } else if (eqnNum) {
+ children.push(eqnNum);
+ }
+ const htmlNode = makeSpan(["katex-html"], children);
+ htmlNode.setAttribute("aria-hidden", "true");
+
+ // Adjust the strut of the tag to be the maximum height of all children
+ // (the height of the enclosing htmlNode) for proper vertical alignment.
+ if (tagChild) {
+ const strut = tagChild.children[0];
+ strut.style.height = makeEm(htmlNode.height + htmlNode.depth);
+ if (htmlNode.depth) {
+ strut.style.verticalAlign = makeEm(-htmlNode.depth);
+ }
+ }
+ return htmlNode;
+}
+;// ./src/mathMLTree.ts
+/**
+ * These objects store data about MathML nodes. This is the MathML equivalent
+ * of the types in domTree.js. Since MathML handles its own rendering, and
+ * since we're mainly using MathML to improve accessibility, we don't manage
+ * any of the styling state that the plain DOM nodes do.
+ *
+ * The `toNode` and `toMarkup` functions work similarly to how they do in
+ * domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
+ */
+
+
+
+
+
+
+/**
+ * MathML node types used in KaTeX. For a complete list of MathML nodes, see
+ * https://developer.mozilla.org/en-US/docs/Web/MathML/Element.
+ */
+
+function newDocumentFragment(children) {
+ return new DocumentFragment(children);
+}
+
+/**
+ * This node represents a general purpose MathML node of any type. The
+ * constructor requires the type of node to create (for example, `"mo"` or
+ * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags).
+ */
+class MathNode {
+ constructor(type, children, classes) {
+ this.type = void 0;
+ this.attributes = void 0;
+ this.children = void 0;
+ this.classes = void 0;
+ this.type = type;
+ this.attributes = {};
+ this.children = children || [];
+ this.classes = classes || [];
+ }
+
+ /**
+ * Sets an attribute on a MathML node. MathML depends on attributes to convey a
+ * semantic content, so this is used heavily.
+ */
+ setAttribute(name, value) {
+ this.attributes[name] = value;
+ }
+
+ /**
+ * Gets an attribute on a MathML node.
+ */
+ getAttribute(name) {
+ return this.attributes[name];
+ }
+
+ /**
+ * Converts the math node into a MathML-namespaced DOM element.
+ */
+ toNode() {
+ const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type);
+ for (const _ref of Object.entries(this.attributes)) {
+ const attr = _ref[0];
+ const value = _ref[1];
+ node.setAttribute(attr, value);
+ }
+ if (this.classes.length > 0) {
+ node.className = createClass(this.classes);
+ }
+ for (let i = 0; i < this.children.length; i++) {
+ // Combine multiple TextNodes into one TextNode, to prevent
+ // screen readers from reading each as a separate word [#3995]
+ if (this.children[i] instanceof TextNode && this.children[i + 1] instanceof TextNode) {
+ let text = this.children[i].toText() + this.children[++i].toText();
+ while (this.children[i + 1] instanceof TextNode) {
+ text += this.children[++i].toText();
+ }
+ node.appendChild(new TextNode(text).toNode());
+ } else {
+ node.appendChild(this.children[i].toNode());
+ }
+ }
+ return node;
+ }
+
+ /**
+ * Converts the math node into an HTML markup string.
+ */
+ toMarkup() {
+ let markup = "<" + this.type;
+
+ // Add the attributes
+ for (const _ref2 of Object.entries(this.attributes)) {
+ const attr = _ref2[0];
+ const value = _ref2[1];
+ markup += " " + attr + "=\"";
+ markup += utils_escape(value);
+ markup += "\"";
+ }
+ if (this.classes.length > 0) {
+ markup += " class =\"" + utils_escape(createClass(this.classes)) + "\"";
+ }
+ markup += ">";
+ for (let i = 0; i < this.children.length; i++) {
+ markup += this.children[i].toMarkup();
+ }
+ markup += "</" + this.type + ">";
+ return markup;
+ }
+
+ /**
+ * Converts the math node into a string, similar to innerText, but escaped.
+ */
+ toText() {
+ return this.children.map(child => child.toText()).join("");
+ }
+}
+
+/**
+ * This node represents a piece of text.
+ */
+class TextNode {
+ constructor(text) {
+ this.text = void 0;
+ this.text = text;
+ }
+
+ /**
+ * Converts the text node into a DOM text node.
+ */
+ toNode() {
+ return document.createTextNode(this.text);
+ }
+
+ /**
+ * Converts the text node into escaped HTML markup
+ * (representing the text itself).
+ */
+ toMarkup() {
+ return utils_escape(this.toText());
+ }
+
+ /**
+ * Converts the text node into a string
+ * (representing the text itself).
+ */
+ toText() {
+ return this.text;
+ }
+}
+
+/**
+ * This node represents a space, but may render as <mspace.../> or as text,
+ * depending on the width.
+ */
+class SpaceNode {
+ /**
+ * Create a Space node with width given in CSS ems.
+ */
+ constructor(width) {
+ this.width = void 0;
+ this.character = void 0;
+ this.width = width;
+ // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html
+ // for a table of space-like characters. We use Unicode
+ // representations instead of &LongNames; as it's not clear how to
+ // make the latter via document.createTextNode.
+ if (width >= 0.05555 && width <= 0.05556) {
+ this.character = "\u200a"; // &VeryThinSpace;
+ } else if (width >= 0.1666 && width <= 0.1667) {
+ this.character = "\u2009"; // &ThinSpace;
+ } else if (width >= 0.2222 && width <= 0.2223) {
+ this.character = "\u2005"; // &MediumSpace;
+ } else if (width >= 0.2777 && width <= 0.2778) {
+ this.character = "\u2005\u200a"; // &ThickSpace;
+ } else if (width >= -0.05556 && width <= -0.05555) {
+ this.character = "\u200a\u2063"; // &NegativeVeryThinSpace;
+ } else if (width >= -0.1667 && width <= -0.1666) {
+ this.character = "\u2009\u2063"; // &NegativeThinSpace;
+ } else if (width >= -0.2223 && width <= -0.2222) {
+ this.character = "\u205f\u2063"; // &NegativeMediumSpace;
+ } else if (width >= -0.2778 && width <= -0.2777) {
+ this.character = "\u2005\u2063"; // &NegativeThickSpace;
+ } else {
+ this.character = null;
+ }
+ }
+
+ /**
+ * Converts the math node into a MathML-namespaced DOM element.
+ */
+ toNode() {
+ if (this.character) {
+ return document.createTextNode(this.character);
+ } else {
+ const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace");
+ node.setAttribute("width", makeEm(this.width));
+ return node;
+ }
+ }
+
+ /**
+ * Converts the math node into an HTML markup string.
+ */
+ toMarkup() {
+ if (this.character) {
+ return "<mtext>" + this.character + "</mtext>";
+ } else {
+ return "<mspace width=\"" + makeEm(this.width) + "\"/>";
+ }
+ }
+
+ /**
+ * Converts the math node into a string, similar to innerText.
+ */
+ toText() {
+ if (this.character) {
+ return this.character;
+ } else {
+ return " ";
+ }
+ }
+}
+;// ./src/buildMathML.ts
+/**
+ * This file converts a parse tree into a corresponding MathML tree. The main
+ * entry point is the `buildMathML` function, which takes a parse tree from the
+ * parser.
+ */
+
+
+
+
+
+
+
+const noVariantSymbols = new Set(["\\imath", "\\jmath"]);
+const rowLikeTypes = new Set(["mrow", "mtable"]);
+
+/**
+ * Takes a symbol and converts it into a MathML text node after performing
+ * optional replacement from symbols.js.
+ */
+const makeText = function (text, mode, options) {
+ var _options$fontFamily, _options$font;
+ if (src_symbols[mode][text] && src_symbols[mode][text].replace && text.charCodeAt(0) !== 0xD835 && !(Object.prototype.hasOwnProperty.call(ligatures, text) && ((options == null || (_options$fontFamily = options.fontFamily) == null ? void 0 : _options$fontFamily.slice(4, 6)) === "tt" || (options == null || (_options$font = options.font) == null ? void 0 : _options$font.slice(4, 6)) === "tt"))) {
+ text = src_symbols[mode][text].replace;
+ }
+ return new TextNode(text);
+};
+
+/**
+ * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
+ * unless the array has length 1. Always returns a single node.
+ */
+const makeRow = function (body) {
+ if (body.length === 1) {
+ return body[0];
+ } else {
+ return new MathNode("mrow", body);
+ }
+};
+const mathFontVariants = {
+ mathit: "italic",
+ boldsymbol: group => group.type === "textord" ? "bold" : "bold-italic",
+ mathbf: "bold",
+ mathbb: "double-struck",
+ mathsfit: "sans-serif-italic",
+ mathfrak: "fraktur",
+ mathscr: "script",
+ mathcal: "script",
+ mathsf: "sans-serif",
+ mathtt: "monospace"
+};
+
+/**
+ * Returns the math variant as a string or null if none is required.
+ */
+const getVariant = (group, options) => {
+ // Handle \text... font specifiers as best we can.
+ // MathML has a limited list of allowable mathvariant specifiers; see
+ // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt
+ if (group.mode === "text") {
+ if (options.fontFamily === "texttt") {
+ return "monospace";
+ } else if (options.fontFamily === "textsf") {
+ if (options.fontShape === "textit" && options.fontWeight === "textbf") {
+ return "sans-serif-bold-italic";
+ } else if (options.fontShape === "textit") {
+ return "sans-serif-italic";
+ } else if (options.fontWeight === "textbf") {
+ return "bold-sans-serif";
+ } else {
+ return "sans-serif";
+ }
+ } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
+ return "bold-italic";
+ } else if (options.fontShape === "textit") {
+ return "italic";
+ } else if (options.fontWeight === "textbf") {
+ return "bold";
+ }
+ }
+ const font = options.font;
+ if (!font || font === "mathnormal") {
+ return null;
+ }
+ const mode = group.mode;
+ const mathVariant = mathFontVariants[font];
+ if (mathVariant) {
+ return typeof mathVariant === "function" ? mathVariant(group) : mathVariant;
+ }
+ let text = group.text;
+ if (noVariantSymbols.has(text)) {
+ return null;
+ }
+ if (src_symbols[mode][text]) {
+ const replacement = src_symbols[mode][text].replace;
+ if (replacement) {
+ text = replacement;
+ }
+ }
+ const fontName = fontMap[font].fontName;
+ if (getCharacterMetrics(text, fontName, mode)) {
+ return fontMap[font].variant;
+ }
+ return null;
+};
+
+/**
+ * Check for <mi>.</mi> which is how a dot renders in MathML,
+ * or <mo separator="true" lspace="0em" rspace="0em">,</mo>
+ * which is how a braced comma {,} renders in MathML
+ */
+function isNumberPunctuation(group) {
+ if (!group) {
+ return false;
+ }
+ if (group.type === 'mi' && group.children.length === 1) {
+ const child = group.children[0];
+ return child instanceof TextNode && child.text === '.';
+ } else if (group.type === 'mo' && group.children.length === 1 && group.getAttribute('separator') === 'true' && group.getAttribute('lspace') === '0em' && group.getAttribute('rspace') === '0em') {
+ const child = group.children[0];
+ return child instanceof TextNode && child.text === ',';
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Takes a list of nodes, builds them, and returns a list of the generated
+ * MathML nodes. Also combine consecutive <mtext> outputs into a single
+ * <mtext> tag.
+ */
+const buildMathML_buildExpression = function (expression, options, isOrdgroup) {
+ if (expression.length === 1) {
+ const group = buildMathML_buildGroup(expression[0], options);
+ if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
+ // When TeX writers want to suppress spacing on an operator,
+ // they often put the operator by itself inside braces.
+ group.setAttribute("lspace", "0em");
+ group.setAttribute("rspace", "0em");
+ }
+ return [group];
+ }
+ const groups = [];
+ let lastGroup;
+ for (let i = 0; i < expression.length; i++) {
+ const group = buildMathML_buildGroup(expression[i], options);
+ if (group instanceof MathNode && lastGroup instanceof MathNode) {
+ // Concatenate adjacent <mtext>s
+ if (group.type === 'mtext' && lastGroup.type === 'mtext' && group.getAttribute('mathvariant') === lastGroup.getAttribute('mathvariant')) {
+ lastGroup.children.push(...group.children);
+ continue;
+ // Concatenate adjacent <mn>s
+ } else if (group.type === 'mn' && lastGroup.type === 'mn') {
+ lastGroup.children.push(...group.children);
+ continue;
+ // Concatenate <mn>...</mn> followed by <mi>.</mi>
+ } else if (isNumberPunctuation(group) && lastGroup.type === 'mn') {
+ lastGroup.children.push(...group.children);
+ continue;
+ // Concatenate <mi>.</mi> followed by <mn>...</mn>
+ } else if (group.type === 'mn' && isNumberPunctuation(lastGroup)) {
+ group.children = [...lastGroup.children, ...group.children];
+ groups.pop();
+ // Put preceding <mn>...</mn> or <mi>.</mi> inside base of
+ // <msup><mn>...base...</mn>...exponent...</msup> (or <msub>)
+ } else if ((group.type === 'msup' || group.type === 'msub') && group.children.length >= 1 && (lastGroup.type === 'mn' || isNumberPunctuation(lastGroup))) {
+ const base = group.children[0];
+ if (base instanceof MathNode && base.type === 'mn') {
+ base.children = [...lastGroup.children, ...base.children];
+ groups.pop();
+ }
+ // \not
+ } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) {
+ const lastChild = lastGroup.children[0];
+ if (lastChild instanceof TextNode && lastChild.text === '\u0338' && (group.type === 'mo' || group.type === 'mi' || group.type === 'mn')) {
+ const child = group.children[0];
+ if (child instanceof TextNode && child.text.length > 0) {
+ // Overlay with combining character long solidus
+ child.text = child.text.slice(0, 1) + "\u0338" + child.text.slice(1);
+ groups.pop();
+ }
+ }
+ }
+ }
+ groups.push(group);
+ lastGroup = group;
+ }
+ return groups;
+};
+
+/**
+ * Equivalent to buildExpression, but wraps the elements in an <mrow>
+ * if there's more than one. Returns a single node instead of an array.
+ */
+const buildExpressionRow = function (expression, options, isOrdgroup) {
+ return makeRow(buildMathML_buildExpression(expression, options, isOrdgroup));
+};
+
+/**
+ * Takes a group from the parser and calls the appropriate groupBuilders function
+ * on it to produce a MathML node.
+ */
+const buildMathML_buildGroup = function (group, options) {
+ if (!group) {
+ return new MathNode("mrow");
+ }
+ if (_mathmlGroupBuilders[group.type]) {
+ // TODO(ts): MathMLBuilder returns MathDomNode but all concrete
+ // builders return MathNode. Widening the return type here would
+ // require updating all callers that assume MathNode.
+ return _mathmlGroupBuilders[group.type](group, options);
+ } else {
+ throw new src_ParseError("Got group of unknown type: '" + group.type + "'");
+ }
+};
+
+/**
+ * Takes a full parse tree and settings and builds a MathML representation of
+ * it. In particular, we put the elements from building the parse tree into a
+ * <semantics> tag so we can also include that TeX source as an annotation.
+ *
+ * Note that we actually return a domTree element with a `<math>` inside it so
+ * we can do appropriate styling.
+ */
+function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly) {
+ const expression = buildMathML_buildExpression(tree, options);
+
+ // TODO: Make a pass thru the MathML similar to buildHTML.traverseNonSpaceNodes
+ // and add spacing nodes. This is necessary only adjacent to math operators
+ // like \sin or \lim or to subsup elements that contain math operators.
+ // MathML takes care of the other spacing issues.
+
+ // Wrap up the expression in an mrow so it is presented in the semantics
+ // tag correctly, unless it's a single <mrow> or <mtable>.
+ let wrapper;
+ if (expression.length === 1 && expression[0] instanceof MathNode && rowLikeTypes.has(expression[0].type)) {
+ wrapper = expression[0];
+ } else {
+ wrapper = new MathNode("mrow", expression);
+ }
+
+ // Build a TeX annotation of the source
+ const annotation = new MathNode("annotation", [new TextNode(texExpression)]);
+ annotation.setAttribute("encoding", "application/x-tex");
+ const semantics = new MathNode("semantics", [wrapper, annotation]);
+ const math = new MathNode("math", [semantics]);
+ math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
+ if (isDisplayMode) {
+ math.setAttribute("display", "block");
+ }
+
+ // You can't style <math> nodes, so we wrap the node in a span.
+ // NOTE: The span class is not typed to have <math> nodes as children, and
+ // we don't want to make the children type more generic since the children
+ // of span are expected to have more fields in `buildHtml` contexts.
+ // The MathNode implements VirtualNode (toNode/toMarkup) which is all that
+ // Span needs from its children for rendering.
+ // TODO(ts): Span's child type is HtmlDomNode, but MathNode only implements
+ // VirtualNode. The double-cast acknowledges this architectural limitation.
+ const wrapperClass = forMathmlOnly ? "katex" : "katex-mathml";
+ return makeSpan([wrapperClass], [math]);
+}
+;// ./src/Options.ts
+/**
+ * This file contains information about the options that the Parser carries
+ * around with it while parsing. Data is held in an `Options` object, and when
+ * recursing, a new `Options` object can be created with the `.with*` and
+ * `.reset` functions.
+ */
+
+
+const sizeStyleMap = [
+// Each element contains [textsize, scriptsize, scriptscriptsize].
+// The size mappings are taken from TeX with \normalsize=10pt.
+[1, 1, 1],
+// size1: [5, 5, 5] \tiny
+[2, 1, 1],
+// size2: [6, 5, 5]
+[3, 1, 1],
+// size3: [7, 5, 5] \scriptsize
+[4, 2, 1],
+// size4: [8, 6, 5] \footnotesize
+[5, 2, 1],
+// size5: [9, 6, 5] \small
+[6, 3, 1],
+// size6: [10, 7, 5] \normalsize
+[7, 4, 2],
+// size7: [12, 8, 6] \large
+[8, 6, 3],
+// size8: [14.4, 10, 7] \Large
+[9, 7, 6],
+// size9: [17.28, 12, 10] \LARGE
+[10, 8, 7],
+// size10: [20.74, 14.4, 12] \huge
+[11, 10, 9] // size11: [24.88, 20.74, 17.28] \HUGE
+];
+const sizeMultipliers = [
+// fontMetrics.js:getGlobalMetrics also uses size indexes, so if
+// you change size indexes, change that function.
+0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488];
+const sizeAtStyle = function (size, style) {
+ return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1];
+};
+/**
+ * This is the main options class. It contains the current style, size, color,
+ * and font.
+ *
+ * Options objects should not be modified. To create a new Options with
+ * different properties, call a `.having*` method.
+ */
+class Options {
+ constructor(data) {
+ this.style = void 0;
+ this.color = void 0;
+ this.size = void 0;
+ this.textSize = void 0;
+ this.phantom = void 0;
+ // A font family applies to a group of fonts (i.e. SansSerif), while a font
+ // represents a specific font (i.e. SansSerif Bold).
+ // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
+ this.font = void 0;
+ this.fontFamily = void 0;
+ this.fontWeight = void 0;
+ this.fontShape = void 0;
+ this.sizeMultiplier = void 0;
+ this.maxSize = void 0;
+ this.minRuleThickness = void 0;
+ this._fontMetrics = void 0;
+ this.style = data.style;
+ this.color = data.color;
+ this.size = data.size || Options.BASESIZE;
+ this.textSize = data.textSize || this.size;
+ this.phantom = !!data.phantom;
+ this.font = data.font || "";
+ this.fontFamily = data.fontFamily || "";
+ this.fontWeight = data.fontWeight || "";
+ this.fontShape = data.fontShape || "";
+ this.sizeMultiplier = sizeMultipliers[this.size - 1];
+ this.maxSize = data.maxSize;
+ this.minRuleThickness = data.minRuleThickness;
+ this._fontMetrics = undefined;
+ }
+
+ /**
+ * Returns a new options object with the same properties as "this". Properties
+ * from "extension" will be copied to the new options object.
+ */
+ extend(extension) {
+ const data = {
+ style: this.style,
+ size: this.size,
+ textSize: this.textSize,
+ color: this.color,
+ phantom: this.phantom,
+ font: this.font,
+ fontFamily: this.fontFamily,
+ fontWeight: this.fontWeight,
+ fontShape: this.fontShape,
+ maxSize: this.maxSize,
+ minRuleThickness: this.minRuleThickness
+ };
+ Object.assign(data, extension);
+ return new Options(data);
+ }
+
+ /**
+ * Return an options object with the given style. If `this.style === style`,
+ * returns `this`.
+ */
+ havingStyle(style) {
+ if (this.style === style) {
+ return this;
+ } else {
+ return this.extend({
+ style: style,
+ size: sizeAtStyle(this.textSize, style)
+ });
+ }
+ }
+
+ /**
+ * Return an options object with a cramped version of the current style. If
+ * the current style is cramped, returns `this`.
+ */
+ havingCrampedStyle() {
+ return this.havingStyle(this.style.cramp());
+ }
+
+ /**
+ * Return an options object with the given size and in at least `\textstyle`.
+ * Returns `this` if appropriate.
+ */
+ havingSize(size) {
+ if (this.size === size && this.textSize === size) {
+ return this;
+ } else {
+ return this.extend({
+ style: this.style.text(),
+ size: size,
+ textSize: size,
+ sizeMultiplier: sizeMultipliers[size - 1]
+ });
+ }
+ }
+
+ /**
+ * Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted,
+ * changes to at least `\textstyle`.
+ */
+ havingBaseStyle(style) {
+ style = style || this.style.text();
+ const wantSize = sizeAtStyle(Options.BASESIZE, style);
+ if (this.size === wantSize && this.textSize === Options.BASESIZE && this.style === style) {
+ return this;
+ } else {
+ return this.extend({
+ style: style,
+ size: wantSize
+ });
+ }
+ }
+
+ /**
+ * Remove the effect of sizing changes such as \Huge.
+ * Keep the effect of the current style, such as \scriptstyle.
+ */
+ havingBaseSizing() {
+ let size;
+ switch (this.style.id) {
+ case 4:
+ case 5:
+ size = 3; // normalsize in scriptstyle
+ break;
+ case 6:
+ case 7:
+ size = 1; // normalsize in scriptscriptstyle
+ break;
+ default:
+ size = 6;
+ // normalsize in textstyle or displaystyle
+ }
+ return this.extend({
+ style: this.style.text(),
+ size: size
+ });
+ }
+
+ /**
+ * Create a new options object with the given color.
+ */
+ withColor(color) {
+ return this.extend({
+ color: color
+ });
+ }
+
+ /**
+ * Create a new options object with "phantom" set to true.
+ */
+ withPhantom() {
+ return this.extend({
+ phantom: true
+ });
+ }
+
+ /**
+ * Creates a new options object with the given math font or old text font.
+ * @type {[type]}
+ */
+ withFont(font) {
+ return this.extend({
+ font
+ });
+ }
+
+ /**
+ * Create a new options objects with the given fontFamily.
+ */
+ withTextFontFamily(fontFamily) {
+ return this.extend({
+ fontFamily,
+ font: ""
+ });
+ }
+
+ /**
+ * Creates a new options object with the given font weight
+ */
+ withTextFontWeight(fontWeight) {
+ return this.extend({
+ fontWeight,
+ font: ""
+ });
+ }
+
+ /**
+ * Creates a new options object with the given font weight
+ */
+ withTextFontShape(fontShape) {
+ return this.extend({
+ fontShape,
+ font: ""
+ });
+ }
+
+ /**
+ * Return the CSS sizing classes required to switch from enclosing options
+ * `oldOptions` to `this`. Returns an array of classes.
+ */
+ sizingClasses(oldOptions) {
+ if (oldOptions.size !== this.size) {
+ return ["katex-sizing", "reset-size" + oldOptions.size, "size" + this.size];
+ } else {
+ return [];
+ }
+ }
+
+ /**
+ * Return the CSS sizing classes required to switch to the base size. Like
+ * `this.havingSize(BASESIZE).sizingClasses(this)`.
+ */
+ baseSizingClasses() {
+ if (this.size !== Options.BASESIZE) {
+ return ["katex-sizing", "reset-size" + this.size, "size" + Options.BASESIZE];
+ } else {
+ return [];
+ }
+ }
+
+ /**
+ * Return the font metrics for this size.
+ */
+ fontMetrics() {
+ if (!this._fontMetrics) {
+ this._fontMetrics = getGlobalMetrics(this.size);
+ }
+ return this._fontMetrics;
+ }
+
+ /**
+ * Gets the CSS color of the current options object
+ */
+ getColor() {
+ if (this.phantom) {
+ return "transparent";
+ } else {
+ return this.color;
+ }
+ }
+}
+/**
+ * The base size index.
+ */
+Options.BASESIZE = 6;
+/* harmony default export */ var src_Options = (Options);
+;// ./src/buildTree.ts
+
+
+
+
+
+const optionsFromSettings = function (settings) {
+ return new src_Options({
+ style: settings.displayMode ? src_Style.DISPLAY : src_Style.TEXT,
+ maxSize: settings.maxSize,
+ minRuleThickness: settings.minRuleThickness
+ });
+};
+const displayWrap = function (node, settings) {
+ if (settings.displayMode) {
+ const classes = ["katex-display"];
+ if (settings.leqno) {
+ classes.push("leqno");
+ }
+ if (settings.fleqn) {
+ classes.push("fleqn");
+ }
+ node = makeSpan(classes, [node]);
+ }
+ return node;
+};
+const buildTree = function (tree, expression, settings) {
+ const options = optionsFromSettings(settings);
+ let katexNode;
+ if (settings.output === "mathml") {
+ return buildMathML(tree, expression, options, settings.displayMode, true);
+ } else if (settings.output === "html") {
+ const htmlNode = buildHTML(tree, options);
+ katexNode = makeSpan(["katex"], [htmlNode]);
+ } else {
+ const mathMLNode = buildMathML(tree, expression, options, settings.displayMode, false);
+ const htmlNode = buildHTML(tree, options);
+ katexNode = makeSpan(["katex"], [mathMLNode, htmlNode]);
+ }
+ return displayWrap(katexNode, settings);
+};
+const buildHTMLTree = function (tree, expression, settings) {
+ const options = optionsFromSettings(settings);
+ const htmlNode = buildHTML(tree, options);
+ const katexNode = makeSpan(["katex"], [htmlNode]);
+ return displayWrap(katexNode, settings);
+};
+/* harmony default export */ var src_buildTree = ((/* unused pure expression or super */ null && (buildTree)));
+;// ./src/stretchy.ts
+/**
+ * This file provides support to buildMathML.js and buildHTML.js
+ * for stretchy wide elements rendered from SVG files
+ * and other CSS trickery.
+ */
+
+
+
+
+
+const stretchyCodePoint = {
+ widehat: "^",
+ widecheck: "ˇ",
+ widetilde: "~",
+ utilde: "~",
+ overleftarrow: "\u2190",
+ underleftarrow: "\u2190",
+ xleftarrow: "\u2190",
+ overrightarrow: "\u2192",
+ underrightarrow: "\u2192",
+ xrightarrow: "\u2192",
+ underbrace: "\u23df",
+ overbrace: "\u23de",
+ underbracket: "\u23b5",
+ overbracket: "\u23b4",
+ overgroup: "\u23e0",
+ undergroup: "\u23e1",
+ overleftrightarrow: "\u2194",
+ underleftrightarrow: "\u2194",
+ xleftrightarrow: "\u2194",
+ Overrightarrow: "\u21d2",
+ xRightarrow: "\u21d2",
+ overleftharpoon: "\u21bc",
+ xleftharpoonup: "\u21bc",
+ overrightharpoon: "\u21c0",
+ xrightharpoonup: "\u21c0",
+ xLeftarrow: "\u21d0",
+ xLeftrightarrow: "\u21d4",
+ xhookleftarrow: "\u21a9",
+ xhookrightarrow: "\u21aa",
+ xmapsto: "\u21a6",
+ xrightharpoondown: "\u21c1",
+ xleftharpoondown: "\u21bd",
+ xrightleftharpoons: "\u21cc",
+ xleftrightharpoons: "\u21cb",
+ xtwoheadleftarrow: "\u219e",
+ xtwoheadrightarrow: "\u21a0",
+ xlongequal: "=",
+ xtofrom: "\u21c4",
+ xrightleftarrows: "\u21c4",
+ xrightequilibrium: "\u21cc",
+ // Not a perfect match.
+ xleftequilibrium: "\u21cb",
+ // None better available.
+ "\\cdrightarrow": "\u2192",
+ "\\cdleftarrow": "\u2190",
+ "\\cdlongequal": "="
+};
+const stretchyMathML = function (label) {
+ const node = new MathNode("mo", [new TextNode(stretchyCodePoint[label.replace(/^\\/, '')])]);
+ node.setAttribute("stretchy", "true");
+ return node;
+};
+
+// Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts.
+// Copyright (c) 2009-2010, Design Science, Inc. (<www.mathjax.org>)
+// Copyright (c) 2014-2017 Khan Academy (<www.khanacademy.org>)
+// Licensed under the SIL Open Font License, Version 1.1.
+// See \nhttp://scripts.sil.org/OFL
+
+// Very Long SVGs
+// Many of the KaTeX stretchy wide elements use a long SVG image and an
+// overflow: hidden tactic to achieve a stretchy image while avoiding
+// distortion of arrowheads or brace corners.
+
+// The SVG typically contains a very long (400 em) arrow.
+
+// The SVG is in a container span that has overflow: hidden, so the span
+// acts like a window that exposes only part of the SVG.
+
+// The SVG always has a longer, thinner aspect ratio than the container span.
+// After the SVG fills 100% of the height of the container span,
+// there is a long arrow shaft left over. That left-over shaft is not shown.
+// Instead, it is sliced off because the span's CSS has overflow: hidden.
+
+// Thus, the reader sees an arrow that matches the subject matter width
+// without distortion.
+
+// Some functions, such as \cancel, need to vary their aspect ratio. These
+// functions do not get the overflow SVG treatment.
+
+// In the katexImagesData object just below, the dimensions all
+// correspond to path geometry inside the relevant SVG.
+// For example, \overrightarrow uses the same arrowhead as glyph U+2192
+// from the KaTeX Main font. The scaling factor is 1000.
+// That is, inside the font, that arrowhead is 522 units tall, which
+// corresponds to 0.522 em inside the document.
+
+const katexImagesData = {
+ // path(s), minWidth, height, align
+ overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
+ overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
+ underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
+ underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
+ xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"],
+ "\\cdrightarrow": [["rightarrow"], 3.0, 522, "xMaxYMin"],
+ // CD minwwidth2.5pc
+ xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"],
+ "\\cdleftarrow": [["leftarrow"], 3.0, 522, "xMinYMin"],
+ Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"],
+ xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"],
+ xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"],
+ overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"],
+ xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"],
+ xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"],
+ overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
+ xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
+ xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"],
+ xlongequal: [["longequal"], 0.888, 334, "xMinYMin"],
+ "\\cdlongequal": [["longequal"], 3.0, 334, "xMinYMin"],
+ xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"],
+ xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"],
+ overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
+ overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548],
+ underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548],
+ underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
+ xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522],
+ xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560],
+ xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716],
+ xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716],
+ xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522],
+ xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522],
+ overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
+ underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
+ overbracket: [["leftbracketover", "rightbracketover"], 1.6, 440],
+ underbracket: [["leftbracketunder", "rightbracketunder"], 1.6, 410],
+ overgroup: [["leftgroup", "rightgroup"], 0.888, 342],
+ undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342],
+ xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522],
+ xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528],
+ // The next three arrows are from the mhchem package.
+ // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the
+ // document as \xrightarrow or \xrightleftharpoons. Those have
+ // min-length = 1.75em, so we set min-length on these next three to match.
+ xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901],
+ xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716],
+ xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716]
+};
+const wideAccentLabels = new Set(["widehat", "widecheck", "widetilde", "utilde"]);
+const stretchySvg = function (group, options) {
+ // Create a span with inline SVG for the element.
+ function buildSvgSpan_() {
+ let viewBoxWidth = 400000; // default
+ const label = group.label.slice(1);
+ if (wideAccentLabels.has(label) && 'base' in group) {
+ // There are four SVG images available for each function.
+ // Choose a taller image when there are more characters.
+ const numChars = group.base.type === "ordgroup" ? group.base.body.length : 1;
+ let viewBoxHeight;
+ let pathName;
+ let height;
+ if (numChars > 5) {
+ if (label === "widehat" || label === "widecheck") {
+ viewBoxHeight = 420;
+ viewBoxWidth = 2364;
+ height = 0.42;
+ pathName = label + "4";
+ } else {
+ viewBoxHeight = 312;
+ viewBoxWidth = 2340;
+ height = 0.34;
+ pathName = "tilde4";
+ }
+ } else {
+ const imgIndex = [1, 1, 2, 2, 3, 3][numChars];
+ if (label === "widehat" || label === "widecheck") {
+ viewBoxWidth = [0, 1062, 2364, 2364, 2364][imgIndex];
+ viewBoxHeight = [0, 239, 300, 360, 420][imgIndex];
+ height = [0, 0.24, 0.3, 0.3, 0.36, 0.42][imgIndex];
+ pathName = label + imgIndex;
+ } else {
+ viewBoxWidth = [0, 600, 1033, 2339, 2340][imgIndex];
+ viewBoxHeight = [0, 260, 286, 306, 312][imgIndex];
+ height = [0, 0.26, 0.286, 0.3, 0.306, 0.34][imgIndex];
+ pathName = "tilde" + imgIndex;
+ }
+ }
+ const path = new PathNode(pathName);
+ const svgNode = new SvgNode([path], {
+ "width": "100%",
+ "height": makeEm(height),
+ "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight,
+ "preserveAspectRatio": "none"
+ });
+ return {
+ span: makeSvgSpan([], [svgNode], options),
+ minWidth: 0,
+ height
+ };
+ } else {
+ const spans = [];
+ const data = katexImagesData[label];
+ if (!data) {
+ throw new Error("No SVG data for \"" + label + "\".");
+ }
+ const paths = data[0],
+ minWidth = data[1],
+ viewBoxHeight = data[2];
+ const height = viewBoxHeight / 1000;
+ const numSvgChildren = paths.length;
+ let widthClasses;
+ let aligns;
+ if (numSvgChildren === 1) {
+ if (data.length !== 4) {
+ throw new Error("Expected 4-tuple for single-path SVG data \"" + label + "\".");
+ }
+ widthClasses = ["hide-tail"];
+ aligns = [data[3]];
+ } else if (numSvgChildren === 2) {
+ widthClasses = ["halfarrow-left", "halfarrow-right"];
+ aligns = ["xMinYMin", "xMaxYMin"];
+ } else if (numSvgChildren === 3) {
+ widthClasses = ["brace-left", "brace-center", "brace-right"];
+ aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"];
+ } else {
+ throw new Error("Correct katexImagesData or update code here to support\n " + numSvgChildren + " children.");
+ }
+ for (let i = 0; i < numSvgChildren; i++) {
+ const path = new PathNode(paths[i]);
+ const svgNode = new SvgNode([path], {
+ "width": "400em",
+ "height": makeEm(height),
+ "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight,
+ "preserveAspectRatio": aligns[i] + " slice"
+ });
+ const span = makeSvgSpan([widthClasses[i]], [svgNode], options);
+ if (numSvgChildren === 1) {
+ return {
+ span,
+ minWidth,
+ height
+ };
+ } else {
+ span.style.height = makeEm(height);
+ spans.push(span);
+ }
+ }
+ return {
+ span: makeSpan(["katex-stretchy"], spans, options),
+ minWidth,
+ height
+ };
+ }
+ } // buildSvgSpan_()
+ const _buildSvgSpan_ = buildSvgSpan_(),
+ span = _buildSvgSpan_.span,
+ minWidth = _buildSvgSpan_.minWidth,
+ height = _buildSvgSpan_.height;
+
+ // Note that we are returning span.depth = 0.
+ // Any adjustments relative to the baseline must be done in buildHTML.
+ span.height = height;
+ span.style.height = makeEm(height);
+ if (minWidth > 0) {
+ span.style.minWidth = makeEm(minWidth);
+ }
+ return span;
+};
+const stretchyEnclose = function (inner, label, topPad, bottomPad, options) {
+ // Return an image span for \cancel, \bcancel, \xcancel, \fbox, or \angl
+ let img;
+ const totalHeight = inner.height + inner.depth + topPad + bottomPad;
+ if (/fbox|color|angl/.test(label)) {
+ img = makeSpan(["katex-stretchy", label], [], options);
+ if (label === "fbox") {
+ const color = options.color && options.getColor();
+ if (color) {
+ img.style.borderColor = color;
+ }
+ }
+ } else {
+ // \cancel, \bcancel, or \xcancel
+ // Since \cancel's SVG is inline and it omits the viewBox attribute,
+ // its stroke-width will not vary with span area.
+
+ const lines = [];
+ if (/^[bx]cancel$/.test(label)) {
+ lines.push(new LineNode({
+ "x1": "0",
+ "y1": "0",
+ "x2": "100%",
+ "y2": "100%",
+ "stroke-width": "0.046em"
+ }));
+ }
+ if (/^x?cancel$/.test(label)) {
+ lines.push(new LineNode({
+ "x1": "0",
+ "y1": "100%",
+ "x2": "100%",
+ "y2": "0",
+ "stroke-width": "0.046em"
+ }));
+ }
+ const svgNode = new SvgNode(lines, {
+ "width": "100%",
+ "height": makeEm(totalHeight)
+ });
+ img = makeSvgSpan([], [svgNode], options);
+ }
+ img.height = totalHeight;
+ img.style.height = makeEm(totalHeight);
+ return img;
+};
+;// ./src/atoms.ts
+/**
+ * Small module for atom-group constants and type guard. Kept separate from
+ * `symbols.ts` so that consumers (notably `contrib/render-a11y-string`) can
+ * pull in `isAtom` without dragging in the ~870-line symbol tables.
+ */
+
+const atomList = ["bin", "close", "inner", "open", "punct", "rel"];
+const nonAtomList = ["accent-token", "mathord", "op-token", "spacing", "textord"];
+const Atoms = new Set(atomList);
+const NonAtoms = new Set(nonAtomList);
+function isAtom(value) {
+ return Atoms.has(value);
+}
+;// ./src/parseNode.ts
+
+
+/**
+ * Asserts that the node is of the given type and returns it with stricter
+ * typing. Throws if the node's type does not match.
+ */
+function assertNodeType(node, type) {
+ if (!node || node.type !== type) {
+ throw new Error("Expected node of type " + type + ", but got " + (node ? "node of type " + node.type : String(node)));
+ }
+ return node;
+}
+
+/**
+ * Returns the node more strictly typed iff it is of the given type. Otherwise,
+ * returns null.
+ */
+function assertSymbolNodeType(node) {
+ const typedNode = checkSymbolNodeType(node);
+ if (!typedNode) {
+ throw new Error("Expected node of symbol group type, but got " + (node ? "node of type " + node.type : String(node)));
+ }
+ return typedNode;
+}
+
+/**
+ * Returns the node more strictly typed if it is of the given type. Otherwise,
+ * returns null.
+ */
+function checkSymbolNodeType(node) {
+ if (node.type === "atom" || NonAtoms.has(node.type)) {
+ return node;
+ }
+ return null;
+}
+
+/**
+ * Returns the string spelled out by a group of plain characters, throwing the
+ * given ParseError if the group holds anything else. With allowSpaces, a
+ * literal space counts as a character; `~` and `\ ` do not.
+ */
+function assertCharacterGroup(group, errorMessage, allowSpaces) {
+ let text = "";
+ for (const node of group.body) {
+ if (node.type === "textord") {
+ text += node.text;
+ } else if (allowSpaces && node.type === "spacing" && node.text === " ") {
+ text += " ";
+ } else {
+ throw new src_ParseError(errorMessage, group);
+ }
+ }
+ return text;
+}
+;// ./src/functions/accent.ts
+
+
+
+
+
+
+
+
+
+
+const getBaseSymbol = group => {
+ if (group instanceof SymbolNode) {
+ return group;
+ }
+ if (hasHtmlDomChildren(group) && group.children.length === 1) {
+ return getBaseSymbol(group.children[0]);
+ }
+};
+
+// NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but
+// also "supsub" since an accent can affect super/subscripting.
+const htmlBuilder = (grp, options) => {
+ // Accents are handled in the TeXbook pg. 443, rule 12.
+ let base;
+ let group;
+ let supSubGroup;
+ if (grp && grp.type === "supsub") {
+ // If our base is a character box, and we have superscripts and
+ // subscripts, the supsub will defer to us. In particular, we want
+ // to attach the superscripts and subscripts to the inner body (so
+ // that the position of the superscripts and subscripts won't be
+ // affected by the height of the accent). We accomplish this by
+ // sticking the base of the accent into the base of the supsub, and
+ // rendering that, while keeping track of where the accent is.
+
+ // The real accent group is the base of the supsub group
+ group = assertNodeType(grp.base, "accent");
+ // The character box is the base of the accent group
+ base = group.base;
+ // Stick the character box into the base of the supsub group
+ grp.base = base;
+
+ // Rerender the supsub group with its new base, and store that
+ // result.
+ supSubGroup = assertSpan(buildGroup(grp, options));
+
+ // reset original base
+ grp.base = group;
+ } else {
+ group = assertNodeType(grp, "accent");
+ base = group.base;
+ }
+
+ // Build the base group
+ const body = buildGroup(base, options.havingCrampedStyle());
+
+ // Does the accent need to shift for the skew of a character?
+ const mustShift = group.isShifty && isCharacterBox(base);
+
+ // Calculate the skew of the accent. This is based on the line "If the
+ // nucleus is not a single character, let s = 0; otherwise set s to the
+ // kern amount for the nucleus followed by the \skewchar of its font."
+ // Note that our skew metrics are just the kern between each character
+ // and the skewchar.
+ let skew = 0;
+ if (mustShift) {
+ var _getBaseSymbol$skew, _getBaseSymbol;
+ // Read the skew from the rendered base symbol.
+ // This preserves font metrics from font wrappers like \mathbb.
+ skew = (_getBaseSymbol$skew = (_getBaseSymbol = getBaseSymbol(body)) == null ? void 0 : _getBaseSymbol.skew) != null ? _getBaseSymbol$skew : 0;
+ }
+ const accentBelow = group.label === "\\c";
+
+ // calculate the amount of space between the body and the accent
+ let clearance = accentBelow ? body.height + body.depth : Math.min(body.height, options.fontMetrics().xHeight);
+
+ // Build the accent
+ let accentBody;
+ if (!group.isStretchy) {
+ let accent;
+ let width;
+ if (group.label === "\\vec") {
+ // Before version 0.9, \vec used the combining font glyph U+20D7.
+ // But browsers, especially Safari, are not consistent in how they
+ // render combining characters when not preceded by a character.
+ // So now we use an SVG.
+ // If Safari reforms, we should consider reverting to the glyph.
+ accent = staticSvg("vec", options);
+ width = svgData.vec[1];
+ } else {
+ accent = makeOrd({
+ type: "textord",
+ mode: group.mode,
+ text: group.label
+ }, options);
+ accent = assertSymbolDomNode(accent);
+ // Remove the italic correction of the accent, because it only serves to
+ // shift the accent over to a place we don't want.
+ accent.italic = 0;
+ width = accent.width;
+ if (accentBelow) {
+ clearance += accent.depth;
+ }
+ }
+ accentBody = makeSpan(["accent-body"], [accent]);
+
+ // "Full" accents expand the width of the resulting symbol to be
+ // at least the width of the accent, and overlap directly onto the
+ // character without any vertical offset.
+ const accentFull = group.label === "\\textcircled";
+ if (accentFull) {
+ accentBody.classes.push('accent-full');
+ clearance = body.height;
+ }
+
+ // Shift the accent over by the skew.
+ let left = skew;
+
+ // CSS defines `.katex .katex-accent .accent-body:not(.accent-full) { width: 0 }`
+ // so that the accent doesn't contribute to the bounding box.
+ // We need to shift the character by its width (effectively half
+ // its width) to compensate.
+ if (!accentFull) {
+ left -= width / 2;
+ }
+ accentBody.style.left = makeEm(left);
+
+ // \textcircled uses the \bigcirc glyph, so it needs some
+ // vertical adjustment to match LaTeX.
+ if (group.label === "\\textcircled") {
+ accentBody.style.top = ".2em";
+ }
+ accentBody = makeVList({
+ positionType: "firstBaseline",
+ children: [{
+ type: "elem",
+ elem: body
+ }, {
+ type: "kern",
+ size: -clearance
+ }, {
+ type: "elem",
+ elem: accentBody
+ }]
+ }, options);
+ } else {
+ accentBody = stretchySvg(group, options);
+ accentBody = makeVList({
+ positionType: "firstBaseline",
+ children: [{
+ type: "elem",
+ elem: body
+ }, {
+ type: "elem",
+ elem: accentBody,
+ wrapperClasses: ["svg-align"],
+ wrapperStyle: skew > 0 ? {
+ width: "calc(100% - " + makeEm(2 * skew) + ")",
+ marginLeft: makeEm(2 * skew)
+ } : undefined
+ }]
+ }, options);
+ }
+ const accentWrap = makeSpan(["mord", "katex-accent"], [accentBody], options);
+ if (supSubGroup) {
+ // Here, we replace the "base" child of the supsub with our newly
+ // generated accent.
+ supSubGroup.children[0] = accentWrap;
+
+ // Since we don't rerun the height calculation after replacing the
+ // accent, we manually recalculate height.
+ supSubGroup.height = Math.max(accentWrap.height, supSubGroup.height);
+
+ // Accents should always be ords, even when their innards are not.
+ supSubGroup.classes[0] = "mord";
+ return supSubGroup;
+ } else {
+ return accentWrap;
+ }
+};
+const mathmlBuilder = (group, options) => {
+ const accentNode = group.isStretchy ? stretchyMathML(group.label) : new MathNode("mo", [makeText(group.label, group.mode)]);
+ const node = new MathNode("mover", [buildMathML_buildGroup(group.base, options), accentNode]);
+ node.setAttribute("accent", "true");
+ return node;
+};
+const NON_STRETCHY_ACCENT_REGEX = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map(accent => "\\" + accent).join("|"));
+
+// Accents
+defineFunction({
+ type: "accent",
+ names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"],
+ numArgs: 1,
+ handler: (context, args) => {
+ const base = normalizeArgument(args[0]);
+ const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName);
+ const isShifty = !isStretchy || context.funcName === "\\widehat" || context.funcName === "\\widetilde" || context.funcName === "\\widecheck";
+ return {
+ type: "accent",
+ mode: context.parser.mode,
+ label: context.funcName,
+ isStretchy: isStretchy,
+ isShifty: isShifty,
+ base: base
+ };
+ },
+ htmlBuilder,
+ mathmlBuilder
+});
+
+// Text-mode accents
+defineFunction({
+ type: "accent",
+ names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\c", "\\r", "\\H", "\\v", "\\textcircled"],
+ numArgs: 1,
+ allowedInText: true,
+ allowedInMath: true,
+ // unless in strict mode
+ argTypes: ["primitive"],
+ handler: (context, args) => {
+ const base = args[0];
+ let mode = context.parser.mode;
+ if (mode === "math") {
+ context.parser.settings.reportNonstrict("mathVsTextAccents", "LaTeX's accent " + context.funcName + " works only in text mode");
+ mode = "text";
+ }
+ return {
+ type: "accent",
+ mode: mode,
+ label: context.funcName,
+ isStretchy: false,
+ isShifty: true,
+ base: base
+ };
+ }
+});
+;// ./src/functions/accentunder.ts
+// Horizontal overlap functions
+
+
+
+
+
+
+defineFunction({
+ type: "accentUnder",
+ names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"],
+ numArgs: 1,
+ handler: (_ref, args) => {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const base = args[0];
+ return {
+ type: "accentUnder",
+ mode: parser.mode,
+ label: funcName,
+ base: base
+ };
+ },
+ htmlBuilder: (group, options) => {
+ // Treat under accents much like underlines.
+ const innerGroup = buildGroup(group.base, options);
+ const accentBody = stretchySvg(group, options);
+ const kern = group.label === "\\utilde" ? 0.12 : 0;
+
+ // Generate the vlist, with the appropriate kerns
+ const vlist = makeVList({
+ positionType: "top",
+ positionData: innerGroup.height,
+ children: [{
+ type: "elem",
+ elem: accentBody,
+ wrapperClasses: ["svg-align"]
+ }, {
+ type: "kern",
+ size: kern
+ }, {
+ type: "elem",
+ elem: innerGroup
+ }]
+ }, options);
+ return makeSpan(["mord", "accentunder"], [vlist], options);
+ },
+ mathmlBuilder: (group, options) => {
+ const accentNode = stretchyMathML(group.label);
+ const node = new MathNode("munder", [buildMathML_buildGroup(group.base, options), accentNode]);
+ node.setAttribute("accentunder", "true");
+ return node;
+ }
+});
+;// ./src/functions/arrow.ts
+
+
+
+
+
+
+// Helper function
+const paddedNode = group => {
+ const node = new MathNode("mpadded", group ? [group] : []);
+ node.setAttribute("width", "+0.6em");
+ node.setAttribute("lspace", "0.3em");
+ return node;
+};
+
+// Stretchy arrows with an optional argument
+defineFunction({
+ type: "xArrow",
+ names: ["\\xleftarrow", "\\xrightarrow", "\\xLeftarrow", "\\xRightarrow", "\\xleftrightarrow", "\\xLeftrightarrow", "\\xhookleftarrow", "\\xhookrightarrow", "\\xmapsto", "\\xrightharpoondown", "\\xrightharpoonup", "\\xleftharpoondown", "\\xleftharpoonup", "\\xrightleftharpoons", "\\xleftrightharpoons", "\\xlongequal", "\\xtwoheadrightarrow", "\\xtwoheadleftarrow", "\\xtofrom",
+ // The next 3 functions are here to support the mhchem extension.
+ // Direct use of these functions is discouraged and may break someday.
+ "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium",
+ // The next 3 functions are here only to support the {CD} environment.
+ "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"],
+ numArgs: 1,
+ numOptionalArgs: 1,
+ handler(_ref, args, optArgs) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ return {
+ type: "xArrow",
+ mode: parser.mode,
+ label: funcName,
+ body: args[0],
+ below: optArgs[0]
+ };
+ },
+ htmlBuilder(group, options) {
+ const style = options.style;
+
+ // Build the argument groups in the appropriate style.
+ // Ref: amsmath.dtx: \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}%
+
+ // Some groups can return document fragments. Handle those by wrapping
+ // them in a span.
+ let newOptions = options.havingStyle(style.sup());
+ const upperGroup = wrapFragment(buildGroup(group.body, newOptions, options), options);
+ const arrowPrefix = group.label.slice(0, 2) === "\\x" ? "x" : "cd";
+ upperGroup.classes.push(arrowPrefix + "-arrow-pad");
+ let lowerGroup;
+ if (group.below) {
+ // Build the lower group
+ newOptions = options.havingStyle(style.sub());
+ lowerGroup = wrapFragment(buildGroup(group.below, newOptions, options), options);
+ lowerGroup.classes.push(arrowPrefix + "-arrow-pad");
+ }
+ const arrowBody = stretchySvg(group, options);
+
+ // Re shift: Note that stretchySvg returned arrowBody.depth = 0.
+ // The point we want on the math axis is at 0.5 * arrowBody.height.
+ const arrowShift = -options.fontMetrics().axisHeight + 0.5 * arrowBody.height;
+ // 2 mu kern. Ref: amsmath.dtx: #7\if0#2\else\mkern#2mu\fi
+ let upperShift = -options.fontMetrics().axisHeight - 0.5 * arrowBody.height - 0.111; // 0.111 em = 2 mu
+ if (upperGroup.depth > 0.25 || group.label === "\\xleftequilibrium") {
+ upperShift -= upperGroup.depth; // shift up if depth encroaches
+ }
+
+ // Generate the vlist
+ let vlist;
+ if (lowerGroup) {
+ const lowerShift = -options.fontMetrics().axisHeight + lowerGroup.height + 0.5 * arrowBody.height + 0.111;
+ vlist = makeVList({
+ positionType: "individualShift",
+ children: [{
+ type: "elem",
+ elem: upperGroup,
+ shift: upperShift
+ }, {
+ type: "elem",
+ elem: arrowBody,
+ shift: arrowShift,
+ wrapperClasses: ["svg-align"]
+ }, {
+ type: "elem",
+ elem: lowerGroup,
+ shift: lowerShift
+ }]
+ }, options);
+ } else {
+ vlist = makeVList({
+ positionType: "individualShift",
+ children: [{
+ type: "elem",
+ elem: upperGroup,
+ shift: upperShift
+ }, {
+ type: "elem",
+ elem: arrowBody,
+ shift: arrowShift,
+ wrapperClasses: ["svg-align"]
+ }]
+ }, options);
+ }
+ return makeSpan(["mrel", "x-arrow"], [vlist], options);
+ },
+ mathmlBuilder(group, options) {
+ const arrowNode = stretchyMathML(group.label);
+ arrowNode.setAttribute("minsize", group.label.charAt(0) === "x" ? "1.75em" : "3.0em");
+ let node;
+ if (group.body) {
+ const upperNode = paddedNode(buildMathML_buildGroup(group.body, options));
+ if (group.below) {
+ const lowerNode = paddedNode(buildMathML_buildGroup(group.below, options));
+ node = new MathNode("munderover", [arrowNode, lowerNode, upperNode]);
+ } else {
+ node = new MathNode("mover", [arrowNode, upperNode]);
+ }
+ } else if (group.below) {
+ const lowerNode = paddedNode(buildMathML_buildGroup(group.below, options));
+ node = new MathNode("munder", [arrowNode, lowerNode]);
+ } else {
+ // This should never happen.
+ // Parser.js throws an error if there is no argument.
+ node = paddedNode();
+ node = new MathNode("mover", [arrowNode, node]);
+ }
+ return node;
+ }
+});
+;// ./src/functions/mclass.ts
+
+
+
+
+
+
+function mclass_htmlBuilder(group, options) {
+ const elements = buildExpression(group.body, options, true);
+ return makeSpan([group.mclass], elements, options);
+}
+function mclass_mathmlBuilder(group, options) {
+ let node;
+ const inner = buildMathML_buildExpression(group.body, options);
+ if (group.mclass === "minner") {
+ node = new MathNode("mpadded", inner);
+ } else if (group.mclass === "mord") {
+ if (group.isCharacterBox) {
+ node = inner[0];
+ node.type = "mi";
+ } else {
+ node = new MathNode("mi", inner);
+ }
+ } else {
+ if (group.isCharacterBox) {
+ node = inner[0];
+ node.type = "mo";
+ } else {
+ node = new MathNode("mo", inner);
+ }
+
+ // Set spacing based on what is the most likely adjacent atom type.
+ // See TeXbook p170.
+ if (group.mclass === "mbin") {
+ node.attributes.lspace = "0.22em"; // medium space
+ node.attributes.rspace = "0.22em";
+ } else if (group.mclass === "mpunct") {
+ node.attributes.lspace = "0em";
+ node.attributes.rspace = "0.17em"; // thinspace
+ } else if (group.mclass === "mopen" || group.mclass === "mclose") {
+ node.attributes.lspace = "0em";
+ node.attributes.rspace = "0em";
+ }
+ // MathML <mo> default space is 5/18 em, so <mrel> needs no action.
+ // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo
+ }
+ return node;
+}
+
+// Math class commands except \mathop
+defineFunction({
+ type: "mclass",
+ names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"],
+ numArgs: 1,
+ primitive: true,
+ handler(_ref, args) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const body = args[0];
+ return {
+ type: "mclass",
+ mode: parser.mode,
+ mclass: "m" + funcName.slice(5),
+ body: ordargument(body),
+ isCharacterBox: isCharacterBox(body)
+ };
+ },
+ htmlBuilder: mclass_htmlBuilder,
+ mathmlBuilder: mclass_mathmlBuilder
+});
+const binrelClass = arg => {
+ // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument.
+ // (by rendering separately and with {}s before and after, and measuring
+ // the change in spacing). We'll do roughly the same by detecting the
+ // atom type directly.
+ const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg;
+ if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) {
+ return "m" + atom.family;
+ } else {
+ return "mord";
+ }
+};
+
+// \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord.
+// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX.
+defineFunction({
+ type: "mclass",
+ names: ["\\@binrel"],
+ numArgs: 2,
+ handler(_ref2, args) {
+ let parser = _ref2.parser;
+ return {
+ type: "mclass",
+ mode: parser.mode,
+ mclass: binrelClass(args[0]),
+ body: ordargument(args[1]),
+ isCharacterBox: isCharacterBox(args[1])
+ };
+ }
+});
+
+// Build a relation or stacked op by placing one symbol on top of another
+defineFunction({
+ type: "mclass",
+ names: ["\\stackrel", "\\overset", "\\underset"],
+ numArgs: 2,
+ handler(_ref3, args) {
+ let parser = _ref3.parser,
+ funcName = _ref3.funcName;
+ const baseArg = args[1];
+ const shiftedArg = args[0];
+ let mclass;
+ if (funcName !== "\\stackrel") {
+ // LaTeX applies \binrel spacing to \overset and \underset.
+ mclass = binrelClass(baseArg);
+ } else {
+ mclass = "mrel"; // for \stackrel
+ }
+ const baseOp = {
+ type: "op",
+ mode: baseArg.mode,
+ limits: true,
+ alwaysHandleSupSub: true,
+ parentIsSupSub: false,
+ symbol: false,
+ suppressBaseShift: funcName !== "\\stackrel",
+ body: ordargument(baseArg)
+ };
+ const supsub = funcName === "\\underset" ? {
+ type: "supsub",
+ mode: shiftedArg.mode,
+ base: baseOp,
+ sub: shiftedArg
+ } : {
+ type: "supsub",
+ mode: shiftedArg.mode,
+ base: baseOp,
+ sup: shiftedArg
+ };
+ return {
+ type: "mclass",
+ mode: parser.mode,
+ mclass,
+ body: [supsub],
+ isCharacterBox: isCharacterBox(supsub)
+ };
+ }
+});
+;// ./src/functions/pmb.ts
+
+
+
+
+
+
+// \pmb is a simulation of bold font.
+// The version of \pmb in ambsy.sty works by typesetting three copies
+// with small offsets. We use CSS text-shadow.
+// It's a hack. Not as good as a real bold font. Better than nothing.
+
+defineFunction({
+ type: "pmb",
+ names: ["\\pmb"],
+ numArgs: 1,
+ allowedInText: true,
+ handler(_ref, args) {
+ let parser = _ref.parser;
+ return {
+ type: "pmb",
+ mode: parser.mode,
+ mclass: binrelClass(args[0]),
+ body: ordargument(args[0])
+ };
+ },
+ htmlBuilder(group, options) {
+ const elements = buildExpression(group.body, options, true);
+ const node = makeSpan([group.mclass], elements, options);
+ node.style.textShadow = "0.02em 0.01em 0.04px";
+ return node;
+ },
+ mathmlBuilder(group, style) {
+ const inner = buildMathML_buildExpression(group.body, style);
+ // Wrap with an <mstyle> element.
+ const node = new MathNode("mstyle", inner);
+ node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px");
+ return node;
+ }
+});
+;// ./src/environments/cd.ts
+
+
+
+
+
+
+
+
+const cdArrowFunctionName = {
+ ">": "\\\\cdrightarrow",
+ "<": "\\\\cdleftarrow",
+ "=": "\\\\cdlongequal",
+ "A": "\\uparrow",
+ "V": "\\downarrow",
+ "|": "\\Vert",
+ ".": "no arrow"
+};
+const newCell = () => {
+ // Create an empty cell, to be filled below with parse nodes.
+ // The parseTree from this module must be constructed like the
+ // one created by parseArray(), so an empty CD cell must
+ // be a ParseNode<"styling">. And CD is always displaystyle.
+ return {
+ type: "styling",
+ body: [],
+ mode: "math",
+ style: "display",
+ resetFont: true
+ };
+};
+const isStartOfArrow = node => {
+ return node.type === "textord" && node.text === "@";
+};
+const isLabelEnd = (node, endChar) => {
+ return (node.type === "mathord" || node.type === "atom") && node.text === endChar;
+};
+function cdArrow(arrowChar, labels, parser) {
+ // Return a parse tree of an arrow and its labels.
+ // This acts in a way similar to a macro expansion.
+ const funcName = cdArrowFunctionName[arrowChar];
+ switch (funcName) {
+ case "\\\\cdrightarrow":
+ case "\\\\cdleftarrow":
+ return parser.callFunction(funcName, [labels[0]], [labels[1]]);
+ case "\\uparrow":
+ case "\\downarrow":
+ {
+ const leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []);
+ const bareArrow = {
+ type: "atom",
+ text: funcName,
+ mode: "math",
+ family: "rel"
+ };
+ const sizedArrow = parser.callFunction("\\Big", [bareArrow], []);
+ const rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []);
+ const arrowGroup = {
+ type: "ordgroup",
+ mode: "math",
+ body: [leftLabel, sizedArrow, rightLabel]
+ };
+ return parser.callFunction("\\\\cdparent", [arrowGroup], []);
+ }
+ case "\\\\cdlongequal":
+ return parser.callFunction("\\\\cdlongequal", [], []);
+ case "\\Vert":
+ {
+ const arrow = {
+ type: "textord",
+ text: "\\Vert",
+ mode: "math"
+ };
+ return parser.callFunction("\\Big", [arrow], []);
+ }
+ default:
+ return {
+ type: "textord",
+ text: " ",
+ mode: "math"
+ };
+ }
+}
+function parseCD(parser) {
+ // Get the array's parse nodes with \\ temporarily mapped to \cr.
+ const parsedRows = [];
+ parser.gullet.beginGroup();
+ parser.gullet.macros.set("\\cr", "\\\\\\relax");
+ parser.gullet.beginGroup();
+ while (true) {
+ // Get the parse nodes for the next row.
+ parsedRows.push(parser.parseExpression(false, "\\\\"));
+ parser.gullet.endGroup();
+ parser.gullet.beginGroup();
+ const next = parser.fetch().text;
+ if (next === "&" || next === "\\\\") {
+ parser.consume();
+ } else if (next === "\\end") {
+ if (parsedRows[parsedRows.length - 1].length === 0) {
+ parsedRows.pop(); // final row ended in \\
+ }
+ break;
+ } else {
+ throw new src_ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken);
+ }
+ }
+ let row = [];
+ const body = [row];
+
+ // Loop thru the parse nodes. Collect them into cells and arrows.
+ for (let i = 0; i < parsedRows.length; i++) {
+ // Start a new row.
+ const rowNodes = parsedRows[i];
+ // Create the first cell.
+ let cell = newCell();
+ for (let j = 0; j < rowNodes.length; j++) {
+ if (!isStartOfArrow(rowNodes[j])) {
+ // If a parseNode is not an arrow, it goes into a cell.
+ cell.body.push(rowNodes[j]);
+ } else {
+ // Parse node j is an "@", the start of an arrow.
+ // Before starting on the arrow, push the cell into `row`.
+ row.push(cell);
+
+ // Now collect parseNodes into an arrow.
+ // The character after "@" defines the arrow type.
+ j += 1;
+ const arrowChar = assertSymbolNodeType(rowNodes[j]).text;
+
+ // Create two empty label nodes. We may or may not use them.
+ const labels = new Array(2);
+ labels[0] = {
+ type: "ordgroup",
+ mode: "math",
+ body: []
+ };
+ labels[1] = {
+ type: "ordgroup",
+ mode: "math",
+ body: []
+ };
+
+ // Process the arrow.
+ if ("=|.".includes(arrowChar)) {
+ // Three "arrows", ``@=`, `@|`, and `@.`, do not take labels.
+ // Do nothing here.
+ } else if ("<>AV".includes(arrowChar)) {
+ // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take
+ // two optional labels. E.g. the right-point arrow syntax is
+ // really: @>{optional label}>{optional label}>
+ // Collect parseNodes into labels.
+ for (let labelNum = 0; labelNum < 2; labelNum++) {
+ let inLabel = true;
+ for (let k = j + 1; k < rowNodes.length; k++) {
+ if (isLabelEnd(rowNodes[k], arrowChar)) {
+ inLabel = false;
+ j = k;
+ break;
+ }
+ if (isStartOfArrow(rowNodes[k])) {
+ throw new src_ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[k]);
+ }
+ labels[labelNum].body.push(rowNodes[k]);
+ }
+ if (inLabel) {
+ // isLabelEnd never returned a true.
+ throw new src_ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[j]);
+ }
+ }
+ } else {
+ throw new src_ParseError("Expected one of \"<>AV=|.\" after @", rowNodes[j]);
+ }
+
+ // Now join the arrow to its labels.
+ const arrow = cdArrow(arrowChar, labels, parser);
+
+ // Wrap the arrow in ParseNode<"styling">.
+ // This is done to match parseArray() behavior.
+ const wrappedArrow = {
+ type: "styling",
+ body: [arrow],
+ mode: "math",
+ style: "display",
+ // CD is always displaystyle.
+ resetFont: true
+ };
+ row.push(wrappedArrow);
+ // In CD's syntax, cells are implicit. That is, everything that
+ // is not an arrow gets collected into a cell. So create an empty
+ // cell now. It will collect upcoming parseNodes.
+ cell = newCell();
+ }
+ }
+ if (i % 2 === 0) {
+ // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell
+ // The last cell is not yet pushed into `row`, so:
+ row.push(cell);
+ } else {
+ // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow
+ // Remove the empty cell that was placed at the beginning of `row`.
+ row.shift();
+ }
+ row = [];
+ body.push(row);
+ }
+
+ // End row group
+ parser.gullet.endGroup();
+ // End array group defining \\
+ parser.gullet.endGroup();
+
+ // define column separation.
+ const cols = new Array(body[0].length).fill({
+ type: "align",
+ align: "c",
+ pregap: 0.25,
+ // CD package sets \enskip between columns.
+ postgap: 0.25 // So pre and post each get half an \enskip, i.e. 0.25em.
+ });
+ return {
+ type: "array",
+ mode: "math",
+ body,
+ arraystretch: 1,
+ addJot: true,
+ rowGaps: [null],
+ cols,
+ colSeparationType: "CD",
+ hLinesBeforeRow: new Array(body.length + 1).fill([])
+ };
+}
+
+// The functions below are not available for general use.
+// They are here only for internal use by the {CD} environment in placing labels
+// next to vertical arrows.
+
+// We don't need any such functions for horizontal arrows because we can reuse
+// the functionality that already exists for extensible arrows.
+
+defineFunction({
+ type: "cdlabel",
+ names: ["\\\\cdleft", "\\\\cdright"],
+ numArgs: 1,
+ handler(_ref, args) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ return {
+ type: "cdlabel",
+ mode: parser.mode,
+ side: funcName.slice(4),
+ label: args[0]
+ };
+ },
+ htmlBuilder(group, options) {
+ const newOptions = options.havingStyle(options.style.sup());
+ const label = wrapFragment(buildGroup(group.label, newOptions, options), options);
+ label.classes.push("cd-label-" + group.side);
+ label.style.bottom = makeEm(0.8 - label.depth);
+ // Zero out label height & depth, so vertical align of arrow is set
+ // by the arrow height, not by the label.
+ label.height = 0;
+ label.depth = 0;
+ return label;
+ },
+ mathmlBuilder(group, options) {
+ let label = new MathNode("mrow", [buildMathML_buildGroup(group.label, options)]);
+ label = new MathNode("mpadded", [label]);
+ label.setAttribute("width", "0");
+ if (group.side === "left") {
+ label.setAttribute("lspace", "-1width");
+ }
+ // We have to guess at vertical alignment. We know the arrow is 1.8em tall,
+ // But we don't know the height or depth of the label.
+ label.setAttribute("voffset", "0.7em");
+ label = new MathNode("mstyle", [label]);
+ label.setAttribute("displaystyle", "false");
+ label.setAttribute("scriptlevel", "1");
+ return label;
+ }
+});
+defineFunction({
+ type: "cdlabelparent",
+ names: ["\\\\cdparent"],
+ numArgs: 1,
+ handler(_ref2, args) {
+ let parser = _ref2.parser;
+ return {
+ type: "cdlabelparent",
+ mode: parser.mode,
+ fragment: args[0]
+ };
+ },
+ htmlBuilder(group, options) {
+ // Wrap the vertical arrow and its labels.
+ // The parent gets position: relative. The child gets position: absolute.
+ // So CSS can locate the label correctly.
+ const parent = wrapFragment(buildGroup(group.fragment, options), options);
+ parent.classes.push("cd-vert-arrow");
+ return parent;
+ },
+ mathmlBuilder(group, options) {
+ return new MathNode("mrow", [buildMathML_buildGroup(group.fragment, options)]);
+ }
+});
+;// ./src/functions/char.ts
+
+
+
+
+// \@char is an internal function that takes a grouped decimal argument like
+// {123} and converts into symbol with code 123. It is used by the *macro*
+// \char defined in macros.js.
+defineFunction({
+ type: "textord",
+ names: ["\\@char"],
+ numArgs: 1,
+ allowedInText: true,
+ handler(_ref, args) {
+ let parser = _ref.parser;
+ const arg = assertNodeType(args[0], "ordgroup");
+ const number = assertCharacterGroup(arg, "\\@char has non-numeric argument");
+ let code = parseInt(number);
+ let text;
+ if (isNaN(code)) {
+ throw new src_ParseError("\\@char has non-numeric argument " + number);
+ // If we drop IE support, the following code could be replaced with
+ // text = String.fromCodePoint(code)
+ } else if (code < 0 || code >= 0x10ffff) {
+ throw new src_ParseError("\\@char with invalid code point " + number);
+ } else if (code <= 0xffff) {
+ text = String.fromCharCode(code);
+ } else {
+ // Astral code point; split into surrogate halves
+ code -= 0x10000;
+ text = String.fromCharCode((code >> 10) + 0xd800, (code & 0x3ff) + 0xdc00);
+ }
+ return {
+ type: "textord",
+ mode: parser.mode,
+ text: text
+ };
+ }
+});
+;// ./src/functions/color.ts
+
+
+
+
+
+
+const color_htmlBuilder = (group, options) => {
+ const elements = buildExpression(group.body, options.withColor(group.color), false);
+
+ // \color isn't supposed to affect the type of the elements it contains.
+ // To accomplish this, we wrap the results in a fragment, so the inner
+ // elements will be able to directly interact with their neighbors. For
+ // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
+ return makeFragment(elements);
+};
+const color_mathmlBuilder = (group, options) => {
+ const inner = buildMathML_buildExpression(group.body, options.withColor(group.color));
+ const node = new MathNode("mstyle", inner);
+ node.setAttribute("mathcolor", group.color);
+ return node;
+};
+defineFunction({
+ type: "color",
+ names: ["\\textcolor"],
+ numArgs: 2,
+ allowedInText: true,
+ argTypes: ["color", "original"],
+ handler(_ref, args) {
+ let parser = _ref.parser;
+ const color = assertNodeType(args[0], "color-token").color;
+ const body = args[1];
+ return {
+ type: "color",
+ mode: parser.mode,
+ color,
+ body: ordargument(body)
+ };
+ },
+ htmlBuilder: color_htmlBuilder,
+ mathmlBuilder: color_mathmlBuilder
+});
+defineFunction({
+ type: "color",
+ names: ["\\color"],
+ numArgs: 1,
+ allowedInText: true,
+ argTypes: ["color"],
+ handler(_ref2, args) {
+ let parser = _ref2.parser,
+ breakOnTokenText = _ref2.breakOnTokenText;
+ const color = assertNodeType(args[0], "color-token").color;
+
+ // Set macro \current@color in current namespace to store the current
+ // color, mimicking the behavior of color.sty.
+ // This is currently used just to correctly color a \right
+ // that follows a \color command.
+ parser.gullet.macros.set("\\current@color", color);
+
+ // Parse out the implicit body that should be colored.
+ const body = parser.parseExpression(true, breakOnTokenText);
+ return {
+ type: "color",
+ mode: parser.mode,
+ color,
+ body
+ };
+ }
+});
+;// ./src/functions/cr.ts
+// Row breaks within tabular environments, and line breaks at top level
+
+
+
+
+
+
+
+// \DeclareRobustCommand\\{...\@xnewline}
+defineFunction({
+ type: "cr",
+ names: ["\\\\"],
+ numArgs: 0,
+ numOptionalArgs: 0,
+ allowedInText: true,
+ handler(_ref, args, optArgs) {
+ let parser = _ref.parser;
+ const size = parser.gullet.future().text === "[" ? parser.parseSizeGroup(true) : null;
+ const newLine = !parser.settings.displayMode || !parser.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode");
+ return {
+ type: "cr",
+ mode: parser.mode,
+ newLine,
+ size: size && assertNodeType(size, "size").value
+ };
+ },
+ // The following builders are called only at the top level,
+ // not within tabular/array environments.
+
+ htmlBuilder(group, options) {
+ const span = makeSpan(["mspace"], [], options);
+ if (group.newLine) {
+ span.classes.push("katex-newline");
+ if (group.size) {
+ span.style.marginTop = makeEm(calculateSize(group.size, options));
+ }
+ }
+ return span;
+ },
+ mathmlBuilder(group, options) {
+ const node = new MathNode("mspace");
+ if (group.newLine) {
+ node.setAttribute("linebreak", "newline");
+ if (group.size) {
+ node.setAttribute("height", makeEm(calculateSize(group.size, options)));
+ }
+ }
+ return node;
+ }
+});
+;// ./src/functions/def.ts
+
+
+
+const globalMap = {
+ "\\global": "\\global",
+ "\\long": "\\\\globallong",
+ "\\\\globallong": "\\\\globallong",
+ "\\def": "\\gdef",
+ "\\gdef": "\\gdef",
+ "\\edef": "\\xdef",
+ "\\xdef": "\\xdef",
+ "\\let": "\\\\globallet",
+ "\\futurelet": "\\\\globalfuture"
+};
+const checkControlSequence = tok => {
+ const name = tok.text;
+ if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) {
+ throw new src_ParseError("Expected a control sequence", tok);
+ }
+ return name;
+};
+const getRHS = parser => {
+ let tok = parser.gullet.popToken();
+ if (tok.text === "=") {
+ // consume optional equals
+ tok = parser.gullet.popToken();
+ if (tok.text === " ") {
+ // consume one optional space
+ tok = parser.gullet.popToken();
+ }
+ }
+ return tok;
+};
+const letCommand = (parser, name, tok, global) => {
+ let macro = parser.gullet.macros.get(tok.text);
+ if (macro == null) {
+ // don't expand it later even if a macro with the same name is defined
+ // e.g., \let\foo=\frac \def\frac{\relax} \frac12
+ tok.noexpand = true;
+ macro = {
+ tokens: [tok],
+ numArgs: 0,
+ // reproduce the same behavior in expansion
+ unexpandable: !parser.gullet.isExpandable(tok.text)
+ };
+ }
+ parser.gullet.macros.set(name, macro, global);
+};
+
+// <assignment> -> <non-macro assignment>|<macro assignment>
+// <non-macro assignment> -> <simple assignment>|\global<non-macro assignment>
+// <macro assignment> -> <definition>|<prefix><macro assignment>
+// <prefix> -> \global|\long|\outer
+defineFunction({
+ type: "internal",
+ names: ["\\global", "\\long", "\\\\globallong" // can’t be entered directly
+ ],
+ numArgs: 0,
+ allowedInText: true,
+ handler(_ref) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ parser.consumeSpaces();
+ const token = parser.fetch();
+ if (globalMap[token.text]) {
+ // KaTeX doesn't have \par, so ignore \long
+ if (funcName === "\\global" || funcName === "\\\\globallong") {
+ token.text = globalMap[token.text];
+ }
+ return assertNodeType(parser.parseFunction(), "internal");
+ }
+ throw new src_ParseError("Invalid token after macro prefix", token);
+ }
+});
+
+// Basic support for macro definitions: \def, \gdef, \edef, \xdef
+// <definition> -> <def><control sequence><definition text>
+// <def> -> \def|\gdef|\edef|\xdef
+// <definition text> -> <parameter text><left brace><balanced text><right brace>
+defineFunction({
+ type: "internal",
+ names: ["\\def", "\\gdef", "\\edef", "\\xdef"],
+ numArgs: 0,
+ allowedInText: true,
+ primitive: true,
+ handler(_ref2) {
+ let parser = _ref2.parser,
+ funcName = _ref2.funcName;
+ let tok = parser.gullet.popToken();
+ const name = tok.text;
+ if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) {
+ throw new src_ParseError("Expected a control sequence", tok);
+ }
+ let numArgs = 0;
+ let insert;
+ const delimiters = [[]];
+ // <parameter text> contains no braces
+ while (parser.gullet.future().text !== "{") {
+ tok = parser.gullet.popToken();
+ if (tok.text === "#") {
+ // If the very last character of the <parameter text> is #, so that
+ // this # is immediately followed by {, TeX will behave as if the {
+ // had been inserted at the right end of both the parameter text
+ // and the replacement text.
+ if (parser.gullet.future().text === "{") {
+ insert = parser.gullet.future();
+ delimiters[numArgs].push("{");
+ break;
+ }
+
+ // A parameter, the first appearance of # must be followed by 1,
+ // the next by 2, and so on; up to nine #’s are allowed
+ tok = parser.gullet.popToken();
+ if (!/^[1-9]$/.test(tok.text)) {
+ throw new src_ParseError("Invalid argument number \"" + tok.text + "\"");
+ }
+ if (parseInt(tok.text) !== numArgs + 1) {
+ throw new src_ParseError("Argument number \"" + tok.text + "\" out of order");
+ }
+ numArgs++;
+ delimiters.push([]);
+ } else if (tok.text === "EOF") {
+ throw new src_ParseError("Expected a macro definition");
+ } else {
+ delimiters[numArgs].push(tok.text);
+ }
+ }
+ // replacement text, enclosed in '{' and '}' and properly nested
+ let _parser$gullet$consum = parser.gullet.consumeArg(),
+ tokens = _parser$gullet$consum.tokens;
+ if (insert) {
+ tokens.unshift(insert);
+ }
+ if (funcName === "\\edef" || funcName === "\\xdef") {
+ tokens = parser.gullet.expandTokens(tokens);
+ tokens.reverse(); // to fit in with stack order
+ }
+ // Final arg is the expansion of the macro
+ parser.gullet.macros.set(name, {
+ tokens,
+ numArgs,
+ delimiters
+ }, funcName === globalMap[funcName]);
+ return {
+ type: "internal",
+ mode: parser.mode
+ };
+ }
+});
+
+// <simple assignment> -> <let assignment>
+// <let assignment> -> \futurelet<control sequence><token><token>
+// | \let<control sequence><equals><one optional space><token>
+// <equals> -> <optional spaces>|<optional spaces>=
+defineFunction({
+ type: "internal",
+ names: ["\\let", "\\\\globallet" // can’t be entered directly
+ ],
+ numArgs: 0,
+ allowedInText: true,
+ primitive: true,
+ handler(_ref3) {
+ let parser = _ref3.parser,
+ funcName = _ref3.funcName;
+ const name = checkControlSequence(parser.gullet.popToken());
+ parser.gullet.consumeSpaces();
+ const tok = getRHS(parser);
+ letCommand(parser, name, tok, funcName === "\\\\globallet");
+ return {
+ type: "internal",
+ mode: parser.mode
+ };
+ }
+});
+
+// ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf
+defineFunction({
+ type: "internal",
+ names: ["\\futurelet", "\\\\globalfuture" // can’t be entered directly
+ ],
+ numArgs: 0,
+ allowedInText: true,
+ primitive: true,
+ handler(_ref4) {
+ let parser = _ref4.parser,
+ funcName = _ref4.funcName;
+ const name = checkControlSequence(parser.gullet.popToken());
+ const middle = parser.gullet.popToken();
+ const tok = parser.gullet.popToken();
+ letCommand(parser, name, tok, funcName === "\\\\globalfuture");
+ parser.gullet.pushToken(tok);
+ parser.gullet.pushToken(middle);
+ return {
+ type: "internal",
+ mode: parser.mode
+ };
+ }
+});
+;// ./src/delimiter.ts
+/**
+ * This file deals with creating delimiters of various sizes. The TeXbook
+ * discusses these routines on page 441-442, in the "Another subroutine sets box
+ * x to a specified variable delimiter" paragraph.
+ *
+ * There are three main routines here. `makeSmallDelim` makes a delimiter in the
+ * normal font, but in either text, script, or scriptscript style.
+ * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1,
+ * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of
+ * smaller pieces that are stacked on top of one another.
+ *
+ * The functions take a parameter `center`, which determines if the delimiter
+ * should be centered around the axis.
+ *
+ * Then, there are three exposed functions. `sizedDelim` makes a delimiter in
+ * one of the given sizes. This is used for things like `\bigl`.
+ * `customSizedDelim` makes a delimiter with a given total height+depth. It is
+ * called in places like `\sqrt`. `leftRightDelim` makes an appropriate
+ * delimiter which surrounds an expression of a given height an depth. It is
+ * used in `\left` and `\right`.
+ */
+
+
+
+
+
+
+
+
+
+
+/**
+ * Get the metrics for a given symbol and font, after transformation (i.e.
+ * after following replacement from symbols.js)
+ */
+const getMetrics = function (symbol, font, mode) {
+ const replace = src_symbols.math[symbol] && src_symbols.math[symbol].replace;
+ const metrics = getCharacterMetrics(replace || symbol, font, mode);
+ if (!metrics) {
+ throw new Error("Unsupported symbol " + symbol + " and font size " + font + ".");
+ }
+ return metrics;
+};
+
+/**
+ * Puts a delimiter span in a given style, and adds appropriate height, depth,
+ * and maxFontSizes.
+ */
+const styleWrap = function (delim, toStyle, options, classes) {
+ const newOptions = options.havingBaseStyle(toStyle);
+ const span = makeSpan(classes.concat(newOptions.sizingClasses(options)), [delim], options);
+ const delimSizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier;
+ span.height *= delimSizeMultiplier;
+ span.depth *= delimSizeMultiplier;
+ span.maxFontSize = newOptions.sizeMultiplier;
+ return span;
+};
+const centerSpan = function (span, options, style) {
+ const newOptions = options.havingBaseStyle(style);
+ const shift = (1 - options.sizeMultiplier / newOptions.sizeMultiplier) * options.fontMetrics().axisHeight;
+ span.classes.push("delimcenter");
+ span.style.top = makeEm(shift);
+ span.height -= shift;
+ span.depth += shift;
+};
+
+/**
+ * Makes a small delimiter. This is a delimiter that comes in the Main-Regular
+ * font, but is restyled to either be in textstyle, scriptstyle, or
+ * scriptscriptstyle.
+ */
+const makeSmallDelim = function (delim, style, center, options, mode, classes) {
+ const text = makeSymbol(delim, "Main-Regular", mode, options);
+ const span = styleWrap(text, style, options, classes);
+ if (center) {
+ centerSpan(span, options, style);
+ }
+ return span;
+};
+
+/**
+ * Builds a symbol in the given font size (note size is an integer)
+ */
+const mathrmSize = function (value, size, mode, options) {
+ return makeSymbol(value, "Size" + size + "-Regular", mode, options);
+};
+
+/**
+ * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
+ * Size3, or Size4 fonts. It is always rendered in textstyle.
+ */
+const makeLargeDelim = function (delim, size, center, options, mode, classes) {
+ const inner = mathrmSize(delim, size, mode, options);
+ const span = styleWrap(makeSpan(["delimsizing", "size" + size], [inner], options), src_Style.TEXT, options, classes);
+ if (center) {
+ centerSpan(span, options, src_Style.TEXT);
+ }
+ return span;
+};
+
+/**
+ * Make a span from a font glyph with the given offset and in the given font.
+ * This is used in makeStackedDelim to make the stacking pieces for the delimiter.
+ */
+const makeGlyphSpan = function (symbol, font, mode) {
+ let sizeClass;
+ // Apply the correct CSS class to choose the right font.
+ if (font === "Size1-Regular") {
+ sizeClass = "delim-size1";
+ } else /* if (font === "Size4-Regular") */{
+ sizeClass = "delim-size4";
+ }
+ const corner = makeSpan(["delimsizinginner", sizeClass], [makeSpan([], [makeSymbol(symbol, font, mode)])]);
+
+ // Since this will be passed into `makeVList` in the end, wrap the element
+ // in the appropriate tag that VList uses.
+ return {
+ type: "elem",
+ elem: corner
+ };
+};
+const makeInner = function (ch, height, options) {
+ // Create a span with inline SVG for the inner part of a tall stacked delimiter.
+ const width = fontMetricsData['Size4-Regular'][ch.charCodeAt(0)] ? fontMetricsData['Size4-Regular'][ch.charCodeAt(0)][4] : fontMetricsData['Size1-Regular'][ch.charCodeAt(0)][4];
+ const path = new PathNode("inner", innerPath(ch, Math.round(1000 * height)));
+ const svgNode = new SvgNode([path], {
+ "width": makeEm(width),
+ "height": makeEm(height),
+ // Override CSS rule `.katex svg { width: 100% }`
+ "style": "width:" + makeEm(width),
+ "viewBox": "0 0 " + 1000 * width + " " + Math.round(1000 * height),
+ "preserveAspectRatio": "xMinYMin"
+ });
+ const span = makeSvgSpan([], [svgNode], options);
+ span.height = height;
+ span.style.height = makeEm(height);
+ span.style.width = makeEm(width);
+ return {
+ type: "elem",
+ elem: span
+ };
+};
+
+// Helpers for makeStackedDelim
+const lapInEms = 0.008;
+const lap = {
+ type: "kern",
+ size: -1 * lapInEms
+};
+const verts = new Set(["|", "\\lvert", "\\rvert", "\\vert"]);
+const doubleVerts = new Set(["\\|", "\\lVert", "\\rVert", "\\Vert"]);
+
+/**
+ * Make a stacked delimiter out of a given delimiter, with the total height at
+ * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
+ */
+const makeStackedDelim = function (delim, heightTotal, center, options, mode, classes) {
+ // There are four parts, the top, an optional middle, a repeated part, and a
+ // bottom.
+ let top;
+ let middle;
+ let repeat;
+ let bottom;
+ let svgLabel = "";
+ let viewBoxWidth = 0;
+ top = repeat = bottom = delim;
+ middle = null;
+ // Also keep track of what font the delimiters are in
+ let font = "Size1-Regular";
+
+ // We set the parts and font based on the symbol. Note that we use
+ // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
+ // repeats of the arrows
+ if (delim === "\\uparrow") {
+ repeat = bottom = "\u23d0";
+ } else if (delim === "\\Uparrow") {
+ repeat = bottom = "\u2016";
+ } else if (delim === "\\downarrow") {
+ top = repeat = "\u23d0";
+ } else if (delim === "\\Downarrow") {
+ top = repeat = "\u2016";
+ } else if (delim === "\\updownarrow") {
+ top = "\\uparrow";
+ repeat = "\u23d0";
+ bottom = "\\downarrow";
+ } else if (delim === "\\Updownarrow") {
+ top = "\\Uparrow";
+ repeat = "\u2016";
+ bottom = "\\Downarrow";
+ } else if (verts.has(delim)) {
+ repeat = "\u2223";
+ svgLabel = "vert";
+ viewBoxWidth = 333;
+ } else if (doubleVerts.has(delim)) {
+ repeat = "\u2225";
+ svgLabel = "doublevert";
+ viewBoxWidth = 556;
+ } else if (delim === "[" || delim === "\\lbrack") {
+ top = "\u23a1";
+ repeat = "\u23a2";
+ bottom = "\u23a3";
+ font = "Size4-Regular";
+ svgLabel = "lbrack";
+ viewBoxWidth = 667;
+ } else if (delim === "]" || delim === "\\rbrack") {
+ top = "\u23a4";
+ repeat = "\u23a5";
+ bottom = "\u23a6";
+ font = "Size4-Regular";
+ svgLabel = "rbrack";
+ viewBoxWidth = 667;
+ } else if (delim === "\\lfloor" || delim === "\u230a") {
+ repeat = top = "\u23a2";
+ bottom = "\u23a3";
+ font = "Size4-Regular";
+ svgLabel = "lfloor";
+ viewBoxWidth = 667;
+ } else if (delim === "\\lceil" || delim === "\u2308") {
+ top = "\u23a1";
+ repeat = bottom = "\u23a2";
+ font = "Size4-Regular";
+ svgLabel = "lceil";
+ viewBoxWidth = 667;
+ } else if (delim === "\\rfloor" || delim === "\u230b") {
+ repeat = top = "\u23a5";
+ bottom = "\u23a6";
+ font = "Size4-Regular";
+ svgLabel = "rfloor";
+ viewBoxWidth = 667;
+ } else if (delim === "\\rceil" || delim === "\u2309") {
+ top = "\u23a4";
+ repeat = bottom = "\u23a5";
+ font = "Size4-Regular";
+ svgLabel = "rceil";
+ viewBoxWidth = 667;
+ } else if (delim === "(" || delim === "\\lparen") {
+ top = "\u239b";
+ repeat = "\u239c";
+ bottom = "\u239d";
+ font = "Size4-Regular";
+ svgLabel = "lparen";
+ viewBoxWidth = 875;
+ } else if (delim === ")" || delim === "\\rparen") {
+ top = "\u239e";
+ repeat = "\u239f";
+ bottom = "\u23a0";
+ font = "Size4-Regular";
+ svgLabel = "rparen";
+ viewBoxWidth = 875;
+ } else if (delim === "\\{" || delim === "\\lbrace") {
+ top = "\u23a7";
+ middle = "\u23a8";
+ bottom = "\u23a9";
+ repeat = "\u23aa";
+ font = "Size4-Regular";
+ } else if (delim === "\\}" || delim === "\\rbrace") {
+ top = "\u23ab";
+ middle = "\u23ac";
+ bottom = "\u23ad";
+ repeat = "\u23aa";
+ font = "Size4-Regular";
+ } else if (delim === "\\lgroup" || delim === "\u27ee") {
+ top = "\u23a7";
+ bottom = "\u23a9";
+ repeat = "\u23aa";
+ font = "Size4-Regular";
+ } else if (delim === "\\rgroup" || delim === "\u27ef") {
+ top = "\u23ab";
+ bottom = "\u23ad";
+ repeat = "\u23aa";
+ font = "Size4-Regular";
+ } else if (delim === "\\lmoustache" || delim === "\u23b0") {
+ top = "\u23a7";
+ bottom = "\u23ad";
+ repeat = "\u23aa";
+ font = "Size4-Regular";
+ } else if (delim === "\\rmoustache" || delim === "\u23b1") {
+ top = "\u23ab";
+ bottom = "\u23a9";
+ repeat = "\u23aa";
+ font = "Size4-Regular";
+ }
+
+ // Get the metrics of the four sections
+ const topMetrics = getMetrics(top, font, mode);
+ const topHeightTotal = topMetrics.height + topMetrics.depth;
+ const repeatMetrics = getMetrics(repeat, font, mode);
+ const repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
+ const bottomMetrics = getMetrics(bottom, font, mode);
+ const bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
+ let middleHeightTotal = 0;
+ let middleFactor = 1;
+ if (middle !== null) {
+ const middleMetrics = getMetrics(middle, font, mode);
+ middleHeightTotal = middleMetrics.height + middleMetrics.depth;
+ middleFactor = 2; // repeat symmetrically above and below middle
+ }
+
+ // Calculate the minimal height that the delimiter can have.
+ // It is at least the size of the top, bottom, and optional middle combined.
+ const minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal;
+
+ // Compute the number of copies of the repeat symbol we will need
+ const repeatCount = Math.max(0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal)));
+
+ // Compute the total height of the delimiter including all the symbols
+ const realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal;
+
+ // The center of the delimiter is placed at the center of the axis. Note
+ // that in this context, "center" means that the delimiter should be
+ // centered around the axis in the current style, while normally it is
+ // centered around the axis in textstyle.
+ let axisHeight = options.fontMetrics().axisHeight;
+ if (center) {
+ axisHeight *= options.sizeMultiplier;
+ }
+ // Calculate the depth
+ const depth = realHeightTotal / 2 - axisHeight;
+
+ // Now, we start building the pieces that will go into the vlist
+ // Keep a list of the pieces of the stacked delimiter
+ const stack = [];
+ if (svgLabel.length > 0) {
+ // Instead of stacking glyphs, create a single SVG.
+ // This evades browser problems with imprecise positioning of spans.
+ const midHeight = realHeightTotal - topHeightTotal - bottomHeightTotal;
+ const viewBoxHeight = Math.round(realHeightTotal * 1000);
+ const pathStr = tallDelim(svgLabel, Math.round(midHeight * 1000));
+ const path = new PathNode(svgLabel, pathStr);
+ const width = makeEm(viewBoxWidth / 1000);
+ const height = makeEm(viewBoxHeight / 1000);
+ const svg = new SvgNode([path], {
+ "width": width,
+ "height": height,
+ "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight
+ });
+ const wrapper = makeSvgSpan([], [svg], options);
+ wrapper.height = viewBoxHeight / 1000;
+ wrapper.style.width = width;
+ wrapper.style.height = height;
+ stack.push({
+ type: "elem",
+ elem: wrapper
+ });
+ } else {
+ // Stack glyphs
+ // Start by adding the bottom symbol
+ stack.push(makeGlyphSpan(bottom, font, mode));
+ stack.push(lap); // overlap
+
+ if (middle === null) {
+ // The middle section will be an SVG. Make it an extra 0.016em tall.
+ // We'll overlap by 0.008em at top and bottom.
+ const innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms;
+ stack.push(makeInner(repeat, innerHeight, options));
+ } else {
+ // When there is a middle bit, we need the middle part and two repeated
+ // sections
+ const innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms;
+ stack.push(makeInner(repeat, innerHeight, options));
+ // Now insert the middle of the brace.
+ stack.push(lap);
+ stack.push(makeGlyphSpan(middle, font, mode));
+ stack.push(lap);
+ stack.push(makeInner(repeat, innerHeight, options));
+ }
+
+ // Add the top symbol
+ stack.push(lap);
+ stack.push(makeGlyphSpan(top, font, mode));
+ }
+
+ // Finally, build the vlist
+ const newOptions = options.havingBaseStyle(src_Style.TEXT);
+ const inner = makeVList({
+ positionType: "bottom",
+ positionData: depth,
+ children: stack
+ }, newOptions);
+ return styleWrap(makeSpan(["delimsizing", "mult"], [inner], newOptions), src_Style.TEXT, options, classes);
+};
+
+// All surds have 0.08em padding above the vinculum inside the SVG.
+// That keeps browser span height rounding error from pinching the line.
+const vbPad = 80; // padding above the surd, measured inside the viewBox.
+const emPad = 0.08; // padding, in ems, measured in the document.
+
+const sqrtSvg = function (sqrtName, height, viewBoxHeight, extraVinculum, options) {
+ const path = sqrtPath(sqrtName, extraVinculum, viewBoxHeight);
+ const pathNode = new PathNode(sqrtName, path);
+ const svg = new SvgNode([pathNode], {
+ // Note: 1000:1 ratio of viewBox to document em width.
+ "width": "400em",
+ "height": makeEm(height),
+ "viewBox": "0 0 400000 " + viewBoxHeight,
+ "preserveAspectRatio": "xMinYMin slice"
+ });
+ return makeSvgSpan(["hide-tail"], [svg], options);
+};
+
+/**
+ * Make a sqrt image of the given height,
+ */
+const makeSqrtImage = function (height, options) {
+ // Define a newOptions that removes the effect of size changes such as \Huge.
+ // We don't pick different a height surd for \Huge. For it, we scale up.
+ const newOptions = options.havingBaseSizing();
+
+ // Pick the desired surd glyph from a sequence of surds.
+ const delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier, stackLargeDelimiterSequence, newOptions);
+ let sizeMultiplier = newOptions.sizeMultiplier; // default
+
+ // The standard sqrt SVGs each have a 0.04em thick vinculum.
+ // If Settings.minRuleThickness is larger than that, we add extraVinculum.
+ const extraVinculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness);
+
+ // Create a span containing an SVG image of a sqrt symbol.
+ let span;
+ let spanHeight;
+ let texHeight;
+ let viewBoxHeight;
+ let advanceWidth;
+
+ // We create viewBoxes with 80 units of "padding" above each surd.
+ // Then browser rounding error on the parent span height will not
+ // encroach on the ink of the vinculum. But that padding is not
+ // included in the TeX-like `height` used for calculation of
+ // vertical alignment. So texHeight = span.height < span.style.height.
+
+ if (delim.type === "small") {
+ // Get an SVG that is derived from glyph U+221A in font KaTeX-Main.
+ // 1000 unit normal glyph height.
+ viewBoxHeight = 1000 + 1000 * extraVinculum + vbPad;
+ if (height < 1.0) {
+ sizeMultiplier = 1.0; // mimic a \textfont radical
+ } else if (height < 1.4) {
+ sizeMultiplier = 0.7; // mimic a \scriptfont radical
+ }
+ spanHeight = (1.0 + extraVinculum + emPad) / sizeMultiplier;
+ texHeight = (1.00 + extraVinculum) / sizeMultiplier;
+ span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraVinculum, options);
+ span.style.minWidth = "0.853em";
+ advanceWidth = 0.833 / sizeMultiplier; // from the font.
+ } else if (delim.type === "large") {
+ // These SVGs come from fonts: KaTeX_Size1, _Size2, etc.
+ viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size];
+ texHeight = (sizeToMaxHeight[delim.size] + extraVinculum) / sizeMultiplier;
+ spanHeight = (sizeToMaxHeight[delim.size] + extraVinculum + emPad) / sizeMultiplier;
+ span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, extraVinculum, options);
+ span.style.minWidth = "1.02em";
+ advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font.
+ } else {
+ // Tall sqrt. In TeX, this would be stacked using multiple glyphs.
+ // We'll use a single SVG to accomplish the same thing.
+ spanHeight = height + extraVinculum + emPad;
+ texHeight = height + extraVinculum;
+ viewBoxHeight = Math.floor(1000 * height + extraVinculum) + vbPad;
+ span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraVinculum, options);
+ span.style.minWidth = "0.742em";
+ advanceWidth = 1.056;
+ }
+ span.height = texHeight;
+ span.style.height = makeEm(spanHeight);
+ return {
+ span,
+ advanceWidth,
+ // Calculate the actual line width.
+ // This actually should depend on the chosen font -- e.g. \boldmath
+ // should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and
+ // have thicker rules.
+ ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraVinculum) * sizeMultiplier
+ };
+};
+
+// There are three kinds of delimiters, delimiters that stack when they become
+// too large
+const stackLargeDelimiters = new Set(["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"]);
+
+// delimiters that always stack
+const stackAlwaysDelimiters = new Set(["\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1"]);
+
+// and delimiters that never stack
+const stackNeverDelimiters = new Set(["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"]);
+
+// Metrics of the different sizes. Found by looking at TeX's output of
+// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
+// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
+const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
+
+/**
+ * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
+ */
+const makeSizedDelim = function (delim, size, options, mode, classes) {
+ // < and > turn into \langle and \rangle in delimiters
+ if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
+ delim = "\\langle";
+ } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
+ delim = "\\rangle";
+ }
+
+ // Sized delimiters are never centered.
+ if (stackLargeDelimiters.has(delim) || stackNeverDelimiters.has(delim)) {
+ return makeLargeDelim(delim, size, false, options, mode, classes);
+ } else if (stackAlwaysDelimiters.has(delim)) {
+ return makeStackedDelim(delim, sizeToMaxHeight[size], false, options, mode, classes);
+ } else {
+ throw new src_ParseError("Illegal delimiter: '" + delim + "'");
+ }
+};
+
+/**
+ * There are three different sequences of delimiter sizes that the delimiters
+ * follow depending on the kind of delimiter. This is used when creating custom
+ * sized delimiters to decide whether to create a small, large, or stacked
+ * delimiter.
+ *
+ * In real TeX, these sequences aren't explicitly defined, but are instead
+ * defined inside the font metrics. Since there are only three sequences that
+ * are possible for the delimiters that TeX defines, it is easier to just encode
+ * them explicitly here.
+ */
+
+// Delimiters that never stack try small delimiters and large delimiters only
+const stackNeverDelimiterSequence = [{
+ type: "small",
+ style: src_Style.SCRIPTSCRIPT
+}, {
+ type: "small",
+ style: src_Style.SCRIPT
+}, {
+ type: "small",
+ style: src_Style.TEXT
+}, {
+ type: "large",
+ size: 1
+}, {
+ type: "large",
+ size: 2
+}, {
+ type: "large",
+ size: 3
+}, {
+ type: "large",
+ size: 4
+}];
+
+// Delimiters that always stack try the small delimiters first, then stack
+const stackAlwaysDelimiterSequence = [{
+ type: "small",
+ style: src_Style.SCRIPTSCRIPT
+}, {
+ type: "small",
+ style: src_Style.SCRIPT
+}, {
+ type: "small",
+ style: src_Style.TEXT
+}, {
+ type: "stack"
+}];
+
+// Delimiters that stack when large try the small and then large delimiters, and
+// stack afterwards
+const stackLargeDelimiterSequence = [{
+ type: "small",
+ style: src_Style.SCRIPTSCRIPT
+}, {
+ type: "small",
+ style: src_Style.SCRIPT
+}, {
+ type: "small",
+ style: src_Style.TEXT
+}, {
+ type: "large",
+ size: 1
+}, {
+ type: "large",
+ size: 2
+}, {
+ type: "large",
+ size: 3
+}, {
+ type: "large",
+ size: 4
+}, {
+ type: "stack"
+}];
+
+/**
+ * Get the font used in a delimiter based on what kind of delimiter it is.
+ * TODO(#963) Use more specific font family return type once that is introduced.
+ */
+const delimTypeToFont = function (type) {
+ if (type.type === "small") {
+ return "Main-Regular";
+ } else if (type.type === "large") {
+ return "Size" + type.size + "-Regular";
+ } else if (type.type === "stack") {
+ return "Size4-Regular";
+ } else {
+ const delimKind = type.type;
+ throw new Error("Add support for delim type '" + delimKind + "' here.");
+ }
+};
+
+/**
+ * Traverse a sequence of types of delimiters to decide what kind of delimiter
+ * should be used to create a delimiter of the given height+depth.
+ */
+const traverseSequence = function (delim, height, sequence, options) {
+ // Here, we choose the index we should start at in the sequences. In smaller
+ // sizes (which correspond to larger numbers in style.size) we start earlier
+ // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts
+ // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2
+ const start = Math.min(2, 3 - options.style.size);
+ for (let i = start; i < sequence.length; i++) {
+ const delimType = sequence[i];
+ if (delimType.type === "stack") {
+ // This is always the last delimiter, so we just break the loop now.
+ break;
+ }
+ const metrics = getMetrics(delim, delimTypeToFont(delimType), "math");
+ let heightDepth = metrics.height + metrics.depth;
+
+ // Small delimiters are scaled down versions of the same font, so we
+ // account for the style change size.
+ if (delimType.type === "small") {
+ const newOptions = options.havingBaseStyle(delimType.style);
+ heightDepth *= newOptions.sizeMultiplier;
+ }
+
+ // Check if the delimiter at this size works for the given height.
+ if (heightDepth > height) {
+ return delimType;
+ }
+ }
+
+ // If we reached the end of the sequence, return the last sequence element.
+ return sequence[sequence.length - 1];
+};
+
+/**
+ * Make a delimiter of a given height+depth, with optional centering. Here, we
+ * traverse the sequences, and create a delimiter that the sequence tells us to.
+ */
+const makeCustomSizedDelim = function (delim, height, center, options, mode, classes) {
+ if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
+ delim = "\\langle";
+ } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
+ delim = "\\rangle";
+ }
+
+ // Decide what sequence to use
+ let sequence;
+ if (stackNeverDelimiters.has(delim)) {
+ sequence = stackNeverDelimiterSequence;
+ } else if (stackLargeDelimiters.has(delim)) {
+ sequence = stackLargeDelimiterSequence;
+ } else {
+ sequence = stackAlwaysDelimiterSequence;
+ }
+
+ // Look through the sequence
+ const delimType = traverseSequence(delim, height, sequence, options);
+
+ // Get the delimiter from font glyphs.
+ // Depending on the sequence element we decided on, call the
+ // appropriate function.
+ if (delimType.type === "small") {
+ return makeSmallDelim(delim, delimType.style, center, options, mode, classes);
+ } else if (delimType.type === "large") {
+ return makeLargeDelim(delim, delimType.size, center, options, mode, classes);
+ } else /* if (delimType.type === "stack") */{
+ return makeStackedDelim(delim, height, center, options, mode, classes);
+ }
+};
+
+/**
+ * Make a delimiter for use with `\left` and `\right`, given a height and depth
+ * of an expression that the delimiters surround.
+ */
+const makeLeftRightDelim = function (delim, height, depth, options, mode, classes) {
+ // We always center \left/\right delimiters, so the axis is always shifted
+ const axisHeight = options.fontMetrics().axisHeight * options.sizeMultiplier;
+
+ // Taken from TeX source, tex.web, function make_left_right
+ const delimiterFactor = 901;
+ const delimiterExtend = 5.0 / options.fontMetrics().ptPerEm;
+ const maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight);
+ const totalHeight = Math.max(
+ // In real TeX, calculations are done using integral values which are
+ // 65536 per pt, or 655360 per em. So, the division here truncates in
+ // TeX but doesn't here, producing different results. If we wanted to
+ // exactly match TeX's calculation, we could do
+ // Math.floor(655360 * maxDistFromAxis / 500) *
+ // delimiterFactor / 655360
+ // (To see the difference, compare
+ // x^{x^{\left(\rule{0.1em}{0.68em}\right)}}
+ // in TeX and KaTeX)
+ maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend);
+
+ // Finally, we defer to `makeCustomSizedDelim` with our calculated total
+ // height
+ return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes);
+};
+;// ./src/functions/delimsizing.ts
+
+
+
+
+
+
+
+
+
+// Extra data needed for the delimiter handler down below
+const delimiterSizes = {
+ "\\bigl": {
+ mclass: "mopen",
+ size: 1
+ },
+ "\\Bigl": {
+ mclass: "mopen",
+ size: 2
+ },
+ "\\biggl": {
+ mclass: "mopen",
+ size: 3
+ },
+ "\\Biggl": {
+ mclass: "mopen",
+ size: 4
+ },
+ "\\bigr": {
+ mclass: "mclose",
+ size: 1
+ },
+ "\\Bigr": {
+ mclass: "mclose",
+ size: 2
+ },
+ "\\biggr": {
+ mclass: "mclose",
+ size: 3
+ },
+ "\\Biggr": {
+ mclass: "mclose",
+ size: 4
+ },
+ "\\bigm": {
+ mclass: "mrel",
+ size: 1
+ },
+ "\\Bigm": {
+ mclass: "mrel",
+ size: 2
+ },
+ "\\biggm": {
+ mclass: "mrel",
+ size: 3
+ },
+ "\\Biggm": {
+ mclass: "mrel",
+ size: 4
+ },
+ "\\big": {
+ mclass: "mord",
+ size: 1
+ },
+ "\\Big": {
+ mclass: "mord",
+ size: 2
+ },
+ "\\bigg": {
+ mclass: "mord",
+ size: 3
+ },
+ "\\Bigg": {
+ mclass: "mord",
+ size: 4
+ }
+};
+const delimiters = new Set(["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."]);
+
+/**
+ * An HtmlDomNode that carries an `isMiddle` property, used by the
+ * \middle command to communicate delimiter info to the \left/\right builder.
+ */
+
+function isMiddleDelimNode(node) {
+ return 'isMiddle' in node;
+}
+
+// Delimiter functions
+function checkDelimiter(delim, context) {
+ const symDelim = checkSymbolNodeType(delim);
+ if (symDelim && delimiters.has(symDelim.text)) {
+ return symDelim;
+ } else if (symDelim) {
+ throw new src_ParseError("Invalid delimiter '" + symDelim.text + "' after '" + context.funcName + "'", delim);
+ } else {
+ throw new src_ParseError("Invalid delimiter type '" + delim.type + "'", delim);
+ }
+}
+defineFunction({
+ type: "delimsizing",
+ names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"],
+ numArgs: 1,
+ argTypes: ["primitive"],
+ handler: (context, args) => {
+ const delim = checkDelimiter(normalizeArgument(args[0]), context);
+ return {
+ type: "delimsizing",
+ mode: context.parser.mode,
+ size: delimiterSizes[context.funcName].size,
+ mclass: delimiterSizes[context.funcName].mclass,
+ delim: delim.text
+ };
+ },
+ htmlBuilder: (group, options) => {
+ if (group.delim === ".") {
+ // Empty delimiters still count as elements, even though they don't
+ // show anything.
+ return makeSpan([group.mclass]);
+ }
+ return makeSizedDelim(group.delim, group.size, options, group.mode, [group.mclass]);
+ },
+ mathmlBuilder: group => {
+ const children = [];
+ if (group.delim !== ".") {
+ children.push(makeText(group.delim, group.mode));
+ }
+ const node = new MathNode("mo", children);
+ if (group.mclass === "mopen" || group.mclass === "mclose") {
+ // Only some of the delimsizing functions act as fences, and they
+ // return "mopen" or "mclose" mclass.
+ node.setAttribute("fence", "true");
+ } else {
+ // Explicitly disable fencing if it's not a fence, to override the
+ // defaults.
+ node.setAttribute("fence", "false");
+ }
+ node.setAttribute("stretchy", "true");
+ const size = makeEm(sizeToMaxHeight[group.size]);
+ node.setAttribute("minsize", size);
+ node.setAttribute("maxsize", size);
+ return node;
+ }
+});
+function assertParsed(group) {
+ if (!group.body) {
+ throw new Error("Bug: The leftright ParseNode wasn't fully parsed.");
+ }
+}
+defineFunction({
+ type: "leftright-right",
+ names: ["\\right"],
+ numArgs: 1,
+ primitive: true,
+ handler: (context, args) => {
+ // \left case below triggers parsing of \right in
+ // `const right = parser.parseFunction();`
+ // uses this return value.
+ const color = context.parser.gullet.macros.get("\\current@color");
+ if (color && typeof color !== "string") {
+ throw new src_ParseError("\\current@color set to non-string in \\right");
+ }
+ return {
+ type: "leftright-right",
+ mode: context.parser.mode,
+ delim: checkDelimiter(args[0], context).text,
+ color // undefined if not set via \color
+ };
+ }
+});
+defineFunction({
+ type: "leftright",
+ names: ["\\left"],
+ numArgs: 1,
+ primitive: true,
+ handler: (context, args) => {
+ const delim = checkDelimiter(args[0], context);
+ const parser = context.parser;
+ // Parse out the implicit body
+ ++parser.leftrightDepth;
+ // parseExpression stops before '\\right'
+ const body = parser.parseExpression(false);
+ --parser.leftrightDepth;
+ // Check the next token
+ parser.expect("\\right", false);
+ const right = assertNodeType(parser.parseFunction(), "leftright-right");
+ return {
+ type: "leftright",
+ mode: parser.mode,
+ body,
+ left: delim.text,
+ right: right.delim,
+ rightColor: right.color
+ };
+ },
+ htmlBuilder: (group, options) => {
+ assertParsed(group);
+ // Build the inner expression
+ const inner = buildExpression(group.body, options, true, ["mopen", "mclose"]);
+ let innerHeight = 0;
+ let innerDepth = 0;
+ let hadMiddle = false;
+
+ // Calculate its height and depth
+ for (let i = 0; i < inner.length; i++) {
+ const node = inner[i];
+ if (isMiddleDelimNode(node)) {
+ hadMiddle = true;
+ } else {
+ innerHeight = Math.max(inner[i].height, innerHeight);
+ innerDepth = Math.max(inner[i].depth, innerDepth);
+ }
+ }
+
+ // The size of delimiters is the same, regardless of what style we are
+ // in. Thus, to correctly calculate the size of delimiter we need around
+ // a group, we scale down the inner size based on the size.
+ innerHeight *= options.sizeMultiplier;
+ innerDepth *= options.sizeMultiplier;
+ let leftDelim;
+ if (group.left === ".") {
+ // Empty delimiters in \left and \right make null delimiter spaces.
+ leftDelim = makeNullDelimiter(options, ["mopen"]);
+ } else {
+ // Otherwise, use leftRightDelim to generate the correct sized
+ // delimiter.
+ leftDelim = makeLeftRightDelim(group.left, innerHeight, innerDepth, options, group.mode, ["mopen"]);
+ }
+ // Add it to the beginning of the expression
+ inner.unshift(leftDelim);
+
+ // Handle middle delimiters
+ if (hadMiddle) {
+ for (let i = 1; i < inner.length; i++) {
+ const middleDelim = inner[i];
+ if (isMiddleDelimNode(middleDelim)) {
+ const isMiddle = middleDelim.isMiddle;
+ // Apply the options that were active when \middle was called
+ inner[i] = makeLeftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []);
+ }
+ }
+ }
+ let rightDelim;
+ // Same for the right delimiter, but using color specified by \color
+ if (group.right === ".") {
+ rightDelim = makeNullDelimiter(options, ["mclose"]);
+ } else {
+ const colorOptions = group.rightColor ? options.withColor(group.rightColor) : options;
+ rightDelim = makeLeftRightDelim(group.right, innerHeight, innerDepth, colorOptions, group.mode, ["mclose"]);
+ }
+ // Add it to the end of the expression.
+ inner.push(rightDelim);
+ return makeSpan(["minner"], inner, options);
+ },
+ mathmlBuilder: (group, options) => {
+ assertParsed(group);
+ const inner = buildMathML_buildExpression(group.body, options);
+ if (group.left !== ".") {
+ const leftNode = new MathNode("mo", [makeText(group.left, group.mode)]);
+ leftNode.setAttribute("fence", "true");
+ inner.unshift(leftNode);
+ }
+ if (group.right !== ".") {
+ const rightNode = new MathNode("mo", [makeText(group.right, group.mode)]);
+ rightNode.setAttribute("fence", "true");
+ if (group.rightColor) {
+ rightNode.setAttribute("mathcolor", group.rightColor);
+ }
+ inner.push(rightNode);
+ }
+ return makeRow(inner);
+ }
+});
+defineFunction({
+ type: "middle",
+ names: ["\\middle"],
+ numArgs: 1,
+ primitive: true,
+ handler: (context, args) => {
+ const delim = checkDelimiter(args[0], context);
+ if (!context.parser.leftrightDepth) {
+ throw new src_ParseError("\\middle without preceding \\left", delim);
+ }
+ return {
+ type: "middle",
+ mode: context.parser.mode,
+ delim: delim.text
+ };
+ },
+ htmlBuilder: (group, options) => {
+ let middleDelim;
+ if (group.delim === ".") {
+ middleDelim = makeNullDelimiter(options, []);
+ } else {
+ middleDelim = makeSizedDelim(group.delim, 1, options, group.mode, []);
+
+ // Patch an ad-hoc property onto the node so the \left/\right
+ // builder can reconstruct appropriately sized middle delimiters.
+ // isMiddle is not part of HtmlDomNode; the read side uses
+ // isMiddleDelimNode() to check before accessing.
+ middleDelim.isMiddle = {
+ delim: group.delim,
+ options
+ };
+ }
+ return middleDelim;
+ },
+ mathmlBuilder: (group, options) => {
+ // A Firefox \middle will stretch a character vertically only if it
+ // is in the fence part of the operator dictionary at:
+ // https://www.w3.org/TR/MathML3/appendixc.html.
+ // So we need to avoid U+2223 and use plain "|" instead.
+ const textNode = group.delim === "\\vert" || group.delim === "|" ? makeText("|", "text") : makeText(group.delim, group.mode);
+ const middleNode = new MathNode("mo", [textNode]);
+ middleNode.setAttribute("fence", "true");
+ // MathML gives 5/18em spacing to each <mo> element.
+ // \middle should get delimiter spacing instead.
+ middleNode.setAttribute("lspace", "0.05em");
+ middleNode.setAttribute("rspace", "0.05em");
+ return middleNode;
+ }
+});
+;// ./src/functions/enclose.ts
+
+
+
+
+
+
+
+
+
+
+
+const enclose_htmlBuilder = (group, options) => {
+ // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase
+ // Some groups can return document fragments. Handle those by wrapping
+ // them in a span.
+ const inner = wrapFragment(buildGroup(group.body, options), options);
+ const label = group.label.slice(1);
+ let scale = options.sizeMultiplier;
+ let img;
+ let imgShift;
+
+ // In the LaTeX cancel package, line geometry is slightly different
+ // depending on whether the subject is wider than it is tall, or vice versa.
+ // We don't know the width of a group, so as a proxy, we test if
+ // the subject is a single character. This captures most of the
+ // subjects that should get the "tall" treatment.
+ const isSingleChar = isCharacterBox(group.body);
+ if (label === "sout") {
+ img = makeSpan(["katex-stretchy", "katex-sout"]);
+ img.height = options.fontMetrics().defaultRuleThickness / scale;
+ imgShift = -0.5 * options.fontMetrics().xHeight;
+ } else if (label === "phase") {
+ // Set a couple of dimensions from the steinmetz package.
+ const lineWeight = calculateSize({
+ number: 0.6,
+ unit: "pt"
+ }, options);
+ const clearance = calculateSize({
+ number: 0.35,
+ unit: "ex"
+ }, options);
+
+ // Prevent size changes like \Huge from affecting line thickness
+ const newOptions = options.havingBaseSizing();
+ scale = scale / newOptions.sizeMultiplier;
+ const angleHeight = inner.height + inner.depth + lineWeight + clearance;
+ // Reserve a left pad for the angle.
+ inner.style.paddingLeft = makeEm(angleHeight / 2 + lineWeight);
+
+ // Create an SVG
+ const viewBoxHeight = Math.floor(1000 * angleHeight * scale);
+ const path = phasePath(viewBoxHeight);
+ const svgNode = new SvgNode([new PathNode("phase", path)], {
+ "width": "400em",
+ "height": makeEm(viewBoxHeight / 1000),
+ "viewBox": "0 0 400000 " + viewBoxHeight,
+ "preserveAspectRatio": "xMinYMin slice"
+ });
+ // Wrap it in a span with overflow: hidden.
+ img = makeSvgSpan(["hide-tail"], [svgNode], options);
+ img.style.height = makeEm(angleHeight);
+ imgShift = inner.depth + lineWeight + clearance;
+ } else {
+ // Add horizontal padding
+ if (/cancel/.test(label)) {
+ if (!isSingleChar) {
+ inner.classes.push("cancel-pad");
+ }
+ } else if (label === "angl") {
+ inner.classes.push("anglpad");
+ } else {
+ inner.classes.push("boxpad");
+ }
+
+ // Add vertical padding
+ let topPad;
+ let bottomPad;
+ let ruleThickness = 0;
+ // ref: cancel package: \advance\totalheight2\p@ % "+2"
+ if (/box/.test(label)) {
+ ruleThickness = Math.max(options.fontMetrics().fboxrule,
+ // default
+ options.minRuleThickness // User override.
+ );
+ topPad = options.fontMetrics().fboxsep + (label === "colorbox" ? 0 : ruleThickness);
+ bottomPad = topPad;
+ } else if (label === "angl") {
+ ruleThickness = Math.max(options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
+ topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself.
+ bottomPad = Math.max(0, 0.25 - inner.depth);
+ } else {
+ topPad = isSingleChar ? 0.2 : 0;
+ bottomPad = topPad;
+ }
+ img = stretchyEnclose(inner, label, topPad, bottomPad, options);
+ if (/fbox|boxed|fcolorbox/.test(label)) {
+ img.style.borderStyle = "solid";
+ img.style.borderWidth = makeEm(ruleThickness);
+ } else if (label === "angl" && ruleThickness !== 0.049) {
+ img.style.borderTopWidth = makeEm(ruleThickness);
+ img.style.borderRightWidth = makeEm(ruleThickness);
+ }
+ imgShift = inner.depth + bottomPad;
+ if (group.backgroundColor) {
+ img.style.backgroundColor = group.backgroundColor;
+ if (group.borderColor) {
+ img.style.borderColor = group.borderColor;
+ }
+ }
+ }
+ let vlist;
+ if (group.backgroundColor) {
+ vlist = makeVList({
+ positionType: "individualShift",
+ children: [
+ // Put the color background behind inner;
+ {
+ type: "elem",
+ elem: img,
+ shift: imgShift
+ }, {
+ type: "elem",
+ elem: inner,
+ shift: 0
+ }]
+ }, options);
+ } else {
+ const classes = /cancel|phase/.test(label) ? ["svg-align"] : [];
+ vlist = makeVList({
+ positionType: "individualShift",
+ children: [
+ // Write the \cancel stroke on top of inner.
+ {
+ type: "elem",
+ elem: inner,
+ shift: 0
+ }, {
+ type: "elem",
+ elem: img,
+ shift: imgShift,
+ wrapperClasses: classes
+ }]
+ }, options);
+ }
+ if (/cancel/.test(label)) {
+ // The cancel package documentation says that cancel lines add their height
+ // to the expression, but tests show that isn't how it actually works.
+ vlist.height = inner.height;
+ vlist.depth = inner.depth;
+ }
+ if (/cancel/.test(label) && !isSingleChar) {
+ // cancel does not create horiz space for its line extension.
+ return makeSpan(["mord", "cancel-lap"], [vlist], options);
+ } else {
+ return makeSpan(["mord"], [vlist], options);
+ }
+};
+const enclose_mathmlBuilder = (group, options) => {
+ let fboxsep;
+ const node = new MathNode(group.label.includes("colorbox") ? "mpadded" : "menclose", [buildMathML_buildGroup(group.body, options)]);
+ switch (group.label) {
+ case "\\cancel":
+ node.setAttribute("notation", "updiagonalstrike");
+ break;
+ case "\\bcancel":
+ node.setAttribute("notation", "downdiagonalstrike");
+ break;
+ case "\\phase":
+ node.setAttribute("notation", "phasorangle");
+ break;
+ case "\\sout":
+ node.setAttribute("notation", "horizontalstrike");
+ break;
+ case "\\fbox":
+ node.setAttribute("notation", "box");
+ break;
+ case "\\angl":
+ node.setAttribute("notation", "actuarial");
+ break;
+ case "\\fcolorbox":
+ case "\\colorbox":
+ // <menclose> doesn't have a good notation option. So use <mpadded>
+ // instead. Set some attributes that come included with <menclose>.
+ fboxsep = options.fontMetrics().fboxsep * options.fontMetrics().ptPerEm;
+ node.setAttribute("width", "+" + 2 * fboxsep + "pt");
+ node.setAttribute("height", "+" + 2 * fboxsep + "pt");
+ node.setAttribute("lspace", fboxsep + "pt"); //
+ node.setAttribute("voffset", fboxsep + "pt");
+ if (group.label === "\\fcolorbox") {
+ const thk = Math.max(options.fontMetrics().fboxrule,
+ // default
+ options.minRuleThickness // user override
+ );
+ node.setAttribute("style", "border: " + makeEm(thk) + " solid " + group.borderColor);
+ }
+ break;
+ case "\\xcancel":
+ node.setAttribute("notation", "updiagonalstrike downdiagonalstrike");
+ break;
+ }
+ if (group.backgroundColor) {
+ node.setAttribute("mathbackground", group.backgroundColor);
+ }
+ return node;
+};
+defineFunction({
+ type: "enclose",
+ names: ["\\colorbox"],
+ numArgs: 2,
+ allowedInText: true,
+ argTypes: ["color", "hbox"],
+ handler(_ref, args, optArgs) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const color = assertNodeType(args[0], "color-token").color;
+ const body = args[1];
+ return {
+ type: "enclose",
+ mode: parser.mode,
+ label: funcName,
+ backgroundColor: color,
+ body
+ };
+ },
+ htmlBuilder: enclose_htmlBuilder,
+ mathmlBuilder: enclose_mathmlBuilder
+});
+defineFunction({
+ type: "enclose",
+ names: ["\\fcolorbox"],
+ numArgs: 3,
+ allowedInText: true,
+ argTypes: ["color", "color", "hbox"],
+ handler(_ref2, args, optArgs) {
+ let parser = _ref2.parser,
+ funcName = _ref2.funcName;
+ const borderColor = assertNodeType(args[0], "color-token").color;
+ const backgroundColor = assertNodeType(args[1], "color-token").color;
+ const body = args[2];
+ return {
+ type: "enclose",
+ mode: parser.mode,
+ label: funcName,
+ backgroundColor,
+ borderColor,
+ body
+ };
+ }
+});
+defineFunction({
+ type: "enclose",
+ names: ["\\fbox"],
+ numArgs: 1,
+ argTypes: ["hbox"],
+ allowedInText: true,
+ handler(_ref3, args) {
+ let parser = _ref3.parser;
+ return {
+ type: "enclose",
+ mode: parser.mode,
+ label: "\\fbox",
+ body: args[0]
+ };
+ }
+});
+defineFunction({
+ type: "enclose",
+ names: ["\\cancel", "\\bcancel", "\\xcancel", "\\phase"],
+ numArgs: 1,
+ handler(_ref4, args) {
+ let parser = _ref4.parser,
+ funcName = _ref4.funcName;
+ const body = args[0];
+ return {
+ type: "enclose",
+ mode: parser.mode,
+ label: funcName,
+ body
+ };
+ }
+});
+defineFunction({
+ type: "enclose",
+ names: ["\\sout"],
+ numArgs: 1,
+ allowedInText: true,
+ handler(_ref5, args) {
+ let parser = _ref5.parser,
+ funcName = _ref5.funcName;
+ if (parser.mode === "math") {
+ parser.settings.reportNonstrict("mathVsSout", "LaTeX's \\sout works only in text mode");
+ }
+ const body = args[0];
+ return {
+ type: "enclose",
+ mode: parser.mode,
+ label: funcName,
+ body
+ };
+ }
+});
+defineFunction({
+ type: "enclose",
+ names: ["\\angl"],
+ numArgs: 1,
+ argTypes: ["hbox"],
+ allowedInText: false,
+ handler(_ref6, args) {
+ let parser = _ref6.parser;
+ return {
+ type: "enclose",
+ mode: parser.mode,
+ label: "\\angl",
+ body: args[0]
+ };
+ }
+});
+;// ./src/defineEnvironment.ts
+
+
+/**
+ * The context contains the following properties:
+ * - mode: current parsing mode.
+ * - envName: the name of the environment, one of the listed names.
+ * - parser: the parser object.
+ */
+
+/**
+ * - context: information and references provided by the parser
+ * - args: an array of arguments passed to \begin{name}
+ * - optArgs: an array of optional arguments passed to \begin{name}
+ */
+
+/**
+ * - numArgs: (default 0) The number of arguments after the \begin{name} function.
+ * - argTypes: (optional) Just like for a function
+ * - allowedInText: (default false) Whether or not the environment is allowed
+ * inside text mode (not enforced yet).
+ * - numOptionalArgs: (default 0) Just like for a function
+ */
+
+/**
+ * Final environment spec for use at parse time.
+ * This is almost identical to `EnvDefSpec`, except it
+ * 1. includes the function handler
+ * 2. requires all arguments except argType
+ * It is generated by `defineEnvironment()` below.
+ */
+
+/**
+ * All registered environments.
+ * `environments.js` exports this same dictionary again and makes it public.
+ * `Parser.js` requires this dictionary via `environments.js`.
+ */
+const _environments = {};
+function defineEnvironment(_ref) {
+ let type = _ref.type,
+ names = _ref.names,
+ props = _ref.props,
+ handler = _ref.handler,
+ htmlBuilder = _ref.htmlBuilder,
+ mathmlBuilder = _ref.mathmlBuilder;
+ // Set default values of environments.
+ const data = {
+ type,
+ numArgs: props.numArgs || 0,
+ allowedInText: false,
+ numOptionalArgs: 0,
+ handler
+ };
+ for (let i = 0; i < names.length; ++i) {
+ // TODO: The value type of _environments should be a type union of all
+ // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is
+ // an existential type.
+ _environments[names[i]] = data;
+ }
+ if (htmlBuilder) {
+ _htmlGroupBuilders[type] = htmlBuilder;
+ }
+ if (mathmlBuilder) {
+ _mathmlGroupBuilders[type] = mathmlBuilder;
+ }
+}
+;// ./src/defineMacro.ts
+/**
+ * Provides context to macros defined by functions. Implemented by
+ * MacroExpander.
+ */
+
+/** Macro tokens (in reverse order). */
+
+/**
+ * All registered global/built-in macros.
+ * `macros.js` exports this same dictionary again and makes it public.
+ * `Parser.js` requires this dictionary via `macros.js`.
+ */
+const _macros = {};
+
+// This function might one day accept an additional argument and do more things.
+function defineMacro(name, body) {
+ _macros[name] = body;
+}
+;// ./src/SourceLocation.ts
+/**
+ * Lexing or parsing positional information for error reporting.
+ * This object is immutable.
+ */
+class SourceLocation {
+ // End offset, zero-based exclusive.
+
+ constructor(lexer, start, end) {
+ // The + prefix indicates that these fields aren't writeable
+ this.lexer = void 0;
+ // Lexer holding the input string.
+ this.start = void 0;
+ // Start offset, zero-based inclusive.
+ this.end = void 0;
+ this.lexer = lexer;
+ this.start = start;
+ this.end = end;
+ }
+
+ /**
+ * Merges two `SourceLocation`s from location providers, given they are
+ * provided in order of appearance.
+ * - Returns the first one's location if only the first is provided.
+ * - Returns a merged range of the first and the last if both are provided
+ * and their lexers match.
+ * - Otherwise, returns null.
+ */
+ static range(first, second) {
+ if (!second) {
+ return first && first.loc;
+ } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) {
+ return null;
+ } else {
+ return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end);
+ }
+ }
+}
+;// ./src/Token.ts
+
+
+/**
+ * Interface required to break circular dependency between Token, Lexer, and
+ * ParseError.
+ */
+
+/**
+ * The resulting token returned from `lex`.
+ *
+ * It consists of the token text plus some position information.
+ * The position information is essentially a range in an input string,
+ * but instead of referencing the bare input string, we refer to the lexer.
+ * That way it is possible to attach extra metadata to the input string,
+ * like for example a file name or similar.
+ *
+ * The position information is optional, so it is OK to construct synthetic
+ * tokens if appropriate. Not providing available position information may
+ * lead to degraded error reporting, though.
+ */
+class Token {
+ // used in \noexpand
+
+ constructor(text,
+ // the text of this token
+ loc) {
+ this.text = void 0;
+ this.loc = void 0;
+ this.noexpand = void 0;
+ // don't expand the token
+ this.treatAsRelax = void 0;
+ this.text = text;
+ this.loc = loc;
+ }
+
+ /**
+ * Given a pair of tokens (this and endToken), compute a `Token` encompassing
+ * the whole input range enclosed by these two.
+ */
+ range(endToken,
+ // last token of the range, inclusive
+ text // the text of the newly constructed token
+ ) {
+ return new Token(text, SourceLocation.range(this, endToken));
+ }
+}
+;// ./src/environments/array.ts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// Data stored in the ParseNode associated with the environment.
+
+// Type to indicate column separation in MathML
+
+// Helper functions
+function getHLines(parser) {
+ // Return an array. The array length = number of hlines.
+ // Each element in the array tells if the line is dashed.
+ const hlineInfo = [];
+ parser.consumeSpaces();
+ let nxt = parser.fetch().text;
+ if (nxt === "\\relax") {
+ // \relax is an artifact of the \cr macro below
+ parser.consume();
+ parser.consumeSpaces();
+ nxt = parser.fetch().text;
+ }
+ while (nxt === "\\hline" || nxt === "\\hdashline") {
+ parser.consume();
+ hlineInfo.push(nxt === "\\hdashline");
+ parser.consumeSpaces();
+ nxt = parser.fetch().text;
+ }
+ return hlineInfo;
+}
+const validateAmsEnvironmentContext = context => {
+ const settings = context.parser.settings;
+ if (!settings.displayMode) {
+ throw new src_ParseError("{" + context.envName + "} can be used only in" + " display mode.");
+ }
+};
+const gatherEnvironments = new Set(["gather", "gather*"]);
+
+// autoTag (an argument to parseArray) can be one of three values:
+// * undefined: Regular (not-top-level) array; no tags on each row
+// * true: Automatic equation numbering, overridable by \tag
+// * false: Tags allowed on each row, but no automatic numbering
+// This function *doesn't* work with the "split" environment name.
+function getAutoTag(name) {
+ if (!name.includes("ed")) {
+ return !name.includes("*");
+ }
+ // return undefined;
+}
+
+/**
+ * Parse the body of the environment, with rows delimited by \\ and
+ * columns delimited by &, and create a nested list in row-major order
+ * with one group per cell. If given an optional argument style
+ * ("text", "display", etc.), then each cell is cast into that style.
+ */
+function parseArray(parser, _ref, style) {
+ let hskipBeforeAndAfter = _ref.hskipBeforeAndAfter,
+ addJot = _ref.addJot,
+ cols = _ref.cols,
+ arraystretch = _ref.arraystretch,
+ colSeparationType = _ref.colSeparationType,
+ autoTag = _ref.autoTag,
+ singleRow = _ref.singleRow,
+ emptySingleRow = _ref.emptySingleRow,
+ maxNumCols = _ref.maxNumCols,
+ leqno = _ref.leqno;
+ parser.gullet.beginGroup();
+ if (!singleRow) {
+ // \cr is equivalent to \\ without the optional size argument (see below)
+ // TODO: provide helpful error when \cr is used outside array environment
+ parser.gullet.macros.set("\\cr", "\\\\\\relax");
+ }
+
+ // Get current arraystretch if it's not set by the environment
+ if (!arraystretch) {
+ const stretch = parser.gullet.expandMacroAsText("\\arraystretch");
+ if (stretch == null) {
+ // Default \arraystretch from lttab.dtx
+ arraystretch = 1;
+ } else {
+ arraystretch = parseFloat(stretch);
+ if (!arraystretch || arraystretch < 0) {
+ throw new src_ParseError("Invalid \\arraystretch: " + stretch);
+ }
+ }
+ }
+
+ // Start group for first cell
+ parser.gullet.beginGroup();
+ let row = [];
+ const body = [row];
+ const rowGaps = [];
+ const hLinesBeforeRow = [];
+ const tags = autoTag != null ? [] : undefined;
+
+ // amsmath uses \global\@eqnswtrue and \global\@eqnswfalse to represent
+ // whether this row should have an equation number. Simulate this with
+ // a \@eqnsw macro set to 1 or 0.
+ function beginRow() {
+ if (autoTag) {
+ parser.gullet.macros.set("\\@eqnsw", "1", true);
+ }
+ }
+ function endRow() {
+ if (tags) {
+ if (parser.gullet.macros.get("\\df@tag")) {
+ tags.push(parser.subparse([new Token("\\df@tag")]));
+ parser.gullet.macros.set("\\df@tag", undefined, true);
+ } else {
+ tags.push(Boolean(autoTag) && parser.gullet.macros.get("\\@eqnsw") === "1");
+ }
+ }
+ }
+ beginRow();
+
+ // Test for \hline at the top of the array.
+ hLinesBeforeRow.push(getHLines(parser));
+ while (true) {
+ // Parse each cell in its own group (namespace)
+ const cellBody = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
+ parser.gullet.endGroup();
+ parser.gullet.beginGroup();
+ let cell = {
+ type: "ordgroup",
+ mode: parser.mode,
+ body: cellBody
+ };
+ if (style) {
+ cell = {
+ type: "styling",
+ mode: parser.mode,
+ style,
+ resetFont: true,
+ body: [cell]
+ };
+ }
+ row.push(cell);
+ const next = parser.fetch().text;
+ if (next === "&") {
+ if (maxNumCols && row.length === maxNumCols) {
+ if (singleRow || colSeparationType) {
+ // {equation} or {split}
+ throw new src_ParseError("Too many tab characters: &", parser.nextToken);
+ } else {
+ // {array} environment
+ parser.settings.reportNonstrict("textEnv", "Too few columns " + "specified in the {array} column argument.");
+ }
+ }
+ parser.consume();
+ } else if (next === "\\end") {
+ endRow();
+ // Arrays terminate newlines with `\crcr` which consumes a `\cr` if
+ // the last line is empty. However, AMS environments keep the
+ // empty row if it's the only one.
+ // NOTE: Currently, `cell` is the last item added into `row`.
+ if (row.length === 1 && cell.type === "styling" && cell.body.length === 1 && cell.body[0].type === "ordgroup" && cell.body[0].body.length === 0 && (body.length > 1 || !emptySingleRow)) {
+ body.pop();
+ }
+ if (hLinesBeforeRow.length < body.length + 1) {
+ hLinesBeforeRow.push([]);
+ }
+ break;
+ } else if (next === "\\\\") {
+ parser.consume();
+ let size;
+ // \def\Let@{\let\\\math@cr}
+ // \def\math@cr{...\math@cr@}
+ // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}}
+ // \def\math@cr@@[#1]{...\math@cr@@@...}
+ // \def\math@cr@@@{\cr}
+ if (parser.gullet.future().text !== " ") {
+ size = parser.parseSizeGroup(true);
+ }
+ rowGaps.push(size ? size.value : null);
+ endRow();
+
+ // check for \hline(s) following the row separator
+ hLinesBeforeRow.push(getHLines(parser));
+ row = [];
+ body.push(row);
+ beginRow();
+ } else {
+ throw new src_ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken);
+ }
+ }
+
+ // End cell group
+ parser.gullet.endGroup();
+ // End array group defining \cr
+ parser.gullet.endGroup();
+ return {
+ type: "array",
+ mode: parser.mode,
+ addJot,
+ arraystretch,
+ body,
+ cols,
+ rowGaps,
+ hskipBeforeAndAfter,
+ hLinesBeforeRow,
+ colSeparationType,
+ tags,
+ leqno
+ };
+}
+
+// Decides on a style for cells in an array according to whether the given
+// environment name starts with the letter 'd'.
+function dCellStyle(envName) {
+ if (envName.slice(0, 1) === "d") {
+ return "display";
+ } else {
+ return "text";
+ }
+}
+const array_htmlBuilder = function (group, options) {
+ let r;
+ let c;
+ const nr = group.body.length;
+ const hLinesBeforeRow = group.hLinesBeforeRow;
+ let nc = 0;
+ const body = new Array(nr);
+ const hlines = [];
+ const ruleThickness = Math.max(
+ // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em.
+ options.fontMetrics().arrayRuleWidth, options.minRuleThickness // User override.
+ );
+
+ // Horizontal spacing
+ const pt = 1 / options.fontMetrics().ptPerEm;
+ let arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls
+ if (group.colSeparationType && group.colSeparationType === "small") {
+ // We're in a {smallmatrix}. Default column space is \thickspace,
+ // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}.
+ // But that needs adjustment because LaTeX applies \scriptstyle to the
+ // entire array, including the colspace, but this function applies
+ // \scriptstyle only inside each element.
+ const localMultiplier = options.havingStyle(src_Style.SCRIPT).sizeMultiplier;
+ arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier);
+ }
+
+ // Vertical spacing
+ const baselineskip = group.colSeparationType === "CD" ? calculateSize({
+ number: 3,
+ unit: "ex"
+ }, options) : 12 * pt; // see size10.clo
+ // Default \jot from ltmath.dtx
+ // TODO(edemaine): allow overriding \jot via \setlength (#687)
+ const jot = 3 * pt;
+ const arrayskip = group.arraystretch * baselineskip;
+ const arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
+ const arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx
+
+ let totalHeight = 0;
+
+ // Set a position for \hline(s) at the top of the array, if any.
+ function setHLinePos(hlinesInGap) {
+ for (let i = 0; i < hlinesInGap.length; ++i) {
+ if (i > 0) {
+ totalHeight += 0.25;
+ }
+ hlines.push({
+ pos: totalHeight,
+ isDashed: hlinesInGap[i]
+ });
+ }
+ }
+ setHLinePos(hLinesBeforeRow[0]);
+ for (r = 0; r < group.body.length; ++r) {
+ const inrow = group.body[r];
+ let height = arstrutHeight; // \@array adds an \@arstrut
+ let depth = arstrutDepth; // to each tow (via the template)
+
+ if (nc < inrow.length) {
+ nc = inrow.length;
+ }
+ const outrow = {
+ cells: new Array(inrow.length),
+ height: 0,
+ depth: 0,
+ pos: 0
+ };
+ for (c = 0; c < inrow.length; ++c) {
+ const elt = buildGroup(inrow[c], options);
+ if (depth < elt.depth) {
+ depth = elt.depth;
+ }
+ if (height < elt.height) {
+ height = elt.height;
+ }
+ outrow.cells[c] = elt;
+ }
+ const rowGap = group.rowGaps[r];
+ let gap = 0;
+ if (rowGap) {
+ gap = calculateSize(rowGap, options);
+ if (gap > 0) {
+ // \@argarraycr
+ gap += arstrutDepth;
+ if (depth < gap) {
+ depth = gap; // \@xargarraycr
+ }
+ gap = 0;
+ }
+ }
+ // In AMS multiline environments such as aligned and gathered, rows
+ // correspond to lines that have additional \jot added between lines
+ // via \openup.
+ // We simulate this by adding \jot depth to each row except the last.
+ if (group.addJot && r < group.body.length - 1) {
+ depth += jot;
+ }
+ outrow.height = height;
+ outrow.depth = depth;
+ totalHeight += height;
+ outrow.pos = totalHeight;
+ totalHeight += depth + gap; // \@yargarraycr
+ body[r] = outrow;
+
+ // Set a position for \hline(s), if any.
+ setHLinePos(hLinesBeforeRow[r + 1]);
+ }
+ const offset = totalHeight / 2 + options.fontMetrics().axisHeight;
+ const colDescriptions = group.cols || [];
+ const cols = [];
+ let colSep;
+ let colDescrNum;
+ const tagSpans = [];
+ if (group.tags && group.tags.some(tag => tag)) {
+ // An environment with manual tags and/or automatic equation numbers.
+ // Create node(s), the latter of which trigger CSS counter increment.
+ for (r = 0; r < nr; ++r) {
+ const rw = body[r];
+ const shift = rw.pos - offset;
+ const tag = group.tags[r];
+ let tagSpan;
+ if (tag === true) {
+ // automatic numbering
+ tagSpan = makeSpan(["eqn-num"], [], options);
+ } else if (tag === false) {
+ // \nonumber/\notag or starred environment
+ tagSpan = makeSpan([], [], options);
+ } else {
+ // manual \tag
+ tagSpan = makeSpan([], buildExpression(tag, options, true), options);
+ }
+ tagSpan.depth = rw.depth;
+ tagSpan.height = rw.height;
+ tagSpans.push({
+ type: "elem",
+ elem: tagSpan,
+ shift
+ });
+ }
+ }
+ for (c = 0, colDescrNum = 0;
+ // Continue while either there are more columns or more column
+ // descriptions, so trailing separators don't get lost.
+ c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) {
+ var _colDescr3;
+ let colDescr = colDescriptions[colDescrNum];
+ let firstSeparator = true;
+ while (((_colDescr = colDescr) == null ? void 0 : _colDescr.type) === "separator") {
+ var _colDescr;
+ // If there is more than one separator in a row, add a space
+ // between them.
+ if (!firstSeparator) {
+ colSep = makeSpan(["arraycolsep"], []);
+ colSep.style.width = makeEm(options.fontMetrics().doubleRuleSep);
+ cols.push(colSep);
+ }
+ if (colDescr.separator === "|" || colDescr.separator === ":") {
+ const lineType = colDescr.separator === "|" ? "solid" : "dashed";
+ const separator = makeSpan(["vertical-separator"], [], options);
+ separator.style.height = makeEm(totalHeight);
+ separator.style.borderRightWidth = makeEm(ruleThickness);
+ separator.style.borderRightStyle = lineType;
+ separator.style.margin = "0 " + makeEm(-ruleThickness / 2);
+ const shift = totalHeight - offset;
+ if (shift) {
+ separator.style.verticalAlign = makeEm(-shift);
+ }
+ cols.push(separator);
+ } else {
+ throw new src_ParseError("Invalid separator type: " + colDescr.separator);
+ }
+ colDescrNum++;
+ colDescr = colDescriptions[colDescrNum];
+ firstSeparator = false;
+ }
+ if (c >= nc) {
+ continue;
+ }
+ let sepwidth;
+ if (c > 0 || group.hskipBeforeAndAfter) {
+ var _colDescr$pregap, _colDescr2;
+ sepwidth = (_colDescr$pregap = (_colDescr2 = colDescr) == null ? void 0 : _colDescr2.pregap) != null ? _colDescr$pregap : arraycolsep;
+ if (sepwidth !== 0) {
+ colSep = makeSpan(["arraycolsep"], []);
+ colSep.style.width = makeEm(sepwidth);
+ cols.push(colSep);
+ }
+ }
+ const colElems = [];
+ for (r = 0; r < nr; ++r) {
+ const row = body[r];
+ const elem = row.cells[c];
+ if (!elem) {
+ continue;
+ }
+ const shift = row.pos - offset;
+ elem.depth = row.depth;
+ elem.height = row.height;
+ colElems.push({
+ type: "elem",
+ elem: elem,
+ shift: shift
+ });
+ }
+ const colVList = makeVList({
+ positionType: "individualShift",
+ children: colElems
+ }, options);
+ const colSpan = makeSpan(["col-align-" + (((_colDescr3 = colDescr) == null ? void 0 : _colDescr3.align) || "c")], [colVList]);
+ cols.push(colSpan);
+ if (c < nc - 1 || group.hskipBeforeAndAfter) {
+ var _colDescr$postgap, _colDescr4;
+ sepwidth = (_colDescr$postgap = (_colDescr4 = colDescr) == null ? void 0 : _colDescr4.postgap) != null ? _colDescr$postgap : arraycolsep;
+ if (sepwidth !== 0) {
+ colSep = makeSpan(["arraycolsep"], []);
+ colSep.style.width = makeEm(sepwidth);
+ cols.push(colSep);
+ }
+ }
+ }
+ let tableBody = makeSpan(["mtable"], cols);
+
+ // Add \hline(s), if any.
+ if (hlines.length > 0) {
+ const line = makeLineSpan("katex-hline", options, ruleThickness);
+ const dashes = makeLineSpan("katex-hdashline", options, ruleThickness);
+ const vListElems = [{
+ type: "elem",
+ elem: tableBody,
+ shift: 0
+ }];
+ while (hlines.length > 0) {
+ const hline = hlines.pop();
+ const lineShift = hline.pos - offset;
+ if (hline.isDashed) {
+ vListElems.push({
+ type: "elem",
+ elem: dashes,
+ shift: lineShift
+ });
+ } else {
+ vListElems.push({
+ type: "elem",
+ elem: line,
+ shift: lineShift
+ });
+ }
+ }
+ tableBody = makeVList({
+ positionType: "individualShift",
+ children: vListElems
+ }, options);
+ }
+ if (tagSpans.length === 0) {
+ return makeSpan(["mord"], [tableBody], options);
+ } else {
+ const eqnNumCol = makeVList({
+ positionType: "individualShift",
+ children: tagSpans
+ }, options);
+ const tagCol = makeSpan(["katex-tag"], [eqnNumCol], options);
+ return makeFragment([tableBody, tagCol]);
+ }
+};
+const alignMap = {
+ c: "center ",
+ l: "left ",
+ r: "right "
+};
+const array_mathmlBuilder = function (group, options) {
+ const tbl = [];
+ const glue = new MathNode("mtd", [], ["mtr-glue"]);
+ const tag = new MathNode("mtd", [], ["mml-eqn-num"]);
+ for (let i = 0; i < group.body.length; i++) {
+ const rw = group.body[i];
+ const row = [];
+ for (let j = 0; j < rw.length; j++) {
+ row.push(new MathNode("mtd", [buildMathML_buildGroup(rw[j], options)]));
+ }
+ if (group.tags && group.tags[i]) {
+ row.unshift(glue);
+ row.push(glue);
+ if (group.leqno) {
+ row.unshift(tag);
+ } else {
+ row.push(tag);
+ }
+ }
+ tbl.push(new MathNode("mtr", row));
+ }
+ let table = new MathNode("mtable", tbl);
+
+ // Set column alignment, row spacing, column spacing, and
+ // array lines by setting attributes on the table element.
+
+ // Set the row spacing. In MathML, we specify a gap distance.
+ // We do not use rowGap[] because MathML automatically increases
+ // cell height with the height/depth of the element content.
+
+ // LaTeX \arraystretch multiplies the row baseline-to-baseline distance.
+ // We simulate this by adding (arraystretch - 1)em to the gap. This
+ // does a reasonable job of adjusting arrays containing 1 em tall content.
+
+ // The 0.16 and 0.09 values are found empirically. They produce an array
+ // similar to LaTeX and in which content does not interfere with \hlines.
+ const gap = group.arraystretch === 0.5 ? 0.1 // {smallmatrix}, {subarray}
+ : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);
+ table.setAttribute("rowspacing", makeEm(gap));
+
+ // MathML table lines go only between cells.
+ // To place a line on an edge we'll use <menclose>, if necessary.
+ let menclose = "";
+ let align = "";
+ if (group.cols && group.cols.length > 0) {
+ // Find column alignment, column spacing, and vertical lines.
+ const cols = group.cols;
+ let columnLines = "";
+ let prevTypeWasAlign = false;
+ let iStart = 0;
+ let iEnd = cols.length;
+ if (cols[0].type === "separator") {
+ menclose += "top ";
+ iStart = 1;
+ }
+ if (cols[cols.length - 1].type === "separator") {
+ menclose += "bottom ";
+ iEnd -= 1;
+ }
+ for (let i = iStart; i < iEnd; i++) {
+ const col = cols[i];
+ if (col.type === "align") {
+ align += alignMap[col.align];
+ if (prevTypeWasAlign) {
+ columnLines += "none ";
+ }
+ prevTypeWasAlign = true;
+ } else if (col.type === "separator") {
+ // MathML accepts only single lines between cells.
+ // So we read only the first of consecutive separators.
+ if (prevTypeWasAlign) {
+ columnLines += col.separator === "|" ? "solid " : "dashed ";
+ prevTypeWasAlign = false;
+ }
+ }
+ }
+ table.setAttribute("columnalign", align.trim());
+ if (/[sd]/.test(columnLines)) {
+ table.setAttribute("columnlines", columnLines.trim());
+ }
+ }
+
+ // Set column spacing.
+ if (group.colSeparationType === "align") {
+ const cols = group.cols || [];
+ let spacing = "";
+ for (let i = 1; i < cols.length; i++) {
+ spacing += i % 2 ? "0em " : "1em ";
+ }
+ table.setAttribute("columnspacing", spacing.trim());
+ } else if (group.colSeparationType === "alignat" || group.colSeparationType === "gather") {
+ table.setAttribute("columnspacing", "0em");
+ } else if (group.colSeparationType === "small") {
+ table.setAttribute("columnspacing", "0.2778em");
+ } else if (group.colSeparationType === "CD") {
+ table.setAttribute("columnspacing", "0.5em");
+ } else {
+ table.setAttribute("columnspacing", "1em");
+ }
+
+ // Address \hline and \hdashline
+ let rowLines = "";
+ const hlines = group.hLinesBeforeRow;
+ menclose += hlines[0].length > 0 ? "left " : "";
+ menclose += hlines[hlines.length - 1].length > 0 ? "right " : "";
+ for (let i = 1; i < hlines.length - 1; i++) {
+ rowLines += hlines[i].length === 0 ? "none "
+ // MathML accepts only a single line between rows. Read one element.
+ : hlines[i][0] ? "dashed " : "solid ";
+ }
+ if (/[sd]/.test(rowLines)) {
+ table.setAttribute("rowlines", rowLines.trim());
+ }
+ if (menclose !== "") {
+ table = new MathNode("menclose", [table]);
+ table.setAttribute("notation", menclose.trim());
+ }
+ if (group.arraystretch && group.arraystretch < 1) {
+ // A small array. Wrap in scriptstyle so row gap is not too large.
+ table = new MathNode("mstyle", [table]);
+ table.setAttribute("scriptlevel", "1");
+ }
+ return table;
+};
+
+// Convenience function for align, align*, aligned, alignat, alignat*, alignedat.
+const alignedHandler = function (context, args) {
+ if (!context.envName.includes("ed")) {
+ validateAmsEnvironmentContext(context);
+ }
+ const cols = [];
+ const isSplit = context.envName === "split";
+ const res = parseArray(context.parser, {
+ cols,
+ addJot: true,
+ autoTag: isSplit ? undefined : getAutoTag(context.envName),
+ emptySingleRow: true,
+ colSeparationType: context.envName.includes("at") ? "alignat" : "align",
+ maxNumCols: isSplit ? 2 : undefined,
+ leqno: context.parser.settings.leqno
+ }, "display");
+
+ // Determining number of columns.
+ // 1. If the first argument is given, we use it as a number of columns,
+ // and makes sure that each row doesn't exceed that number.
+ // 2. Otherwise, just count number of columns = maximum number
+ // of cells in each row ("aligned" mode -- isAligned will be true).
+ //
+ // At the same time, prepend empty group {} at beginning of every second
+ // cell in each row (starting with second cell) so that operators become
+ // binary. This behavior is implemented in amsmath's \start@aligned.
+ let numMaths = 0;
+ let numCols = 0;
+ const emptyGroup = {
+ type: "ordgroup",
+ mode: context.mode,
+ body: []
+ };
+ if (args[0] && args[0].type === "ordgroup") {
+ const message = "Number of columns should be a positive integer";
+ const numColumns = assertCharacterGroup(args[0], message);
+ if (!/^[0-9]+$/.test(numColumns) || Number(numColumns) < 1) {
+ throw new src_ParseError(message, args[0]);
+ }
+ numMaths = Number(numColumns);
+ numCols = numMaths * 2;
+ }
+ const isAligned = !numCols;
+ res.body.forEach(function (row) {
+ for (let i = 1; i < row.length; i += 2) {
+ // Modify ordgroup node within styling node
+ const styling = assertNodeType(row[i], "styling");
+ const ordgroup = assertNodeType(styling.body[0], "ordgroup");
+ ordgroup.body.unshift(emptyGroup);
+ }
+ if (!isAligned) {
+ // Case 1
+ const curMaths = row.length / 2;
+ if (numMaths < curMaths) {
+ throw new src_ParseError("Too many math in a row: " + ("expected " + numMaths + ", but got " + curMaths), row[0]);
+ }
+ } else if (numCols < row.length) {
+ // Case 2
+ numCols = row.length;
+ }
+ });
+
+ // Adjusting alignment.
+ // In aligned mode, we add one \qquad between columns;
+ // otherwise we add nothing.
+ for (let i = 0; i < numCols; ++i) {
+ let align = "r";
+ let pregap = 0;
+ if (i % 2 === 1) {
+ align = "l";
+ } else if (i > 0 && isAligned) {
+ // "aligned" mode.
+ pregap = 1; // add one \quad
+ }
+ cols[i] = {
+ type: "align",
+ align: align,
+ pregap: pregap,
+ postgap: 0
+ };
+ }
+ res.colSeparationType = isAligned ? "align" : "alignat";
+ return res;
+};
+
+// Arrays are part of LaTeX, defined in lttab.dtx so its documentation
+// is part of the source2e.pdf file of LaTeX2e source documentation.
+// {darray} is an {array} environment where cells are set in \displaystyle,
+// as defined in nccmath.sty.
+defineEnvironment({
+ type: "array",
+ names: ["array", "darray"],
+ props: {
+ numArgs: 1
+ },
+ handler(context, args) {
+ // Since no types are specified above, the two possibilities are
+ // - The argument is wrapped in {} or [], in which case Parser's
+ // parseGroup() returns an "ordgroup" wrapping some symbol node.
+ // - The argument is a bare symbol node.
+ const symNode = checkSymbolNodeType(args[0]);
+ const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
+ const cols = colalign.map(function (nde) {
+ const node = assertSymbolNodeType(nde);
+ const ca = node.text;
+ if ("lcr".includes(ca)) {
+ return {
+ type: "align",
+ align: ca
+ };
+ } else if (ca === "|") {
+ return {
+ type: "separator",
+ separator: "|"
+ };
+ } else if (ca === ":") {
+ return {
+ type: "separator",
+ separator: ":"
+ };
+ }
+ throw new src_ParseError("Unknown column alignment: " + ca, nde);
+ });
+ const res = {
+ cols,
+ hskipBeforeAndAfter: true,
+ // \@preamble in lttab.dtx
+ maxNumCols: cols.length
+ };
+ return parseArray(context.parser, res, dCellStyle(context.envName));
+ },
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+
+// The matrix environments of amsmath builds on the array environment
+// of LaTeX, which is discussed above.
+// The mathtools package adds starred versions of the same environments.
+// These have an optional argument to choose left|center|right justification.
+defineEnvironment({
+ type: "array",
+ names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"],
+ props: {
+ numArgs: 0
+ },
+ handler(context) {
+ const delimiters = {
+ "matrix": null,
+ "pmatrix": ["(", ")"],
+ "bmatrix": ["[", "]"],
+ "Bmatrix": ["\\{", "\\}"],
+ "vmatrix": ["|", "|"],
+ "Vmatrix": ["\\Vert", "\\Vert"]
+ }[context.envName.replace("*", "")];
+ // \hskip -\arraycolsep in amsmath
+ let colAlign = "c";
+ const payload = {
+ hskipBeforeAndAfter: false,
+ cols: [{
+ type: "align",
+ align: colAlign
+ }]
+ };
+ if (context.envName.charAt(context.envName.length - 1) === "*") {
+ // It's one of the mathtools starred functions.
+ // Parse the optional alignment argument.
+ const parser = context.parser;
+ parser.consumeSpaces();
+ if (parser.fetch().text === "[") {
+ parser.consume();
+ parser.consumeSpaces();
+ colAlign = parser.fetch().text;
+ if (!"lcr".includes(colAlign)) {
+ throw new src_ParseError("Expected l or c or r", parser.nextToken);
+ }
+ parser.consume();
+ parser.consumeSpaces();
+ parser.expect("]");
+ parser.consume();
+ payload.cols = [{
+ type: "align",
+ align: colAlign
+ }];
+ }
+ }
+ const res = parseArray(context.parser, payload, dCellStyle(context.envName));
+ // Populate cols with the correct number of column alignment specs.
+ const numCols = Math.max(0, ...res.body.map(row => row.length));
+ res.cols = new Array(numCols).fill({
+ type: "align",
+ align: colAlign
+ });
+ return delimiters ? {
+ type: "leftright",
+ mode: context.mode,
+ body: [res],
+ left: delimiters[0],
+ right: delimiters[1],
+ rightColor: undefined // \right uninfluenced by \color in array
+ } : res;
+ },
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+defineEnvironment({
+ type: "array",
+ names: ["smallmatrix"],
+ props: {
+ numArgs: 0
+ },
+ handler(context) {
+ const payload = {
+ arraystretch: 0.5
+ };
+ const res = parseArray(context.parser, payload, "script");
+ res.colSeparationType = "small";
+ return res;
+ },
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+defineEnvironment({
+ type: "array",
+ names: ["subarray"],
+ props: {
+ numArgs: 1
+ },
+ handler(context, args) {
+ // Parsing of {subarray} is similar to {array}
+ const symNode = checkSymbolNodeType(args[0]);
+ const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
+ const cols = colalign.map(function (nde) {
+ const node = assertSymbolNodeType(nde);
+ const ca = node.text;
+ // {subarray} only recognizes "l" & "c"
+ if ("lc".includes(ca)) {
+ return {
+ type: "align",
+ align: ca
+ };
+ }
+ throw new src_ParseError("Unknown column alignment: " + ca, nde);
+ });
+ if (cols.length > 1) {
+ throw new src_ParseError("{subarray} can contain only one column");
+ }
+ const payload = {
+ cols,
+ hskipBeforeAndAfter: false,
+ arraystretch: 0.5
+ };
+ const res = parseArray(context.parser, payload, "script");
+ if (res.body.length > 0 && res.body[0].length > 1) {
+ throw new src_ParseError("{subarray} can contain only one column");
+ }
+ return res;
+ },
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+
+// A cases environment (in amsmath.sty) is almost equivalent to
+// \def\arraystretch{1.2}%
+// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
+// {dcases} is a {cases} environment where cells are set in \displaystyle,
+// as defined in mathtools.sty.
+// {rcases} is another mathtools environment. It's brace is on the right side.
+defineEnvironment({
+ type: "array",
+ names: ["cases", "dcases", "rcases", "drcases"],
+ props: {
+ numArgs: 0
+ },
+ handler(context) {
+ const payload = {
+ arraystretch: 1.2,
+ cols: [{
+ type: "align",
+ align: "l",
+ pregap: 0,
+ // TODO(kevinb) get the current style.
+ // For now we use the metrics for TEXT style which is what we were
+ // doing before. Before attempting to get the current style we
+ // should look at TeX's behavior especially for \over and matrices.
+ postgap: 1.0 /* 1em quad */
+ }, {
+ type: "align",
+ align: "l",
+ pregap: 0,
+ postgap: 0
+ }]
+ };
+ const res = parseArray(context.parser, payload, dCellStyle(context.envName));
+ return {
+ type: "leftright",
+ mode: context.mode,
+ body: [res],
+ left: context.envName.includes("r") ? "." : "\\{",
+ right: context.envName.includes("r") ? "\\}" : ".",
+ rightColor: undefined
+ };
+ },
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+
+// In the align environment, one uses ampersands, &, to specify number of
+// columns in each row, and to locate spacing between each column.
+// align gets automatic numbering. align* and aligned do not.
+// The alignedat environment can be used in math mode.
+// Note that we assume \nomallineskiplimit to be zero,
+// so that \strut@ is the same as \strut.
+defineEnvironment({
+ type: "array",
+ names: ["align", "align*", "aligned", "split"],
+ props: {
+ numArgs: 0
+ },
+ handler: alignedHandler,
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+
+// A gathered environment is like an array environment with one centered
+// column, but where rows are considered lines so get \jot line spacing
+// and contents are set in \displaystyle.
+defineEnvironment({
+ type: "array",
+ names: ["gathered", "gather", "gather*"],
+ props: {
+ numArgs: 0
+ },
+ handler(context) {
+ if (gatherEnvironments.has(context.envName)) {
+ validateAmsEnvironmentContext(context);
+ }
+ const res = {
+ cols: [{
+ type: "align",
+ align: "c"
+ }],
+ addJot: true,
+ colSeparationType: "gather",
+ autoTag: getAutoTag(context.envName),
+ emptySingleRow: true,
+ leqno: context.parser.settings.leqno
+ };
+ return parseArray(context.parser, res, "display");
+ },
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+
+// alignat environment is like an align environment, but one must explicitly
+// specify maximum number of columns in each row, and can adjust spacing between
+// each columns.
+defineEnvironment({
+ type: "array",
+ names: ["alignat", "alignat*", "alignedat"],
+ props: {
+ numArgs: 1
+ },
+ handler: alignedHandler,
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+defineEnvironment({
+ type: "array",
+ names: ["equation", "equation*"],
+ props: {
+ numArgs: 0
+ },
+ handler(context) {
+ validateAmsEnvironmentContext(context);
+ const res = {
+ autoTag: getAutoTag(context.envName),
+ emptySingleRow: true,
+ singleRow: true,
+ maxNumCols: 1,
+ leqno: context.parser.settings.leqno
+ };
+ return parseArray(context.parser, res, "display");
+ },
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+defineEnvironment({
+ type: "array",
+ names: ["CD"],
+ props: {
+ numArgs: 0
+ },
+ handler(context) {
+ validateAmsEnvironmentContext(context);
+ return parseCD(context.parser);
+ },
+ htmlBuilder: array_htmlBuilder,
+ mathmlBuilder: array_mathmlBuilder
+});
+defineMacro("\\nonumber", "\\gdef\\@eqnsw{0}");
+defineMacro("\\notag", "\\nonumber");
+
+// Catch \hline outside array environment
+defineFunction({
+ type: "text",
+ // Doesn't matter what this is.
+ names: ["\\hline", "\\hdashline"],
+ numArgs: 0,
+ allowedInText: true,
+ allowedInMath: true,
+ handler(context, args) {
+ throw new src_ParseError(context.funcName + " valid only within array environment");
+ }
+});
+;// ./src/environments.ts
+
+const environments = _environments;
+/* harmony default export */ var src_environments = (environments);
+
+// All environment definitions should be imported below
+
+;// ./src/functions/environment.ts
+
+
+
+
+// Environment delimiters. HTML/MathML rendering is defined in the corresponding
+// defineEnvironment definitions.
+defineFunction({
+ type: "environment",
+ names: ["\\begin", "\\end"],
+ numArgs: 1,
+ argTypes: ["text"],
+ handler(_ref, args) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const nameGroup = args[0];
+ if (nameGroup.type !== "ordgroup") {
+ throw new src_ParseError("Invalid environment name", nameGroup);
+ }
+ const envName = assertCharacterGroup(nameGroup, "Environment name should contain only text characters and spaces", true);
+ if (funcName === "\\begin") {
+ // begin...end is similar to left...right
+ if (!Object.prototype.hasOwnProperty.call(src_environments, envName)) {
+ throw new src_ParseError("No such environment: " + envName, nameGroup);
+ }
+ // Build the environment object. Arguments and other information will
+ // be made available to the begin and end methods using properties.
+ const env = src_environments[envName];
+ const _parser$parseArgument = parser.parseArguments("\\begin{" + envName + "}", env),
+ args = _parser$parseArgument.args,
+ optArgs = _parser$parseArgument.optArgs;
+ const context = {
+ mode: parser.mode,
+ envName,
+ parser
+ };
+ const result = env.handler(context, args, optArgs);
+ parser.expect("\\end", false);
+ const endNameToken = parser.nextToken;
+ const end = assertNodeType(parser.parseFunction(), "environment");
+ if (end.name !== envName) {
+ throw new src_ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken);
+ }
+ // env.handler returns the specific node type (e.g. "array"),
+ // not "environment". This cast is unavoidable: defineFunction
+ // requires the handler to return ParseNode<"environment"> but
+ // \begin delegates to environment handlers with different types.
+ return result;
+ }
+ return {
+ type: "environment",
+ mode: parser.mode,
+ name: envName,
+ nameGroup
+ };
+ }
+});
+;// ./src/functions/font.ts
+// TODO(kevinb): implement \\sl and \\sc
+
+
+
+
+
+
+const font_htmlBuilder = (group, options) => {
+ const font = group.font;
+ const newOptions = options.withFont(font);
+ return buildGroup(group.body, newOptions);
+};
+const font_mathmlBuilder = (group, options) => {
+ const font = group.font;
+ const newOptions = options.withFont(font);
+ return buildMathML_buildGroup(group.body, newOptions);
+};
+const fontAliases = {
+ "\\Bbb": "\\mathbb",
+ "\\bold": "\\mathbf",
+ "\\frak": "\\mathfrak"
+};
+defineFunction({
+ type: "font",
+ names: [
+ // styles, except \boldsymbol defined below
+ "\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", "\\mathsfit",
+ // families
+ "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt",
+ // aliases, except \bm defined below
+ "\\Bbb", "\\bold", "\\frak"],
+ numArgs: 1,
+ allowedInArgument: true,
+ handler: (_ref, args) => {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const body = normalizeArgument(args[0]);
+ const func = funcName in fontAliases ? fontAliases[funcName] : funcName;
+ return {
+ type: "font",
+ mode: parser.mode,
+ font: func.slice(1),
+ body
+ };
+ },
+ htmlBuilder: font_htmlBuilder,
+ mathmlBuilder: font_mathmlBuilder
+});
+defineFunction({
+ type: "mclass",
+ names: ["\\boldsymbol", "\\bm"],
+ numArgs: 1,
+ handler: (_ref2, args) => {
+ let parser = _ref2.parser;
+ const body = args[0];
+ // amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the
+ // argument's bin|rel|ord status
+ return {
+ type: "mclass",
+ mode: parser.mode,
+ mclass: binrelClass(body),
+ body: [{
+ type: "font",
+ mode: parser.mode,
+ font: "boldsymbol",
+ body
+ }],
+ isCharacterBox: isCharacterBox(body)
+ };
+ }
+});
+
+// Old font changing functions
+defineFunction({
+ type: "font",
+ names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"],
+ numArgs: 0,
+ allowedInText: true,
+ handler: (_ref3, args) => {
+ let parser = _ref3.parser,
+ funcName = _ref3.funcName,
+ breakOnTokenText = _ref3.breakOnTokenText;
+ const mode = parser.mode;
+ const body = parser.parseExpression(true, breakOnTokenText);
+ return {
+ type: "font",
+ mode: mode,
+ font: "math" + funcName.slice(1),
+ body: {
+ type: "ordgroup",
+ mode: parser.mode,
+ body
+ }
+ };
+ }
+});
+;// ./src/functions/genfrac.ts
+
+
+
+
+
+
+
+
+
+const genfrac_htmlBuilder = (group, options) => {
+ // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e).
+ const style = options.style;
+ const nstyle = style.fracNum();
+ const dstyle = style.fracDen();
+ let newOptions;
+ newOptions = options.havingStyle(nstyle);
+ const numerm = buildGroup(group.numer, newOptions, options);
+ if (group.continued) {
+ // \cfrac inserts a \strut into the numerator.
+ // Get \strut dimensions from TeXbook page 353.
+ const hStrut = 8.5 / options.fontMetrics().ptPerEm;
+ const dStrut = 3.5 / options.fontMetrics().ptPerEm;
+ numerm.height = numerm.height < hStrut ? hStrut : numerm.height;
+ numerm.depth = numerm.depth < dStrut ? dStrut : numerm.depth;
+ }
+ newOptions = options.havingStyle(dstyle);
+ const denomm = buildGroup(group.denom, newOptions, options);
+ let rule;
+ let ruleWidth;
+ let ruleSpacing;
+ if (group.hasBarLine) {
+ if (group.barSize) {
+ ruleWidth = calculateSize(group.barSize, options);
+ rule = makeLineSpan("frac-line", options, ruleWidth);
+ } else {
+ rule = makeLineSpan("frac-line", options);
+ }
+ ruleWidth = rule.height;
+ ruleSpacing = rule.height;
+ } else {
+ rule = null;
+ ruleWidth = 0;
+ ruleSpacing = options.fontMetrics().defaultRuleThickness;
+ }
+
+ // Rule 15b
+ let numShift;
+ let clearance;
+ let denomShift;
+ if (style.size === src_Style.DISPLAY.size) {
+ numShift = options.fontMetrics().num1;
+ if (ruleWidth > 0) {
+ clearance = 3 * ruleSpacing;
+ } else {
+ clearance = 7 * ruleSpacing;
+ }
+ denomShift = options.fontMetrics().denom1;
+ } else {
+ if (ruleWidth > 0) {
+ numShift = options.fontMetrics().num2;
+ clearance = ruleSpacing;
+ } else {
+ numShift = options.fontMetrics().num3;
+ clearance = 3 * ruleSpacing;
+ }
+ denomShift = options.fontMetrics().denom2;
+ }
+ let frac;
+ if (!rule) {
+ // Rule 15c
+ const candidateClearance = numShift - numerm.depth - (denomm.height - denomShift);
+ if (candidateClearance < clearance) {
+ numShift += 0.5 * (clearance - candidateClearance);
+ denomShift += 0.5 * (clearance - candidateClearance);
+ }
+ frac = makeVList({
+ positionType: "individualShift",
+ children: [{
+ type: "elem",
+ elem: denomm,
+ shift: denomShift
+ }, {
+ type: "elem",
+ elem: numerm,
+ shift: -numShift
+ }]
+ }, options);
+ } else {
+ // Rule 15d
+ const axisHeight = options.fontMetrics().axisHeight;
+ if (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth) < clearance) {
+ numShift += clearance - (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth));
+ }
+ if (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift) < clearance) {
+ denomShift += clearance - (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift));
+ }
+ const midShift = -(axisHeight - 0.5 * ruleWidth);
+ frac = makeVList({
+ positionType: "individualShift",
+ children: [{
+ type: "elem",
+ elem: denomm,
+ shift: denomShift
+ }, {
+ type: "elem",
+ elem: rule,
+ shift: midShift
+ }, {
+ type: "elem",
+ elem: numerm,
+ shift: -numShift
+ }]
+ }, options);
+ }
+
+ // Since we manually change the style sometimes (with \dfrac or \tfrac),
+ // account for the possible size change here.
+ newOptions = options.havingStyle(style);
+ frac.height *= newOptions.sizeMultiplier / options.sizeMultiplier;
+ frac.depth *= newOptions.sizeMultiplier / options.sizeMultiplier;
+
+ // Rule 15e
+ let delimSize;
+ if (style.size === src_Style.DISPLAY.size) {
+ delimSize = options.fontMetrics().delim1;
+ } else if (style.size === src_Style.SCRIPTSCRIPT.size) {
+ delimSize = options.havingStyle(src_Style.SCRIPT).fontMetrics().delim2;
+ } else {
+ delimSize = options.fontMetrics().delim2;
+ }
+ let leftDelim;
+ let rightDelim;
+ if (group.leftDelim == null) {
+ leftDelim = makeNullDelimiter(options, ["mopen"]);
+ } else {
+ leftDelim = makeCustomSizedDelim(group.leftDelim, delimSize, true, options.havingStyle(style), group.mode, ["mopen"]);
+ }
+ if (group.continued) {
+ rightDelim = makeSpan([]); // zero width for \cfrac
+ } else if (group.rightDelim == null) {
+ rightDelim = makeNullDelimiter(options, ["mclose"]);
+ } else {
+ rightDelim = makeCustomSizedDelim(group.rightDelim, delimSize, true, options.havingStyle(style), group.mode, ["mclose"]);
+ }
+ return makeSpan(["mord"].concat(newOptions.sizingClasses(options)), [leftDelim, makeSpan(["mfrac"], [frac]), rightDelim], options);
+};
+const genfrac_mathmlBuilder = (group, options) => {
+ const node = new MathNode("mfrac", [buildMathML_buildGroup(group.numer, options), buildMathML_buildGroup(group.denom, options)]);
+ if (!group.hasBarLine) {
+ node.setAttribute("linethickness", "0px");
+ } else if (group.barSize) {
+ const ruleWidth = calculateSize(group.barSize, options);
+ node.setAttribute("linethickness", makeEm(ruleWidth));
+ }
+ if (group.leftDelim != null || group.rightDelim != null) {
+ const withDelims = [];
+ if (group.leftDelim != null) {
+ const leftOp = new MathNode("mo", [new TextNode(group.leftDelim.replace("\\", ""))]);
+ leftOp.setAttribute("fence", "true");
+ withDelims.push(leftOp);
+ }
+ withDelims.push(node);
+ if (group.rightDelim != null) {
+ const rightOp = new MathNode("mo", [new TextNode(group.rightDelim.replace("\\", ""))]);
+ rightOp.setAttribute("fence", "true");
+ withDelims.push(rightOp);
+ }
+ return makeRow(withDelims);
+ }
+ return node;
+};
+const wrapWithStyle = (frac, style) => {
+ if (!style) {
+ return frac;
+ }
+ const wrapper = {
+ type: "styling",
+ mode: frac.mode,
+ style,
+ body: [frac]
+ };
+
+ // @ts-ignore defineFunction handler needs to return ParseNode<"genfrac">
+ return wrapper;
+};
+defineFunction({
+ type: "genfrac",
+ names: ["\\cfrac", "\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac",
+ // can’t be entered directly
+ "\\\\bracefrac", "\\\\brackfrac" // ditto
+ ],
+ numArgs: 2,
+ allowedInArgument: true,
+ handler: (_ref, args) => {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const numer = args[0];
+ const denom = args[1];
+ let hasBarLine;
+ let leftDelim = null;
+ let rightDelim = null;
+ switch (funcName) {
+ case "\\cfrac":
+ case "\\dfrac":
+ case "\\frac":
+ case "\\tfrac":
+ hasBarLine = true;
+ break;
+ case "\\\\atopfrac":
+ hasBarLine = false;
+ break;
+ case "\\dbinom":
+ case "\\binom":
+ case "\\tbinom":
+ hasBarLine = false;
+ leftDelim = "(";
+ rightDelim = ")";
+ break;
+ case "\\\\bracefrac":
+ hasBarLine = false;
+ leftDelim = "\\{";
+ rightDelim = "\\}";
+ break;
+ case "\\\\brackfrac":
+ hasBarLine = false;
+ leftDelim = "[";
+ rightDelim = "]";
+ break;
+ default:
+ throw new Error("Unrecognized genfrac command");
+ }
+ const continued = funcName === "\\cfrac";
+ let style = null;
+ if (continued || funcName.startsWith("\\d")) {
+ style = "display";
+ } else if (funcName.startsWith("\\t")) {
+ style = "text";
+ }
+ return wrapWithStyle({
+ type: "genfrac",
+ mode: parser.mode,
+ numer,
+ denom,
+ continued,
+ hasBarLine,
+ leftDelim,
+ rightDelim,
+ barSize: null
+ }, style);
+ },
+ htmlBuilder: genfrac_htmlBuilder,
+ mathmlBuilder: genfrac_mathmlBuilder
+});
+
+// Infix generalized fractions -- these are not rendered directly, but replaced
+// immediately by one of the variants above.
+defineFunction({
+ type: "infix",
+ names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"],
+ numArgs: 0,
+ infix: true,
+ handler(_ref2) {
+ let parser = _ref2.parser,
+ funcName = _ref2.funcName,
+ token = _ref2.token;
+ let replaceWith;
+ switch (funcName) {
+ case "\\over":
+ replaceWith = "\\frac";
+ break;
+ case "\\choose":
+ replaceWith = "\\binom";
+ break;
+ case "\\atop":
+ replaceWith = "\\\\atopfrac";
+ break;
+ case "\\brace":
+ replaceWith = "\\\\bracefrac";
+ break;
+ case "\\brack":
+ replaceWith = "\\\\brackfrac";
+ break;
+ default:
+ throw new Error("Unrecognized infix genfrac command");
+ }
+ return {
+ type: "infix",
+ mode: parser.mode,
+ replaceWith,
+ token
+ };
+ }
+});
+const stylArray = ["display", "text", "script", "scriptscript"];
+const delimFromValue = function (delimString) {
+ let delim = null;
+ if (delimString.length > 0) {
+ delim = delimString;
+ delim = delim === "." ? null : delim;
+ }
+ return delim;
+};
+defineFunction({
+ type: "genfrac",
+ names: ["\\genfrac"],
+ numArgs: 6,
+ allowedInArgument: true,
+ argTypes: ["math", "math", "size", "text", "math", "math"],
+ handler(_ref3, args) {
+ let parser = _ref3.parser;
+ const numer = args[4];
+ const denom = args[5];
+
+ // Look into the parse nodes to get the desired delimiters.
+ const leftNode = normalizeArgument(args[0]);
+ const leftDelim = leftNode.type === "atom" && leftNode.family === "open" ? delimFromValue(leftNode.text) : null;
+ const rightNode = normalizeArgument(args[1]);
+ const rightDelim = rightNode.type === "atom" && rightNode.family === "close" ? delimFromValue(rightNode.text) : null;
+ const barNode = assertNodeType(args[2], "size");
+ let hasBarLine;
+ let barSize = null;
+ if (barNode.isBlank) {
+ // \genfrac acts differently than \above.
+ // \genfrac treats an empty size group as a signal to use a
+ // standard bar size. \above would see size = 0 and omit the bar.
+ hasBarLine = true;
+ } else {
+ barSize = barNode.value;
+ hasBarLine = barSize.number > 0;
+ }
+
+ // Find out if we want displaystyle, textstyle, etc.
+ let size = null;
+ let styl = args[3];
+ if (styl.type === "ordgroup") {
+ if (styl.body.length > 0) {
+ const textOrd = assertNodeType(styl.body[0], "textord");
+ size = stylArray[Number(textOrd.text)];
+ }
+ } else {
+ styl = assertNodeType(styl, "textord");
+ size = stylArray[Number(styl.text)];
+ }
+ return wrapWithStyle({
+ type: "genfrac",
+ mode: parser.mode,
+ numer,
+ denom,
+ continued: false,
+ hasBarLine,
+ barSize,
+ leftDelim,
+ rightDelim
+ }, size);
+ }
+});
+
+// \above is an infix fraction that also defines a fraction bar size.
+defineFunction({
+ type: "infix",
+ names: ["\\above"],
+ numArgs: 1,
+ argTypes: ["size"],
+ infix: true,
+ handler(_ref4, args) {
+ let parser = _ref4.parser,
+ funcName = _ref4.funcName,
+ token = _ref4.token;
+ return {
+ type: "infix",
+ mode: parser.mode,
+ replaceWith: "\\\\abovefrac",
+ size: assertNodeType(args[0], "size").value,
+ token
+ };
+ }
+});
+defineFunction({
+ type: "genfrac",
+ names: ["\\\\abovefrac"],
+ numArgs: 3,
+ argTypes: ["math", "size", "math"],
+ handler: (_ref5, args) => {
+ let parser = _ref5.parser,
+ funcName = _ref5.funcName;
+ const numer = args[0];
+ const barSize = assertNodeType(args[1], "infix").size;
+ if (!barSize) {
+ throw new Error("\\\\abovefrac expected size, but got " + String(barSize));
+ }
+ const denom = args[2];
+ const hasBarLine = barSize.number > 0;
+ return {
+ type: "genfrac",
+ mode: parser.mode,
+ numer,
+ denom,
+ continued: false,
+ hasBarLine,
+ barSize,
+ leftDelim: null,
+ rightDelim: null
+ };
+ }
+});
+;// ./src/functions/horizBrace.ts
+
+
+
+
+
+
+
+
+// NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but
+// also "supsub" since an over/underbrace can affect super/subscripting.
+const horizBrace_htmlBuilder = (grp, options) => {
+ const style = options.style;
+
+ // Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node.
+ let supSubGroup;
+ let group;
+ if (grp.type === "supsub") {
+ // Ref: LaTeX source2e: }}}}\limits}
+ // i.e. LaTeX treats the brace similar to an op and passes it
+ // with \limits, so we need to assign supsub style.
+ supSubGroup = grp.sup ? buildGroup(grp.sup, options.havingStyle(style.sup()), options) : buildGroup(grp.sub, options.havingStyle(style.sub()), options);
+ group = assertNodeType(grp.base, "horizBrace");
+ } else {
+ group = assertNodeType(grp, "horizBrace");
+ }
+
+ // Build the base group
+ const body = buildGroup(group.base, options.havingBaseStyle(src_Style.DISPLAY));
+
+ // Create the stretchy element
+ const braceBody = stretchySvg(group, options);
+
+ // Generate the vlist, with the appropriate kerns ┏━━━━━━━━┓
+ // This first vlist contains the content and the brace: equation
+ let vlist;
+ if (group.isOver) {
+ vlist = makeVList({
+ positionType: "firstBaseline",
+ children: [{
+ type: "elem",
+ elem: body
+ }, {
+ type: "kern",
+ size: 0.1
+ }, {
+ type: "elem",
+ elem: braceBody,
+ wrapperClasses: ["svg-align"]
+ }]
+ }, options);
+ } else {
+ vlist = makeVList({
+ positionType: "bottom",
+ positionData: body.depth + 0.1 + braceBody.height,
+ children: [{
+ type: "elem",
+ elem: braceBody,
+ wrapperClasses: ["svg-align"]
+ }, {
+ type: "kern",
+ size: 0.1
+ }, {
+ type: "elem",
+ elem: body
+ }]
+ }, options);
+ }
+ if (supSubGroup) {
+ // To write the supsub, wrap the first vlist in another vlist:
+ // They can't all go in the same vlist, because the note might be
+ // wider than the equation. We want the equation to control the
+ // brace width.
+
+ // note long note long note
+ // ┏━━━━━━━━┓ or ┏━━━┓ not ┏━━━━━━━━━┓
+ // equation eqn eqn
+
+ const vSpan = makeSpan(["minner", group.isOver ? "mover" : "munder"], [vlist], options);
+ if (group.isOver) {
+ vlist = makeVList({
+ positionType: "firstBaseline",
+ children: [{
+ type: "elem",
+ elem: vSpan
+ }, {
+ type: "kern",
+ size: 0.2
+ }, {
+ type: "elem",
+ elem: supSubGroup
+ }]
+ }, options);
+ } else {
+ vlist = makeVList({
+ positionType: "bottom",
+ positionData: vSpan.depth + 0.2 + supSubGroup.height + supSubGroup.depth,
+ children: [{
+ type: "elem",
+ elem: supSubGroup
+ }, {
+ type: "kern",
+ size: 0.2
+ }, {
+ type: "elem",
+ elem: vSpan
+ }]
+ }, options);
+ }
+ }
+ return makeSpan(["minner", group.isOver ? "mover" : "munder"], [vlist], options);
+};
+const horizBrace_mathmlBuilder = (group, options) => {
+ const accentNode = stretchyMathML(group.label);
+ return new MathNode(group.isOver ? "mover" : "munder", [buildMathML_buildGroup(group.base, options), accentNode]);
+};
+
+// Horizontal stretchy braces
+defineFunction({
+ type: "horizBrace",
+ names: ["\\overbrace", "\\underbrace", "\\overbracket", "\\underbracket"],
+ numArgs: 1,
+ handler(_ref, args) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ return {
+ type: "horizBrace",
+ mode: parser.mode,
+ label: funcName,
+ isOver: funcName.includes("\\over"),
+ base: args[0]
+ };
+ },
+ htmlBuilder: horizBrace_htmlBuilder,
+ mathmlBuilder: horizBrace_mathmlBuilder
+});
+;// ./src/functions/href.ts
+
+
+
+
+
+
+defineFunction({
+ type: "href",
+ names: ["\\href"],
+ numArgs: 2,
+ argTypes: ["url", "original"],
+ allowedInText: true,
+ handler: (_ref, args) => {
+ let parser = _ref.parser;
+ const body = args[1];
+ const href = assertNodeType(args[0], "url").url;
+ if (!parser.settings.isTrusted({
+ command: "\\href",
+ url: href
+ })) {
+ return parser.formatUnsupportedCmd("\\href");
+ }
+ return {
+ type: "href",
+ mode: parser.mode,
+ href,
+ body: ordargument(body)
+ };
+ },
+ htmlBuilder: (group, options) => {
+ const elements = buildExpression(group.body, options, false);
+ return makeAnchor(group.href, [], elements, options);
+ },
+ mathmlBuilder: (group, options) => {
+ let math = buildExpressionRow(group.body, options);
+ if (!(math instanceof MathNode)) {
+ math = new MathNode("mrow", [math]);
+ }
+ math.setAttribute("href", group.href);
+ return math;
+ }
+});
+defineFunction({
+ type: "href",
+ names: ["\\url"],
+ numArgs: 1,
+ argTypes: ["url"],
+ allowedInText: true,
+ handler: (_ref2, args) => {
+ let parser = _ref2.parser;
+ const href = assertNodeType(args[0], "url").url;
+ if (!parser.settings.isTrusted({
+ command: "\\url",
+ url: href
+ })) {
+ return parser.formatUnsupportedCmd("\\url");
+ }
+ const chars = [];
+ for (let i = 0; i < href.length; i++) {
+ let c = href[i];
+ if (c === "~") {
+ c = "\\textasciitilde";
+ }
+ chars.push({
+ type: "textord",
+ mode: "text",
+ text: c
+ });
+ }
+ const body = {
+ type: "text",
+ mode: parser.mode,
+ font: "\\texttt",
+ body: chars
+ };
+ return {
+ type: "href",
+ mode: parser.mode,
+ href,
+ body: ordargument(body)
+ };
+ }
+});
+;// ./src/functions/hbox.ts
+
+
+
+
+
+
+// \hbox is provided for compatibility with LaTeX \vcenter.
+// In LaTeX, \vcenter can act only on a box, as in
+// \vcenter{\hbox{$\frac{a+b}{\dfrac{c}{d}}$}}
+// This function by itself doesn't do anything but prevent a soft line break.
+
+defineFunction({
+ type: "hbox",
+ names: ["\\hbox"],
+ numArgs: 1,
+ argTypes: ["text"],
+ allowedInText: true,
+ primitive: true,
+ handler(_ref, args) {
+ let parser = _ref.parser;
+ return {
+ type: "hbox",
+ mode: parser.mode,
+ body: ordargument(args[0])
+ };
+ },
+ htmlBuilder(group, options) {
+ const elements = buildExpression(group.body, options.withFont(''), false);
+ return makeFragment(elements);
+ },
+ mathmlBuilder(group, options) {
+ return new MathNode("mrow", buildMathML_buildExpression(group.body, options.withFont('')));
+ }
+});
+;// ./src/functions/html.ts
+
+
+
+
+
+
+defineFunction({
+ type: "html",
+ names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"],
+ numArgs: 2,
+ argTypes: ["raw", "original"],
+ allowedInText: true,
+ handler: (_ref, args) => {
+ let parser = _ref.parser,
+ funcName = _ref.funcName,
+ token = _ref.token;
+ const value = assertNodeType(args[0], "raw").string;
+ const body = args[1];
+ if (parser.settings.strict) {
+ parser.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode");
+ }
+ let trustContext;
+ const attributes = {};
+ switch (funcName) {
+ case "\\htmlClass":
+ attributes.class = value;
+ trustContext = {
+ command: "\\htmlClass",
+ class: value
+ };
+ break;
+ case "\\htmlId":
+ attributes.id = value;
+ trustContext = {
+ command: "\\htmlId",
+ id: value
+ };
+ break;
+ case "\\htmlStyle":
+ attributes.style = value;
+ trustContext = {
+ command: "\\htmlStyle",
+ style: value
+ };
+ break;
+ case "\\htmlData":
+ {
+ // `{,}` escapes a literal comma. Braces are used rather than a
+ // backslash because `\,` is a macro (a thin space) that expands
+ // away before this raw argument is ever read.
+ const ESCAPED_COMMA = "{,}";
+ const data = [];
+ let current = "";
+ for (let i = 0; i < value.length; i++) {
+ if (value.startsWith(ESCAPED_COMMA, i)) {
+ current += ",";
+ i += ESCAPED_COMMA.length - 1;
+ } else if (value[i] === ",") {
+ data.push(current);
+ current = "";
+ } else {
+ current += value[i];
+ }
+ }
+ data.push(current);
+ for (let i = 0; i < data.length; i++) {
+ const item = data[i];
+ const firstEquals = item.indexOf("=");
+ if (firstEquals < 0) {
+ throw new src_ParseError("\\htmlData key/value '" + item + "'" + " missing equals sign");
+ }
+ const key = item.slice(0, firstEquals);
+ const value = item.slice(firstEquals + 1);
+ attributes["data-" + key.trim()] = value;
+ }
+ trustContext = {
+ command: "\\htmlData",
+ attributes
+ };
+ break;
+ }
+ default:
+ throw new Error("Unrecognized html command");
+ }
+ if (!parser.settings.isTrusted(trustContext)) {
+ return parser.formatUnsupportedCmd(funcName);
+ }
+ return {
+ type: "html",
+ mode: parser.mode,
+ attributes,
+ body: ordargument(body)
+ };
+ },
+ htmlBuilder: (group, options) => {
+ const elements = buildExpression(group.body, options, false);
+ const classes = ["enclosing"];
+ if (group.attributes.class) {
+ classes.push(...group.attributes.class.trim().split(/\s+/));
+ }
+ const span = makeSpan(classes, elements, options);
+ for (const _ref2 of Object.entries(group.attributes)) {
+ const attr = _ref2[0];
+ const value = _ref2[1];
+ if (attr !== "class") {
+ span.setAttribute(attr, value);
+ }
+ }
+ return span;
+ },
+ mathmlBuilder: (group, options) => {
+ return buildExpressionRow(group.body, options);
+ }
+});
+;// ./src/functions/htmlmathml.ts
+
+
+
+
+defineFunction({
+ type: "htmlmathml",
+ names: ["\\html@mathml"],
+ numArgs: 2,
+ allowedInArgument: true,
+ allowedInText: true,
+ handler: (_ref, args) => {
+ let parser = _ref.parser;
+ return {
+ type: "htmlmathml",
+ mode: parser.mode,
+ html: ordargument(args[0]),
+ mathml: ordargument(args[1])
+ };
+ },
+ htmlBuilder: (group, options) => {
+ const elements = buildExpression(group.html, options, false);
+ return makeFragment(elements);
+ },
+ mathmlBuilder: (group, options) => {
+ return buildExpressionRow(group.mathml, options);
+ }
+});
+;// ./src/functions/includegraphics.ts
+
+
+
+
+
+
+const sizeData = function (str) {
+ if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) {
+ // str is a number with no unit specified.
+ // default unit is bp, per graphix package.
+ return {
+ number: +str,
+ unit: "bp"
+ };
+ } else {
+ const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str);
+ if (!match) {
+ throw new src_ParseError("Invalid size: '" + str + "' in \\includegraphics");
+ }
+ const data = {
+ number: +(match[1] + match[2]),
+ // sign + magnitude, cast to number
+ unit: match[3]
+ };
+ if (!validUnit(data)) {
+ throw new src_ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics.");
+ }
+ return data;
+ }
+};
+defineFunction({
+ type: "includegraphics",
+ names: ["\\includegraphics"],
+ numArgs: 1,
+ numOptionalArgs: 1,
+ argTypes: ["raw", "url"],
+ allowedInText: false,
+ handler: (_ref, args, optArgs) => {
+ let parser = _ref.parser;
+ let width = {
+ number: 0,
+ unit: "em"
+ };
+ let height = {
+ number: 0.9,
+ unit: "em"
+ }; // sorta character sized.
+ let totalheight = {
+ number: 0,
+ unit: "em"
+ };
+ let alt = "";
+ if (optArgs[0]) {
+ const attributeStr = assertNodeType(optArgs[0], "raw").string;
+
+ // Parser.js does not parse key/value pairs. We get a string.
+ const attributes = attributeStr.split(",");
+ for (let i = 0; i < attributes.length; i++) {
+ const keyVal = attributes[i].split("=");
+ if (keyVal.length === 2) {
+ const str = keyVal[1].trim();
+ switch (keyVal[0].trim()) {
+ case "alt":
+ alt = str;
+ break;
+ case "width":
+ width = sizeData(str);
+ break;
+ case "height":
+ height = sizeData(str);
+ break;
+ case "totalheight":
+ totalheight = sizeData(str);
+ break;
+ default:
+ throw new src_ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.");
+ }
+ }
+ }
+ }
+ const src = assertNodeType(args[0], "url").url;
+ if (alt === "") {
+ // No alt given. Use the file name. Strip away the path.
+ alt = src;
+ alt = alt.replace(/^.*[\\/]/, '');
+ alt = alt.substring(0, alt.lastIndexOf('.'));
+ }
+ if (!parser.settings.isTrusted({
+ command: "\\includegraphics",
+ url: src
+ })) {
+ return parser.formatUnsupportedCmd("\\includegraphics");
+ }
+ return {
+ type: "includegraphics",
+ mode: parser.mode,
+ alt: alt,
+ width: width,
+ height: height,
+ totalheight: totalheight,
+ src: src
+ };
+ },
+ htmlBuilder: (group, options) => {
+ const height = calculateSize(group.height, options);
+ let depth = 0;
+ if (group.totalheight.number > 0) {
+ depth = calculateSize(group.totalheight, options) - height;
+ }
+ let width = 0;
+ if (group.width.number > 0) {
+ width = calculateSize(group.width, options);
+ }
+ const style = {
+ height: makeEm(height + depth)
+ };
+ if (width > 0) {
+ style.width = makeEm(width);
+ }
+ if (depth > 0) {
+ style.verticalAlign = makeEm(-depth);
+ }
+ const node = new Img(group.src, group.alt, style);
+ node.height = height;
+ node.depth = depth;
+ return node;
+ },
+ mathmlBuilder: (group, options) => {
+ const node = new MathNode("mglyph", []);
+ node.setAttribute("alt", group.alt);
+ const height = calculateSize(group.height, options);
+ let depth = 0;
+ if (group.totalheight.number > 0) {
+ depth = calculateSize(group.totalheight, options) - height;
+ node.setAttribute("valign", makeEm(-depth));
+ }
+ node.setAttribute("height", makeEm(height + depth));
+ if (group.width.number > 0) {
+ const width = calculateSize(group.width, options);
+ node.setAttribute("width", makeEm(width));
+ }
+ node.setAttribute("src", group.src);
+ return node;
+ }
+});
+;// ./src/functions/kern.ts
+// Horizontal spacing commands
+
+
+
+
+
+
+
+// TODO: \hskip and \mskip should support plus and minus in lengths
+
+defineFunction({
+ type: "kern",
+ names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"],
+ numArgs: 1,
+ argTypes: ["size"],
+ primitive: true,
+ allowedInText: true,
+ handler(_ref, args) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const size = assertNodeType(args[0], "size");
+ if (parser.settings.strict) {
+ const mathFunction = funcName[1] === 'm'; // \mkern, \mskip
+ const muUnit = size.value.unit === 'mu';
+ if (mathFunction) {
+ if (!muUnit) {
+ parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " supports only mu units, " + ("not " + size.value.unit + " units"));
+ }
+ if (parser.mode !== "math") {
+ parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " works only in math mode");
+ }
+ } else {
+ // !mathFunction
+ if (muUnit) {
+ parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " doesn't support mu units");
+ }
+ }
+ }
+ return {
+ type: "kern",
+ mode: parser.mode,
+ dimension: size.value
+ };
+ },
+ htmlBuilder(group, options) {
+ return makeGlue(group.dimension, options);
+ },
+ mathmlBuilder(group, options) {
+ const dimension = calculateSize(group.dimension, options);
+ return new SpaceNode(dimension);
+ }
+});
+;// ./src/functions/lap.ts
+// Horizontal overlap functions
+
+
+
+
+
+
+defineFunction({
+ type: "lap",
+ names: ["\\mathllap", "\\mathrlap", "\\mathclap"],
+ numArgs: 1,
+ allowedInText: true,
+ handler: (_ref, args) => {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const body = args[0];
+ return {
+ type: "lap",
+ mode: parser.mode,
+ alignment: funcName.slice(5),
+ body
+ };
+ },
+ htmlBuilder: (group, options) => {
+ // mathllap, mathrlap, mathclap
+ let inner;
+ if (group.alignment === "clap") {
+ // ref: https://www.math.lsu.edu/~aperlis/publications/mathclap/
+ inner = makeSpan([], [buildGroup(group.body, options)]);
+ // wrap, since CSS will center a .clap > .katex-inner > span
+ inner = makeSpan(["katex-inner"], [inner], options);
+ } else {
+ inner = makeSpan(["katex-inner"], [buildGroup(group.body, options)]);
+ }
+ const fix = makeSpan(["katex-fix"], []);
+ let node = makeSpan([group.alignment], [inner, fix], options);
+
+ // At this point, we have correctly set horizontal alignment of the
+ // two items involved in the lap.
+ // Next, use a strut to set the height of the HTML bounding box.
+ // Otherwise, a tall argument may be misplaced.
+ // This code resolved issue #1153
+ const strut = makeSpan(["katex-strut"]);
+ strut.style.height = makeEm(node.height + node.depth);
+ if (node.depth) {
+ strut.style.verticalAlign = makeEm(-node.depth);
+ }
+ node.children.unshift(strut);
+
+ // Next, prevent vertical misplacement when next to something tall.
+ // This code resolves issue #1234
+ node = makeSpan(["katex-thinbox"], [node], options);
+ return makeSpan(["mord", "katex-vbox"], [node], options);
+ },
+ mathmlBuilder: (group, options) => {
+ // mathllap, mathrlap, mathclap
+ const node = new MathNode("mpadded", [buildMathML_buildGroup(group.body, options)]);
+ if (group.alignment !== "rlap") {
+ const offset = group.alignment === "llap" ? "-1" : "-0.5";
+ node.setAttribute("lspace", offset + "width");
+ }
+ node.setAttribute("width", "0px");
+ return node;
+ }
+});
+;// ./src/functions/math.ts
+
+
+
+// Switching from text mode back to math mode
+defineFunction({
+ type: "styling",
+ names: ["\\(", "$"],
+ numArgs: 0,
+ allowedInText: true,
+ allowedInMath: false,
+ handler(_ref, args) {
+ let funcName = _ref.funcName,
+ parser = _ref.parser;
+ const outerMode = parser.mode;
+ parser.switchMode("math");
+ const close = funcName === "\\(" ? "\\)" : "$";
+ const body = parser.parseExpression(false, close);
+ parser.expect(close);
+ parser.switchMode(outerMode);
+ return {
+ type: "styling",
+ mode: parser.mode,
+ style: "text",
+ resetFont: true,
+ body
+ };
+ }
+});
+
+// Check for extra closing math delimiters
+defineFunction({
+ type: "text",
+ // Doesn't matter what this is.
+ names: ["\\)", "\\]"],
+ numArgs: 0,
+ allowedInText: true,
+ allowedInMath: false,
+ handler(context, args) {
+ throw new src_ParseError("Mismatched " + context.funcName);
+ }
+});
+;// ./src/functions/mathchoice.ts
+
+
+
+
+
+const chooseMathStyle = (group, options) => {
+ switch (options.style.size) {
+ case src_Style.DISPLAY.size:
+ return group.display;
+ case src_Style.TEXT.size:
+ return group.text;
+ case src_Style.SCRIPT.size:
+ return group.script;
+ case src_Style.SCRIPTSCRIPT.size:
+ return group.scriptscript;
+ default:
+ return group.text;
+ }
+};
+defineFunction({
+ type: "mathchoice",
+ names: ["\\mathchoice"],
+ numArgs: 4,
+ primitive: true,
+ handler: (_ref, args) => {
+ let parser = _ref.parser;
+ return {
+ type: "mathchoice",
+ mode: parser.mode,
+ display: ordargument(args[0]),
+ text: ordargument(args[1]),
+ script: ordargument(args[2]),
+ scriptscript: ordargument(args[3])
+ };
+ },
+ htmlBuilder: (group, options) => {
+ const body = chooseMathStyle(group, options);
+ const elements = buildExpression(body, options, false);
+ return makeFragment(elements);
+ },
+ mathmlBuilder: (group, options) => {
+ const body = chooseMathStyle(group, options);
+ return buildExpressionRow(body, options);
+ }
+});
+;// ./src/functions/utils/assembleSupSub.ts
+
+
+
+
+
+// For an operator with limits, assemble the base, sup, and sub into a span.
+
+const assembleSupSub = (base, supGroup, subGroup, options, style, slant, baseShift) => {
+ base = makeSpan([], [base]);
+ const subIsSingleCharacter = subGroup && isCharacterBox(subGroup);
+ let sub;
+ let sup;
+ // We manually have to handle the superscripts and subscripts. This,
+ // aside from the kern calculations, is copied from supsub.
+ if (supGroup) {
+ const elem = buildGroup(supGroup, options.havingStyle(style.sup()), options);
+ sup = {
+ elem,
+ kern: Math.max(options.fontMetrics().bigOpSpacing1, options.fontMetrics().bigOpSpacing3 - elem.depth)
+ };
+ }
+ if (subGroup) {
+ const elem = buildGroup(subGroup, options.havingStyle(style.sub()), options);
+ sub = {
+ elem,
+ kern: Math.max(options.fontMetrics().bigOpSpacing2, options.fontMetrics().bigOpSpacing4 - elem.height)
+ };
+ }
+
+ // Build the final group as a vlist of the possible subscript, base,
+ // and possible superscript.
+ let finalGroup;
+ if (sup && sub) {
+ const bottom = options.fontMetrics().bigOpSpacing5 + sub.elem.height + sub.elem.depth + sub.kern + base.depth + baseShift;
+ finalGroup = makeVList({
+ positionType: "bottom",
+ positionData: bottom,
+ children: [{
+ type: "kern",
+ size: options.fontMetrics().bigOpSpacing5
+ }, {
+ type: "elem",
+ elem: sub.elem,
+ marginLeft: makeEm(-slant)
+ }, {
+ type: "kern",
+ size: sub.kern
+ }, {
+ type: "elem",
+ elem: base
+ }, {
+ type: "kern",
+ size: sup.kern
+ }, {
+ type: "elem",
+ elem: sup.elem,
+ marginLeft: makeEm(slant)
+ }, {
+ type: "kern",
+ size: options.fontMetrics().bigOpSpacing5
+ }]
+ }, options);
+ } else if (sub) {
+ const top = base.height - baseShift;
+
+ // Shift the limits by the slant of the symbol. Note
+ // that we are supposed to shift the limits by 1/2 of the slant,
+ // but since we are centering the limits adding a full slant of
+ // margin will shift by 1/2 that.
+ finalGroup = makeVList({
+ positionType: "top",
+ positionData: top,
+ children: [{
+ type: "kern",
+ size: options.fontMetrics().bigOpSpacing5
+ }, {
+ type: "elem",
+ elem: sub.elem,
+ marginLeft: makeEm(-slant)
+ }, {
+ type: "kern",
+ size: sub.kern
+ }, {
+ type: "elem",
+ elem: base
+ }]
+ }, options);
+ } else if (sup) {
+ const bottom = base.depth + baseShift;
+ finalGroup = makeVList({
+ positionType: "bottom",
+ positionData: bottom,
+ children: [{
+ type: "elem",
+ elem: base
+ }, {
+ type: "kern",
+ size: sup.kern
+ }, {
+ type: "elem",
+ elem: sup.elem,
+ marginLeft: makeEm(slant)
+ }, {
+ type: "kern",
+ size: options.fontMetrics().bigOpSpacing5
+ }]
+ }, options);
+ } else {
+ // This case probably shouldn't occur (this would mean the
+ // supsub was sending us a group with no superscript or
+ // subscript) but be safe.
+ return base;
+ }
+ const parts = [finalGroup];
+ if (sub && slant !== 0 && !subIsSingleCharacter) {
+ // A negative margin-left was applied to the lower limit.
+ // Avoid an overlap by placing a spacer on the left on the group.
+ const spacer = makeSpan(["mspace"], [], options);
+ spacer.style.marginRight = makeEm(slant);
+ parts.unshift(spacer);
+ }
+ return makeSpan(["mop", "op-limits"], parts, options);
+};
+;// ./src/functions/op.ts
+// Limits, symbols
+
+
+
+
+
+
+
+
+
+
+// Most operators have a large successor symbol, but these don't.
+const noSuccessor = new Set(["\\smallint"]);
+
+// NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also
+// "supsub" since some of them (like \int) can affect super/subscripting.
+const op_htmlBuilder = (grp, options) => {
+ // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
+ let supGroup;
+ let subGroup;
+ let hasLimits = false;
+ let group;
+ if (grp.type === "supsub") {
+ // If we have limits, supsub will pass us its group to handle. Pull
+ // out the superscript and subscript and set the group to the op in
+ // its base.
+ supGroup = grp.sup;
+ subGroup = grp.sub;
+ group = assertNodeType(grp.base, "op");
+ hasLimits = true;
+ } else {
+ group = assertNodeType(grp, "op");
+ }
+ const style = options.style;
+ let large = false;
+ if (style.size === src_Style.DISPLAY.size && group.symbol && !noSuccessor.has(group.name)) {
+ // Most symbol operators get larger in displaystyle (rule 13)
+ large = true;
+ }
+ let base;
+ // Italic correction from the symbol glyph, captured before the symbol
+ // may be wrapped in a vlist (for \oiint/\oiiint). Stays 0 for non-symbol ops.
+ let symbolItalic;
+ if (group.symbol) {
+ // If this is a symbol, create the symbol.
+ const fontName = large ? "Size2-Regular" : "Size1-Regular";
+ let stash = "";
+ if (group.name === "\\oiint" || group.name === "\\oiiint") {
+ // No font glyphs yet, so use a glyph w/o the oval.
+ // TODO: When font glyphs are available, delete this code.
+ stash = group.name.slice(1);
+ group.name = stash === "oiint" ? "\\iint" : "\\iiint";
+ }
+ base = makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]);
+ symbolItalic = base.italic;
+ if (stash.length > 0) {
+ // We're in \oiint or \oiiint. Overlay the oval.
+ // TODO: When font glyphs are available, delete this code.
+ const oval = staticSvg(stash + "Size" + (large ? "2" : "1"), options);
+ base = makeVList({
+ positionType: "individualShift",
+ children: [{
+ type: "elem",
+ elem: base,
+ shift: 0
+ }, {
+ type: "elem",
+ elem: oval,
+ shift: large ? 0.08 : 0
+ }]
+ }, options);
+ group.name = "\\" + stash;
+ base.classes.unshift("mop");
+ // Carry the italic correction from the original symbol to the
+ // vlist wrapper so supsub can use it for subscript positioning.
+ base.italic = symbolItalic;
+ }
+ } else if (group.body) {
+ // If this is a list, compose that list.
+ const inner = buildExpression(group.body, options, true);
+ if (inner.length === 1 && inner[0] instanceof SymbolNode) {
+ base = inner[0];
+ base.classes[0] = "mop"; // replace old mclass
+ } else {
+ base = makeSpan(["mop"], inner, options);
+ }
+ } else {
+ // Otherwise, this is a text operator. Build the text from the
+ // operator's name.
+ const output = [];
+ for (let i = 1; i < group.name.length; i++) {
+ output.push(mathsym(group.name[i], group.mode, options));
+ }
+ base = makeSpan(["mop"], output, options);
+ }
+
+ // If content of op is a single symbol, shift it vertically.
+ let baseShift = 0;
+ let slant = 0;
+ if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) {
+ var _base$italic;
+ // We suppress the shift of the base of \overset and \underset. Otherwise,
+ // shift the symbol so its center lies on the axis (rule 13). It
+ // appears that our fonts have the centers of the symbols already
+ // almost on the axis, so these numbers are very small. Note we
+ // don't actually apply this here, but instead it is used either in
+ // the vlist creation or separately when there are no limits.
+ baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight;
+
+ // The slant of the symbol is just its italic correction.
+ // SymbolNode carries .italic natively; Span (for \oiint/\oiiint)
+ // only has it set when nonzero, so default to 0.
+ slant = (_base$italic = base.italic) != null ? _base$italic : 0;
+ }
+ if (hasLimits) {
+ return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift);
+ } else {
+ if (baseShift) {
+ base.style.position = "relative";
+ base.style.top = makeEm(baseShift);
+ }
+ return base;
+ }
+};
+const op_mathmlBuilder = (group, options) => {
+ let node;
+ if (group.symbol) {
+ // This is a symbol. Just add the symbol.
+ node = new MathNode("mo", [makeText(group.name, group.mode)]);
+ if (noSuccessor.has(group.name)) {
+ node.setAttribute("largeop", "false");
+ }
+ } else if (group.body) {
+ // This is an operator with children. Add them.
+ node = new MathNode("mo", buildMathML_buildExpression(group.body, options));
+ } else {
+ // This is a text operator. Add all the characters from the
+ // operator's name.
+ node = new MathNode("mi", [new TextNode(group.name.slice(1))]);
+ // Append an <mo>&ApplyFunction;</mo>.
+ // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4
+ const operator = new MathNode("mo", [makeText("\u2061", "text")]);
+ if (group.parentIsSupSub) {
+ node = new MathNode("mrow", [node, operator]);
+ } else {
+ node = newDocumentFragment([node, operator]);
+ }
+ }
+ return node;
+};
+const singleCharBigOps = {
+ "\u220F": "\\prod",
+ "\u2210": "\\coprod",
+ "\u2211": "\\sum",
+ "\u22c0": "\\bigwedge",
+ "\u22c1": "\\bigvee",
+ "\u22c2": "\\bigcap",
+ "\u22c3": "\\bigcup",
+ "\u2a00": "\\bigodot",
+ "\u2a01": "\\bigoplus",
+ "\u2a02": "\\bigotimes",
+ "\u2a04": "\\biguplus",
+ "\u2a06": "\\bigsqcup"
+};
+defineFunction({
+ type: "op",
+ names: ["\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220F", "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00", "\u2a01", "\u2a02", "\u2a04", "\u2a06"],
+ numArgs: 0,
+ handler: (_ref, args) => {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ let fName = funcName;
+ if (fName.length === 1) {
+ fName = singleCharBigOps[fName];
+ }
+ return {
+ type: "op",
+ mode: parser.mode,
+ limits: true,
+ parentIsSupSub: false,
+ symbol: true,
+ name: fName
+ };
+ },
+ htmlBuilder: op_htmlBuilder,
+ mathmlBuilder: op_mathmlBuilder
+});
+defineFunction({
+ type: "op",
+ names: ["\\mathop"],
+ numArgs: 1,
+ primitive: true,
+ handler: (_ref2, args) => {
+ let parser = _ref2.parser;
+ const body = args[0];
+ return {
+ type: "op",
+ mode: parser.mode,
+ limits: false,
+ parentIsSupSub: false,
+ symbol: false,
+ body: ordargument(body)
+ };
+ }
+});
+
+// There are 2 flags for operators; whether they produce limits in
+// displaystyle, and whether they are symbols and should grow in
+// displaystyle. These four groups cover the four possible choices.
+const singleCharIntegrals = {
+ "\u222b": "\\int",
+ "\u222c": "\\iint",
+ "\u222d": "\\iiint",
+ "\u222e": "\\oint",
+ "\u222f": "\\oiint",
+ "\u2230": "\\oiiint"
+};
+
+// No limits, not symbols
+defineFunction({
+ type: "op",
+ names: ["\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th"],
+ numArgs: 0,
+ handler(_ref3) {
+ let parser = _ref3.parser,
+ funcName = _ref3.funcName;
+ return {
+ type: "op",
+ mode: parser.mode,
+ limits: false,
+ parentIsSupSub: false,
+ symbol: false,
+ name: funcName
+ };
+ }
+});
+
+// Limits, not symbols
+defineFunction({
+ type: "op",
+ names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"],
+ numArgs: 0,
+ handler(_ref4) {
+ let parser = _ref4.parser,
+ funcName = _ref4.funcName;
+ return {
+ type: "op",
+ mode: parser.mode,
+ limits: true,
+ parentIsSupSub: false,
+ symbol: false,
+ name: funcName
+ };
+ }
+});
+
+// No limits, symbols
+defineFunction({
+ type: "op",
+ names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"],
+ numArgs: 0,
+ allowedInArgument: true,
+ handler(_ref5) {
+ let parser = _ref5.parser,
+ funcName = _ref5.funcName;
+ let fName = funcName;
+ if (fName.length === 1) {
+ fName = singleCharIntegrals[fName];
+ }
+ return {
+ type: "op",
+ mode: parser.mode,
+ limits: false,
+ parentIsSupSub: false,
+ symbol: true,
+ name: fName
+ };
+ }
+});
+;// ./src/functions/operatorname.ts
+
+
+
+
+
+
+
+
+
+// NOTE: Unlike most `htmlBuilder`s, this one handles not only
+// "operatorname", but also "supsub" since \operatorname* can
+// affect super/subscripting.
+const operatorname_htmlBuilder = (grp, options) => {
+ // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
+ let supGroup;
+ let subGroup;
+ let hasLimits = false;
+ let group;
+ if (grp.type === "supsub") {
+ // If we have limits, supsub will pass us its group to handle. Pull
+ // out the superscript and subscript and set the group to the op in
+ // its base.
+ supGroup = grp.sup;
+ subGroup = grp.sub;
+ group = assertNodeType(grp.base, "operatorname");
+ hasLimits = true;
+ } else {
+ group = assertNodeType(grp, "operatorname");
+ }
+ let base;
+ if (group.body.length > 0) {
+ const body = group.body.map(child => {
+ const childText = "text" in child ? child.text : undefined;
+ if (typeof childText === "string") {
+ return {
+ type: "textord",
+ mode: child.mode,
+ text: childText
+ };
+ } else {
+ return child;
+ }
+ });
+
+ // Consolidate function names into symbol characters.
+ const expression = buildExpression(body, options.withFont("mathrm"), true);
+ for (let i = 0; i < expression.length; i++) {
+ const child = expression[i];
+ if (child instanceof SymbolNode) {
+ // Per amsopn package,
+ // change minus to hyphen and \ast to asterisk
+ child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
+ }
+ }
+ base = makeSpan(["mop"], expression, options);
+ } else {
+ base = makeSpan(["mop"], [], options);
+ }
+ if (hasLimits) {
+ return assembleSupSub(base, supGroup, subGroup, options, options.style, 0, 0);
+ } else {
+ return base;
+ }
+};
+const operatorname_mathmlBuilder = (group, options) => {
+ // The steps taken here are similar to the html version.
+ let expression = buildMathML_buildExpression(group.body, options.withFont("mathrm"));
+
+ // Is expression a string or has it something like a fraction?
+ let isAllString = true; // default
+ for (let i = 0; i < expression.length; i++) {
+ const node = expression[i];
+ if (node instanceof SpaceNode) {
+ // Do nothing
+ } else if (node instanceof MathNode) {
+ switch (node.type) {
+ case "mi":
+ case "mn":
+ case "mspace":
+ case "mtext":
+ break;
+ // Do nothing yet.
+ case "mo":
+ {
+ const child = node.children[0];
+ if (node.children.length === 1 && child instanceof TextNode) {
+ child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
+ } else {
+ isAllString = false;
+ }
+ break;
+ }
+ default:
+ isAllString = false;
+ }
+ } else {
+ isAllString = false;
+ }
+ }
+ if (isAllString) {
+ // Write a single TextNode instead of multiple nested tags.
+ const word = expression.map(node => node.toText()).join("");
+ expression = [new TextNode(word)];
+ }
+ const identifier = new MathNode("mi", expression);
+ identifier.setAttribute("mathvariant", "normal");
+
+ // \u2061 is the same as &ApplyFunction;
+ // ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp
+ const operator = new MathNode("mo", [makeText("\u2061", "text")]);
+ if (group.parentIsSupSub) {
+ return new MathNode("mrow", [identifier, operator]);
+ } else {
+ return newDocumentFragment([identifier, operator]);
+ }
+};
+
+// \operatorname
+// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
+defineFunction({
+ type: "operatorname",
+ names: ["\\operatorname@", "\\operatornamewithlimits"],
+ numArgs: 1,
+ handler: (_ref, args) => {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const body = args[0];
+ return {
+ type: "operatorname",
+ mode: parser.mode,
+ body: ordargument(body),
+ alwaysHandleSupSub: funcName === "\\operatornamewithlimits",
+ limits: false,
+ parentIsSupSub: false
+ };
+ },
+ htmlBuilder: operatorname_htmlBuilder,
+ mathmlBuilder: operatorname_mathmlBuilder
+});
+defineMacro("\\operatorname", "\\@ifstar\\operatornamewithlimits\\operatorname@");
+;// ./src/functions/ordgroup.ts
+
+
+
+
+defineFunctionBuilders({
+ type: "ordgroup",
+ htmlBuilder(group, options) {
+ if (group.semisimple) {
+ return makeFragment(buildExpression(group.body, options, false));
+ }
+ return makeSpan(["mord"], buildExpression(group.body, options, true), options);
+ },
+ mathmlBuilder(group, options) {
+ return buildExpressionRow(group.body, options, true);
+ }
+});
+;// ./src/functions/overline.ts
+
+
+
+
+
+defineFunction({
+ type: "overline",
+ names: ["\\overline"],
+ numArgs: 1,
+ handler(_ref, args) {
+ let parser = _ref.parser;
+ const body = args[0];
+ return {
+ type: "overline",
+ mode: parser.mode,
+ body
+ };
+ },
+ htmlBuilder(group, options) {
+ // Overlines are handled in the TeXbook pg 443, Rule 9.
+
+ // Build the inner group in the cramped style.
+ const innerGroup = buildGroup(group.body, options.havingCrampedStyle());
+
+ // Create the line above the body
+ const line = makeLineSpan("overline-line", options);
+
+ // Generate the vlist, with the appropriate kerns
+ const defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
+ const vlist = makeVList({
+ positionType: "firstBaseline",
+ children: [{
+ type: "elem",
+ elem: innerGroup
+ }, {
+ type: "kern",
+ size: 3 * defaultRuleThickness
+ }, {
+ type: "elem",
+ elem: line
+ }, {
+ type: "kern",
+ size: defaultRuleThickness
+ }]
+ }, options);
+ return makeSpan(["mord", "katex-overline"], [vlist], options);
+ },
+ mathmlBuilder(group, options) {
+ const operator = new MathNode("mo", [new TextNode("\u203e")]);
+ operator.setAttribute("stretchy", "true");
+ const node = new MathNode("mover", [buildMathML_buildGroup(group.body, options), operator]);
+ node.setAttribute("accent", "true");
+ return node;
+ }
+});
+;// ./src/functions/phantom.ts
+
+
+
+
+
+
+defineFunction({
+ type: "phantom",
+ names: ["\\phantom"],
+ numArgs: 1,
+ allowedInText: true,
+ handler: (_ref, args) => {
+ let parser = _ref.parser;
+ const body = args[0];
+ return {
+ type: "phantom",
+ mode: parser.mode,
+ body: ordargument(body)
+ };
+ },
+ htmlBuilder: (group, options) => {
+ const elements = buildExpression(group.body, options.withPhantom(), false);
+
+ // \phantom isn't supposed to affect the elements it contains.
+ // See "color" for more details.
+ return makeFragment(elements);
+ },
+ mathmlBuilder: (group, options) => {
+ const inner = buildMathML_buildExpression(group.body, options);
+ return new MathNode("mphantom", inner);
+ }
+});
+defineMacro("\\hphantom", "\\smash{\\phantom{#1}}");
+defineFunction({
+ type: "vphantom",
+ names: ["\\vphantom"],
+ numArgs: 1,
+ allowedInText: true,
+ handler: (_ref2, args) => {
+ let parser = _ref2.parser;
+ const body = args[0];
+ return {
+ type: "vphantom",
+ mode: parser.mode,
+ body
+ };
+ },
+ htmlBuilder: (group, options) => {
+ const inner = makeSpan(["katex-inner"], [buildGroup(group.body, options.withPhantom())]);
+ const fix = makeSpan(["katex-fix"], []);
+ return makeSpan(["mord", "rlap"], [inner, fix], options);
+ },
+ mathmlBuilder: (group, options) => {
+ const inner = buildMathML_buildExpression(ordargument(group.body), options);
+ const phantom = new MathNode("mphantom", inner);
+ const node = new MathNode("mpadded", [phantom]);
+ node.setAttribute("width", "0px");
+ return node;
+ }
+});
+;// ./src/functions/raisebox.ts
+
+
+
+
+
+
+
+
+// Box manipulation
+defineFunction({
+ type: "raisebox",
+ names: ["\\raisebox"],
+ numArgs: 2,
+ argTypes: ["size", "hbox"],
+ allowedInText: true,
+ handler(_ref, args) {
+ let parser = _ref.parser;
+ const amount = assertNodeType(args[0], "size").value;
+ const body = args[1];
+ return {
+ type: "raisebox",
+ mode: parser.mode,
+ dy: amount,
+ body
+ };
+ },
+ htmlBuilder(group, options) {
+ const body = buildGroup(group.body, options);
+ const dy = calculateSize(group.dy, options);
+ return makeVList({
+ positionType: "shift",
+ positionData: -dy,
+ children: [{
+ type: "elem",
+ elem: body
+ }]
+ }, options);
+ },
+ mathmlBuilder(group, options) {
+ const node = new MathNode("mpadded", [buildMathML_buildGroup(group.body, options)]);
+ const dy = group.dy.number + group.dy.unit;
+ node.setAttribute("voffset", dy);
+ return node;
+ }
+});
+;// ./src/functions/relax.ts
+
+defineFunction({
+ type: "internal",
+ names: ["\\relax"],
+ numArgs: 0,
+ allowedInText: true,
+ allowedInArgument: true,
+ handler(_ref) {
+ let parser = _ref.parser;
+ return {
+ type: "internal",
+ mode: parser.mode
+ };
+ }
+});
+;// ./src/functions/rule.ts
+
+
+
+
+
+defineFunction({
+ type: "rule",
+ names: ["\\rule"],
+ numArgs: 2,
+ numOptionalArgs: 1,
+ allowedInText: true,
+ allowedInMath: true,
+ argTypes: ["size", "size", "size"],
+ handler(_ref, args, optArgs) {
+ let parser = _ref.parser;
+ const shift = optArgs[0];
+ const width = assertNodeType(args[0], "size");
+ const height = assertNodeType(args[1], "size");
+ return {
+ type: "rule",
+ mode: parser.mode,
+ shift: shift && assertNodeType(shift, "size").value,
+ width: width.value,
+ height: height.value
+ };
+ },
+ htmlBuilder(group, options) {
+ // Make an empty span for the rule
+ const rule = makeSpan(["mord", "katex-rule"], [], options);
+
+ // Calculate the shift, width, and height of the rule, and account for units
+ const width = calculateSize(group.width, options);
+ const height = calculateSize(group.height, options);
+ const shift = group.shift ? calculateSize(group.shift, options) : 0;
+
+ // Style the rule to the right size
+ rule.style.borderRightWidth = makeEm(width);
+ rule.style.borderTopWidth = makeEm(height);
+ rule.style.bottom = makeEm(shift);
+
+ // Record the height and width
+ rule.width = width;
+ rule.height = height + shift;
+ rule.depth = -shift;
+ // Font size is the number large enough that the browser will
+ // reserve at least `absHeight` space above the baseline.
+ // The 1.125 factor was empirically determined
+ rule.maxFontSize = height * 1.125 * options.sizeMultiplier;
+ return rule;
+ },
+ mathmlBuilder(group, options) {
+ const width = calculateSize(group.width, options);
+ const height = calculateSize(group.height, options);
+ const shift = group.shift ? calculateSize(group.shift, options) : 0;
+ const color = options.color && options.getColor() || "black";
+ const rule = new MathNode("mspace");
+ rule.setAttribute("mathbackground", color);
+ rule.setAttribute("width", makeEm(width));
+ rule.setAttribute("height", makeEm(height));
+ const wrapper = new MathNode("mpadded", [rule]);
+ if (shift >= 0) {
+ wrapper.setAttribute("height", makeEm(shift));
+ } else {
+ wrapper.setAttribute("height", makeEm(shift));
+ wrapper.setAttribute("depth", makeEm(-shift));
+ }
+ wrapper.setAttribute("voffset", makeEm(shift));
+ return wrapper;
+ }
+});
+;// ./src/functions/sizing.ts
+
+
+
+
+
+
+function sizingGroup(value, options, baseOptions) {
+ const inner = buildExpression(value, options, false);
+ const multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier;
+
+ // Add size-resetting classes to the inner list and set maxFontSize
+ // manually. Handle nested size changes.
+ for (let i = 0; i < inner.length; i++) {
+ const pos = inner[i].classes.indexOf("katex-sizing");
+ if (pos < 0) {
+ Array.prototype.push.apply(inner[i].classes, options.sizingClasses(baseOptions));
+ } else if (inner[i].classes[pos + 1] === "reset-size" + options.size) {
+ // This is a nested size change: e.g., inner[i] is the "b" in
+ // `\Huge a \small b`. Override the old size (the `reset-` class)
+ // but not the new size.
+ inner[i].classes[pos + 1] = "reset-size" + baseOptions.size;
+ }
+ inner[i].height *= multiplier;
+ inner[i].depth *= multiplier;
+ }
+ return makeFragment(inner);
+}
+const sizeFuncs = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"];
+const sizing_htmlBuilder = (group, options) => {
+ // Handle sizing operators like \Huge. Real TeX doesn't actually allow
+ // these functions inside of math expressions, so we do some special
+ // handling.
+ const newOptions = options.havingSize(group.size);
+ return sizingGroup(group.body, newOptions, options);
+};
+defineFunction({
+ type: "sizing",
+ names: sizeFuncs,
+ numArgs: 0,
+ allowedInText: true,
+ handler: (_ref, args) => {
+ let breakOnTokenText = _ref.breakOnTokenText,
+ funcName = _ref.funcName,
+ parser = _ref.parser;
+ const body = parser.parseExpression(false, breakOnTokenText);
+ return {
+ type: "sizing",
+ mode: parser.mode,
+ // Figure out what size to use based on the list of functions above
+ size: sizeFuncs.indexOf(funcName) + 1,
+ body
+ };
+ },
+ htmlBuilder: sizing_htmlBuilder,
+ mathmlBuilder: (group, options) => {
+ const newOptions = options.havingSize(group.size);
+ const inner = buildMathML_buildExpression(group.body, newOptions);
+ const node = new MathNode("mstyle", inner);
+
+ // TODO(emily): This doesn't produce the correct size for nested size
+ // changes, because we don't keep state of what style we're currently
+ // in, so we can't reset the size to normal before changing it. Now
+ // that we're passing an options parameter we should be able to fix
+ // this.
+ node.setAttribute("mathsize", makeEm(newOptions.sizeMultiplier));
+ return node;
+ }
+});
+;// ./src/functions/smash.ts
+// smash, with optional [tb], as in AMS
+
+
+
+
+
+
+defineFunction({
+ type: "smash",
+ names: ["\\smash"],
+ numArgs: 1,
+ numOptionalArgs: 1,
+ allowedInText: true,
+ handler: (_ref, args, optArgs) => {
+ let parser = _ref.parser;
+ let smashHeight = false;
+ let smashDepth = false;
+ const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup");
+ if (tbArg) {
+ // Optional [tb] argument is engaged.
+ // ref: amsmath: \renewcommand{\smash}[1][tb]{%
+ // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
+ let letter;
+ for (let i = 0; i < tbArg.body.length; ++i) {
+ const node = tbArg.body[i];
+ letter = assertSymbolNodeType(node).text;
+ if (letter === "t") {
+ smashHeight = true;
+ } else if (letter === "b") {
+ smashDepth = true;
+ } else {
+ smashHeight = false;
+ smashDepth = false;
+ break;
+ }
+ }
+ } else {
+ smashHeight = true;
+ smashDepth = true;
+ }
+ const body = args[0];
+ return {
+ type: "smash",
+ mode: parser.mode,
+ body,
+ smashHeight,
+ smashDepth
+ };
+ },
+ htmlBuilder: (group, options) => {
+ const node = makeSpan([], [buildGroup(group.body, options)]);
+ if (!group.smashHeight && !group.smashDepth) {
+ return node;
+ }
+ if (group.smashHeight) {
+ node.height = 0;
+ }
+ if (group.smashDepth) {
+ node.depth = 0;
+ }
+ if (group.smashHeight && group.smashDepth) {
+ // Symmetric \smash can stay in inline layout.
+ return makeSpan(["mord", "katex-smash"], [node], options);
+ }
+
+ // In order to influence makeVList for asymmetric smashing, we have to
+ // reset the children.
+ if (node.children) {
+ for (let i = 0; i < node.children.length; i++) {
+ if (group.smashHeight) {
+ node.children[i].height = 0;
+ }
+ if (group.smashDepth) {
+ node.children[i].depth = 0;
+ }
+ }
+ }
+
+ // At this point, we've reset the TeX-like height and depth values.
+ // But the span still has an HTML line height.
+ // makeVList applies "display: table-cell", which prevents the browser
+ // from acting on that line height. So we'll call makeVList now.
+
+ const smashedNode = makeVList({
+ positionType: "firstBaseline",
+ children: [{
+ type: "elem",
+ elem: node
+ }]
+ }, options);
+
+ // For spacing, TeX treats \smash as a math group (same spacing as ord).
+ return makeSpan(["mord"], [smashedNode], options);
+ },
+ mathmlBuilder: (group, options) => {
+ const node = new MathNode("mpadded", [buildMathML_buildGroup(group.body, options)]);
+ if (group.smashHeight) {
+ node.setAttribute("height", "0px");
+ }
+ if (group.smashDepth) {
+ node.setAttribute("depth", "0px");
+ }
+ return node;
+ }
+});
+;// ./src/functions/sqrt.ts
+
+
+
+
+
+
+
+
+defineFunction({
+ type: "sqrt",
+ names: ["\\sqrt"],
+ numArgs: 1,
+ numOptionalArgs: 1,
+ handler(_ref, args, optArgs) {
+ let parser = _ref.parser;
+ const index = optArgs[0];
+ const body = args[0];
+ return {
+ type: "sqrt",
+ mode: parser.mode,
+ body,
+ index
+ };
+ },
+ htmlBuilder(group, options) {
+ // Square roots are handled in the TeXbook pg. 443, Rule 11.
+
+ // First, we do the same steps as in overline to build the inner group
+ // and line
+ let inner = buildGroup(group.body, options.havingCrampedStyle());
+ if (inner.height === 0) {
+ // Render a small surd.
+ inner.height = options.fontMetrics().xHeight;
+ }
+
+ // Some groups can return document fragments. Handle those by wrapping
+ // them in a span.
+ inner = wrapFragment(inner, options);
+
+ // Calculate the minimum size for the \surd delimiter
+ const metrics = options.fontMetrics();
+ const theta = metrics.defaultRuleThickness;
+ let phi = theta;
+ if (options.style.id < src_Style.TEXT.id) {
+ phi = options.fontMetrics().xHeight;
+ }
+
+ // Calculate the clearance between the body and line
+ let lineClearance = theta + phi / 4;
+ const minDelimiterHeight = inner.height + inner.depth + lineClearance + theta;
+
+ // Create a sqrt SVG of the required minimum size
+ const _makeSqrtImage = makeSqrtImage(minDelimiterHeight, options),
+ img = _makeSqrtImage.span,
+ ruleWidth = _makeSqrtImage.ruleWidth,
+ advanceWidth = _makeSqrtImage.advanceWidth;
+ const delimDepth = img.height - ruleWidth;
+
+ // Adjust the clearance based on the delimiter size
+ if (delimDepth > inner.height + inner.depth + lineClearance) {
+ lineClearance = (lineClearance + delimDepth - inner.height - inner.depth) / 2;
+ }
+
+ // Shift the sqrt image
+ const imgShift = img.height - inner.height - lineClearance - ruleWidth;
+ inner.style.paddingLeft = makeEm(advanceWidth);
+
+ // Overlay the image and the argument.
+ const body = makeVList({
+ positionType: "firstBaseline",
+ children: [{
+ type: "elem",
+ elem: inner,
+ wrapperClasses: ["svg-align"]
+ }, {
+ type: "kern",
+ size: -(inner.height + imgShift)
+ }, {
+ type: "elem",
+ elem: img
+ }, {
+ type: "kern",
+ size: ruleWidth
+ }]
+ }, options);
+ if (!group.index) {
+ return makeSpan(["mord", "sqrt"], [body], options);
+ } else {
+ // Handle the optional root index
+
+ // The index is always in scriptscript style
+ const newOptions = options.havingStyle(src_Style.SCRIPTSCRIPT);
+ const rootm = buildGroup(group.index, newOptions, options);
+
+ // The amount the index is shifted by. This is taken from the TeX
+ // source, in the definition of `\r@@t`.
+ const toShift = 0.6 * (body.height - body.depth);
+
+ // Build a VList with the superscript shifted up correctly
+ const rootVList = makeVList({
+ positionType: "shift",
+ positionData: -toShift,
+ children: [{
+ type: "elem",
+ elem: rootm
+ }]
+ }, options);
+ // Add a class surrounding it so we can add on the appropriate
+ // kerning
+ const rootVListWrap = makeSpan(["katex-root"], [rootVList]);
+ return makeSpan(["mord", "sqrt"], [rootVListWrap, body], options);
+ }
+ },
+ mathmlBuilder(group, options) {
+ const body = group.body,
+ index = group.index;
+ return index ? new MathNode("mroot", [buildMathML_buildGroup(body, options), buildMathML_buildGroup(index, options)]) : new MathNode("msqrt", [buildMathML_buildGroup(body, options)]);
+ }
+});
+;// ./src/functions/styling.ts
+
+
+
+
+
+const styling_styleMap = {
+ "display": src_Style.DISPLAY,
+ "text": src_Style.TEXT,
+ "script": src_Style.SCRIPT,
+ "scriptscript": src_Style.SCRIPTSCRIPT
+};
+function isStyleStr(s) {
+ return s in styling_styleMap;
+}
+defineFunction({
+ type: "styling",
+ names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"],
+ numArgs: 0,
+ allowedInText: true,
+ primitive: true,
+ handler(_ref, args) {
+ let breakOnTokenText = _ref.breakOnTokenText,
+ funcName = _ref.funcName,
+ parser = _ref.parser;
+ // parse out the implicit body
+ const body = parser.parseExpression(true, breakOnTokenText);
+
+ // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g.
+ // here and in buildHTML and de-dupe the enumeration of all the styles).
+ const style = funcName.slice(1, funcName.length - 5);
+ if (!isStyleStr(style)) {
+ throw new Error("Unknown style: " + style);
+ }
+ return {
+ type: "styling",
+ mode: parser.mode,
+ // Figure out what style to use by pulling out the style from
+ // the function name
+ style,
+ body
+ };
+ },
+ htmlBuilder(group, options) {
+ // Style changes are handled in the TeXbook on pg. 442, Rule 3.
+ const newStyle = styling_styleMap[group.style];
+ let newOptions = options.havingStyle(newStyle);
+ if (group.resetFont) {
+ newOptions = newOptions.withFont('');
+ }
+ return sizingGroup(group.body, newOptions, options);
+ },
+ mathmlBuilder(group, options) {
+ // Figure out what style we're changing to.
+ const newStyle = styling_styleMap[group.style];
+ let newOptions = options.havingStyle(newStyle);
+ if (group.resetFont) {
+ newOptions = newOptions.withFont('');
+ }
+ const inner = buildMathML_buildExpression(group.body, newOptions);
+ const node = new MathNode("mstyle", inner);
+ const styleAttributes = {
+ "display": ["0", "true"],
+ "text": ["0", "false"],
+ "script": ["1", "false"],
+ "scriptscript": ["2", "false"]
+ };
+ const attr = styleAttributes[group.style];
+ node.setAttribute("scriptlevel", attr[0]);
+ node.setAttribute("displaystyle", attr[1]);
+ return node;
+ }
+});
+;// ./src/functions/supsub.ts
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**
+ * Sometimes, groups perform special rules when they have superscripts or
+ * subscripts attached to them. This function lets the `supsub` group know that
+ * Sometimes, groups perform special rules when they have superscripts or
+ * its inner element should handle the superscripts and subscripts instead of
+ * handling them itself.
+ */
+const htmlBuilderDelegate = function (group, options
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+) {
+ const base = group.base;
+ if (!base) {
+ return null;
+ } else if (base.type === "op") {
+ // Operators handle supsubs differently when they have limits
+ // (e.g. `\displaystyle\sum_2^3`)
+ const delegate = base.limits && (options.style.size === src_Style.DISPLAY.size || base.alwaysHandleSupSub);
+ return delegate ? op_htmlBuilder : null;
+ } else if (base.type === "operatorname") {
+ const delegate = base.alwaysHandleSupSub && (options.style.size === src_Style.DISPLAY.size || base.limits);
+ return delegate ? operatorname_htmlBuilder : null;
+ } else if (base.type === "accent") {
+ return isCharacterBox(base.base) ? htmlBuilder : null;
+ } else if (base.type === "horizBrace") {
+ const isSup = !group.sub;
+ return isSup === base.isOver ? horizBrace_htmlBuilder : null;
+ } else {
+ return null;
+ }
+};
+
+// Super scripts and subscripts, whose precise placement can depend on other
+// functions that precede them.
+defineFunctionBuilders({
+ type: "supsub",
+ htmlBuilder(group, options) {
+ // Superscript and subscripts are handled in the TeXbook on page
+ // 445-446, rules 18(a-f).
+
+ // Here is where we defer to the inner group if it should handle
+ // superscripts and subscripts itself.
+ const builderDelegate = htmlBuilderDelegate(group, options);
+ if (builderDelegate) {
+ return builderDelegate(group, options);
+ }
+ const valueBase = group.base,
+ valueSup = group.sup,
+ valueSub = group.sub;
+ const base = buildGroup(valueBase, options);
+ let supm;
+ let subm;
+ const metrics = options.fontMetrics();
+
+ // Rule 18a
+ let supShift = 0;
+ let subShift = 0;
+ const isCharBox = valueBase && isCharacterBox(valueBase);
+ if (valueSup) {
+ const newOptions = options.havingStyle(options.style.sup());
+ supm = buildGroup(valueSup, newOptions, options);
+ if (!isCharBox) {
+ supShift = base.height - newOptions.fontMetrics().supDrop * newOptions.sizeMultiplier / options.sizeMultiplier;
+ }
+ }
+ if (valueSub) {
+ const newOptions = options.havingStyle(options.style.sub());
+ subm = buildGroup(valueSub, newOptions, options);
+ if (!isCharBox) {
+ subShift = base.depth + newOptions.fontMetrics().subDrop * newOptions.sizeMultiplier / options.sizeMultiplier;
+ }
+ }
+
+ // Rule 18c
+ let minSupShift;
+ if (options.style === src_Style.DISPLAY) {
+ minSupShift = metrics.sup1;
+ } else if (options.style.cramped) {
+ minSupShift = metrics.sup3;
+ } else {
+ minSupShift = metrics.sup2;
+ }
+
+ // scriptspace is a font-size-independent size, so scale it
+ // appropriately for use as the marginRight.
+ const multiplier = options.sizeMultiplier;
+ const marginRight = makeEm(0.5 / metrics.ptPerEm / multiplier);
+ let marginLeft = null;
+ if (subm) {
+ // Subscripts shouldn't be shifted by the base's italic correction.
+ // Account for that by shifting the subscript back the appropriate
+ // amount. Note we only do this when the base is a single symbol.
+ const isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint");
+ if (base instanceof SymbolNode || isOiint) {
+ var _italic;
+ // SymbolNode has .italic natively; for \oiint/\oiiint the
+ // op builder stores .italic on the wrapping Span.
+ marginLeft = makeEm(-((_italic = base.italic) != null ? _italic : 0));
+ }
+ }
+ let supsub;
+ if (supm && subm) {
+ supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
+ subShift = Math.max(subShift, metrics.sub2);
+ const ruleWidth = metrics.defaultRuleThickness;
+
+ // Rule 18e
+ const maxWidth = 4 * ruleWidth;
+ if (supShift - supm.depth - (subm.height - subShift) < maxWidth) {
+ subShift = maxWidth - (supShift - supm.depth) + subm.height;
+ const psi = 0.8 * metrics.xHeight - (supShift - supm.depth);
+ if (psi > 0) {
+ supShift += psi;
+ subShift -= psi;
+ }
+ }
+ const vlistElem = [{
+ type: "elem",
+ elem: subm,
+ shift: subShift,
+ marginRight,
+ marginLeft
+ }, {
+ type: "elem",
+ elem: supm,
+ shift: -supShift,
+ marginRight
+ }];
+ supsub = makeVList({
+ positionType: "individualShift",
+ children: vlistElem
+ }, options);
+ } else if (subm) {
+ // Rule 18b
+ subShift = Math.max(subShift, metrics.sub1, subm.height - 0.8 * metrics.xHeight);
+ const vlistElem = [{
+ type: "elem",
+ elem: subm,
+ marginLeft,
+ marginRight
+ }];
+ supsub = makeVList({
+ positionType: "shift",
+ positionData: subShift,
+ children: vlistElem
+ }, options);
+ } else if (supm) {
+ // Rule 18c, d
+ supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
+ supsub = makeVList({
+ positionType: "shift",
+ positionData: -supShift,
+ children: [{
+ type: "elem",
+ elem: supm,
+ marginRight
+ }]
+ }, options);
+ } else {
+ throw new Error("supsub must have either sup or sub.");
+ }
+
+ // Wrap the supsub vlist in a span.msupsub to reset text-align.
+ const mclass = getTypeOfDomTree(base, "right") || "mord";
+ return makeSpan([mclass], [base, makeSpan(["msupsub"], [supsub])], options);
+ },
+ mathmlBuilder(group, options) {
+ // Is the inner group a relevant horizontal brace?
+ let isBrace = false;
+ let isOver;
+ let isSup;
+ if (group.base && group.base.type === "horizBrace") {
+ isSup = !!group.sup;
+ if (isSup === group.base.isOver) {
+ isBrace = true;
+ isOver = group.base.isOver;
+ }
+ }
+ if (group.base && (group.base.type === "op" || group.base.type === "operatorname")) {
+ group.base.parentIsSupSub = true;
+ }
+ const children = [buildMathML_buildGroup(group.base, options)];
+ if (group.sub) {
+ children.push(buildMathML_buildGroup(group.sub, options));
+ }
+ if (group.sup) {
+ children.push(buildMathML_buildGroup(group.sup, options));
+ }
+ let nodeType;
+ if (isBrace) {
+ nodeType = isOver ? "mover" : "munder";
+ } else if (!group.sub) {
+ const base = group.base;
+ if (base && base.type === "op" && base.limits && (options.style === src_Style.DISPLAY || base.alwaysHandleSupSub)) {
+ nodeType = "mover";
+ } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === src_Style.DISPLAY)) {
+ nodeType = "mover";
+ } else {
+ nodeType = "msup";
+ }
+ } else if (!group.sup) {
+ const base = group.base;
+ if (base && base.type === "op" && base.limits && (options.style === src_Style.DISPLAY || base.alwaysHandleSupSub)) {
+ nodeType = "munder";
+ } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === src_Style.DISPLAY)) {
+ nodeType = "munder";
+ } else {
+ nodeType = "msub";
+ }
+ } else {
+ const base = group.base;
+ if (base && base.type === "op" && base.limits && options.style === src_Style.DISPLAY) {
+ nodeType = "munderover";
+ } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (options.style === src_Style.DISPLAY || base.limits)) {
+ nodeType = "munderover";
+ } else {
+ nodeType = "msubsup";
+ }
+ }
+ return new MathNode(nodeType, children);
+ }
+});
+;// ./src/functions/symbolsOp.ts
+
+
+
+
+
+// Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js.
+
+defineFunctionBuilders({
+ type: "atom",
+ htmlBuilder(group, options) {
+ return mathsym(group.text, group.mode, options, ["m" + group.family]);
+ },
+ mathmlBuilder(group, options) {
+ const node = new MathNode("mo", [makeText(group.text, group.mode)]);
+ if (group.family === "bin") {
+ const variant = getVariant(group, options);
+ if (variant === "bold-italic") {
+ node.setAttribute("mathvariant", variant);
+ }
+ } else if (group.family === "punct") {
+ node.setAttribute("separator", "true");
+ } else if (group.family === "open" || group.family === "close") {
+ // Delims built here should not stretch vertically.
+ // See delimsizing.js for stretchy delims.
+ node.setAttribute("stretchy", "false");
+ }
+ return node;
+ }
+});
+;// ./src/functions/symbolsOrd.ts
+
+
+
+
+// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in
+// src/symbols.js.
+
+const defaultVariant = {
+ "mi": "italic",
+ "mn": "normal",
+ "mtext": "normal"
+};
+defineFunctionBuilders({
+ type: "mathord",
+ htmlBuilder(group, options) {
+ return makeOrd(group, options);
+ },
+ mathmlBuilder(group, options) {
+ const node = new MathNode("mi", [makeText(group.text, group.mode, options)]);
+ const variant = getVariant(group, options) || "italic";
+ if (variant !== defaultVariant[node.type]) {
+ node.setAttribute("mathvariant", variant);
+ }
+ return node;
+ }
+});
+defineFunctionBuilders({
+ type: "textord",
+ htmlBuilder(group, options) {
+ return makeOrd(group, options);
+ },
+ mathmlBuilder(group, options) {
+ const text = makeText(group.text, group.mode, options);
+ const variant = getVariant(group, options) || "normal";
+ let node;
+ if (group.mode === 'text') {
+ node = new MathNode("mtext", [text]);
+ } else if (/[0-9]/.test(group.text)) {
+ node = new MathNode("mn", [text]);
+ } else if (group.text === "\\prime") {
+ node = new MathNode("mo", [text]);
+ } else {
+ node = new MathNode("mi", [text]);
+ }
+ if (variant !== defaultVariant[node.type]) {
+ node.setAttribute("mathvariant", variant);
+ }
+ return node;
+ }
+});
+;// ./src/functions/symbolsSpacing.ts
+
+
+
+
+
+// A map of CSS-based spacing functions to their CSS class.
+const cssSpace = new Map([["\\nobreak", "nobreak"], ["\\allowbreak", "allowbreak"]]);
+
+// A lookup table to determine whether a spacing function/symbol should be
+// treated like a regular space character. If a symbol or command is a key
+// in this table, then it should be a regular space character. Furthermore,
+// the associated value may have a `className` specifying an extra CSS class
+// to add to the created `span`.
+const regularSpace = new Map([[" ", {}], ["\\ ", {}], ["~", {
+ className: "nobreak"
+}], ["\\space", {}], ["\\nobreakspace", {
+ className: "nobreak"
+}]]);
+
+// ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in
+// src/symbols.js.
+defineFunctionBuilders({
+ type: "spacing",
+ htmlBuilder(group, options) {
+ const regularSpaceItem = regularSpace.get(group.text);
+ const cssSpaceClass = cssSpace.get(group.text);
+ if (regularSpaceItem) {
+ const className = regularSpaceItem.className || "";
+ // Spaces are generated by adding an actual space. Each of these
+ // things has an entry in the symbols table, so these will be turned
+ // into appropriate outputs.
+ if (group.mode === "text") {
+ const ord = makeOrd(group, options);
+ ord.classes.push(className);
+ return ord;
+ } else {
+ return makeSpan(["mspace", className], [mathsym(group.text, group.mode, options)], options);
+ }
+ } else if (cssSpaceClass) {
+ // Spaces based on just a CSS class.
+ return makeSpan(["mspace", cssSpaceClass], [], options);
+ } else {
+ throw new src_ParseError("Unknown type of space \"" + group.text + "\"");
+ }
+ },
+ mathmlBuilder(group, options) {
+ let node;
+ if (regularSpace.has(group.text)) {
+ node = new MathNode("mtext", [new TextNode("\u00a0")]);
+ } else if (cssSpace.has(group.text)) {
+ // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored
+ return new MathNode("mspace");
+ } else {
+ throw new src_ParseError("Unknown type of space \"" + group.text + "\"");
+ }
+ return node;
+ }
+});
+;// ./src/functions/tag.ts
+
+
+
+const pad = () => {
+ const padNode = new MathNode("mtd", []);
+ padNode.setAttribute("width", "50%");
+ return padNode;
+};
+defineFunctionBuilders({
+ type: "tag",
+ mathmlBuilder(group, options) {
+ const table = new MathNode("mtable", [new MathNode("mtr", [pad(), new MathNode("mtd", [buildExpressionRow(group.body, options)]), pad(), new MathNode("mtd", [buildExpressionRow(group.tag, options)])])]);
+ table.setAttribute("width", "100%");
+ return table;
+
+ // TODO: Left-aligned tags.
+ // Currently, the group and options passed here do not contain
+ // enough info to set tag alignment. `leqno` is in Settings but it is
+ // not passed to Options. On the HTML side, leqno is
+ // set by a CSS class applied in buildTree.js. That would have worked
+ // in MathML if browsers supported <mlabeledtr>. Since they don't, we
+ // need to rewrite the way this function is called.
+ }
+});
+;// ./src/functions/text.ts
+
+
+
+
+// Non-mathy text, possibly in a font
+const textFontFamilies = {
+ "\\text": undefined,
+ "\\textrm": "textrm",
+ "\\textsf": "textsf",
+ "\\texttt": "texttt",
+ "\\textnormal": "textrm"
+};
+const textFontWeights = {
+ "\\textbf": "textbf",
+ "\\textmd": "textmd"
+};
+const textFontShapes = {
+ "\\textit": "textit",
+ "\\textup": "textup"
+};
+const optionsWithFont = (group, options) => {
+ const font = group.font;
+ // Checks if the argument is a font family or a font style.
+ if (!font) {
+ return options;
+ } else if (textFontFamilies[font]) {
+ return options.withTextFontFamily(textFontFamilies[font]);
+ } else if (textFontWeights[font]) {
+ return options.withTextFontWeight(textFontWeights[font]);
+ } else if (font === "\\emph") {
+ return options.fontShape === "textit" ? options.withTextFontShape("textup") : options.withTextFontShape("textit");
+ }
+ return options.withTextFontShape(textFontShapes[font]);
+};
+defineFunction({
+ type: "text",
+ names: [
+ // Font families
+ "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal",
+ // Font weights
+ "\\textbf", "\\textmd",
+ // Font Shapes
+ "\\textit", "\\textup", "\\emph"],
+ numArgs: 1,
+ argTypes: ["text"],
+ allowedInArgument: true,
+ allowedInText: true,
+ handler(_ref, args) {
+ let parser = _ref.parser,
+ funcName = _ref.funcName;
+ const body = args[0];
+ return {
+ type: "text",
+ mode: parser.mode,
+ body: ordargument(body),
+ font: funcName
+ };
+ },
+ htmlBuilder(group, options) {
+ const newOptions = optionsWithFont(group, options);
+ const inner = buildExpression(group.body, newOptions, true);
+ return makeSpan(["mord", "text"], inner, newOptions);
+ },
+ mathmlBuilder(group, options) {
+ const newOptions = optionsWithFont(group, options);
+ return buildExpressionRow(group.body, newOptions);
+ }
+});
+;// ./src/functions/underline.ts
+
+
+
+
+
+defineFunction({
+ type: "underline",
+ names: ["\\underline"],
+ numArgs: 1,
+ allowedInText: true,
+ handler(_ref, args) {
+ let parser = _ref.parser;
+ return {
+ type: "underline",
+ mode: parser.mode,
+ body: args[0]
+ };
+ },
+ htmlBuilder(group, options) {
+ // Underlines are handled in the TeXbook pg 443, Rule 10.
+ // Build the inner group.
+ const innerGroup = buildGroup(group.body, options);
+
+ // Create the line to go below the body
+ const line = makeLineSpan("underline-line", options);
+
+ // Generate the vlist, with the appropriate kerns
+ const defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
+ const vlist = makeVList({
+ positionType: "top",
+ positionData: innerGroup.height,
+ children: [{
+ type: "kern",
+ size: defaultRuleThickness
+ }, {
+ type: "elem",
+ elem: line
+ }, {
+ type: "kern",
+ size: 3 * defaultRuleThickness
+ }, {
+ type: "elem",
+ elem: innerGroup
+ }]
+ }, options);
+ return makeSpan(["mord", "katex-underline"], [vlist], options);
+ },
+ mathmlBuilder(group, options) {
+ const operator = new MathNode("mo", [new TextNode("\u203e")]);
+ operator.setAttribute("stretchy", "true");
+ const node = new MathNode("munder", [buildMathML_buildGroup(group.body, options), operator]);
+ node.setAttribute("accentunder", "true");
+ return node;
+ }
+});
+;// ./src/functions/vcenter.ts
+
+
+
+
+
+
+// \vcenter: Vertically center the argument group on the math axis.
+
+defineFunction({
+ type: "vcenter",
+ names: ["\\vcenter"],
+ numArgs: 1,
+ argTypes: ["original"],
+ // In LaTeX, \vcenter can act only on a box.
+ allowedInText: false,
+ handler(_ref, args) {
+ let parser = _ref.parser;
+ return {
+ type: "vcenter",
+ mode: parser.mode,
+ body: args[0]
+ };
+ },
+ htmlBuilder(group, options) {
+ const body = buildGroup(group.body, options);
+ const axisHeight = options.fontMetrics().axisHeight;
+ const dy = 0.5 * (body.height - axisHeight - (body.depth + axisHeight));
+ return makeVList({
+ positionType: "shift",
+ positionData: dy,
+ children: [{
+ type: "elem",
+ elem: body
+ }]
+ }, options);
+ },
+ mathmlBuilder(group, options) {
+ // There is no way to do this in MathML.
+ // Write a class as a breadcrumb in case some post-processor wants
+ // to perform a vcenter adjustment.
+ // Wrap in mrow to ensure valid MathML when placed inside mo (e.g., \mathrel)
+ const mpadded = new MathNode("mpadded", [buildMathML_buildGroup(group.body, options)], ["vcenter"]);
+ return new MathNode("mrow", [mpadded]);
+ }
+});
+;// ./src/functions/verb.ts
+
+
+
+
+defineFunction({
+ type: "verb",
+ names: ["\\verb"],
+ numArgs: 0,
+ allowedInText: true,
+ handler(context, args, optArgs) {
+ // \verb and \verb* are dealt with directly in Parser.js.
+ // If we end up here, it's because of a failure to match the two delimiters
+ // in the regex in Lexer.js. LaTeX raises the following error when \verb is
+ // terminated by end of line (or file).
+ throw new src_ParseError("\\verb ended by end of line instead of matching delimiter");
+ },
+ htmlBuilder(group, options) {
+ const text = makeVerb(group);
+ const body = [];
+ // \verb enters text mode and therefore is sized like \textstyle
+ const newOptions = options.havingStyle(options.style.text());
+ for (let i = 0; i < text.length; i++) {
+ let c = text[i];
+ if (c === '~') {
+ c = '\\textasciitilde';
+ }
+ body.push(makeSymbol(c, "Typewriter-Regular", group.mode, newOptions, ["mord", "texttt"]));
+ }
+ return makeSpan(["mord", "text"].concat(newOptions.sizingClasses(options)), tryCombineChars(body), newOptions);
+ },
+ mathmlBuilder(group, options) {
+ const text = new TextNode(makeVerb(group));
+ const node = new MathNode("mtext", [text]);
+ node.setAttribute("mathvariant", "monospace");
+ return node;
+ }
+});
+
+/**
+ * Converts verb group into body string.
+ *
+ * \verb* replaces each space with an open box \u2423
+ * \verb replaces each space with a no-break space \xA0
+ */
+const makeVerb = group => group.body.replace(/ /g, group.star ? '\u2423' : '\xA0');
+;// ./src/functions.ts
+/** Include this to ensure that all functions are defined. */
+
+const functions = _functions;
+/* harmony default export */ var src_functions = (functions);
+
+// TODO(kevinb): have functions return an object and call defineFunction with
+// that object in this file instead of relying on side-effects.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+;// ./src/Lexer.ts
+/**
+ * The Lexer class handles tokenizing the input in various ways. Since our
+ * parser expects us to be able to backtrack, the lexer allows lexing from any
+ * given starting point.
+ *
+ * Its main exposed function is the `lex` function, which takes a position to
+ * lex from and a type of token to lex. It defers to the appropriate `_innerLex`
+ * function.
+ *
+ * The various `_innerLex` functions perform the actual lexing of different
+ * kinds.
+ */
+
+
+
+
+/* The following tokenRegex
+ * - matches typical whitespace (but not NBSP etc.) using its first group
+ * - does not match any control character \x00-\x1f except whitespace
+ * - does not match a bare backslash
+ * - matches any ASCII character except those just mentioned
+ * - does not match the BMP private use area \uE000-\uF8FF
+ * - does not match bare surrogate code units
+ * - matches any BMP character except for those just described
+ * - matches any valid Unicode surrogate pair
+ * - matches a backslash followed by one or more whitespace characters
+ * - matches a backslash followed by one or more letters then whitespace
+ * - matches a backslash followed by any BMP character
+ * Capturing groups:
+ * [1] regular whitespace
+ * [2] backslash followed by whitespace
+ * [3] anything else, which may include:
+ * [4] left character of \verb*
+ * [5] left character of \verb
+ * [6] backslash followed by word, excluding any trailing whitespace
+ * Just because the Lexer matches something doesn't mean it's valid input:
+ * If there is no matching function or symbol definition, the Parser will
+ * still reject the input.
+ */
+const spaceRegexString = "[ \r\n\t]";
+const controlWordRegexString = "\\\\[a-zA-Z@]+";
+const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]";
+const controlWordWhitespaceRegexString = "(" + controlWordRegexString + ")" + spaceRegexString + "*";
+const controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*";
+const combiningDiacriticalMarkString = "[\u0300-\u036f]";
+const combiningDiacriticalMarksEndRegex = new RegExp(combiningDiacriticalMarkString + "+$");
+const tokenRegexString = "(" + spaceRegexString + "+)|" + (// whitespace
+controlSpaceRegexString + "|") +
+// \whitespace
+"([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + (// single codepoint
+combiningDiacriticalMarkString + "*") +
+// ...plus accents
+"|[\uD800-\uDBFF][\uDC00-\uDFFF]" + (// surrogate pair
+combiningDiacriticalMarkString + "*") +
+// ...plus accents
+"|\\\\verb\\*([^]).*?\\4" +
+// \verb*
+"|\\\\verb([^*a-zA-Z]).*?\\5" + (// \verb unstarred
+"|" + controlWordWhitespaceRegexString) + (// \macroName + spaces
+"|" + controlSymbolRegexString + ")"); // \\, \', etc.
+
+/** Main Lexer class */
+class Lexer {
+ constructor(input, settings) {
+ this.input = void 0;
+ this.settings = void 0;
+ this.tokenRegex = void 0;
+ // Category codes. The lexer only supports comment characters (14) for now.
+ // MacroExpander additionally distinguishes active (13).
+ this.catcodes = void 0;
+ // Separate accents from characters
+ this.input = input;
+ this.settings = settings;
+ this.tokenRegex = new RegExp(tokenRegexString, 'g');
+ this.catcodes = {
+ "%": 14,
+ // comment character
+ "~": 13 // active character
+ };
+ }
+ setCatcode(char, code) {
+ this.catcodes[char] = code;
+ }
+
+ /**
+ * This function lexes a single token.
+ */
+ lex() {
+ const input = this.input;
+ const pos = this.tokenRegex.lastIndex;
+ if (pos === input.length) {
+ return new Token("EOF", new SourceLocation(this, pos, pos));
+ }
+ const match = this.tokenRegex.exec(input);
+ if (match === null || match.index !== pos) {
+ throw new src_ParseError("Unexpected character: '" + input[pos] + "'", new Token(input[pos], new SourceLocation(this, pos, pos + 1)));
+ }
+ const text = match[6] || match[3] || (match[2] ? "\\ " : " ");
+ if (this.catcodes[text] === 14) {
+ // comment character
+ const nlIndex = input.indexOf('\n', this.tokenRegex.lastIndex);
+ if (nlIndex === -1) {
+ this.tokenRegex.lastIndex = input.length; // EOF
+ this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would " + "fail because of commenting the end of math mode (e.g. $)");
+ } else {
+ this.tokenRegex.lastIndex = nlIndex + 1;
+ }
+ return this.lex();
+ }
+ return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex));
+ }
+}
+;// ./src/Namespace.ts
+/**
+ * A `Namespace` refers to a space of nameable things like macros or lengths,
+ * which can be `set` either globally or local to a nested group, using an
+ * undo stack similar to how TeX implements this functionality.
+ * Performance-wise, `get` and local `set` take constant time, while global
+ * `set` takes time proportional to the depth of group nesting.
+ */
+
+
+class Namespace {
+ /**
+ * Both arguments are optional. The first argument is an object of
+ * built-in mappings which never change. The second argument is an object
+ * of initial (global-level) mappings, which will constantly change
+ * according to any global/top-level `set`s done.
+ */
+ constructor(builtins, globalMacros) {
+ if (builtins === void 0) {
+ builtins = {};
+ }
+ if (globalMacros === void 0) {
+ globalMacros = {};
+ }
+ this.current = void 0;
+ this.builtins = void 0;
+ this.undefStack = void 0;
+ this.current = globalMacros;
+ this.builtins = builtins;
+ this.undefStack = [];
+ }
+
+ /**
+ * Start a new nested group, affecting future local `set`s.
+ */
+ beginGroup() {
+ this.undefStack.push({});
+ }
+
+ /**
+ * End current nested group, restoring values before the group began.
+ */
+ endGroup() {
+ if (this.undefStack.length === 0) {
+ throw new src_ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug");
+ }
+ const undefs = this.undefStack.pop();
+ for (const key of Object.keys(undefs)) {
+ if (undefs[key] === undefined) {
+ delete this.current[key];
+ } else {
+ this.current[key] = undefs[key];
+ }
+ }
+ }
+
+ /**
+ * Ends all currently nested groups (if any), restoring values before the
+ * groups began. Useful in case of an error in the middle of parsing.
+ */
+ endGroups() {
+ while (this.undefStack.length > 0) {
+ this.endGroup();
+ }
+ }
+
+ /**
+ * Detect whether `name` has a definition. Equivalent to
+ * `get(name) != null`.
+ */
+ has(name) {
+ return Object.prototype.hasOwnProperty.call(this.current, name) || Object.prototype.hasOwnProperty.call(this.builtins, name);
+ }
+
+ /**
+ * Get the current value of a name, or `undefined` if there is no value.
+ *
+ * Note: Do not use `if (namespace.get(...))` to detect whether a macro
+ * is defined, as the definition may be the empty string which evaluates
+ * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or
+ * `if (namespace.has(...))`.
+ */
+ get(name) {
+ if (Object.prototype.hasOwnProperty.call(this.current, name)) {
+ return this.current[name];
+ } else if (Object.prototype.hasOwnProperty.call(this.builtins, name)) {
+ return this.builtins[name];
+ } else {
+ return undefined;
+ }
+ }
+
+ /**
+ * Set the current value of a name, and optionally set it globally too.
+ * Local set() sets the current value and (when appropriate) adds an undo
+ * operation to the undo stack. Global set() may change the undo
+ * operation at every level, so takes time linear in their number.
+ * A value of undefined means to delete existing definitions.
+ */
+ set(name, value, global) {
+ if (global === void 0) {
+ global = false;
+ }
+ if (global) {
+ // Global set is equivalent to setting in all groups. Simulate this
+ // by destroying any undos currently scheduled for this name,
+ // and adding an undo with the *new* value (in case it later gets
+ // locally reset within this environment).
+ for (let i = 0; i < this.undefStack.length; i++) {
+ delete this.undefStack[i][name];
+ }
+ if (this.undefStack.length > 0) {
+ this.undefStack[this.undefStack.length - 1][name] = value;
+ }
+ } else {
+ // Undo this set at end of this group (possibly to `undefined`),
+ // unless an undo is already in place, in which case that older
+ // value is the correct one.
+ const top = this.undefStack[this.undefStack.length - 1];
+ if (top && !Object.prototype.hasOwnProperty.call(top, name)) {
+ top[name] = Object.prototype.hasOwnProperty.call(this.current, name) ? this.current[name] : undefined;
+ }
+ }
+ if (value == null) {
+ delete this.current[name];
+ } else {
+ this.current[name] = value;
+ }
+ }
+}
+;// ./src/macros.ts
+/**
+ * Predefined macros for KaTeX.
+ * This can be used to define some commands in terms of others.
+ */
+
+// Export global macros object from defineMacro
+
+const macros = _macros;
+/* harmony default export */ var src_macros = (macros);
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////
+// macro tools
+
+defineMacro("\\noexpand", function (context) {
+ // The expansion is the token itself; but that token is interpreted
+ // as if its meaning were ‘\relax’ if it is a control sequence that
+ // would ordinarily be expanded by TeX’s expansion rules.
+ const t = context.popToken();
+ if (context.isExpandable(t.text)) {
+ t.noexpand = true;
+ t.treatAsRelax = true;
+ }
+ return {
+ tokens: [t],
+ numArgs: 0
+ };
+});
+defineMacro("\\expandafter", function (context) {
+ // TeX first reads the token that comes immediately after \expandafter,
+ // without expanding it; let’s call this token t. Then TeX reads the
+ // token that comes after t (and possibly more tokens, if that token
+ // has an argument), replacing it by its expansion. Finally TeX puts
+ // t back in front of that expansion.
+ const t = context.popToken();
+ context.expandOnce(true); // expand only an expandable token
+ return {
+ tokens: [t],
+ numArgs: 0
+ };
+});
+
+// LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2
+// TeX source: \long\def\@firstoftwo#1#2{#1}
+defineMacro("\\@firstoftwo", function (context) {
+ const args = context.consumeArgs(2);
+ return {
+ tokens: args[0],
+ numArgs: 0
+ };
+});
+
+// LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1
+// TeX source: \long\def\@secondoftwo#1#2{#2}
+defineMacro("\\@secondoftwo", function (context) {
+ const args = context.consumeArgs(2);
+ return {
+ tokens: args[1],
+ numArgs: 0
+ };
+});
+
+// LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded)
+// symbol that isn't a space, consuming any spaces but not consuming the
+// first nonspace character. If that nonspace character matches #1, then
+// the macro expands to #2; otherwise, it expands to #3.
+defineMacro("\\@ifnextchar", function (context) {
+ const args = context.consumeArgs(3); // symbol, if, else
+ context.consumeSpaces();
+ const nextToken = context.future();
+ if (args[0].length === 1 && args[0][0].text === nextToken.text) {
+ return {
+ tokens: args[1],
+ numArgs: 0
+ };
+ } else {
+ return {
+ tokens: args[2],
+ numArgs: 0
+ };
+ }
+});
+
+// LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol.
+// If it is `*`, then it consumes the symbol, and the macro expands to #1;
+// otherwise, the macro expands to #2 (without consuming the symbol).
+// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}}
+defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}");
+
+// LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode
+defineMacro("\\TextOrMath", function (context) {
+ const args = context.consumeArgs(2);
+ if (context.mode === 'text') {
+ return {
+ tokens: args[0],
+ numArgs: 0
+ };
+ } else {
+ return {
+ tokens: args[1],
+ numArgs: 0
+ };
+ }
+});
+
+// Lookup table for parsing numbers in base 8 through 16
+const digitToNumber = {
+ "0": 0,
+ "1": 1,
+ "2": 2,
+ "3": 3,
+ "4": 4,
+ "5": 5,
+ "6": 6,
+ "7": 7,
+ "8": 8,
+ "9": 9,
+ "a": 10,
+ "A": 10,
+ "b": 11,
+ "B": 11,
+ "c": 12,
+ "C": 12,
+ "d": 13,
+ "D": 13,
+ "e": 14,
+ "E": 14,
+ "f": 15,
+ "F": 15
+};
+
+// TeX \char makes a literal character (catcode 12) using the following forms:
+// (see The TeXBook, p. 43)
+// \char123 -- decimal
+// \char'123 -- octal
+// \char"123 -- hex
+// \char`x -- character that can be written (i.e. isn't active)
+// \char`\x -- character that cannot be written (e.g. %)
+// These all refer to characters from the font, so we turn them into special
+// calls to a function \@char dealt with in the Parser.
+defineMacro("\\char", function (context) {
+ let token = context.popToken();
+ let base;
+ let number = 0;
+ if (token.text === "'") {
+ base = 8;
+ token = context.popToken();
+ } else if (token.text === '"') {
+ base = 16;
+ token = context.popToken();
+ } else if (token.text === "`") {
+ token = context.popToken();
+ if (token.text[0] === "\\") {
+ number = token.text.charCodeAt(1);
+ } else if (token.text === "EOF") {
+ throw new src_ParseError("\\char` missing argument");
+ } else {
+ number = token.text.charCodeAt(0);
+ }
+ } else {
+ base = 10;
+ }
+ if (base) {
+ // Parse a number in the given base, starting with first `token`.
+ number = digitToNumber[token.text];
+ if (number == null || number >= base) {
+ throw new src_ParseError("Invalid base-" + base + " digit " + token.text);
+ }
+ let digit;
+ while ((digit = digitToNumber[context.future().text]) != null && digit < base) {
+ number *= base;
+ number += digit;
+ context.popToken();
+ }
+ }
+ return "\\@char{" + number + "}";
+});
+
+// \newcommand{\macro}[args]{definition}
+// \renewcommand{\macro}[args]{definition}
+// TODO: Optional arguments: \newcommand{\macro}[args][default]{definition}
+const newcommand = (context, existsOK, nonexistsOK, skipIfExists) => {
+ let arg = context.consumeArg().tokens;
+ if (arg.length !== 1) {
+ throw new src_ParseError("\\newcommand's first argument must be a macro name");
+ }
+ const name = arg[0].text;
+ const exists = context.isDefined(name);
+ if (exists && !existsOK) {
+ throw new src_ParseError("\\newcommand{" + name + "} attempting to redefine " + (name + "; use \\renewcommand"));
+ }
+ if (!exists && !nonexistsOK) {
+ throw new src_ParseError("\\renewcommand{" + name + "} when command " + name + " " + "does not yet exist; use \\newcommand");
+ }
+ let numArgs = 0;
+ arg = context.consumeArg().tokens;
+ if (arg.length === 1 && arg[0].text === "[") {
+ let argText = '';
+ let token = context.expandNextToken();
+ while (token.text !== "]" && token.text !== "EOF") {
+ // TODO: Should properly expand arg, e.g., ignore {}s
+ argText += token.text;
+ token = context.expandNextToken();
+ }
+ if (!argText.match(/^\s*[0-9]+\s*$/)) {
+ throw new src_ParseError("Invalid number of arguments: " + argText);
+ }
+ numArgs = parseInt(argText);
+ arg = context.consumeArg().tokens;
+ }
+ if (!(exists && skipIfExists)) {
+ // Final arg is the expansion of the macro
+ context.macros.set(name, {
+ tokens: arg,
+ numArgs
+ });
+ }
+ return '';
+};
+defineMacro("\\newcommand", context => newcommand(context, false, true, false));
+defineMacro("\\renewcommand", context => newcommand(context, true, false, false));
+defineMacro("\\providecommand", context => newcommand(context, true, true, true));
+
+// terminal (console) tools
+defineMacro("\\message", context => {
+ const arg = context.consumeArgs(1)[0];
+ // eslint-disable-next-line no-console
+ console.log(arg.reverse().map(token => token.text).join(""));
+ return '';
+});
+defineMacro("\\errmessage", context => {
+ const arg = context.consumeArgs(1)[0];
+ // eslint-disable-next-line no-console
+ console.error(arg.reverse().map(token => token.text).join(""));
+ return '';
+});
+defineMacro("\\show", context => {
+ const tok = context.popToken();
+ const name = tok.text;
+ // eslint-disable-next-line no-console
+ console.log(tok, context.macros.get(name), src_functions[name], src_symbols.math[name], src_symbols.text[name]);
+ return '';
+});
+
+//////////////////////////////////////////////////////////////////////
+// Grouping
+// \let\bgroup={ \let\egroup=}
+defineMacro("\\bgroup", "{");
+defineMacro("\\egroup", "}");
+
+// Symbols from latex.ltx:
+// \def~{\nobreakspace{}}
+// \def\lq{`}
+// \def\rq{'}
+// \def \aa {\r a}
+// \def \AA {\r A}
+defineMacro("~", "\\nobreakspace");
+defineMacro("\\lq", "`");
+defineMacro("\\rq", "'");
+defineMacro("\\aa", "\\r a");
+defineMacro("\\AA", "\\r A");
+
+// Copyright (C) and registered (R) symbols. Use raw symbol in MathML.
+// \DeclareTextCommandDefault{\textcopyright}{\textcircled{c}}
+// \DeclareTextCommandDefault{\textregistered}{\textcircled{%
+// \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}}
+// \DeclareRobustCommand{\copyright}{%
+// \ifmmode{\nfss@text{\textcopyright}}\else\textcopyright\fi}
+defineMacro("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`©}");
+defineMacro("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}");
+defineMacro("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}");
+
+// Characters omitted from Unicode range 1D400–1D7FF
+defineMacro("\u212C", "\\mathscr{B}"); // script
+defineMacro("\u2130", "\\mathscr{E}");
+defineMacro("\u2131", "\\mathscr{F}");
+defineMacro("\u210B", "\\mathscr{H}");
+defineMacro("\u2110", "\\mathscr{I}");
+defineMacro("\u2112", "\\mathscr{L}");
+defineMacro("\u2133", "\\mathscr{M}");
+defineMacro("\u211B", "\\mathscr{R}");
+defineMacro("\u212D", "\\mathfrak{C}"); // Fraktur
+defineMacro("\u210C", "\\mathfrak{H}");
+defineMacro("\u2128", "\\mathfrak{Z}");
+
+// Define \Bbbk with a macro that works in both HTML and MathML.
+defineMacro("\\Bbbk", "\\Bbb{k}");
+
+// \llap and \rlap render their contents in text mode
+defineMacro("\\llap", "\\mathllap{\\textrm{#1}}");
+defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}");
+defineMacro("\\clap", "\\mathclap{\\textrm{#1}}");
+
+// \mathstrut from the TeXbook, p 360
+defineMacro("\\mathstrut", "\\vphantom{(}");
+
+// \underbar from TeXbook p 353
+defineMacro("\\underbar", "\\underline{\\text{#1}}");
+
+// \not is defined by base/fontmath.ltx via
+// \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36}
+// It's thus treated like a \mathrel, but defined by a symbol that has zero
+// width but extends to the right. We use \rlap to get that spacing.
+// For MathML we write U+0338 here. buildMathML.js will then do the overlay.
+defineMacro("\\not", "\\html@mathml{\\mathrel{\\mathrlap\\@not}\\nobreak}" + "{\\char\"338}");
+
+// Negated symbols from base/fontmath.ltx:
+// \def\neq{\not=} \let\ne=\neq
+// \DeclareRobustCommand
+// \notin{\mathrel{\m@th\mathpalette\c@ncel\in}}
+// \def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
+defineMacro("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}");
+defineMacro("\\ne", "\\neq");
+defineMacro("\u2260", "\\neq");
+defineMacro("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}" + "{\\mathrel{\\char`∉}}");
+defineMacro("\u2209", "\\notin");
+
+// Unicode stacked relations
+defineMacro("\u2258", "\\html@mathml{" + "\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}" + "}{\\mathrel{\\char`\u2258}}");
+defineMacro("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}");
+defineMacro("\u225A", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225A}}");
+defineMacro("\u225B", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}" + "{\\mathrel{\\char`\u225B}}");
+defineMacro("\u225D", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}" + "{\\mathrel{\\char`\u225D}}");
+defineMacro("\u225E", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}" + "{\\mathrel{\\char`\u225E}}");
+defineMacro("\u225F", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225F}}");
+
+// Misc Unicode
+defineMacro("\u27C2", "\\perp");
+defineMacro("\u203C", "\\mathclose{!\\mkern-0.8mu!}");
+defineMacro("\u220C", "\\notni");
+defineMacro("\u231C", "\\ulcorner");
+defineMacro("\u231D", "\\urcorner");
+defineMacro("\u231E", "\\llcorner");
+defineMacro("\u231F", "\\lrcorner");
+defineMacro("\u00A9", "\\copyright");
+defineMacro("\u00AE", "\\textregistered");
+
+// The KaTeX fonts have corners at codepoints that don't match Unicode.
+// For MathML purposes, use the Unicode code point.
+defineMacro("\\ulcorner", "\\html@mathml{\\@ulcorner}{\\mathop{\\char\"231c}}");
+defineMacro("\\urcorner", "\\html@mathml{\\@urcorner}{\\mathop{\\char\"231d}}");
+defineMacro("\\llcorner", "\\html@mathml{\\@llcorner}{\\mathop{\\char\"231e}}");
+defineMacro("\\lrcorner", "\\html@mathml{\\@lrcorner}{\\mathop{\\char\"231f}}");
+
+//////////////////////////////////////////////////////////////////////
+// LaTeX_2ε
+
+// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@
+// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
+// We'll call \varvdots, which gets a glyph from symbols.js.
+// The zero-width rule gets us an equivalent to the vertical 6pt kern.
+defineMacro("\\vdots", "{\\varvdots\\rule{0pt}{15pt}}");
+defineMacro("\u22ee", "\\vdots");
+
+//////////////////////////////////////////////////////////////////////
+// amsmath.sty
+// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf
+
+// Italic Greek capital letters. AMS defines these with \DeclareMathSymbol,
+// but they are equivalent to \mathit{\Letter}.
+defineMacro("\\varGamma", "\\mathit{\\Gamma}");
+defineMacro("\\varDelta", "\\mathit{\\Delta}");
+defineMacro("\\varTheta", "\\mathit{\\Theta}");
+defineMacro("\\varLambda", "\\mathit{\\Lambda}");
+defineMacro("\\varXi", "\\mathit{\\Xi}");
+defineMacro("\\varPi", "\\mathit{\\Pi}");
+defineMacro("\\varSigma", "\\mathit{\\Sigma}");
+defineMacro("\\varUpsilon", "\\mathit{\\Upsilon}");
+defineMacro("\\varPhi", "\\mathit{\\Phi}");
+defineMacro("\\varPsi", "\\mathit{\\Psi}");
+defineMacro("\\varOmega", "\\mathit{\\Omega}");
+
+//\newcommand{\substack}[1]{\subarray{c}#1\endsubarray}
+defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}");
+
+// \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript
+// \mkern-\thinmuskip{:}\mskip6muplus1mu\relax}
+defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" + "\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax");
+
+// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}}
+defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}");
+
+// \def\iff{\DOTSB\;\Longleftrightarrow\;}
+// \def\implies{\DOTSB\;\Longrightarrow\;}
+// \def\impliedby{\DOTSB\;\Longleftarrow\;}
+defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;");
+defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;");
+defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;");
+
+// \def\dddot#1{{\mathop{#1}\limits^{\vbox to-1.4\ex@{\kern-\tw@\ex@
+// \hbox{\normalfont ...}\vss}}}}
+// We use \overset which avoids the vertical shift of \mathop.
+defineMacro("\\dddot", "{\\overset{\\raisebox{-0.1ex}{\\normalsize ...}}{#1}}");
+defineMacro("\\ddddot", "{\\overset{\\raisebox{-0.1ex}{\\normalsize ....}}{#1}}");
+
+// AMSMath's automatic \dots, based on \mdots@@ macro.
+const dotsByToken = {
+ ',': '\\dotsc',
+ '\\not': '\\dotsb',
+ // \keybin@ checks for the following:
+ '+': '\\dotsb',
+ '=': '\\dotsb',
+ '<': '\\dotsb',
+ '>': '\\dotsb',
+ '-': '\\dotsb',
+ '*': '\\dotsb',
+ ':': '\\dotsb',
+ // Symbols whose definition starts with \DOTSB:
+ '\\DOTSB': '\\dotsb',
+ '\\coprod': '\\dotsb',
+ '\\bigvee': '\\dotsb',
+ '\\bigwedge': '\\dotsb',
+ '\\biguplus': '\\dotsb',
+ '\\bigcap': '\\dotsb',
+ '\\bigcup': '\\dotsb',
+ '\\prod': '\\dotsb',
+ '\\sum': '\\dotsb',
+ '\\bigotimes': '\\dotsb',
+ '\\bigoplus': '\\dotsb',
+ '\\bigodot': '\\dotsb',
+ '\\bigsqcup': '\\dotsb',
+ '\\And': '\\dotsb',
+ '\\longrightarrow': '\\dotsb',
+ '\\Longrightarrow': '\\dotsb',
+ '\\longleftarrow': '\\dotsb',
+ '\\Longleftarrow': '\\dotsb',
+ '\\longleftrightarrow': '\\dotsb',
+ '\\Longleftrightarrow': '\\dotsb',
+ '\\mapsto': '\\dotsb',
+ '\\longmapsto': '\\dotsb',
+ '\\hookrightarrow': '\\dotsb',
+ '\\doteq': '\\dotsb',
+ // Symbols whose definition starts with \mathbin:
+ '\\mathbin': '\\dotsb',
+ // Symbols whose definition starts with \mathrel:
+ '\\mathrel': '\\dotsb',
+ '\\relbar': '\\dotsb',
+ '\\Relbar': '\\dotsb',
+ '\\xrightarrow': '\\dotsb',
+ '\\xleftarrow': '\\dotsb',
+ // Symbols whose definition starts with \DOTSI:
+ '\\DOTSI': '\\dotsi',
+ '\\int': '\\dotsi',
+ '\\oint': '\\dotsi',
+ '\\iint': '\\dotsi',
+ '\\iiint': '\\dotsi',
+ '\\iiiint': '\\dotsi',
+ '\\idotsint': '\\dotsi',
+ // Symbols whose definition starts with \DOTSX:
+ '\\DOTSX': '\\dotsx'
+};
+const dotsbGroups = new Set(['bin', 'rel']);
+defineMacro("\\dots", function (context) {
+ // TODO: If used in text mode, should expand to \textellipsis.
+ // However, in KaTeX, \textellipsis and \ldots behave the same
+ // (in text mode), and it's unlikely we'd see any of the math commands
+ // that affect the behavior of \dots when in text mode. So fine for now
+ // (until we support \ifmmode ... \else ... \fi).
+ let thedots = '\\dotso';
+ const next = context.expandAfterFuture().text;
+ if (next in dotsByToken) {
+ thedots = dotsByToken[next];
+ } else if (next.slice(0, 4) === '\\not') {
+ thedots = '\\dotsb';
+ } else if (next in src_symbols.math) {
+ if (dotsbGroups.has(src_symbols.math[next].group)) {
+ thedots = '\\dotsb';
+ }
+ }
+ return thedots;
+});
+const spaceAfterDots = {
+ // \rightdelim@ checks for the following:
+ ')': true,
+ ']': true,
+ '\\rbrack': true,
+ '\\}': true,
+ '\\rbrace': true,
+ '\\rangle': true,
+ '\\rceil': true,
+ '\\rfloor': true,
+ '\\rgroup': true,
+ '\\rmoustache': true,
+ '\\right': true,
+ '\\bigr': true,
+ '\\biggr': true,
+ '\\Bigr': true,
+ '\\Biggr': true,
+ // \extra@ also tests for the following:
+ '$': true,
+ // \extrap@ checks for the following:
+ ';': true,
+ '.': true,
+ ',': true
+};
+defineMacro("\\dotso", function (context) {
+ const next = context.future().text;
+ if (next in spaceAfterDots) {
+ return "\\ldots\\,";
+ } else {
+ return "\\ldots";
+ }
+});
+defineMacro("\\dotsc", function (context) {
+ const next = context.future().text;
+ // \dotsc uses \extra@ but not \extrap@, instead specially checking for
+ // ';' and '.', but doesn't check for ','.
+ if (next in spaceAfterDots && next !== ',') {
+ return "\\ldots\\,";
+ } else {
+ return "\\ldots";
+ }
+});
+defineMacro("\\cdots", function (context) {
+ const next = context.future().text;
+ if (next in spaceAfterDots) {
+ return "\\@cdots\\,";
+ } else {
+ return "\\@cdots";
+ }
+});
+defineMacro("\\dotsb", "\\cdots");
+defineMacro("\\dotsm", "\\cdots");
+defineMacro("\\dotsi", "\\!\\cdots");
+// amsmath doesn't actually define \dotsx, but \dots followed by a macro
+// starting with \DOTSX implies \dotso, and then \extra@ detects this case
+// and forces the added `\,`.
+defineMacro("\\dotsx", "\\ldots\\,");
+
+// \let\DOTSI\relax
+// \let\DOTSB\relax
+// \let\DOTSX\relax
+defineMacro("\\DOTSI", "\\relax");
+defineMacro("\\DOTSB", "\\relax");
+defineMacro("\\DOTSX", "\\relax");
+
+// Spacing, based on amsmath.sty's override of LaTeX defaults
+// \DeclareRobustCommand{\tmspace}[3]{%
+// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax}
+defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax");
+// \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}}
+// TODO: math mode should use \thinmuskip
+defineMacro("\\,", "\\tmspace+{3mu}{.1667em}");
+// \let\thinspace\,
+defineMacro("\\thinspace", "\\,");
+// \def\>{\mskip\medmuskip}
+// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}}
+// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu
+defineMacro("\\>", "\\mskip{4mu}");
+defineMacro("\\:", "\\tmspace+{4mu}{.2222em}");
+// \let\medspace\:
+defineMacro("\\medspace", "\\:");
+// \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}}
+// TODO: math mode should use \thickmuskip = 5mu plus 5mu
+defineMacro("\\;", "\\tmspace+{5mu}{.2777em}");
+// \let\thickspace\;
+defineMacro("\\thickspace", "\\;");
+// \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}}
+// TODO: math mode should use \thinmuskip
+defineMacro("\\!", "\\tmspace-{3mu}{.1667em}");
+// \let\negthinspace\!
+defineMacro("\\negthinspace", "\\!");
+// \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}}
+// TODO: math mode should use \medmuskip
+defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}");
+// \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}}
+// TODO: math mode should use \thickmuskip
+defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}");
+// \def\enspace{\kern.5em }
+defineMacro("\\enspace", "\\kern.5em ");
+// \def\enskip{\hskip.5em\relax}
+defineMacro("\\enskip", "\\hskip.5em\\relax");
+// \def\quad{\hskip1em\relax}
+defineMacro("\\quad", "\\hskip1em\\relax");
+// \def\qquad{\hskip2em\relax}
+defineMacro("\\qquad", "\\hskip2em\\relax");
+
+// \tag@in@display form of \tag
+defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
+defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
+defineMacro("\\tag@literal", context => {
+ if (context.macros.get("\\df@tag")) {
+ throw new src_ParseError("Multiple \\tag");
+ }
+ return "\\gdef\\df@tag{\\text{#1}}";
+});
+
+// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin
+// {\operator@font mod}\penalty900
+// \mkern5mu\nonscript\mskip-\medmuskip}
+// \newcommand{\pod}[1]{\allowbreak
+// \if@display\mkern18mu\else\mkern8mu\fi(#1)}
+// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}}
+// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu
+// \else\mkern12mu\fi{\operator@font mod}\,\,#1}
+// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu
+defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}");
+defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)");
+defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}");
+defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1");
+
+//////////////////////////////////////////////////////////////////////
+// LaTeX source2e
+
+// \expandafter\let\expandafter\@normalcr
+// \csname\expandafter\@gobble\string\\ \endcsname
+// \DeclareRobustCommand\newline{\@normalcr\relax}
+defineMacro("\\newline", "\\\\\\relax");
+
+// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@}
+// TODO: Doesn't normally work in math mode because \@ fails. KaTeX doesn't
+// support \@ yet, so that's omitted, and we add \text so that the result
+// doesn't look funny in math mode.
+defineMacro("\\TeX", "\\textrm{\\html@mathml{" + "T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX" + "}{TeX}}");
+
+// \DeclareRobustCommand{\LaTeX}{L\kern-.36em%
+// {\sbox\z@ T%
+// \vbox to\ht\z@{\hbox{\check@mathfonts
+// \fontsize\sf@size\z@
+// \math@fontsfalse\selectfont
+// A}%
+// \vss}%
+// }%
+// \kern-.15em%
+// \TeX}
+// This code aligns the top of the A with the T (from the perspective of TeX's
+// boxes, though visually the A appears to extend above slightly).
+// We compute the corresponding \raisebox when A is rendered in \normalsize
+// \scriptstyle, which has a scale factor of 0.7 (see Options.js).
+const latexRaiseA = makeEm(fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] - 0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1]);
+defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" + ("L\\kern-.36em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{LaTeX}}");
+
+// New KaTeX logo based on tweaking LaTeX logo
+defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" + ("K\\kern-.17em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{KaTeX}}");
+
+// \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace}
+// \def\@hspace#1{\hskip #1\relax}
+// \def\@hspacer#1{\vrule \@width\z@\nobreak
+// \hskip #1\hskip \z@skip}
+defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace");
+defineMacro("\\@hspace", "\\hskip #1\\relax");
+defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax");
+
+//////////////////////////////////////////////////////////////////////
+// mathtools.sty
+
+//\providecommand\ordinarycolon{:}
+defineMacro("\\ordinarycolon", ":");
+//\def\vcentcolon{\mathrel{\mathop\ordinarycolon}}
+//TODO(edemaine): Not yet centered. Fix via \raisebox or #726
+defineMacro("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}");
+// \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon}
+defineMacro("\\dblcolon", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}" + "{\\mathop{\\char\"2237}}");
+// \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=}
+defineMacro("\\coloneqq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2254}}"); // ≔
+// \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=}
+defineMacro("\\Coloneqq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2237\\char\"3d}}");
+// \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
+defineMacro("\\coloneq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"3a\\char\"2212}}");
+// \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
+defineMacro("\\Coloneq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"2237\\char\"2212}}");
+// \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon}
+defineMacro("\\eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2255}}"); // ≕
+// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon}
+defineMacro("\\Eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"3d\\char\"2237}}");
+// \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon}
+defineMacro("\\eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2239}}");
+// \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon}
+defineMacro("\\Eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"2212\\char\"2237}}");
+// \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx}
+defineMacro("\\colonapprox", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"3a\\char\"2248}}");
+// \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx}
+defineMacro("\\Colonapprox", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"2237\\char\"2248}}");
+// \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim}
+defineMacro("\\colonsim", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"3a\\char\"223c}}");
+// \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim}
+defineMacro("\\Colonsim", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"2237\\char\"223c}}");
+
+// Some Unicode characters are implemented with macros to mathtools functions.
+defineMacro("\u2237", "\\dblcolon"); // ::
+defineMacro("\u2239", "\\eqcolon"); // -:
+defineMacro("\u2254", "\\coloneqq"); // :=
+defineMacro("\u2255", "\\eqqcolon"); // =:
+defineMacro("\u2A74", "\\Coloneqq"); // ::=
+
+//////////////////////////////////////////////////////////////////////
+// colonequals.sty
+
+// Alternate names for mathtools's macros:
+defineMacro("\\ratio", "\\vcentcolon");
+defineMacro("\\coloncolon", "\\dblcolon");
+defineMacro("\\colonequals", "\\coloneqq");
+defineMacro("\\coloncolonequals", "\\Coloneqq");
+defineMacro("\\equalscolon", "\\eqqcolon");
+defineMacro("\\equalscoloncolon", "\\Eqqcolon");
+defineMacro("\\colonminus", "\\coloneq");
+defineMacro("\\coloncolonminus", "\\Coloneq");
+defineMacro("\\minuscolon", "\\eqcolon");
+defineMacro("\\minuscoloncolon", "\\Eqcolon");
+// \colonapprox name is same in mathtools and colonequals.
+defineMacro("\\coloncolonapprox", "\\Colonapprox");
+// \colonsim name is same in mathtools and colonequals.
+defineMacro("\\coloncolonsim", "\\Colonsim");
+
+// Additional macros, implemented by analogy with mathtools definitions:
+defineMacro("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
+defineMacro("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}");
+defineMacro("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
+defineMacro("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}");
+
+// Present in newtxmath, pxfonts and txfonts
+defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}");
+defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}");
+defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}");
+
+//////////////////////////////////////////////////////////////////////
+// From amsopn.sty
+defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}");
+defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}");
+defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}");
+defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}");
+defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}");
+defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}");
+
+//////////////////////////////////////////////////////////////////////
+// MathML alternates for KaTeX glyphs in the Unicode private area
+defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}");
+defineMacro("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}");
+defineMacro("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}");
+defineMacro("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}");
+defineMacro("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}");
+defineMacro("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}");
+defineMacro("\\nshortmid", "\\html@mathml{\\@nshortmid}{∤}");
+defineMacro("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{∦}");
+defineMacro("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}");
+defineMacro("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}");
+defineMacro("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{⊊}");
+defineMacro("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{⫋}");
+defineMacro("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{⊋}");
+defineMacro("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{⫌}");
+defineMacro("\\imath", "\\html@mathml{\\@imath}{\u0131}");
+defineMacro("\\jmath", "\\html@mathml{\\@jmath}{\u0237}");
+
+//////////////////////////////////////////////////////////////////////
+// stmaryrd and semantic
+
+// The stmaryrd and semantic packages render the next four items by calling a
+// glyph. Those glyphs do not exist in the KaTeX fonts. Hence the macros.
+
+defineMacro("\\llbracket", "\\html@mathml{" + "\\mathopen{[\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u27e6}}");
+defineMacro("\\rrbracket", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu]}}" + "{\\mathclose{\\char`\u27e7}}");
+defineMacro("\u27e6", "\\llbracket"); // blackboard bold [
+defineMacro("\u27e7", "\\rrbracket"); // blackboard bold ]
+
+defineMacro("\\lBrace", "\\html@mathml{" + "\\mathopen{\\{\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u2983}}");
+defineMacro("\\rBrace", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu\\}}}" + "{\\mathclose{\\char`\u2984}}");
+defineMacro("\u2983", "\\lBrace"); // blackboard bold {
+defineMacro("\u2984", "\\rBrace"); // blackboard bold }
+
+// TODO: Create variable sized versions of the last two items. I believe that
+// will require new font glyphs.
+
+// The stmaryrd function `\minuso` provides a "Plimsoll" symbol that
+// superimposes the characters \circ and \mathminus. Used in chemistry.
+defineMacro("\\minuso", "\\mathbin{\\html@mathml{" + "{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}" + "{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}" + "{\\char`⦵}}");
+defineMacro("⦵", "\\minuso");
+
+//////////////////////////////////////////////////////////////////////
+// texvc.sty
+
+// The texvc package contains macros available in mediawiki pages.
+// We omit the functions deprecated at
+// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax
+
+// We also omit texvc's \O, which conflicts with \text{\O}
+
+defineMacro("\\darr", "\\downarrow");
+defineMacro("\\dArr", "\\Downarrow");
+defineMacro("\\Darr", "\\Downarrow");
+defineMacro("\\lang", "\\langle");
+defineMacro("\\rang", "\\rangle");
+defineMacro("\\uarr", "\\uparrow");
+defineMacro("\\uArr", "\\Uparrow");
+defineMacro("\\Uarr", "\\Uparrow");
+defineMacro("\\N", "\\mathbb{N}");
+defineMacro("\\R", "\\mathbb{R}");
+defineMacro("\\Z", "\\mathbb{Z}");
+defineMacro("\\alef", "\\aleph");
+defineMacro("\\alefsym", "\\aleph");
+defineMacro("\\Alpha", "\\mathrm{A}");
+defineMacro("\\Beta", "\\mathrm{B}");
+defineMacro("\\bull", "\\bullet");
+defineMacro("\\Chi", "\\mathrm{X}");
+defineMacro("\\clubs", "\\clubsuit");
+defineMacro("\\cnums", "\\mathbb{C}");
+defineMacro("\\Complex", "\\mathbb{C}");
+defineMacro("\\Dagger", "\\ddagger");
+defineMacro("\\diamonds", "\\diamondsuit");
+defineMacro("\\empty", "\\emptyset");
+defineMacro("\\Epsilon", "\\mathrm{E}");
+defineMacro("\\Eta", "\\mathrm{H}");
+defineMacro("\\exist", "\\exists");
+defineMacro("\\harr", "\\leftrightarrow");
+defineMacro("\\hArr", "\\Leftrightarrow");
+defineMacro("\\Harr", "\\Leftrightarrow");
+defineMacro("\\hearts", "\\heartsuit");
+defineMacro("\\image", "\\Im");
+defineMacro("\\infin", "\\infty");
+defineMacro("\\Iota", "\\mathrm{I}");
+defineMacro("\\isin", "\\in");
+defineMacro("\\Kappa", "\\mathrm{K}");
+defineMacro("\\larr", "\\leftarrow");
+defineMacro("\\lArr", "\\Leftarrow");
+defineMacro("\\Larr", "\\Leftarrow");
+defineMacro("\\lrarr", "\\leftrightarrow");
+defineMacro("\\lrArr", "\\Leftrightarrow");
+defineMacro("\\Lrarr", "\\Leftrightarrow");
+defineMacro("\\Mu", "\\mathrm{M}");
+defineMacro("\\natnums", "\\mathbb{N}");
+defineMacro("\\Nu", "\\mathrm{N}");
+defineMacro("\\Omicron", "\\mathrm{O}");
+defineMacro("\\plusmn", "\\pm");
+defineMacro("\\rarr", "\\rightarrow");
+defineMacro("\\rArr", "\\Rightarrow");
+defineMacro("\\Rarr", "\\Rightarrow");
+defineMacro("\\real", "\\Re");
+defineMacro("\\reals", "\\mathbb{R}");
+defineMacro("\\Reals", "\\mathbb{R}");
+defineMacro("\\Rho", "\\mathrm{P}");
+defineMacro("\\sdot", "\\cdot");
+defineMacro("\\sect", "\\S");
+defineMacro("\\spades", "\\spadesuit");
+defineMacro("\\sub", "\\subset");
+defineMacro("\\sube", "\\subseteq");
+defineMacro("\\supe", "\\supseteq");
+defineMacro("\\Tau", "\\mathrm{T}");
+defineMacro("\\thetasym", "\\vartheta");
+// TODO: defineMacro("\\varcoppa", "\\\mbox{\\coppa}");
+defineMacro("\\weierp", "\\wp");
+defineMacro("\\Zeta", "\\mathrm{Z}");
+
+//////////////////////////////////////////////////////////////////////
+// statmath.sty
+// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf
+
+defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
+defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
+defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits");
+
+//////////////////////////////////////////////////////////////////////
+// braket.sty
+// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf
+
+defineMacro("\\bra", "\\mathinner{\\langle{#1}|}");
+defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
+defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
+defineMacro("\\Bra", "\\left\\langle#1\\right|");
+defineMacro("\\Ket", "\\left|#1\\right\\rangle");
+const braketHelper = one => context => {
+ const left = context.consumeArg().tokens;
+ const middle = context.consumeArg().tokens;
+ const middleDouble = context.consumeArg().tokens;
+ const right = context.consumeArg().tokens;
+ const oldMiddle = context.macros.get("|");
+ const oldMiddleDouble = context.macros.get("\\|");
+ context.macros.beginGroup();
+ const midMacro = double => context => {
+ if (one) {
+ // Only modify the first instance of | or \|
+ context.macros.set("|", oldMiddle);
+ if (middleDouble.length) {
+ context.macros.set("\\|", oldMiddleDouble);
+ }
+ }
+ let doubled = double;
+ if (!double && middleDouble.length) {
+ // Mimic \@ifnextchar
+ const nextToken = context.future();
+ if (nextToken.text === "|") {
+ context.popToken();
+ doubled = true;
+ }
+ }
+ return {
+ tokens: doubled ? middleDouble : middle,
+ numArgs: 0
+ };
+ };
+ context.macros.set("|", midMacro(false));
+ if (middleDouble.length) {
+ context.macros.set("\\|", midMacro(true));
+ }
+ const arg = context.consumeArg().tokens;
+ const expanded = context.expandTokens([...right, ...arg, ...left // reversed
+ ]);
+ context.macros.endGroup();
+ return {
+ tokens: expanded.reverse(),
+ numArgs: 0
+ };
+};
+defineMacro("\\bra@ket", braketHelper(false));
+defineMacro("\\bra@set", braketHelper(true));
+defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}");
+defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}");
+defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}");
+// has no support for special || or \|
+
+//////////////////////////////////////////////////////////////////////
+// actuarialangle.dtx
+defineMacro("\\angln", "{\\angl n}");
+
+// Custom Khan Academy colors, should be moved to an optional package
+defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
+defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
+defineMacro("\\pink", "\\textcolor{##ff00af}{#1}");
+defineMacro("\\red", "\\textcolor{##df0030}{#1}");
+defineMacro("\\green", "\\textcolor{##28ae7b}{#1}");
+defineMacro("\\gray", "\\textcolor{gray}{#1}");
+defineMacro("\\purple", "\\textcolor{##9d38bd}{#1}");
+defineMacro("\\blueA", "\\textcolor{##ccfaff}{#1}");
+defineMacro("\\blueB", "\\textcolor{##80f6ff}{#1}");
+defineMacro("\\blueC", "\\textcolor{##63d9ea}{#1}");
+defineMacro("\\blueD", "\\textcolor{##11accd}{#1}");
+defineMacro("\\blueE", "\\textcolor{##0c7f99}{#1}");
+defineMacro("\\tealA", "\\textcolor{##94fff5}{#1}");
+defineMacro("\\tealB", "\\textcolor{##26edd5}{#1}");
+defineMacro("\\tealC", "\\textcolor{##01d1c1}{#1}");
+defineMacro("\\tealD", "\\textcolor{##01a995}{#1}");
+defineMacro("\\tealE", "\\textcolor{##208170}{#1}");
+defineMacro("\\greenA", "\\textcolor{##b6ffb0}{#1}");
+defineMacro("\\greenB", "\\textcolor{##8af281}{#1}");
+defineMacro("\\greenC", "\\textcolor{##74cf70}{#1}");
+defineMacro("\\greenD", "\\textcolor{##1fab54}{#1}");
+defineMacro("\\greenE", "\\textcolor{##0d923f}{#1}");
+defineMacro("\\goldA", "\\textcolor{##ffd0a9}{#1}");
+defineMacro("\\goldB", "\\textcolor{##ffbb71}{#1}");
+defineMacro("\\goldC", "\\textcolor{##ff9c39}{#1}");
+defineMacro("\\goldD", "\\textcolor{##e07d10}{#1}");
+defineMacro("\\goldE", "\\textcolor{##a75a05}{#1}");
+defineMacro("\\redA", "\\textcolor{##fca9a9}{#1}");
+defineMacro("\\redB", "\\textcolor{##ff8482}{#1}");
+defineMacro("\\redC", "\\textcolor{##f9685d}{#1}");
+defineMacro("\\redD", "\\textcolor{##e84d39}{#1}");
+defineMacro("\\redE", "\\textcolor{##bc2612}{#1}");
+defineMacro("\\maroonA", "\\textcolor{##ffbde0}{#1}");
+defineMacro("\\maroonB", "\\textcolor{##ff92c6}{#1}");
+defineMacro("\\maroonC", "\\textcolor{##ed5fa6}{#1}");
+defineMacro("\\maroonD", "\\textcolor{##ca337c}{#1}");
+defineMacro("\\maroonE", "\\textcolor{##9e034e}{#1}");
+defineMacro("\\purpleA", "\\textcolor{##ddd7ff}{#1}");
+defineMacro("\\purpleB", "\\textcolor{##c6b9fc}{#1}");
+defineMacro("\\purpleC", "\\textcolor{##aa87ff}{#1}");
+defineMacro("\\purpleD", "\\textcolor{##7854ab}{#1}");
+defineMacro("\\purpleE", "\\textcolor{##543b78}{#1}");
+defineMacro("\\mintA", "\\textcolor{##f5f9e8}{#1}");
+defineMacro("\\mintB", "\\textcolor{##edf2df}{#1}");
+defineMacro("\\mintC", "\\textcolor{##e0e5cc}{#1}");
+defineMacro("\\grayA", "\\textcolor{##f6f7f7}{#1}");
+defineMacro("\\grayB", "\\textcolor{##f0f1f2}{#1}");
+defineMacro("\\grayC", "\\textcolor{##e3e5e6}{#1}");
+defineMacro("\\grayD", "\\textcolor{##d6d8da}{#1}");
+defineMacro("\\grayE", "\\textcolor{##babec2}{#1}");
+defineMacro("\\grayF", "\\textcolor{##888d93}{#1}");
+defineMacro("\\grayG", "\\textcolor{##626569}{#1}");
+defineMacro("\\grayH", "\\textcolor{##3b3e40}{#1}");
+defineMacro("\\grayI", "\\textcolor{##21242c}{#1}");
+defineMacro("\\kaBlue", "\\textcolor{##314453}{#1}");
+defineMacro("\\kaGreen", "\\textcolor{##71B307}{#1}");
+;// ./src/MacroExpander.ts
+/**
+ * This file contains the “gullet” where macros are expanded
+ * until only non-macro tokens remain.
+ */
+
+
+
+
+
+
+
+
+
+// List of commands that act like macros but aren't defined as a macro,
+// function, or symbol. Used in `isDefined`.
+const implicitCommands = {
+ "^": true,
+ // Parser.js
+ "_": true,
+ // Parser.js
+ "\\limits": true,
+ // Parser.js
+ "\\nolimits": true // Parser.js
+};
+class MacroExpander {
+ constructor(input, settings, mode) {
+ this.settings = void 0;
+ this.expansionCount = void 0;
+ this.lexer = void 0;
+ this.macros = void 0;
+ this.stack = void 0;
+ this.mode = void 0;
+ this.settings = settings;
+ this.expansionCount = 0;
+ this.feed(input);
+ // Make new global namespace
+ this.macros = new Namespace(src_macros, settings.macros);
+ this.mode = mode;
+ this.stack = []; // contains tokens in REVERSE order
+ }
+
+ /**
+ * Feed a new input string to the same MacroExpander
+ * (with existing macros etc.).
+ */
+ feed(input) {
+ this.lexer = new Lexer(input, this.settings);
+ }
+
+ /**
+ * Switches between "text" and "math" modes.
+ */
+ switchMode(newMode) {
+ this.mode = newMode;
+ }
+
+ /**
+ * Start a new group nesting within all namespaces.
+ */
+ beginGroup() {
+ this.macros.beginGroup();
+ }
+
+ /**
+ * End current group nesting within all namespaces.
+ */
+ endGroup() {
+ this.macros.endGroup();
+ }
+
+ /**
+ * Ends all currently nested groups (if any), restoring values before the
+ * groups began. Useful in case of an error in the middle of parsing.
+ */
+ endGroups() {
+ this.macros.endGroups();
+ }
+
+ /**
+ * Returns the topmost token on the stack, without expanding it.
+ * Similar in behavior to TeX's `\futurelet`.
+ */
+ future() {
+ if (this.stack.length === 0) {
+ this.pushToken(this.lexer.lex());
+ }
+ return this.stack[this.stack.length - 1];
+ }
+
+ /**
+ * Remove and return the next unexpanded token.
+ */
+ popToken() {
+ this.future(); // ensure non-empty stack
+ return this.stack.pop();
+ }
+
+ /**
+ * Add a given token to the token stack. In particular, this get be used
+ * to put back a token returned from one of the other methods.
+ */
+ pushToken(token) {
+ this.stack.push(token);
+ }
+
+ /**
+ * Append an array of tokens to the token stack.
+ */
+ pushTokens(tokens) {
+ this.stack.push(...tokens);
+ }
+
+ /**
+ * Find an macro argument without expanding tokens and append the array of
+ * tokens to the token stack. Uses Token as a container for the result.
+ */
+ scanArgument(isOptional) {
+ let start;
+ let end;
+ let tokens;
+ if (isOptional) {
+ this.consumeSpaces(); // \@ifnextchar gobbles any space following it
+ if (this.future().text !== "[") {
+ return null;
+ }
+ start = this.popToken(); // don't include [ in tokens
+ var _this$consumeArg = this.consumeArg(["]"]);
+ tokens = _this$consumeArg.tokens;
+ end = _this$consumeArg.end;
+ } else {
+ var _this$consumeArg2 = this.consumeArg();
+ tokens = _this$consumeArg2.tokens;
+ start = _this$consumeArg2.start;
+ end = _this$consumeArg2.end;
+ }
+
+ // indicate the end of an argument
+ this.pushToken(new Token("EOF", end.loc));
+ this.pushTokens(tokens);
+ return new Token("", SourceLocation.range(start, end));
+ }
+
+ /**
+ * Consume all following space tokens, without expansion.
+ */
+ consumeSpaces() {
+ for (;;) {
+ const token = this.future();
+ if (token.text === " ") {
+ this.stack.pop();
+ } else {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Consume an argument from the token stream, and return the resulting array
+ * of tokens and start/end token.
+ */
+ consumeArg(delims) {
+ // The argument for a delimited parameter is the shortest (possibly
+ // empty) sequence of tokens with properly nested {...} groups that is
+ // followed ... by this particular list of non-parameter tokens.
+ // The argument for an undelimited parameter is the next nonblank
+ // token, unless that token is ‘{’, when the argument will be the
+ // entire {...} group that follows.
+ const tokens = [];
+ const isDelimited = delims && delims.length > 0;
+ if (!isDelimited) {
+ // Ignore spaces between arguments. As the TeXbook says:
+ // "After you have said ‘\def\row#1#2{...}’, you are allowed to
+ // put spaces between the arguments (e.g., ‘\row x n’), because
+ // TeX doesn’t use single spaces as undelimited arguments."
+ this.consumeSpaces();
+ }
+ const start = this.future();
+ let tok;
+ let depth = 0;
+ let match = 0;
+ do {
+ tok = this.popToken();
+ tokens.push(tok);
+ if (tok.text === "{") {
+ ++depth;
+ } else if (tok.text === "}") {
+ --depth;
+ if (depth === -1) {
+ throw new src_ParseError("Extra }", tok);
+ }
+ } else if (tok.text === "EOF") {
+ throw new src_ParseError("Unexpected end of input in a macro argument" + ", expected '" + (delims && isDelimited ? delims[match] : "}") + "'", tok);
+ }
+ if (delims && isDelimited) {
+ if ((depth === 0 || depth === 1 && delims[match] === "{") && tok.text === delims[match]) {
+ ++match;
+ if (match === delims.length) {
+ // don't include delims in tokens
+ tokens.splice(-match, match);
+ break;
+ }
+ } else {
+ match = 0;
+ }
+ }
+ } while (depth !== 0 || isDelimited);
+ // If the argument found ... has the form ‘{<nested tokens>}’,
+ // ... the outermost braces enclosing the argument are removed
+ if (start.text === "{" && tokens[tokens.length - 1].text === "}") {
+ tokens.pop();
+ tokens.shift();
+ }
+ tokens.reverse(); // to fit in with stack order
+ return {
+ tokens,
+ start,
+ end: tok
+ };
+ }
+
+ /**
+ * Consume the specified number of (delimited) arguments from the token
+ * stream and return the resulting array of arguments.
+ */
+ consumeArgs(numArgs, delimiters) {
+ if (delimiters) {
+ if (delimiters.length !== numArgs + 1) {
+ throw new src_ParseError("The length of delimiters doesn't match the number of args!");
+ }
+ const delims = delimiters[0];
+ for (let i = 0; i < delims.length; i++) {
+ const tok = this.popToken();
+ if (delims[i] !== tok.text) {
+ throw new src_ParseError("Use of the macro doesn't match its definition", tok);
+ }
+ }
+ }
+ const args = [];
+ for (let i = 0; i < numArgs; i++) {
+ args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens);
+ }
+ return args;
+ }
+
+ /**
+ * Increment `expansionCount` by the specified amount.
+ * Throw an error if it exceeds `maxExpand`.
+ */
+ countExpansion(amount) {
+ this.expansionCount += amount;
+ if (this.expansionCount > this.settings.maxExpand) {
+ throw new src_ParseError("Too many expansions: infinite loop or " + "need to increase maxExpand setting");
+ }
+ }
+
+ /**
+ * Expand the next token only once if possible.
+ *
+ * If the token is expanded, the resulting tokens will be pushed onto
+ * the stack in reverse order, and the number of such tokens will be
+ * returned. This number might be zero or positive.
+ *
+ * If not, the return value is `false`, and the next token remains at the
+ * top of the stack.
+ *
+ * In either case, the next token will be on the top of the stack,
+ * or the stack will be empty (in case of empty expansion
+ * and no other tokens).
+ *
+ * Used to implement `expandAfterFuture` and `expandNextToken`.
+ *
+ * If expandableOnly, only expandable tokens are expanded and
+ * an undefined control sequence results in an error.
+ */
+ expandOnce(expandableOnly) {
+ const topToken = this.popToken();
+ const name = topToken.text;
+ const expansion = !topToken.noexpand ? this._getExpansion(name) : null;
+ if (expansion == null || expandableOnly && expansion.unexpandable) {
+ if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) {
+ throw new src_ParseError("Undefined control sequence: " + name);
+ }
+ this.pushToken(topToken);
+ return false;
+ }
+ this.countExpansion(1);
+ let tokens = expansion.tokens;
+ const args = this.consumeArgs(expansion.numArgs, expansion.delimiters);
+ if (expansion.numArgs) {
+ // paste arguments in place of the placeholders
+ tokens = tokens.slice(); // make a shallow copy
+ for (let i = tokens.length - 1; i >= 0; --i) {
+ let tok = tokens[i];
+ if (tok.text === "#") {
+ if (i === 0) {
+ throw new src_ParseError("Incomplete placeholder at end of macro body", tok);
+ }
+ tok = tokens[--i]; // next token on stack
+ if (tok.text === "#") {
+ // ## → #
+ tokens.splice(i + 1, 1); // drop first #
+ } else if (/^[1-9]$/.test(tok.text)) {
+ // replace the placeholder with the indicated argument
+ tokens.splice(i, 2, ...args[+tok.text - 1]);
+ } else {
+ throw new src_ParseError("Not a valid argument number", tok);
+ }
+ }
+ }
+ }
+ // Concatenate expansion onto top of stack.
+ this.pushTokens(tokens);
+ return tokens.length;
+ }
+
+ /**
+ * Expand the next token only once (if possible), and return the resulting
+ * top token on the stack (without removing anything from the stack).
+ * Similar in behavior to TeX's `\expandafter\futurelet`.
+ * Equivalent to expandOnce() followed by future().
+ */
+ expandAfterFuture() {
+ this.expandOnce();
+ return this.future();
+ }
+
+ /**
+ * Recursively expand first token, then return first non-expandable token.
+ */
+ expandNextToken() {
+ for (;;) {
+ if (this.expandOnce() === false) {
+ // fully expanded
+ const token = this.stack.pop();
+ // the token after \noexpand is interpreted as if its meaning
+ // were ‘\relax’
+ if (token.treatAsRelax) {
+ token.text = "\\relax";
+ }
+ return token;
+ }
+ }
+ }
+
+ /**
+ * Fully expand the given macro name and return the resulting list of
+ * tokens, or return `undefined` if no such macro is defined.
+ */
+ expandMacro(name) {
+ return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined;
+ }
+
+ /**
+ * Fully expand the given token stream and return the resulting list of
+ * tokens. Note that the input tokens are in reverse order, but the
+ * output tokens are in forward order.
+ */
+ expandTokens(tokens) {
+ const output = [];
+ const oldStackLength = this.stack.length;
+ this.pushTokens(tokens);
+ while (this.stack.length > oldStackLength) {
+ // Expand only expandable tokens
+ if (this.expandOnce(true) === false) {
+ // fully expanded
+ const token = this.stack.pop();
+ if (token.treatAsRelax) {
+ // the expansion of \noexpand is the token itself
+ token.noexpand = false;
+ token.treatAsRelax = false;
+ }
+ output.push(token);
+ }
+ }
+ // Count all of these tokens as additional expansions, to prevent
+ // exponential blowup from linearly many \edef's.
+ this.countExpansion(output.length);
+ return output;
+ }
+
+ /**
+ * Fully expand the given macro name and return the result as a string,
+ * or return `undefined` if no such macro is defined.
+ */
+ expandMacroAsText(name) {
+ const tokens = this.expandMacro(name);
+ if (tokens) {
+ return tokens.map(token => token.text).join("");
+ } else {
+ return tokens;
+ }
+ }
+
+ /**
+ * Returns the expanded macro as a reversed array of tokens and a macro
+ * argument count. Or returns `null` if no such macro.
+ */
+ _getExpansion(name) {
+ const definition = this.macros.get(name);
+ if (definition == null) {
+ // mainly checking for undefined here
+ return definition;
+ }
+ // If a single character has an associated catcode other than 13
+ // (active character), then don't expand it.
+ if (name.length === 1) {
+ const catcode = this.lexer.catcodes[name];
+ if (catcode != null && catcode !== 13) {
+ return;
+ }
+ }
+ const expansion = typeof definition === "function" ? definition(this) : definition;
+ if (typeof expansion === "string") {
+ let numArgs = 0;
+ if (expansion.includes("#")) {
+ const stripped = expansion.replace(/##/g, "");
+ while (stripped.includes("#" + (numArgs + 1))) {
+ ++numArgs;
+ }
+ }
+ const bodyLexer = new Lexer(expansion, this.settings);
+ const tokens = [];
+ let tok = bodyLexer.lex();
+ while (tok.text !== "EOF") {
+ tokens.push(tok);
+ tok = bodyLexer.lex();
+ }
+ tokens.reverse(); // to fit in with stack using push and pop
+ const expanded = {
+ tokens,
+ numArgs
+ };
+ return expanded;
+ }
+ return expansion;
+ }
+
+ /**
+ * Determine whether a command is currently "defined" (has some
+ * functionality), meaning that it's a macro (in the current group),
+ * a function, a symbol, or one of the special commands listed in
+ * `implicitCommands`.
+ */
+ isDefined(name) {
+ return this.macros.has(name) || Object.prototype.hasOwnProperty.call(src_functions, name) || Object.prototype.hasOwnProperty.call(src_symbols.math, name) || Object.prototype.hasOwnProperty.call(src_symbols.text, name) || Object.prototype.hasOwnProperty.call(implicitCommands, name);
+ }
+
+ /**
+ * Determine whether a command is expandable.
+ */
+ isExpandable(name) {
+ const macro = this.macros.get(name);
+ if (macro != null) {
+ return typeof macro === "string" || typeof macro === "function" || !macro.unexpandable;
+ }
+ return Object.prototype.hasOwnProperty.call(src_functions, name) && !src_functions[name].primitive;
+ }
+}
+;// ./src/unicodeSupOrSub.ts
+// Helpers for Parser.js handling of Unicode (sub|super)script characters.
+
+const unicodeSubRegEx = /^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/;
+const uSubsAndSups = Object.freeze({
+ '₊': '+',
+ '₋': '-',
+ '₌': '=',
+ '₍': '(',
+ '₎': ')',
+ '₀': '0',
+ '₁': '1',
+ '₂': '2',
+ '₃': '3',
+ '₄': '4',
+ '₅': '5',
+ '₆': '6',
+ '₇': '7',
+ '₈': '8',
+ '₉': '9',
+ '\u2090': 'a',
+ '\u2091': 'e',
+ '\u2095': 'h',
+ '\u1D62': 'i',
+ '\u2C7C': 'j',
+ '\u2096': 'k',
+ '\u2097': 'l',
+ '\u2098': 'm',
+ '\u2099': 'n',
+ '\u2092': 'o',
+ '\u209A': 'p',
+ '\u1D63': 'r',
+ '\u209B': 's',
+ '\u209C': 't',
+ '\u1D64': 'u',
+ '\u1D65': 'v',
+ '\u2093': 'x',
+ '\u1D66': 'β',
+ '\u1D67': 'γ',
+ '\u1D68': 'ρ',
+ '\u1D69': '\u03d5',
+ '\u1D6A': 'χ',
+ '⁺': '+',
+ '⁻': '-',
+ '⁼': '=',
+ '⁽': '(',
+ '⁾': ')',
+ '⁰': '0',
+ '¹': '1',
+ '²': '2',
+ '³': '3',
+ '⁴': '4',
+ '⁵': '5',
+ '⁶': '6',
+ '⁷': '7',
+ '⁸': '8',
+ '⁹': '9',
+ '\u1D2C': 'A',
+ '\u1D2E': 'B',
+ '\u1D30': 'D',
+ '\u1D31': 'E',
+ '\u1D33': 'G',
+ '\u1D34': 'H',
+ '\u1D35': 'I',
+ '\u1D36': 'J',
+ '\u1D37': 'K',
+ '\u1D38': 'L',
+ '\u1D39': 'M',
+ '\u1D3A': 'N',
+ '\u1D3C': 'O',
+ '\u1D3E': 'P',
+ '\u1D3F': 'R',
+ '\u1D40': 'T',
+ '\u1D41': 'U',
+ '\u2C7D': 'V',
+ '\u1D42': 'W',
+ '\u1D43': 'a',
+ '\u1D47': 'b',
+ '\u1D9C': 'c',
+ '\u1D48': 'd',
+ '\u1D49': 'e',
+ '\u1DA0': 'f',
+ '\u1D4D': 'g',
+ '\u02B0': 'h',
+ '\u2071': 'i',
+ '\u02B2': 'j',
+ '\u1D4F': 'k',
+ '\u02E1': 'l',
+ '\u1D50': 'm',
+ '\u207F': 'n',
+ '\u1D52': 'o',
+ '\u1D56': 'p',
+ '\u02B3': 'r',
+ '\u02E2': 's',
+ '\u1D57': 't',
+ '\u1D58': 'u',
+ '\u1D5B': 'v',
+ '\u02B7': 'w',
+ '\u02E3': 'x',
+ '\u02B8': 'y',
+ '\u1DBB': 'z',
+ '\u1D5D': 'β',
+ '\u1D5E': 'γ',
+ '\u1D5F': 'δ',
+ '\u1D60': '\u03d5',
+ '\u1D61': 'χ',
+ '\u1DBF': 'θ'
+});
+;// ./src/Parser.ts
+/* eslint no-constant-condition:0 */
+
+
+
+
+
+
+
+
+
+
+
+
+// Pre-evaluate both modules as unicodeSymbols require String.normalize()
+const unicodeAccents = {
+ "́": {
+ "text": "\\'",
+ "math": "\\acute"
+ },
+ "̀": {
+ "text": "\\`",
+ "math": "\\grave"
+ },
+ "̈": {
+ "text": "\\\"",
+ "math": "\\ddot"
+ },
+ "̃": {
+ "text": "\\~",
+ "math": "\\tilde"
+ },
+ "̄": {
+ "text": "\\=",
+ "math": "\\bar"
+ },
+ "̆": {
+ "text": "\\u",
+ "math": "\\breve"
+ },
+ "̌": {
+ "text": "\\v",
+ "math": "\\check"
+ },
+ "̂": {
+ "text": "\\^",
+ "math": "\\hat"
+ },
+ "̇": {
+ "text": "\\.",
+ "math": "\\dot"
+ },
+ "̊": {
+ "text": "\\r",
+ "math": "\\mathring"
+ },
+ "̋": {
+ "text": "\\H"
+ },
+ "̧": {
+ "text": "\\c"
+ }
+};
+const unicodeSymbols = {
+ "á": "á",
+ "à": "à",
+ "ä": "ä",
+ "ǟ": "ǟ",
+ "ã": "ã",
+ "ā": "ā",
+ "ă": "ă",
+ "ắ": "ắ",
+ "ằ": "ằ",
+ "ẵ": "ẵ",
+ "ǎ": "ǎ",
+ "â": "â",
+ "ấ": "ấ",
+ "ầ": "ầ",
+ "ẫ": "ẫ",
+ "ȧ": "ȧ",
+ "ǡ": "ǡ",
+ "å": "å",
+ "ǻ": "ǻ",
+ "ḃ": "ḃ",
+ "ć": "ć",
+ "ḉ": "ḉ",
+ "č": "č",
+ "ĉ": "ĉ",
+ "ċ": "ċ",
+ "ç": "ç",
+ "ď": "ď",
+ "ḋ": "ḋ",
+ "ḑ": "ḑ",
+ "é": "é",
+ "è": "è",
+ "ë": "ë",
+ "ẽ": "ẽ",
+ "ē": "ē",
+ "ḗ": "ḗ",
+ "ḕ": "ḕ",
+ "ĕ": "ĕ",
+ "ḝ": "ḝ",
+ "ě": "ě",
+ "ê": "ê",
+ "ế": "ế",
+ "ề": "ề",
+ "ễ": "ễ",
+ "ė": "ė",
+ "ȩ": "ȩ",
+ "ḟ": "ḟ",
+ "ǵ": "ǵ",
+ "ḡ": "ḡ",
+ "ğ": "ğ",
+ "ǧ": "ǧ",
+ "ĝ": "ĝ",
+ "ġ": "ġ",
+ "ģ": "ģ",
+ "ḧ": "ḧ",
+ "ȟ": "ȟ",
+ "ĥ": "ĥ",
+ "ḣ": "ḣ",
+ "ḩ": "ḩ",
+ "í": "í",
+ "ì": "ì",
+ "ï": "ï",
+ "ḯ": "ḯ",
+ "ĩ": "ĩ",
+ "ī": "ī",
+ "ĭ": "ĭ",
+ "ǐ": "ǐ",
+ "î": "î",
+ "ǰ": "ǰ",
+ "ĵ": "ĵ",
+ "ḱ": "ḱ",
+ "ǩ": "ǩ",
+ "ķ": "ķ",
+ "ĺ": "ĺ",
+ "ľ": "ľ",
+ "ļ": "ļ",
+ "ḿ": "ḿ",
+ "ṁ": "ṁ",
+ "ń": "ń",
+ "ǹ": "ǹ",
+ "ñ": "ñ",
+ "ň": "ň",
+ "ṅ": "ṅ",
+ "ņ": "ņ",
+ "ó": "ó",
+ "ò": "ò",
+ "ö": "ö",
+ "ȫ": "ȫ",
+ "õ": "õ",
+ "ṍ": "ṍ",
+ "ṏ": "ṏ",
+ "ȭ": "ȭ",
+ "ō": "ō",
+ "ṓ": "ṓ",
+ "ṑ": "ṑ",
+ "ŏ": "ŏ",
+ "ǒ": "ǒ",
+ "ô": "ô",
+ "ố": "ố",
+ "ồ": "ồ",
+ "ỗ": "ỗ",
+ "ȯ": "ȯ",
+ "ȱ": "ȱ",
+ "ő": "ő",
+ "ṕ": "ṕ",
+ "ṗ": "ṗ",
+ "ŕ": "ŕ",
+ "ř": "ř",
+ "ṙ": "ṙ",
+ "ŗ": "ŗ",
+ "ś": "ś",
+ "ṥ": "ṥ",
+ "š": "š",
+ "ṧ": "ṧ",
+ "ŝ": "ŝ",
+ "ṡ": "ṡ",
+ "ş": "ş",
+ "ẗ": "ẗ",
+ "ť": "ť",
+ "ṫ": "ṫ",
+ "ţ": "ţ",
+ "ú": "ú",
+ "ù": "ù",
+ "ü": "ü",
+ "ǘ": "ǘ",
+ "ǜ": "ǜ",
+ "ǖ": "ǖ",
+ "ǚ": "ǚ",
+ "ũ": "ũ",
+ "ṹ": "ṹ",
+ "ū": "ū",
+ "ṻ": "ṻ",
+ "ŭ": "ŭ",
+ "ǔ": "ǔ",
+ "û": "û",
+ "ů": "ů",
+ "ű": "ű",
+ "ṽ": "ṽ",
+ "ẃ": "ẃ",
+ "ẁ": "ẁ",
+ "ẅ": "ẅ",
+ "ŵ": "ŵ",
+ "ẇ": "ẇ",
+ "ẘ": "ẘ",
+ "ẍ": "ẍ",
+ "ẋ": "ẋ",
+ "ý": "ý",
+ "ỳ": "ỳ",
+ "ÿ": "ÿ",
+ "ỹ": "ỹ",
+ "ȳ": "ȳ",
+ "ŷ": "ŷ",
+ "ẏ": "ẏ",
+ "ẙ": "ẙ",
+ "ź": "ź",
+ "ž": "ž",
+ "ẑ": "ẑ",
+ "ż": "ż",
+ "Á": "Á",
+ "À": "À",
+ "Ä": "Ä",
+ "Ǟ": "Ǟ",
+ "Ã": "Ã",
+ "Ā": "Ā",
+ "Ă": "Ă",
+ "Ắ": "Ắ",
+ "Ằ": "Ằ",
+ "Ẵ": "Ẵ",
+ "Ǎ": "Ǎ",
+ "Â": "Â",
+ "Ấ": "Ấ",
+ "Ầ": "Ầ",
+ "Ẫ": "Ẫ",
+ "Ȧ": "Ȧ",
+ "Ǡ": "Ǡ",
+ "Å": "Å",
+ "Ǻ": "Ǻ",
+ "Ḃ": "Ḃ",
+ "Ć": "Ć",
+ "Ḉ": "Ḉ",
+ "Č": "Č",
+ "Ĉ": "Ĉ",
+ "Ċ": "Ċ",
+ "Ç": "Ç",
+ "Ď": "Ď",
+ "Ḋ": "Ḋ",
+ "Ḑ": "Ḑ",
+ "É": "É",
+ "È": "È",
+ "Ë": "Ë",
+ "Ẽ": "Ẽ",
+ "Ē": "Ē",
+ "Ḗ": "Ḗ",
+ "Ḕ": "Ḕ",
+ "Ĕ": "Ĕ",
+ "Ḝ": "Ḝ",
+ "Ě": "Ě",
+ "Ê": "Ê",
+ "Ế": "Ế",
+ "Ề": "Ề",
+ "Ễ": "Ễ",
+ "Ė": "Ė",
+ "Ȩ": "Ȩ",
+ "Ḟ": "Ḟ",
+ "Ǵ": "Ǵ",
+ "Ḡ": "Ḡ",
+ "Ğ": "Ğ",
+ "Ǧ": "Ǧ",
+ "Ĝ": "Ĝ",
+ "Ġ": "Ġ",
+ "Ģ": "Ģ",
+ "Ḧ": "Ḧ",
+ "Ȟ": "Ȟ",
+ "Ĥ": "Ĥ",
+ "Ḣ": "Ḣ",
+ "Ḩ": "Ḩ",
+ "Í": "Í",
+ "Ì": "Ì",
+ "Ï": "Ï",
+ "Ḯ": "Ḯ",
+ "Ĩ": "Ĩ",
+ "Ī": "Ī",
+ "Ĭ": "Ĭ",
+ "Ǐ": "Ǐ",
+ "Î": "Î",
+ "İ": "İ",
+ "Ĵ": "Ĵ",
+ "Ḱ": "Ḱ",
+ "Ǩ": "Ǩ",
+ "Ķ": "Ķ",
+ "Ĺ": "Ĺ",
+ "Ľ": "Ľ",
+ "Ļ": "Ļ",
+ "Ḿ": "Ḿ",
+ "Ṁ": "Ṁ",
+ "Ń": "Ń",
+ "Ǹ": "Ǹ",
+ "Ñ": "Ñ",
+ "Ň": "Ň",
+ "Ṅ": "Ṅ",
+ "Ņ": "Ņ",
+ "Ó": "Ó",
+ "Ò": "Ò",
+ "Ö": "Ö",
+ "Ȫ": "Ȫ",
+ "Õ": "Õ",
+ "Ṍ": "Ṍ",
+ "Ṏ": "Ṏ",
+ "Ȭ": "Ȭ",
+ "Ō": "Ō",
+ "Ṓ": "Ṓ",
+ "Ṑ": "Ṑ",
+ "Ŏ": "Ŏ",
+ "Ǒ": "Ǒ",
+ "Ô": "Ô",
+ "Ố": "Ố",
+ "Ồ": "Ồ",
+ "Ỗ": "Ỗ",
+ "Ȯ": "Ȯ",
+ "Ȱ": "Ȱ",
+ "Ő": "Ő",
+ "Ṕ": "Ṕ",
+ "Ṗ": "Ṗ",
+ "Ŕ": "Ŕ",
+ "Ř": "Ř",
+ "Ṙ": "Ṙ",
+ "Ŗ": "Ŗ",
+ "Ś": "Ś",
+ "Ṥ": "Ṥ",
+ "Š": "Š",
+ "Ṧ": "Ṧ",
+ "Ŝ": "Ŝ",
+ "Ṡ": "Ṡ",
+ "Ş": "Ş",
+ "Ť": "Ť",
+ "Ṫ": "Ṫ",
+ "Ţ": "Ţ",
+ "Ú": "Ú",
+ "Ù": "Ù",
+ "Ü": "Ü",
+ "Ǘ": "Ǘ",
+ "Ǜ": "Ǜ",
+ "Ǖ": "Ǖ",
+ "Ǚ": "Ǚ",
+ "Ũ": "Ũ",
+ "Ṹ": "Ṹ",
+ "Ū": "Ū",
+ "Ṻ": "Ṻ",
+ "Ŭ": "Ŭ",
+ "Ǔ": "Ǔ",
+ "Û": "Û",
+ "Ů": "Ů",
+ "Ű": "Ű",
+ "Ṽ": "Ṽ",
+ "Ẃ": "Ẃ",
+ "Ẁ": "Ẁ",
+ "Ẅ": "Ẅ",
+ "Ŵ": "Ŵ",
+ "Ẇ": "Ẇ",
+ "Ẍ": "Ẍ",
+ "Ẋ": "Ẋ",
+ "Ý": "Ý",
+ "Ỳ": "Ỳ",
+ "Ÿ": "Ÿ",
+ "Ỹ": "Ỹ",
+ "Ȳ": "Ȳ",
+ "Ŷ": "Ŷ",
+ "Ẏ": "Ẏ",
+ "Ź": "Ź",
+ "Ž": "Ž",
+ "Ẑ": "Ẑ",
+ "Ż": "Ż",
+ "ά": "ά",
+ "ὰ": "ὰ",
+ "ᾱ": "ᾱ",
+ "ᾰ": "ᾰ",
+ "έ": "έ",
+ "ὲ": "ὲ",
+ "ή": "ή",
+ "ὴ": "ὴ",
+ "ί": "ί",
+ "ὶ": "ὶ",
+ "ϊ": "ϊ",
+ "ΐ": "ΐ",
+ "ῒ": "ῒ",
+ "ῑ": "ῑ",
+ "ῐ": "ῐ",
+ "ό": "ό",
+ "ὸ": "ὸ",
+ "ύ": "ύ",
+ "ὺ": "ὺ",
+ "ϋ": "ϋ",
+ "ΰ": "ΰ",
+ "ῢ": "ῢ",
+ "ῡ": "ῡ",
+ "ῠ": "ῠ",
+ "ώ": "ώ",
+ "ὼ": "ὼ",
+ "Ύ": "Ύ",
+ "Ὺ": "Ὺ",
+ "Ϋ": "Ϋ",
+ "Ῡ": "Ῡ",
+ "Ῠ": "Ῠ",
+ "Ώ": "Ώ",
+ "Ὼ": "Ὼ"
+};
+/**
+ * This file contains the parser used to parse out a TeX expression from the
+ * input. Since TeX isn't context-free, standard parsers don't work particularly
+ * well.
+ *
+ * The strategy of this parser is as such:
+ *
+ * The main functions (the `.parse...` ones) take a position in the current
+ * parse string to parse tokens from. The lexer (found in Lexer.js, stored at
+ * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When
+ * individual tokens are needed at a position, the lexer is called to pull out a
+ * token, which is then used.
+ *
+ * The parser has a property called "mode" indicating the mode that
+ * the parser is currently in. Currently it has to be one of "math" or
+ * "text", which denotes whether the current environment is a math-y
+ * one or a text-y one (e.g. inside \text). Currently, this serves to
+ * limit the functions which can be used in text mode.
+ *
+ * The main functions then return an object which contains the useful data that
+ * was parsed at its given point, and a new position at the end of the parsed
+ * data. The main functions can call each other and continue the parsing by
+ * using the returned position as a new starting point.
+ *
+ * There are also extra `.handle...` functions, which pull out some reused
+ * functionality into self-contained functions.
+ *
+ * The functions return ParseNodes.
+ */
+
+class Parser {
+ constructor(input, settings) {
+ this.mode = void 0;
+ this.gullet = void 0;
+ this.settings = void 0;
+ this.leftrightDepth = void 0;
+ this.nextToken = void 0;
+ // Start in math mode
+ this.mode = "math";
+ // Create a new macro expander (gullet) and (indirectly via that) also a
+ // new lexer (mouth) for this parser (stomach, in the language of TeX)
+ this.gullet = new MacroExpander(input, settings, this.mode);
+ // Store the settings for use in parsing
+ this.settings = settings;
+ // Count leftright depth (for \middle errors)
+ this.leftrightDepth = 0;
+ this.nextToken = null;
+ }
+
+ /**
+ * Checks a result to make sure it has the right type, and throws an
+ * appropriate error otherwise.
+ */
+ expect(text, consume) {
+ if (consume === void 0) {
+ consume = true;
+ }
+ if (this.fetch().text !== text) {
+ throw new src_ParseError("Expected '" + text + "', got '" + this.fetch().text + "'", this.fetch());
+ }
+ if (consume) {
+ this.consume();
+ }
+ }
+
+ /**
+ * Discards the current lookahead token, considering it consumed.
+ */
+ consume() {
+ this.nextToken = null;
+ }
+
+ /**
+ * Return the current lookahead token, or if there isn't one (at the
+ * beginning, or if the previous lookahead token was consume()d),
+ * fetch the next token as the new lookahead token and return it.
+ */
+ fetch() {
+ if (this.nextToken == null) {
+ this.nextToken = this.gullet.expandNextToken();
+ }
+ return this.nextToken;
+ }
+
+ /**
+ * Switches between "text" and "math" modes.
+ */
+ switchMode(newMode) {
+ this.mode = newMode;
+ this.gullet.switchMode(newMode);
+ }
+
+ /**
+ * Main parsing function, which parses an entire input.
+ */
+ parse() {
+ if (!this.settings.globalGroup) {
+ // Create a group namespace for the math expression.
+ // (LaTeX creates a new group for every $...$, $$...$$, \[...\].)
+ this.gullet.beginGroup();
+ }
+
+ // Use old \color behavior (same as LaTeX's \textcolor) if requested.
+ // We do this within the group for the math expression, so it doesn't
+ // pollute settings.macros.
+ if (this.settings.colorIsTextColor) {
+ this.gullet.macros.set("\\color", "\\textcolor");
+ }
+ try {
+ // Try to parse the input
+ const parse = this.parseExpression(false);
+
+ // If we succeeded, make sure there's an EOF at the end
+ this.expect("EOF");
+
+ // End the group namespace for the expression
+ if (!this.settings.globalGroup) {
+ this.gullet.endGroup();
+ }
+ return parse;
+
+ // Close any leftover groups in case of a parse error.
+ } finally {
+ this.gullet.endGroups();
+ }
+ }
+
+ /**
+ * Fully parse a separate sequence of tokens as a separate job.
+ * Tokens should be specified in reverse order, as in a MacroDefinition.
+ */
+ subparse(tokens) {
+ // Save the next token from the current job.
+ const oldToken = this.nextToken;
+ this.consume();
+
+ // Run the new job, terminating it with an excess '}'
+ this.gullet.pushToken(new Token("}"));
+ this.gullet.pushTokens(tokens);
+ const parse = this.parseExpression(false);
+ this.expect("}");
+
+ // Restore the next token from the current job.
+ this.nextToken = oldToken;
+ return parse;
+ }
+ /**
+ * Parses an "expression", which is a list of atoms.
+ *
+ * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
+ * happens when functions have higher precedence than infix
+ * nodes in implicit parses.
+ *
+ * `breakOnTokenText`: The text of the token that the expression should end
+ * with, or `null` if something else should end the
+ * expression.
+ */
+ parseExpression(breakOnInfix, breakOnTokenText) {
+ const body = [];
+ // Keep adding atoms to the body until we can't parse any more atoms (either
+ // we reached the end, a }, or a \right)
+ while (true) {
+ // Ignore spaces in math mode
+ if (this.mode === "math") {
+ this.consumeSpaces();
+ }
+ const lex = this.fetch();
+ if (Parser.endOfExpression.has(lex.text)) {
+ break;
+ }
+ if (breakOnTokenText && lex.text === breakOnTokenText) {
+ break;
+ }
+ if (breakOnInfix && src_functions[lex.text] && src_functions[lex.text].infix) {
+ break;
+ }
+ const atom = this.parseAtom(breakOnTokenText);
+ if (!atom) {
+ break;
+ } else if (atom.type === "internal") {
+ // Internal nodes do not appear in parse tree
+ continue;
+ }
+ body.push(atom);
+ }
+ if (this.mode === "text") {
+ this.formLigatures(body);
+ }
+ return this.handleInfixNodes(body);
+ }
+
+ /**
+ * Rewrites infix operators such as \over with corresponding commands such
+ * as \frac.
+ *
+ * There can only be one infix operator per group. If there's more than one
+ * then the expression is ambiguous. This can be resolved by adding {}.
+ */
+ handleInfixNodes(body) {
+ let overIndex = -1;
+ let funcName;
+ for (let i = 0; i < body.length; i++) {
+ const node = body[i];
+ if (node.type === "infix") {
+ if (overIndex !== -1) {
+ throw new src_ParseError("only one infix operator per group", node.token);
+ }
+ overIndex = i;
+ funcName = node.replaceWith;
+ }
+ }
+ if (overIndex !== -1 && funcName) {
+ let numerNode;
+ let denomNode;
+ const numerBody = body.slice(0, overIndex);
+ const denomBody = body.slice(overIndex + 1);
+ if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
+ numerNode = numerBody[0];
+ } else {
+ numerNode = {
+ type: "ordgroup",
+ mode: this.mode,
+ body: numerBody
+ };
+ }
+ if (denomBody.length === 1 && denomBody[0].type === "ordgroup") {
+ denomNode = denomBody[0];
+ } else {
+ denomNode = {
+ type: "ordgroup",
+ mode: this.mode,
+ body: denomBody
+ };
+ }
+ let node;
+ if (funcName === "\\\\abovefrac") {
+ node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []);
+ } else {
+ node = this.callFunction(funcName, [numerNode, denomNode], []);
+ }
+ return [node];
+ } else {
+ return body;
+ }
+ }
+
+ /**
+ * Handle a subscript or superscript with nice errors.
+ */
+ handleSupSubscript(name // For error reporting.
+ ) {
+ const symbolToken = this.fetch();
+ const symbol = symbolToken.text;
+ this.consume();
+ this.consumeSpaces(); // ignore spaces before sup/subscript argument
+
+ // Skip over allowed internal nodes such as \relax
+ let group;
+ do {
+ var _group;
+ group = this.parseGroup(name);
+ } while (((_group = group) == null ? void 0 : _group.type) === "internal");
+ if (!group) {
+ throw new src_ParseError("Expected group after '" + symbol + "'", symbolToken);
+ }
+ return group;
+ }
+
+ /**
+ * Converts the textual input of an unsupported command into a text node
+ * contained within a color node whose color is determined by errorColor
+ */
+ formatUnsupportedCmd(text) {
+ const textordArray = [];
+ for (let i = 0; i < text.length; i++) {
+ textordArray.push({
+ type: "textord",
+ mode: "text",
+ text: text[i]
+ });
+ }
+ const textNode = {
+ type: "text",
+ mode: this.mode,
+ body: textordArray
+ };
+ const colorNode = {
+ type: "color",
+ mode: this.mode,
+ color: this.settings.errorColor,
+ body: [textNode]
+ };
+ return colorNode;
+ }
+
+ /**
+ * Parses a group with optional super/subscripts.
+ */
+ parseAtom(breakOnTokenText) {
+ // The body of an atom is an implicit group, so that things like
+ // \left(x\right)^2 work correctly.
+ const base = this.parseGroup("atom", breakOnTokenText);
+
+ // Internal nodes (e.g. \relax) cannot support super/subscripts.
+ // Instead, we will pick up super/subscripts with blank base next round.
+ if ((base == null ? void 0 : base.type) === "internal") {
+ return base;
+ }
+
+ // In text mode, we don't have superscripts or subscripts
+ if (this.mode === "text") {
+ return base;
+ }
+ let superscript;
+ let subscript;
+ while (true) {
+ // Guaranteed in math mode, so eat any spaces first.
+ this.consumeSpaces();
+
+ // Lex the first token
+ const lex = this.fetch();
+ if (lex.text === "\\limits" || lex.text === "\\nolimits") {
+ // We got a limit control
+ if (base && base.type === "op") {
+ base.limits = lex.text === "\\limits";
+ base.alwaysHandleSupSub = true;
+ } else if (base && base.type === "operatorname") {
+ if (base.alwaysHandleSupSub) {
+ base.limits = lex.text === "\\limits";
+ }
+ } else {
+ throw new src_ParseError("Limit controls must follow a math operator", lex);
+ }
+ this.consume();
+ } else if (lex.text === "^") {
+ // We got a superscript start
+ if (superscript) {
+ throw new src_ParseError("Double superscript", lex);
+ }
+ superscript = this.handleSupSubscript("superscript");
+ } else if (lex.text === "_") {
+ // We got a subscript start
+ if (subscript) {
+ throw new src_ParseError("Double subscript", lex);
+ }
+ subscript = this.handleSupSubscript("subscript");
+ } else if (lex.text === "'") {
+ // We got a prime
+ if (superscript) {
+ throw new src_ParseError("Double superscript", lex);
+ }
+ const prime = {
+ type: "textord",
+ mode: this.mode,
+ text: "\\prime"
+ };
+
+ // Many primes can be grouped together, so we handle this here
+ const primes = [prime];
+ this.consume();
+ // Keep lexing tokens until we get something that's not a prime
+ while (this.fetch().text === "'") {
+ // For each one, add another prime to the list
+ primes.push(prime);
+ this.consume();
+ }
+ // If there's a superscript following the primes, combine that
+ // superscript in with the primes.
+ if (this.fetch().text === "^") {
+ primes.push(this.handleSupSubscript("superscript"));
+ }
+ // Put everything into an ordgroup as the superscript
+ superscript = {
+ type: "ordgroup",
+ mode: this.mode,
+ body: primes
+ };
+ } else if (uSubsAndSups[lex.text]) {
+ // A Unicode subscript or superscript character.
+ // We treat these similarly to the unicode-math package.
+ // So we render a string of Unicode (sub|super)scripts the
+ // same as a (sub|super)script of regular characters.
+ const isSub = unicodeSubRegEx.test(lex.text);
+ const subsupTokens = [];
+ subsupTokens.push(new Token(uSubsAndSups[lex.text]));
+ this.consume();
+ // Continue fetching tokens to fill out the string.
+ while (true) {
+ const token = this.fetch().text;
+ if (!uSubsAndSups[token]) {
+ break;
+ }
+ if (unicodeSubRegEx.test(token) !== isSub) {
+ break;
+ }
+ subsupTokens.unshift(new Token(uSubsAndSups[token]));
+ this.consume();
+ }
+ // Now create a (sub|super)script.
+ const body = this.subparse(subsupTokens);
+ if (isSub) {
+ subscript = {
+ type: "ordgroup",
+ mode: "math",
+ body
+ };
+ } else {
+ superscript = {
+ type: "ordgroup",
+ mode: "math",
+ body
+ };
+ }
+ } else {
+ // If it wasn't ^, _, or ', stop parsing super/subscripts
+ break;
+ }
+ }
+
+ // Base must be set if superscript or subscript are set per logic above,
+ // but need to check here for type check to pass.
+ if (superscript && subscript) {
+ return {
+ type: "supsub",
+ mode: this.mode,
+ base,
+ sup: superscript,
+ sub: subscript
+ };
+ } else if (superscript) {
+ return {
+ type: "supsub",
+ mode: this.mode,
+ base,
+ sup: superscript
+ };
+ } else if (subscript) {
+ return {
+ type: "supsub",
+ mode: this.mode,
+ base,
+ sub: subscript
+ };
+ } else {
+ // Otherwise return the original body
+ return base;
+ }
+ }
+
+ /**
+ * Parses an entire function, including its base and all of its arguments.
+ */
+ parseFunction(breakOnTokenText, name // For determining its context
+ ) {
+ const token = this.fetch();
+ const func = token.text;
+ const funcData = src_functions[func];
+ if (!funcData) {
+ return null;
+ }
+ this.consume(); // consume command token
+
+ if (name && name !== "atom" && !funcData.allowedInArgument) {
+ throw new src_ParseError("Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), token);
+ // Treat undefined allowedInText as false.
+ } else if (this.mode === "text" && !funcData.allowedInText) {
+ throw new src_ParseError("Can't use function '" + func + "' in text mode", token);
+ // Treat undefined allowedInMath as true.
+ } else if (this.mode === "math" && funcData.allowedInMath === false) {
+ throw new src_ParseError("Can't use function '" + func + "' in math mode", token);
+ }
+ const _this$parseArguments = this.parseArguments(func, funcData),
+ args = _this$parseArguments.args,
+ optArgs = _this$parseArguments.optArgs;
+ return this.callFunction(func, args, optArgs, token, breakOnTokenText);
+ }
+
+ /**
+ * Call a function handler with a suitable context and arguments.
+ */
+ callFunction(name, args, optArgs, token, breakOnTokenText) {
+ const context = {
+ funcName: name,
+ parser: this,
+ token,
+ breakOnTokenText
+ };
+ const func = src_functions[name];
+ if (func && func.handler) {
+ return func.handler(context, args, optArgs);
+ } else {
+ throw new src_ParseError("No function handler for " + name);
+ }
+ }
+
+ /**
+ * Parses the arguments of a function or environment
+ */
+ parseArguments(func,
+ // Should look like "\name" or "\begin{name}".
+ funcData) {
+ var _funcData$numOptional;
+ const numOptionalArgs = (_funcData$numOptional = funcData.numOptionalArgs) != null ? _funcData$numOptional : 0;
+ const totalArgs = funcData.numArgs + numOptionalArgs;
+ if (totalArgs === 0) {
+ return {
+ args: [],
+ optArgs: []
+ };
+ }
+ const args = [];
+ const optArgs = [];
+ for (let i = 0; i < totalArgs; i++) {
+ var _funcData$argTypes;
+ let argType = (_funcData$argTypes = funcData.argTypes) == null ? void 0 : _funcData$argTypes[i];
+ const isOptional = i < numOptionalArgs;
+ if ("primitive" in funcData && funcData.primitive && argType == null ||
+ // \sqrt expands into primitive if optional argument doesn't exist
+ funcData.type === "sqrt" && i === 1 && optArgs[0] == null) {
+ argType = "primitive";
+ }
+ const arg = this.parseGroupOfType("argument to '" + func + "'", argType, isOptional);
+ if (isOptional) {
+ optArgs.push(arg);
+ } else if (arg != null) {
+ args.push(arg);
+ } else {
+ // should be unreachable
+ throw new src_ParseError("Null argument, please report this as a bug");
+ }
+ }
+ return {
+ args,
+ optArgs
+ };
+ }
+
+ /**
+ * Parses a group when the mode is changing.
+ */
+ parseGroupOfType(name, type, optional) {
+ switch (type) {
+ case "color":
+ return this.parseColorGroup(optional);
+ case "size":
+ return this.parseSizeGroup(optional);
+ case "url":
+ return this.parseUrlGroup(optional);
+ case "math":
+ case "text":
+ return this.parseArgumentGroup(optional, type);
+ case "hbox":
+ {
+ // hbox argument type wraps the argument in the equivalent of
+ // \hbox, which is like \text but switching to \textstyle size
+ // and resetting math font.
+ const group = this.parseArgumentGroup(optional, "text");
+ return group != null ? {
+ type: "styling",
+ mode: group.mode,
+ body: [group],
+ style: "text",
+ // simulate \textstyle
+ resetFont: true
+ } : null;
+ }
+ case "raw":
+ {
+ const token = this.parseStringGroup(optional);
+ return token != null ? {
+ type: "raw",
+ mode: "text",
+ string: token.text
+ } : null;
+ }
+ case "primitive":
+ {
+ if (optional) {
+ throw new src_ParseError("A primitive argument cannot be optional");
+ }
+ const group = this.parseGroup(name);
+ if (group == null) {
+ throw new src_ParseError("Expected group as " + name, this.fetch());
+ }
+ return group;
+ }
+ case "original":
+ case undefined:
+ return this.parseArgumentGroup(optional);
+ default:
+ throw new src_ParseError("Unknown group type as " + name, this.fetch());
+ }
+ }
+
+ /**
+ * Discard any space tokens, fetching the next non-space token.
+ */
+ consumeSpaces() {
+ while (this.fetch().text === " ") {
+ this.consume();
+ }
+ }
+
+ /**
+ * Parses a group, essentially returning the string formed by the
+ * brace-enclosed tokens plus some position information.
+ */
+ parseStringGroup(optional) {
+ const argToken = this.gullet.scanArgument(optional);
+ if (argToken == null) {
+ return null;
+ }
+ let str = "";
+ let nextToken;
+ while ((nextToken = this.fetch()).text !== "EOF") {
+ str += nextToken.text;
+ this.consume();
+ }
+ this.consume(); // consume the end of the argument
+ argToken.text = str;
+ return argToken;
+ }
+
+ /**
+ * Parses a regex-delimited group: the largest sequence of tokens
+ * whose concatenated strings match `regex`. Returns the string
+ * formed by the tokens plus some position information.
+ */
+ parseRegexGroup(regex, modeName // Used to describe the mode in error messages.
+ ) {
+ const firstToken = this.fetch();
+ let lastToken = firstToken;
+ let str = "";
+ let nextToken;
+ while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) {
+ lastToken = nextToken;
+ str += lastToken.text;
+ this.consume();
+ }
+ if (str === "") {
+ throw new src_ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken);
+ }
+ return firstToken.range(lastToken, str);
+ }
+
+ /**
+ * Parses a color description.
+ */
+ parseColorGroup(optional) {
+ const res = this.parseStringGroup(optional);
+ if (res == null) {
+ return null;
+ }
+ const match = /^(#[a-f0-9]{3,4}|#[a-f0-9]{6}|#[a-f0-9]{8}|[a-f0-9]{6}|[a-z]+)$/i.exec(res.text);
+ if (!match) {
+ throw new src_ParseError("Invalid color: '" + res.text + "'", res);
+ }
+ let color = match[0];
+ if (/^[0-9a-f]{6}$/i.test(color)) {
+ // We allow a 6-digit HTML color spec without a leading "#".
+ // This follows the xcolor package's HTML color model.
+ // Predefined color names are all missed by this RegEx pattern.
+ color = "#" + color;
+ }
+ return {
+ type: "color-token",
+ mode: this.mode,
+ color
+ };
+ }
+
+ /**
+ * Parses a size specification, consisting of magnitude and unit.
+ */
+ parseSizeGroup(optional) {
+ let res;
+ let isBlank = false;
+ // don't expand before parseStringGroup
+ this.gullet.consumeSpaces();
+ if (!optional && this.gullet.future().text !== "{") {
+ res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size");
+ } else {
+ res = this.parseStringGroup(optional);
+ }
+ if (!res) {
+ return null;
+ }
+ if (!optional && res.text.length === 0) {
+ // Because we've tested for what is !optional, this block won't
+ // affect \kern, \hspace, etc. It will capture the mandatory arguments
+ // to \genfrac and \above.
+ res.text = "0pt"; // Enable \above{}
+ isBlank = true; // This is here specifically for \genfrac
+ }
+ const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text);
+ if (!match) {
+ throw new src_ParseError("Invalid size: '" + res.text + "'", res);
+ }
+ const data = {
+ number: +(match[1] + match[2]),
+ // sign + magnitude, cast to number
+ unit: match[3]
+ };
+ if (!validUnit(data)) {
+ throw new src_ParseError("Invalid unit: '" + data.unit + "'", res);
+ }
+ return {
+ type: "size",
+ mode: this.mode,
+ value: data,
+ isBlank
+ };
+ }
+
+ /**
+ * Parses an URL, checking escaped letters and allowed protocols,
+ * and setting the catcode of % as an active character (as in \hyperref).
+ */
+ parseUrlGroup(optional) {
+ this.gullet.lexer.setCatcode("%", 13); // active character
+ this.gullet.lexer.setCatcode("~", 12); // other character
+ const res = this.parseStringGroup(optional);
+ this.gullet.lexer.setCatcode("%", 14); // comment character
+ this.gullet.lexer.setCatcode("~", 13); // active character
+ if (res == null) {
+ return null;
+ }
+ // hyperref package allows backslashes alone in href, but doesn't
+ // generate valid links in such cases; we interpret this as
+ // "undefined" behaviour, and keep them as-is. Some browser will
+ // replace backslashes with forward slashes.
+ const url = res.text.replace(/\\([#$%&~_^{}])/g, '$1');
+ return {
+ type: "url",
+ mode: this.mode,
+ url
+ };
+ }
+
+ /**
+ * Parses an argument with the mode specified.
+ */
+ parseArgumentGroup(optional, mode) {
+ const argToken = this.gullet.scanArgument(optional);
+ if (argToken == null) {
+ return null;
+ }
+ const outerMode = this.mode;
+ if (mode) {
+ // Switch to specified mode
+ this.switchMode(mode);
+ }
+ this.gullet.beginGroup();
+ const expression = this.parseExpression(false, "EOF");
+ // TODO: find an alternative way to denote the end
+ this.expect("EOF"); // expect the end of the argument
+ this.gullet.endGroup();
+ const result = {
+ type: "ordgroup",
+ mode: this.mode,
+ loc: argToken.loc,
+ body: expression
+ };
+ if (mode) {
+ // Switch mode back
+ this.switchMode(outerMode);
+ }
+ return result;
+ }
+
+ /**
+ * Parses an ordinary group, which is either a single nucleus (like "x")
+ * or an expression in braces (like "{x+y}") or an implicit group, a group
+ * that starts at the current position, and ends right before a higher explicit
+ * group ends, or at EOF.
+ */
+ parseGroup(name,
+ // For error reporting.
+ breakOnTokenText) {
+ const firstToken = this.fetch();
+ const text = firstToken.text;
+ let result;
+ // Try to parse an open brace or \begingroup
+ if (text === "{" || text === "\\begingroup") {
+ this.consume();
+ const groupEnd = text === "{" ? "}" : "\\endgroup";
+ this.gullet.beginGroup();
+ // If we get a brace, parse an expression
+ const expression = this.parseExpression(false, groupEnd);
+ const lastToken = this.fetch();
+ this.expect(groupEnd); // Check that we got a matching closing brace
+ this.gullet.endGroup();
+ result = {
+ type: "ordgroup",
+ mode: this.mode,
+ loc: SourceLocation.range(firstToken, lastToken),
+ body: expression,
+ // A group formed by \begingroup...\endgroup is a semi-simple group
+ // which doesn't affect spacing in math mode, i.e., is transparent.
+ // https://tex.stackexchange.com/questions/1930/when-should-one-
+ // use-begingroup-instead-of-bgroup
+ semisimple: text === "\\begingroup" || undefined
+ };
+ } else {
+ // If there exists a function with this name, parse the function.
+ // Otherwise, just return a nucleus
+ result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol();
+ if (result == null && text[0] === "\\" && !Object.prototype.hasOwnProperty.call(implicitCommands, text)) {
+ if (this.settings.throwOnError) {
+ throw new src_ParseError("Undefined control sequence: " + text, firstToken);
+ }
+ result = this.formatUnsupportedCmd(text);
+ this.consume();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Form ligature-like combinations of characters for text mode.
+ * This includes inputs like "--", "---", "``" and "''".
+ * The result will simply replace multiple textord nodes with a single
+ * character in each value by a single textord node having multiple
+ * characters in its value. The representation is still ASCII source.
+ * The group will be modified in place.
+ */
+ formLigatures(group) {
+ let n = group.length - 1;
+ for (let i = 0; i < n; ++i) {
+ const a = group[i];
+ if (a.type !== "textord") {
+ continue;
+ }
+ const v = a.text;
+ const next = group[i + 1];
+ if (!next || next.type !== "textord") {
+ continue;
+ }
+ if (v === "-" && next.text === "-") {
+ const afterNext = group[i + 2];
+ if (i + 1 < n && afterNext && afterNext.type === "textord" && afterNext.text === "-") {
+ group.splice(i, 3, {
+ type: "textord",
+ mode: "text",
+ loc: SourceLocation.range(a, afterNext),
+ text: "---"
+ });
+ n -= 2;
+ } else {
+ group.splice(i, 2, {
+ type: "textord",
+ mode: "text",
+ loc: SourceLocation.range(a, next),
+ text: "--"
+ });
+ n -= 1;
+ }
+ }
+ if ((v === "'" || v === "`") && next.text === v) {
+ group.splice(i, 2, {
+ type: "textord",
+ mode: "text",
+ loc: SourceLocation.range(a, next),
+ text: v + v
+ });
+ n -= 1;
+ }
+ }
+ }
+
+ /**
+ * Parse a single symbol out of the string. Here, we handle single character
+ * symbols and special functions like \verb.
+ */
+ parseSymbol() {
+ const nucleus = this.fetch();
+ let text = nucleus.text;
+ if (/^\\verb[^a-zA-Z]/.test(text)) {
+ this.consume();
+ let arg = text.slice(5);
+ const star = arg.charAt(0) === "*";
+ if (star) {
+ arg = arg.slice(1);
+ }
+ // Lexer's tokenRegex is constructed to always have matching
+ // first/last characters.
+ if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) {
+ throw new src_ParseError("\\verb assertion failed --\n please report what input caused this bug");
+ }
+ arg = arg.slice(1, -1); // remove first and last char
+
+ return {
+ type: "verb",
+ mode: "text",
+ body: arg,
+ star
+ };
+ }
+ // At this point, we should have a symbol, possibly with accents.
+ // First expand any accented base symbol according to unicodeSymbols.
+ if (Object.prototype.hasOwnProperty.call(unicodeSymbols, text[0]) && !src_symbols[this.mode][text[0]]) {
+ // This behavior is not strict (XeTeX-compatible) in math mode.
+ if (this.settings.strict && this.mode === "math") {
+ this.settings.reportNonstrict("unicodeTextInMathMode", "Accented Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
+ }
+ text = unicodeSymbols[text[0]] + text.slice(1);
+ }
+ // Strip off any combining characters
+ const match = combiningDiacriticalMarksEndRegex.exec(text);
+ if (match) {
+ text = text.substring(0, match.index);
+ if (text === 'i') {
+ text = '\u0131'; // dotless i, in math and text mode
+ } else if (text === 'j') {
+ text = '\u0237'; // dotless j, in math and text mode
+ }
+ }
+ // Recognize base symbol
+ let symbol;
+ if (src_symbols[this.mode][text]) {
+ if (this.settings.strict && this.mode === 'math' && extraLatin.includes(text)) {
+ this.settings.reportNonstrict("unicodeTextInMathMode", "Latin-1/Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
+ }
+ const group = src_symbols[this.mode][text].group;
+ const loc = SourceLocation.range(nucleus);
+ let s;
+ if (isAtom(group)) {
+ s = {
+ type: "atom",
+ mode: this.mode,
+ family: group,
+ loc,
+ text
+ };
+ } else {
+ s = {
+ type: group,
+ mode: this.mode,
+ loc,
+ text
+ };
+ }
+ symbol = s;
+ } else if (text.charCodeAt(0) >= 0x80) {
+ // no symbol for e.g. ^
+ if (this.settings.strict) {
+ if (!supportedCodepoint(text.charCodeAt(0))) {
+ this.settings.reportNonstrict("unknownSymbol", "Unrecognized Unicode character \"" + text[0] + "\"" + (" (" + text.charCodeAt(0) + ")"), nucleus);
+ } else if (this.mode === "math") {
+ this.settings.reportNonstrict("unicodeTextInMathMode", "Unicode text character \"" + text[0] + "\" used in math mode", nucleus);
+ }
+ }
+ // All nonmathematical Unicode characters are rendered as if they
+ // are in text mode (wrapped in \text) because that's what it
+ // takes to render them in LaTeX. Setting `mode: this.mode` is
+ // another natural choice (the user requested math mode), but
+ // this makes it more difficult for getCharacterMetrics() to
+ // distinguish Unicode characters without metrics and those for
+ // which we want to simulate the letter M.
+ symbol = {
+ type: "textord",
+ mode: "text",
+ loc: SourceLocation.range(nucleus),
+ text
+ };
+ } else {
+ return null; // EOF, ^, _, {, }, etc.
+ }
+ this.consume();
+ // Transform combining characters into accents
+ if (match) {
+ for (let i = 0; i < match[0].length; i++) {
+ const accent = match[0][i];
+ if (!unicodeAccents[accent]) {
+ throw new src_ParseError("Unknown accent ' " + accent + "'", nucleus);
+ }
+ const command = unicodeAccents[accent][this.mode] || unicodeAccents[accent].text;
+ if (!command) {
+ throw new src_ParseError("Accent " + accent + " unsupported in " + this.mode + " mode", nucleus);
+ }
+ symbol = {
+ type: "accent",
+ mode: this.mode,
+ loc: SourceLocation.range(nucleus),
+ label: command,
+ isStretchy: false,
+ isShifty: true,
+ base: symbol
+ };
+ }
+ }
+ return symbol;
+ }
+}
+Parser.endOfExpression = new Set(["}", "\\endgroup", "\\end", "\\right", "&"]);
+;// ./src/parseTree.ts
+
+
+
+/**
+ * Parses an expression using a Parser, then returns the parsed result.
+ */
+const parseTree = function (toParse, settings) {
+ if (!(typeof toParse === 'string' || toParse instanceof String)) {
+ throw new TypeError('KaTeX can only parse string typed expression');
+ }
+ const parser = new Parser(toParse, settings);
+
+ // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors
+ delete parser.gullet.macros.current["\\df@tag"];
+ let tree = parser.parse();
+
+ // Prevent a color definition from persisting between calls to katex.render().
+ delete parser.gullet.macros.current["\\current@color"];
+ delete parser.gullet.macros.current["\\color"];
+
+ // If the input used \tag, it will set the \df@tag macro to the tag.
+ // In this case, we separately parse the tag and wrap the tree.
+ if (parser.gullet.macros.get("\\df@tag")) {
+ if (!settings.displayMode) {
+ throw new src_ParseError("\\tag works only in display equations");
+ }
+ tree = [{
+ type: "tag",
+ mode: "text",
+ body: tree,
+ tag: parser.subparse([new Token("\\df@tag")])
+ }];
+ }
+ return tree;
+};
+/* harmony default export */ var src_parseTree = (parseTree);
+;// ./katex.ts
+/* eslint no-console:0 */
+/**
+ * This is the main entry point for KaTeX. Here, we expose functions for
+ * rendering expressions either to DOM nodes or to markup strings.
+ *
+ * We also expose the ParseError class to check if errors thrown from KaTeX are
+ * errors in the expression, or errors in javascript handling.
+ */
+
+
+
+
+
+
+
+
+
+
+
+/**
+ * Parse and build an expression, and place that expression in the DOM node
+ * given.
+ */
+let render = function (expression, baseNode, options) {
+ baseNode.textContent = "";
+ const node = renderToDomTree(expression, options).toNode();
+ baseNode.appendChild(node);
+};
+
+// KaTeX's styles don't work properly in quirks mode. Print out an error, and
+// disable rendering.
+if (typeof document !== "undefined") {
+ if (document.compatMode !== "CSS1Compat") {
+ typeof console !== "undefined" && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your " + "website has a suitable doctype.");
+ render = function () {
+ throw new src_ParseError("KaTeX doesn't work in quirks mode.");
+ };
+ }
+}
+
+/**
+ * Parse and build an expression, and return the markup for that.
+ */
+const renderToString = function (expression, options) {
+ const markup = renderToDomTree(expression, options).toMarkup();
+ return markup;
+};
+
+/**
+ * Parse an expression and return the parse tree.
+ */
+const generateParseTree = function (expression, options) {
+ const settings = new Settings(options);
+ return src_parseTree(expression, settings);
+};
+
+/**
+ * If the given error is a KaTeX ParseError and options.throwOnError is false,
+ * renders the invalid LaTeX as a span with hover title giving the KaTeX
+ * error message. Otherwise, simply throws the error.
+ */
+const renderError = function (error, expression, options) {
+ if (options.throwOnError || !(error instanceof src_ParseError)) {
+ throw error;
+ }
+ const node = makeSpan(["katex-error"], [new SymbolNode(expression)]);
+ node.setAttribute("title", error.toString());
+ node.setAttribute("style", "color:" + options.errorColor);
+ return node;
+};
+
+/**
+ * Generates and returns the katex build tree. This is used for advanced
+ * use cases (like rendering to custom output).
+ */
+const renderToDomTree = function (expression, options) {
+ const settings = new Settings(options);
+ try {
+ const tree = src_parseTree(expression, settings);
+ return buildTree(tree, expression, settings);
+ } catch (error) {
+ return renderError(error, expression, settings);
+ }
+};
+
+/**
+ * Generates and returns the katex build tree, with just HTML (no MathML).
+ * This is used for advanced use cases (like rendering to custom output).
+ */
+const renderToHTMLTree = function (expression, options) {
+ const settings = new Settings(options);
+ try {
+ const tree = src_parseTree(expression, settings);
+ return buildHTMLTree(tree, expression, settings);
+ } catch (error) {
+ return renderError(error, expression, settings);
+ }
+};
+const version = "0.18.4";
+const __domTree = {
+ Span: Span,
+ Anchor: Anchor,
+ SymbolNode: SymbolNode,
+ SvgNode: SvgNode,
+ PathNode: PathNode,
+ LineNode: LineNode
+};
+
+// ESM exports
+
+
+// CJS exports and ESM default export
+/* harmony default export */ var katex = ({
+ /**
+ * Current KaTeX version
+ */
+ version,
+ /**
+ * Renders the given LaTeX into an HTML+MathML combination, and adds
+ * it as a child to the specified DOM node.
+ */
+ render,
+ /**
+ * Renders the given LaTeX into an HTML+MathML combination string,
+ * for sending to the client.
+ */
+ renderToString,
+ /**
+ * KaTeX error, usually during parsing.
+ */
+ ParseError: src_ParseError,
+ /**
+ * The schema of Settings
+ */
+ SETTINGS_SCHEMA: SETTINGS_SCHEMA,
+ /**
+ * Parses the given LaTeX into KaTeX's internal parse tree structure,
+ * without rendering to HTML or MathML.
+ *
+ * NOTE: This method is not currently recommended for public use.
+ * The internal tree representation is unstable and is very likely
+ * to change. Use at your own risk.
+ */
+ __parse: generateParseTree,
+ /**
+ * Renders the given LaTeX into an HTML+MathML internal DOM tree
+ * representation, without flattening that representation to a string.
+ *
+ * NOTE: This method is not currently recommended for public use.
+ * The internal tree representation is unstable and is very likely
+ * to change. Use at your own risk.
+ */
+ __renderToDomTree: renderToDomTree,
+ /**
+ * Renders the given LaTeX into an HTML internal DOM tree representation,
+ * without MathML and without flattening that representation to a string.
+ *
+ * NOTE: This method is not currently recommended for public use.
+ * The internal tree representation is unstable and is very likely
+ * to change. Use at your own risk.
+ */
+ __renderToHTMLTree: renderToHTMLTree,
+ /**
+ * extends internal font metrics object with a new object
+ * each key in the new object represents a font name
+ */
+ __setFontMetrics: setFontMetrics,
+ /**
+ * adds a new symbol to builtin symbols table
+ */
+ __defineSymbol: defineSymbol,
+ /**
+ * adds a new function to builtin function list,
+ * which directly produce parse tree elements
+ * and have their own html/mathml builders
+ */
+ __defineFunction: defineFunction,
+ /**
+ * adds a new macro to builtin macro list
+ */
+ __defineMacro: defineMacro,
+ /**
+ * Expose the dom tree node types, which can be useful for type checking nodes.
+ *
+ * NOTE: These methods are not currently recommended for public use.
+ * The internal tree representation is unstable and is very likely
+ * to change. Use at your own risk.
+ */
+ __domTree
+});
+;// ./katex.webpack.js
+/**
+ * This is the webpack entry point for KaTeX. As ECMAScript, flow[1] and jest[2]
+ * doesn't support CSS modules natively, a separate entry point is used and
+ * it is not flowtyped.
+ *
+ * [1] https://gist.github.com/lambdahands/d19e0da96285b749f0ef
+ * [2] https://facebook.github.io/jest/docs/en/webpack.html
+ */
+
+
+/* harmony default export */ var katex_webpack = (katex);
+__webpack_exports__ = __webpack_exports__["default"];
+/******/ return __webpack_exports__;
+/******/ })()
+;
+}); \ No newline at end of file
diff --git a/source/infra/js/katex.min.js b/source/infra/js/katex.min.js
deleted file mode 100644
index f5cd23a..0000000
--- a/source/infra/js/katex.min.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.katex=t():e.katex=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{default:function(){return na}});var r=function e(t,r){this.name=void 0,this.position=void 0,this.length=void 0,this.rawMessage=void 0;var n,a,i="KaTeX parse error: "+t,o=r&&r.loc;if(o&&o.start<=o.end){var s=o.lexer.input;n=o.start,a=o.end,n===s.length?i+=" at end of input: ":i+=" at position "+(n+1)+": ";var l=s.slice(n,a).replace(/[^]/g,"$&\u0332");i+=(n>15?"\u2026"+s.slice(n-15,n):s.slice(0,n))+l+(a+15<s.length?s.slice(a,a+15)+"\u2026":s.slice(a))}var h=new Error(i);return h.name="ParseError",h.__proto__=e.prototype,h.position=n,null!=n&&null!=a&&(h.length=a-n),h.rawMessage=t,h};r.prototype.__proto__=Error.prototype;var n=r,a=/([A-Z])/g,i={"&":"&amp;",">":"&gt;","<":"&lt;",'"':"&quot;","'":"&#x27;"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format <type>"},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color <color>",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:function(e){return"#"+e}},macros:{type:"object",cli:"-m, --macro <def>",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:function(e,t){return t.push(e),t}},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:function(e){return Math.max(0,e)},cli:"--min-rule-thickness <size>",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:function(e){return Math.max(0,e)},cli:"-s, --max-size <n>",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:function(e){return Math.max(0,e)},cli:"-e, --max-expand <n>",cliProcessor:function(e){return"Infinity"===e?1/0:parseInt(e)}},globalGroup:{type:"boolean",cli:!1}};function c(e){if(e.default)return e.default;var t=e.type,r=Array.isArray(t)?t[0]:t;if("string"!=typeof r)return r.enum[0];switch(r){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}var m=function(){function e(e){for(var t in this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{},h)if(h.hasOwnProperty(t)){var r=h[t];this[t]=void 0!==e[t]?r.processor?r.processor(e[t]):e[t]:c(r)}}var t=e.prototype;return t.reportNonstrict=function(e,t,r){var a=this.strict;if("function"==typeof a&&(a=a(e,t,r)),a&&"ignore"!==a){if(!0===a||"error"===a)throw new n("LaTeX-incompatible input and strict mode is set to 'error': "+t+" ["+e+"]",r);"warn"===a?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+a+"': "+t+" ["+e+"]")}},t.useStrictBehavior=function(e,t,r){var n=this.strict;if("function"==typeof n)try{n=n(e,t,r)}catch(e){n="error"}return!(!n||"ignore"===n)&&(!0===n||"error"===n||("warn"===n?("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"),!1):("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]"),!1)))},t.isTrusted=function(e){e.url&&!e.protocol&&(e.protocol=l.protocolFromUrl(e.url));var t="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(t)},e}(),u=function(){function e(e,t,r){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=r}var t=e.prototype;return t.sup=function(){return p[d[this.id]]},t.sub=function(){return p[f[this.id]]},t.fracNum=function(){return p[g[this.id]]},t.fracDen=function(){return p[v[this.id]]},t.cramp=function(){return p[b[this.id]]},t.text=function(){return p[y[this.id]]},t.isTight=function(){return this.size>=2},e}(),p=[new u(0,0,!1),new u(1,0,!0),new u(2,1,!1),new u(3,1,!0),new u(4,2,!1),new u(5,2,!0),new u(6,3,!1),new u(7,3,!0)],d=[4,5,4,5,6,7,6,7],f=[5,5,5,5,7,7,7,7],g=[2,3,4,5,6,7,6,7],v=[3,3,5,5,7,7,7,7],b=[1,1,3,3,5,5,7,7],y=[0,1,2,3,2,3,2,3],x={DISPLAY:p[0],TEXT:p[2],SCRIPT:p[4],SCRIPTSCRIPT:p[6]},w=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];var k=[];function S(e){for(var t=0;t<k.length;t+=2)if(e>=k[t]&&e<=k[t+1])return!0;return!1}w.forEach((function(e){return e.blocks.forEach((function(e){return k.push.apply(k,e)}))}));var M=80,z={doubleleftarrow:"M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",doublerightarrow:"M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",leftarrow:"M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",leftbrace:"M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",leftbraceunder:"M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",leftgroup:"M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",leftgroupunder:"M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",leftharpoon:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",leftharpoonplus:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",leftharpoondown:"M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",leftharpoondownplus:"M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",lefthook:"M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",leftlinesegment:"M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",leftmapsto:"M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",leftToFrom:"M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",longequal:"M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",midbrace:"M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",midbraceunder:"M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",oiintSize1:"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",oiintSize2:"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",oiiintSize1:"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",oiiintSize2:"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",rightarrow:"M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",rightbrace:"M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",rightbraceunder:"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",rightgroup:"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",rightgroupunder:"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",rightharpoon:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",rightharpoonplus:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",rightharpoondown:"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",rightharpoondownplus:"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",righthook:"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",rightlinesegment:"M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",rightToFrom:"M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",twoheadleftarrow:"M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",twoheadrightarrow:"M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",tilde1:"M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",tilde2:"M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",tilde3:"M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",tilde4:"M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",vec:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",widehat1:"M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",widehat2:"M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat3:"M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat4:"M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widecheck1:"M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",widecheck2:"M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck3:"M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck4:"M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",baraboveleftarrow:"M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",rightarrowabovebar:"M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",baraboveshortleftharpoon:"M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",rightharpoonaboveshortbar:"M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",shortbaraboveleftharpoon:"M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",shortrightharpoonabovebar:"M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"},A=function(){function e(e){this.children=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.children=e,this.classes=[],this.height=0,this.depth=0,this.maxFontSize=0,this.style={}}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){for(var e=document.createDocumentFragment(),t=0;t<this.children.length;t++)e.appendChild(this.children[t].toNode());return e},t.toMarkup=function(){for(var e="",t=0;t<this.children.length;t++)e+=this.children[t].toMarkup();return e},t.toText=function(){var e=function(e){return e.toText()};return this.children.map(e).join("")},e}(),T={"AMS-Regular":{32:[0,0,0,0,.25],65:[0,.68889,0,0,.72222],66:[0,.68889,0,0,.66667],67:[0,.68889,0,0,.72222],68:[0,.68889,0,0,.72222],69:[0,.68889,0,0,.66667],70:[0,.68889,0,0,.61111],71:[0,.68889,0,0,.77778],72:[0,.68889,0,0,.77778],73:[0,.68889,0,0,.38889],74:[.16667,.68889,0,0,.5],75:[0,.68889,0,0,.77778],76:[0,.68889,0,0,.66667],77:[0,.68889,0,0,.94445],78:[0,.68889,0,0,.72222],79:[.16667,.68889,0,0,.77778],80:[0,.68889,0,0,.61111],81:[.16667,.68889,0,0,.77778],82:[0,.68889,0,0,.72222],83:[0,.68889,0,0,.55556],84:[0,.68889,0,0,.66667],85:[0,.68889,0,0,.72222],86:[0,.68889,0,0,.72222],87:[0,.68889,0,0,1],88:[0,.68889,0,0,.72222],89:[0,.68889,0,0,.72222],90:[0,.68889,0,0,.66667],107:[0,.68889,0,0,.55556],160:[0,0,0,0,.25],165:[0,.675,.025,0,.75],174:[.15559,.69224,0,0,.94666],240:[0,.68889,0,0,.55556],295:[0,.68889,0,0,.54028],710:[0,.825,0,0,2.33334],732:[0,.9,0,0,2.33334],770:[0,.825,0,0,2.33334],771:[0,.9,0,0,2.33334],989:[.08167,.58167,0,0,.77778],1008:[0,.43056,.04028,0,.66667],8245:[0,.54986,0,0,.275],8463:[0,.68889,0,0,.54028],8487:[0,.68889,0,0,.72222],8498:[0,.68889,0,0,.55556],8502:[0,.68889,0,0,.66667],8503:[0,.68889,0,0,.44445],8504:[0,.68889,0,0,.66667],8513:[0,.68889,0,0,.63889],8592:[-.03598,.46402,0,0,.5],8594:[-.03598,.46402,0,0,.5],8602:[-.13313,.36687,0,0,1],8603:[-.13313,.36687,0,0,1],8606:[.01354,.52239,0,0,1],8608:[.01354,.52239,0,0,1],8610:[.01354,.52239,0,0,1.11111],8611:[.01354,.52239,0,0,1.11111],8619:[0,.54986,0,0,1],8620:[0,.54986,0,0,1],8621:[-.13313,.37788,0,0,1.38889],8622:[-.13313,.36687,0,0,1],8624:[0,.69224,0,0,.5],8625:[0,.69224,0,0,.5],8630:[0,.43056,0,0,1],8631:[0,.43056,0,0,1],8634:[.08198,.58198,0,0,.77778],8635:[.08198,.58198,0,0,.77778],8638:[.19444,.69224,0,0,.41667],8639:[.19444,.69224,0,0,.41667],8642:[.19444,.69224,0,0,.41667],8643:[.19444,.69224,0,0,.41667],8644:[.1808,.675,0,0,1],8646:[.1808,.675,0,0,1],8647:[.1808,.675,0,0,1],8648:[.19444,.69224,0,0,.83334],8649:[.1808,.675,0,0,1],8650:[.19444,.69224,0,0,.83334],8651:[.01354,.52239,0,0,1],8652:[.01354,.52239,0,0,1],8653:[-.13313,.36687,0,0,1],8654:[-.13313,.36687,0,0,1],8655:[-.13313,.36687,0,0,1],8666:[.13667,.63667,0,0,1],8667:[.13667,.63667,0,0,1],8669:[-.13313,.37788,0,0,1],8672:[-.064,.437,0,0,1.334],8674:[-.064,.437,0,0,1.334],8705:[0,.825,0,0,.5],8708:[0,.68889,0,0,.55556],8709:[.08167,.58167,0,0,.77778],8717:[0,.43056,0,0,.42917],8722:[-.03598,.46402,0,0,.5],8724:[.08198,.69224,0,0,.77778],8726:[.08167,.58167,0,0,.77778],8733:[0,.69224,0,0,.77778],8736:[0,.69224,0,0,.72222],8737:[0,.69224,0,0,.72222],8738:[.03517,.52239,0,0,.72222],8739:[.08167,.58167,0,0,.22222],8740:[.25142,.74111,0,0,.27778],8741:[.08167,.58167,0,0,.38889],8742:[.25142,.74111,0,0,.5],8756:[0,.69224,0,0,.66667],8757:[0,.69224,0,0,.66667],8764:[-.13313,.36687,0,0,.77778],8765:[-.13313,.37788,0,0,.77778],8769:[-.13313,.36687,0,0,.77778],8770:[-.03625,.46375,0,0,.77778],8774:[.30274,.79383,0,0,.77778],8776:[-.01688,.48312,0,0,.77778],8778:[.08167,.58167,0,0,.77778],8782:[.06062,.54986,0,0,.77778],8783:[.06062,.54986,0,0,.77778],8785:[.08198,.58198,0,0,.77778],8786:[.08198,.58198,0,0,.77778],8787:[.08198,.58198,0,0,.77778],8790:[0,.69224,0,0,.77778],8791:[.22958,.72958,0,0,.77778],8796:[.08198,.91667,0,0,.77778],8806:[.25583,.75583,0,0,.77778],8807:[.25583,.75583,0,0,.77778],8808:[.25142,.75726,0,0,.77778],8809:[.25142,.75726,0,0,.77778],8812:[.25583,.75583,0,0,.5],8814:[.20576,.70576,0,0,.77778],8815:[.20576,.70576,0,0,.77778],8816:[.30274,.79383,0,0,.77778],8817:[.30274,.79383,0,0,.77778],8818:[.22958,.72958,0,0,.77778],8819:[.22958,.72958,0,0,.77778],8822:[.1808,.675,0,0,.77778],8823:[.1808,.675,0,0,.77778],8828:[.13667,.63667,0,0,.77778],8829:[.13667,.63667,0,0,.77778],8830:[.22958,.72958,0,0,.77778],8831:[.22958,.72958,0,0,.77778],8832:[.20576,.70576,0,0,.77778],8833:[.20576,.70576,0,0,.77778],8840:[.30274,.79383,0,0,.77778],8841:[.30274,.79383,0,0,.77778],8842:[.13597,.63597,0,0,.77778],8843:[.13597,.63597,0,0,.77778],8847:[.03517,.54986,0,0,.77778],8848:[.03517,.54986,0,0,.77778],8858:[.08198,.58198,0,0,.77778],8859:[.08198,.58198,0,0,.77778],8861:[.08198,.58198,0,0,.77778],8862:[0,.675,0,0,.77778],8863:[0,.675,0,0,.77778],8864:[0,.675,0,0,.77778],8865:[0,.675,0,0,.77778],8872:[0,.69224,0,0,.61111],8873:[0,.69224,0,0,.72222],8874:[0,.69224,0,0,.88889],8876:[0,.68889,0,0,.61111],8877:[0,.68889,0,0,.61111],8878:[0,.68889,0,0,.72222],8879:[0,.68889,0,0,.72222],8882:[.03517,.54986,0,0,.77778],8883:[.03517,.54986,0,0,.77778],8884:[.13667,.63667,0,0,.77778],8885:[.13667,.63667,0,0,.77778],8888:[0,.54986,0,0,1.11111],8890:[.19444,.43056,0,0,.55556],8891:[.19444,.69224,0,0,.61111],8892:[.19444,.69224,0,0,.61111],8901:[0,.54986,0,0,.27778],8903:[.08167,.58167,0,0,.77778],8905:[.08167,.58167,0,0,.77778],8906:[.08167,.58167,0,0,.77778],8907:[0,.69224,0,0,.77778],8908:[0,.69224,0,0,.77778],8909:[-.03598,.46402,0,0,.77778],8910:[0,.54986,0,0,.76042],8911:[0,.54986,0,0,.76042],8912:[.03517,.54986,0,0,.77778],8913:[.03517,.54986,0,0,.77778],8914:[0,.54986,0,0,.66667],8915:[0,.54986,0,0,.66667],8916:[0,.69224,0,0,.66667],8918:[.0391,.5391,0,0,.77778],8919:[.0391,.5391,0,0,.77778],8920:[.03517,.54986,0,0,1.33334],8921:[.03517,.54986,0,0,1.33334],8922:[.38569,.88569,0,0,.77778],8923:[.38569,.88569,0,0,.77778],8926:[.13667,.63667,0,0,.77778],8927:[.13667,.63667,0,0,.77778],8928:[.30274,.79383,0,0,.77778],8929:[.30274,.79383,0,0,.77778],8934:[.23222,.74111,0,0,.77778],8935:[.23222,.74111,0,0,.77778],8936:[.23222,.74111,0,0,.77778],8937:[.23222,.74111,0,0,.77778],8938:[.20576,.70576,0,0,.77778],8939:[.20576,.70576,0,0,.77778],8940:[.30274,.79383,0,0,.77778],8941:[.30274,.79383,0,0,.77778],8994:[.19444,.69224,0,0,.77778],8995:[.19444,.69224,0,0,.77778],9416:[.15559,.69224,0,0,.90222],9484:[0,.69224,0,0,.5],9488:[0,.69224,0,0,.5],9492:[0,.37788,0,0,.5],9496:[0,.37788,0,0,.5],9585:[.19444,.68889,0,0,.88889],9586:[.19444,.74111,0,0,.88889],9632:[0,.675,0,0,.77778],9633:[0,.675,0,0,.77778],9650:[0,.54986,0,0,.72222],9651:[0,.54986,0,0,.72222],9654:[.03517,.54986,0,0,.77778],9660:[0,.54986,0,0,.72222],9661:[0,.54986,0,0,.72222],9664:[.03517,.54986,0,0,.77778],9674:[.11111,.69224,0,0,.66667],9733:[.19444,.69224,0,0,.94445],10003:[0,.69224,0,0,.83334],10016:[0,.69224,0,0,.83334],10731:[.11111,.69224,0,0,.66667],10846:[.19444,.75583,0,0,.61111],10877:[.13667,.63667,0,0,.77778],10878:[.13667,.63667,0,0,.77778],10885:[.25583,.75583,0,0,.77778],10886:[.25583,.75583,0,0,.77778],10887:[.13597,.63597,0,0,.77778],10888:[.13597,.63597,0,0,.77778],10889:[.26167,.75726,0,0,.77778],10890:[.26167,.75726,0,0,.77778],10891:[.48256,.98256,0,0,.77778],10892:[.48256,.98256,0,0,.77778],10901:[.13667,.63667,0,0,.77778],10902:[.13667,.63667,0,0,.77778],10933:[.25142,.75726,0,0,.77778],10934:[.25142,.75726,0,0,.77778],10935:[.26167,.75726,0,0,.77778],10936:[.26167,.75726,0,0,.77778],10937:[.26167,.75726,0,0,.77778],10938:[.26167,.75726,0,0,.77778],10949:[.25583,.75583,0,0,.77778],10950:[.25583,.75583,0,0,.77778],10955:[.28481,.79383,0,0,.77778],10956:[.28481,.79383,0,0,.77778],57350:[.08167,.58167,0,0,.22222],57351:[.08167,.58167,0,0,.38889],57352:[.08167,.58167,0,0,.77778],57353:[0,.43056,.04028,0,.66667],57356:[.25142,.75726,0,0,.77778],57357:[.25142,.75726,0,0,.77778],57358:[.41951,.91951,0,0,.77778],57359:[.30274,.79383,0,0,.77778],57360:[.30274,.79383,0,0,.77778],57361:[.41951,.91951,0,0,.77778],57366:[.25142,.75726,0,0,.77778],57367:[.25142,.75726,0,0,.77778],57368:[.25142,.75726,0,0,.77778],57369:[.25142,.75726,0,0,.77778],57370:[.13597,.63597,0,0,.77778],57371:[.13597,.63597,0,0,.77778]},"Caligraphic-Regular":{32:[0,0,0,0,.25],65:[0,.68333,0,.19445,.79847],66:[0,.68333,.03041,.13889,.65681],67:[0,.68333,.05834,.13889,.52653],68:[0,.68333,.02778,.08334,.77139],69:[0,.68333,.08944,.11111,.52778],70:[0,.68333,.09931,.11111,.71875],71:[.09722,.68333,.0593,.11111,.59487],72:[0,.68333,.00965,.11111,.84452],73:[0,.68333,.07382,0,.54452],74:[.09722,.68333,.18472,.16667,.67778],75:[0,.68333,.01445,.05556,.76195],76:[0,.68333,0,.13889,.68972],77:[0,.68333,0,.13889,1.2009],78:[0,.68333,.14736,.08334,.82049],79:[0,.68333,.02778,.11111,.79611],80:[0,.68333,.08222,.08334,.69556],81:[.09722,.68333,0,.11111,.81667],82:[0,.68333,0,.08334,.8475],83:[0,.68333,.075,.13889,.60556],84:[0,.68333,.25417,0,.54464],85:[0,.68333,.09931,.08334,.62583],86:[0,.68333,.08222,0,.61278],87:[0,.68333,.08222,.08334,.98778],88:[0,.68333,.14643,.13889,.7133],89:[.09722,.68333,.08222,.08334,.66834],90:[0,.68333,.07944,.13889,.72473],160:[0,0,0,0,.25]},"Fraktur-Regular":{32:[0,0,0,0,.25],33:[0,.69141,0,0,.29574],34:[0,.69141,0,0,.21471],38:[0,.69141,0,0,.73786],39:[0,.69141,0,0,.21201],40:[.24982,.74947,0,0,.38865],41:[.24982,.74947,0,0,.38865],42:[0,.62119,0,0,.27764],43:[.08319,.58283,0,0,.75623],44:[0,.10803,0,0,.27764],45:[.08319,.58283,0,0,.75623],46:[0,.10803,0,0,.27764],47:[.24982,.74947,0,0,.50181],48:[0,.47534,0,0,.50181],49:[0,.47534,0,0,.50181],50:[0,.47534,0,0,.50181],51:[.18906,.47534,0,0,.50181],52:[.18906,.47534,0,0,.50181],53:[.18906,.47534,0,0,.50181],54:[0,.69141,0,0,.50181],55:[.18906,.47534,0,0,.50181],56:[0,.69141,0,0,.50181],57:[.18906,.47534,0,0,.50181],58:[0,.47534,0,0,.21606],59:[.12604,.47534,0,0,.21606],61:[-.13099,.36866,0,0,.75623],63:[0,.69141,0,0,.36245],65:[0,.69141,0,0,.7176],66:[0,.69141,0,0,.88397],67:[0,.69141,0,0,.61254],68:[0,.69141,0,0,.83158],69:[0,.69141,0,0,.66278],70:[.12604,.69141,0,0,.61119],71:[0,.69141,0,0,.78539],72:[.06302,.69141,0,0,.7203],73:[0,.69141,0,0,.55448],74:[.12604,.69141,0,0,.55231],75:[0,.69141,0,0,.66845],76:[0,.69141,0,0,.66602],77:[0,.69141,0,0,1.04953],78:[0,.69141,0,0,.83212],79:[0,.69141,0,0,.82699],80:[.18906,.69141,0,0,.82753],81:[.03781,.69141,0,0,.82699],82:[0,.69141,0,0,.82807],83:[0,.69141,0,0,.82861],84:[0,.69141,0,0,.66899],85:[0,.69141,0,0,.64576],86:[0,.69141,0,0,.83131],87:[0,.69141,0,0,1.04602],88:[0,.69141,0,0,.71922],89:[.18906,.69141,0,0,.83293],90:[.12604,.69141,0,0,.60201],91:[.24982,.74947,0,0,.27764],93:[.24982,.74947,0,0,.27764],94:[0,.69141,0,0,.49965],97:[0,.47534,0,0,.50046],98:[0,.69141,0,0,.51315],99:[0,.47534,0,0,.38946],100:[0,.62119,0,0,.49857],101:[0,.47534,0,0,.40053],102:[.18906,.69141,0,0,.32626],103:[.18906,.47534,0,0,.5037],104:[.18906,.69141,0,0,.52126],105:[0,.69141,0,0,.27899],106:[0,.69141,0,0,.28088],107:[0,.69141,0,0,.38946],108:[0,.69141,0,0,.27953],109:[0,.47534,0,0,.76676],110:[0,.47534,0,0,.52666],111:[0,.47534,0,0,.48885],112:[.18906,.52396,0,0,.50046],113:[.18906,.47534,0,0,.48912],114:[0,.47534,0,0,.38919],115:[0,.47534,0,0,.44266],116:[0,.62119,0,0,.33301],117:[0,.47534,0,0,.5172],118:[0,.52396,0,0,.5118],119:[0,.52396,0,0,.77351],120:[.18906,.47534,0,0,.38865],121:[.18906,.47534,0,0,.49884],122:[.18906,.47534,0,0,.39054],160:[0,0,0,0,.25],8216:[0,.69141,0,0,.21471],8217:[0,.69141,0,0,.21471],58112:[0,.62119,0,0,.49749],58113:[0,.62119,0,0,.4983],58114:[.18906,.69141,0,0,.33328],58115:[.18906,.69141,0,0,.32923],58116:[.18906,.47534,0,0,.50343],58117:[0,.69141,0,0,.33301],58118:[0,.62119,0,0,.33409],58119:[0,.47534,0,0,.50073]},"Main-Bold":{32:[0,0,0,0,.25],33:[0,.69444,0,0,.35],34:[0,.69444,0,0,.60278],35:[.19444,.69444,0,0,.95833],36:[.05556,.75,0,0,.575],37:[.05556,.75,0,0,.95833],38:[0,.69444,0,0,.89444],39:[0,.69444,0,0,.31944],40:[.25,.75,0,0,.44722],41:[.25,.75,0,0,.44722],42:[0,.75,0,0,.575],43:[.13333,.63333,0,0,.89444],44:[.19444,.15556,0,0,.31944],45:[0,.44444,0,0,.38333],46:[0,.15556,0,0,.31944],47:[.25,.75,0,0,.575],48:[0,.64444,0,0,.575],49:[0,.64444,0,0,.575],50:[0,.64444,0,0,.575],51:[0,.64444,0,0,.575],52:[0,.64444,0,0,.575],53:[0,.64444,0,0,.575],54:[0,.64444,0,0,.575],55:[0,.64444,0,0,.575],56:[0,.64444,0,0,.575],57:[0,.64444,0,0,.575],58:[0,.44444,0,0,.31944],59:[.19444,.44444,0,0,.31944],60:[.08556,.58556,0,0,.89444],61:[-.10889,.39111,0,0,.89444],62:[.08556,.58556,0,0,.89444],63:[0,.69444,0,0,.54305],64:[0,.69444,0,0,.89444],65:[0,.68611,0,0,.86944],66:[0,.68611,0,0,.81805],67:[0,.68611,0,0,.83055],68:[0,.68611,0,0,.88194],69:[0,.68611,0,0,.75555],70:[0,.68611,0,0,.72361],71:[0,.68611,0,0,.90416],72:[0,.68611,0,0,.9],73:[0,.68611,0,0,.43611],74:[0,.68611,0,0,.59444],75:[0,.68611,0,0,.90138],76:[0,.68611,0,0,.69166],77:[0,.68611,0,0,1.09166],78:[0,.68611,0,0,.9],79:[0,.68611,0,0,.86388],80:[0,.68611,0,0,.78611],81:[.19444,.68611,0,0,.86388],82:[0,.68611,0,0,.8625],83:[0,.68611,0,0,.63889],84:[0,.68611,0,0,.8],85:[0,.68611,0,0,.88472],86:[0,.68611,.01597,0,.86944],87:[0,.68611,.01597,0,1.18888],88:[0,.68611,0,0,.86944],89:[0,.68611,.02875,0,.86944],90:[0,.68611,0,0,.70277],91:[.25,.75,0,0,.31944],92:[.25,.75,0,0,.575],93:[.25,.75,0,0,.31944],94:[0,.69444,0,0,.575],95:[.31,.13444,.03194,0,.575],97:[0,.44444,0,0,.55902],98:[0,.69444,0,0,.63889],99:[0,.44444,0,0,.51111],100:[0,.69444,0,0,.63889],101:[0,.44444,0,0,.52708],102:[0,.69444,.10903,0,.35139],103:[.19444,.44444,.01597,0,.575],104:[0,.69444,0,0,.63889],105:[0,.69444,0,0,.31944],106:[.19444,.69444,0,0,.35139],107:[0,.69444,0,0,.60694],108:[0,.69444,0,0,.31944],109:[0,.44444,0,0,.95833],110:[0,.44444,0,0,.63889],111:[0,.44444,0,0,.575],112:[.19444,.44444,0,0,.63889],113:[.19444,.44444,0,0,.60694],114:[0,.44444,0,0,.47361],115:[0,.44444,0,0,.45361],116:[0,.63492,0,0,.44722],117:[0,.44444,0,0,.63889],118:[0,.44444,.01597,0,.60694],119:[0,.44444,.01597,0,.83055],120:[0,.44444,0,0,.60694],121:[.19444,.44444,.01597,0,.60694],122:[0,.44444,0,0,.51111],123:[.25,.75,0,0,.575],124:[.25,.75,0,0,.31944],125:[.25,.75,0,0,.575],126:[.35,.34444,0,0,.575],160:[0,0,0,0,.25],163:[0,.69444,0,0,.86853],168:[0,.69444,0,0,.575],172:[0,.44444,0,0,.76666],176:[0,.69444,0,0,.86944],177:[.13333,.63333,0,0,.89444],184:[.17014,0,0,0,.51111],198:[0,.68611,0,0,1.04166],215:[.13333,.63333,0,0,.89444],216:[.04861,.73472,0,0,.89444],223:[0,.69444,0,0,.59722],230:[0,.44444,0,0,.83055],247:[.13333,.63333,0,0,.89444],248:[.09722,.54167,0,0,.575],305:[0,.44444,0,0,.31944],338:[0,.68611,0,0,1.16944],339:[0,.44444,0,0,.89444],567:[.19444,.44444,0,0,.35139],710:[0,.69444,0,0,.575],711:[0,.63194,0,0,.575],713:[0,.59611,0,0,.575],714:[0,.69444,0,0,.575],715:[0,.69444,0,0,.575],728:[0,.69444,0,0,.575],729:[0,.69444,0,0,.31944],730:[0,.69444,0,0,.86944],732:[0,.69444,0,0,.575],733:[0,.69444,0,0,.575],915:[0,.68611,0,0,.69166],916:[0,.68611,0,0,.95833],920:[0,.68611,0,0,.89444],923:[0,.68611,0,0,.80555],926:[0,.68611,0,0,.76666],928:[0,.68611,0,0,.9],931:[0,.68611,0,0,.83055],933:[0,.68611,0,0,.89444],934:[0,.68611,0,0,.83055],936:[0,.68611,0,0,.89444],937:[0,.68611,0,0,.83055],8211:[0,.44444,.03194,0,.575],8212:[0,.44444,.03194,0,1.14999],8216:[0,.69444,0,0,.31944],8217:[0,.69444,0,0,.31944],8220:[0,.69444,0,0,.60278],8221:[0,.69444,0,0,.60278],8224:[.19444,.69444,0,0,.51111],8225:[.19444,.69444,0,0,.51111],8242:[0,.55556,0,0,.34444],8407:[0,.72444,.15486,0,.575],8463:[0,.69444,0,0,.66759],8465:[0,.69444,0,0,.83055],8467:[0,.69444,0,0,.47361],8472:[.19444,.44444,0,0,.74027],8476:[0,.69444,0,0,.83055],8501:[0,.69444,0,0,.70277],8592:[-.10889,.39111,0,0,1.14999],8593:[.19444,.69444,0,0,.575],8594:[-.10889,.39111,0,0,1.14999],8595:[.19444,.69444,0,0,.575],8596:[-.10889,.39111,0,0,1.14999],8597:[.25,.75,0,0,.575],8598:[.19444,.69444,0,0,1.14999],8599:[.19444,.69444,0,0,1.14999],8600:[.19444,.69444,0,0,1.14999],8601:[.19444,.69444,0,0,1.14999],8636:[-.10889,.39111,0,0,1.14999],8637:[-.10889,.39111,0,0,1.14999],8640:[-.10889,.39111,0,0,1.14999],8641:[-.10889,.39111,0,0,1.14999],8656:[-.10889,.39111,0,0,1.14999],8657:[.19444,.69444,0,0,.70277],8658:[-.10889,.39111,0,0,1.14999],8659:[.19444,.69444,0,0,.70277],8660:[-.10889,.39111,0,0,1.14999],8661:[.25,.75,0,0,.70277],8704:[0,.69444,0,0,.63889],8706:[0,.69444,.06389,0,.62847],8707:[0,.69444,0,0,.63889],8709:[.05556,.75,0,0,.575],8711:[0,.68611,0,0,.95833],8712:[.08556,.58556,0,0,.76666],8715:[.08556,.58556,0,0,.76666],8722:[.13333,.63333,0,0,.89444],8723:[.13333,.63333,0,0,.89444],8725:[.25,.75,0,0,.575],8726:[.25,.75,0,0,.575],8727:[-.02778,.47222,0,0,.575],8728:[-.02639,.47361,0,0,.575],8729:[-.02639,.47361,0,0,.575],8730:[.18,.82,0,0,.95833],8733:[0,.44444,0,0,.89444],8734:[0,.44444,0,0,1.14999],8736:[0,.69224,0,0,.72222],8739:[.25,.75,0,0,.31944],8741:[.25,.75,0,0,.575],8743:[0,.55556,0,0,.76666],8744:[0,.55556,0,0,.76666],8745:[0,.55556,0,0,.76666],8746:[0,.55556,0,0,.76666],8747:[.19444,.69444,.12778,0,.56875],8764:[-.10889,.39111,0,0,.89444],8768:[.19444,.69444,0,0,.31944],8771:[.00222,.50222,0,0,.89444],8773:[.027,.638,0,0,.894],8776:[.02444,.52444,0,0,.89444],8781:[.00222,.50222,0,0,.89444],8801:[.00222,.50222,0,0,.89444],8804:[.19667,.69667,0,0,.89444],8805:[.19667,.69667,0,0,.89444],8810:[.08556,.58556,0,0,1.14999],8811:[.08556,.58556,0,0,1.14999],8826:[.08556,.58556,0,0,.89444],8827:[.08556,.58556,0,0,.89444],8834:[.08556,.58556,0,0,.89444],8835:[.08556,.58556,0,0,.89444],8838:[.19667,.69667,0,0,.89444],8839:[.19667,.69667,0,0,.89444],8846:[0,.55556,0,0,.76666],8849:[.19667,.69667,0,0,.89444],8850:[.19667,.69667,0,0,.89444],8851:[0,.55556,0,0,.76666],8852:[0,.55556,0,0,.76666],8853:[.13333,.63333,0,0,.89444],8854:[.13333,.63333,0,0,.89444],8855:[.13333,.63333,0,0,.89444],8856:[.13333,.63333,0,0,.89444],8857:[.13333,.63333,0,0,.89444],8866:[0,.69444,0,0,.70277],8867:[0,.69444,0,0,.70277],8868:[0,.69444,0,0,.89444],8869:[0,.69444,0,0,.89444],8900:[-.02639,.47361,0,0,.575],8901:[-.02639,.47361,0,0,.31944],8902:[-.02778,.47222,0,0,.575],8968:[.25,.75,0,0,.51111],8969:[.25,.75,0,0,.51111],8970:[.25,.75,0,0,.51111],8971:[.25,.75,0,0,.51111],8994:[-.13889,.36111,0,0,1.14999],8995:[-.13889,.36111,0,0,1.14999],9651:[.19444,.69444,0,0,1.02222],9657:[-.02778,.47222,0,0,.575],9661:[.19444,.69444,0,0,1.02222],9667:[-.02778,.47222,0,0,.575],9711:[.19444,.69444,0,0,1.14999],9824:[.12963,.69444,0,0,.89444],9825:[.12963,.69444,0,0,.89444],9826:[.12963,.69444,0,0,.89444],9827:[.12963,.69444,0,0,.89444],9837:[0,.75,0,0,.44722],9838:[.19444,.69444,0,0,.44722],9839:[.19444,.69444,0,0,.44722],10216:[.25,.75,0,0,.44722],10217:[.25,.75,0,0,.44722],10815:[0,.68611,0,0,.9],10927:[.19667,.69667,0,0,.89444],10928:[.19667,.69667,0,0,.89444],57376:[.19444,.69444,0,0,0]},"Main-BoldItalic":{32:[0,0,0,0,.25],33:[0,.69444,.11417,0,.38611],34:[0,.69444,.07939,0,.62055],35:[.19444,.69444,.06833,0,.94444],37:[.05556,.75,.12861,0,.94444],38:[0,.69444,.08528,0,.88555],39:[0,.69444,.12945,0,.35555],40:[.25,.75,.15806,0,.47333],41:[.25,.75,.03306,0,.47333],42:[0,.75,.14333,0,.59111],43:[.10333,.60333,.03306,0,.88555],44:[.19444,.14722,0,0,.35555],45:[0,.44444,.02611,0,.41444],46:[0,.14722,0,0,.35555],47:[.25,.75,.15806,0,.59111],48:[0,.64444,.13167,0,.59111],49:[0,.64444,.13167,0,.59111],50:[0,.64444,.13167,0,.59111],51:[0,.64444,.13167,0,.59111],52:[.19444,.64444,.13167,0,.59111],53:[0,.64444,.13167,0,.59111],54:[0,.64444,.13167,0,.59111],55:[.19444,.64444,.13167,0,.59111],56:[0,.64444,.13167,0,.59111],57:[0,.64444,.13167,0,.59111],58:[0,.44444,.06695,0,.35555],59:[.19444,.44444,.06695,0,.35555],61:[-.10889,.39111,.06833,0,.88555],63:[0,.69444,.11472,0,.59111],64:[0,.69444,.09208,0,.88555],65:[0,.68611,0,0,.86555],66:[0,.68611,.0992,0,.81666],67:[0,.68611,.14208,0,.82666],68:[0,.68611,.09062,0,.87555],69:[0,.68611,.11431,0,.75666],70:[0,.68611,.12903,0,.72722],71:[0,.68611,.07347,0,.89527],72:[0,.68611,.17208,0,.8961],73:[0,.68611,.15681,0,.47166],74:[0,.68611,.145,0,.61055],75:[0,.68611,.14208,0,.89499],76:[0,.68611,0,0,.69777],77:[0,.68611,.17208,0,1.07277],78:[0,.68611,.17208,0,.8961],79:[0,.68611,.09062,0,.85499],80:[0,.68611,.0992,0,.78721],81:[.19444,.68611,.09062,0,.85499],82:[0,.68611,.02559,0,.85944],83:[0,.68611,.11264,0,.64999],84:[0,.68611,.12903,0,.7961],85:[0,.68611,.17208,0,.88083],86:[0,.68611,.18625,0,.86555],87:[0,.68611,.18625,0,1.15999],88:[0,.68611,.15681,0,.86555],89:[0,.68611,.19803,0,.86555],90:[0,.68611,.14208,0,.70888],91:[.25,.75,.1875,0,.35611],93:[.25,.75,.09972,0,.35611],94:[0,.69444,.06709,0,.59111],95:[.31,.13444,.09811,0,.59111],97:[0,.44444,.09426,0,.59111],98:[0,.69444,.07861,0,.53222],99:[0,.44444,.05222,0,.53222],100:[0,.69444,.10861,0,.59111],101:[0,.44444,.085,0,.53222],102:[.19444,.69444,.21778,0,.4],103:[.19444,.44444,.105,0,.53222],104:[0,.69444,.09426,0,.59111],105:[0,.69326,.11387,0,.35555],106:[.19444,.69326,.1672,0,.35555],107:[0,.69444,.11111,0,.53222],108:[0,.69444,.10861,0,.29666],109:[0,.44444,.09426,0,.94444],110:[0,.44444,.09426,0,.64999],111:[0,.44444,.07861,0,.59111],112:[.19444,.44444,.07861,0,.59111],113:[.19444,.44444,.105,0,.53222],114:[0,.44444,.11111,0,.50167],115:[0,.44444,.08167,0,.48694],116:[0,.63492,.09639,0,.385],117:[0,.44444,.09426,0,.62055],118:[0,.44444,.11111,0,.53222],119:[0,.44444,.11111,0,.76777],120:[0,.44444,.12583,0,.56055],121:[.19444,.44444,.105,0,.56166],122:[0,.44444,.13889,0,.49055],126:[.35,.34444,.11472,0,.59111],160:[0,0,0,0,.25],168:[0,.69444,.11473,0,.59111],176:[0,.69444,0,0,.94888],184:[.17014,0,0,0,.53222],198:[0,.68611,.11431,0,1.02277],216:[.04861,.73472,.09062,0,.88555],223:[.19444,.69444,.09736,0,.665],230:[0,.44444,.085,0,.82666],248:[.09722,.54167,.09458,0,.59111],305:[0,.44444,.09426,0,.35555],338:[0,.68611,.11431,0,1.14054],339:[0,.44444,.085,0,.82666],567:[.19444,.44444,.04611,0,.385],710:[0,.69444,.06709,0,.59111],711:[0,.63194,.08271,0,.59111],713:[0,.59444,.10444,0,.59111],714:[0,.69444,.08528,0,.59111],715:[0,.69444,0,0,.59111],728:[0,.69444,.10333,0,.59111],729:[0,.69444,.12945,0,.35555],730:[0,.69444,0,0,.94888],732:[0,.69444,.11472,0,.59111],733:[0,.69444,.11472,0,.59111],915:[0,.68611,.12903,0,.69777],916:[0,.68611,0,0,.94444],920:[0,.68611,.09062,0,.88555],923:[0,.68611,0,0,.80666],926:[0,.68611,.15092,0,.76777],928:[0,.68611,.17208,0,.8961],931:[0,.68611,.11431,0,.82666],933:[0,.68611,.10778,0,.88555],934:[0,.68611,.05632,0,.82666],936:[0,.68611,.10778,0,.88555],937:[0,.68611,.0992,0,.82666],8211:[0,.44444,.09811,0,.59111],8212:[0,.44444,.09811,0,1.18221],8216:[0,.69444,.12945,0,.35555],8217:[0,.69444,.12945,0,.35555],8220:[0,.69444,.16772,0,.62055],8221:[0,.69444,.07939,0,.62055]},"Main-Italic":{32:[0,0,0,0,.25],33:[0,.69444,.12417,0,.30667],34:[0,.69444,.06961,0,.51444],35:[.19444,.69444,.06616,0,.81777],37:[.05556,.75,.13639,0,.81777],38:[0,.69444,.09694,0,.76666],39:[0,.69444,.12417,0,.30667],40:[.25,.75,.16194,0,.40889],41:[.25,.75,.03694,0,.40889],42:[0,.75,.14917,0,.51111],43:[.05667,.56167,.03694,0,.76666],44:[.19444,.10556,0,0,.30667],45:[0,.43056,.02826,0,.35778],46:[0,.10556,0,0,.30667],47:[.25,.75,.16194,0,.51111],48:[0,.64444,.13556,0,.51111],49:[0,.64444,.13556,0,.51111],50:[0,.64444,.13556,0,.51111],51:[0,.64444,.13556,0,.51111],52:[.19444,.64444,.13556,0,.51111],53:[0,.64444,.13556,0,.51111],54:[0,.64444,.13556,0,.51111],55:[.19444,.64444,.13556,0,.51111],56:[0,.64444,.13556,0,.51111],57:[0,.64444,.13556,0,.51111],58:[0,.43056,.0582,0,.30667],59:[.19444,.43056,.0582,0,.30667],61:[-.13313,.36687,.06616,0,.76666],63:[0,.69444,.1225,0,.51111],64:[0,.69444,.09597,0,.76666],65:[0,.68333,0,0,.74333],66:[0,.68333,.10257,0,.70389],67:[0,.68333,.14528,0,.71555],68:[0,.68333,.09403,0,.755],69:[0,.68333,.12028,0,.67833],70:[0,.68333,.13305,0,.65277],71:[0,.68333,.08722,0,.77361],72:[0,.68333,.16389,0,.74333],73:[0,.68333,.15806,0,.38555],74:[0,.68333,.14028,0,.525],75:[0,.68333,.14528,0,.76888],76:[0,.68333,0,0,.62722],77:[0,.68333,.16389,0,.89666],78:[0,.68333,.16389,0,.74333],79:[0,.68333,.09403,0,.76666],80:[0,.68333,.10257,0,.67833],81:[.19444,.68333,.09403,0,.76666],82:[0,.68333,.03868,0,.72944],83:[0,.68333,.11972,0,.56222],84:[0,.68333,.13305,0,.71555],85:[0,.68333,.16389,0,.74333],86:[0,.68333,.18361,0,.74333],87:[0,.68333,.18361,0,.99888],88:[0,.68333,.15806,0,.74333],89:[0,.68333,.19383,0,.74333],90:[0,.68333,.14528,0,.61333],91:[.25,.75,.1875,0,.30667],93:[.25,.75,.10528,0,.30667],94:[0,.69444,.06646,0,.51111],95:[.31,.12056,.09208,0,.51111],97:[0,.43056,.07671,0,.51111],98:[0,.69444,.06312,0,.46],99:[0,.43056,.05653,0,.46],100:[0,.69444,.10333,0,.51111],101:[0,.43056,.07514,0,.46],102:[.19444,.69444,.21194,0,.30667],103:[.19444,.43056,.08847,0,.46],104:[0,.69444,.07671,0,.51111],105:[0,.65536,.1019,0,.30667],106:[.19444,.65536,.14467,0,.30667],107:[0,.69444,.10764,0,.46],108:[0,.69444,.10333,0,.25555],109:[0,.43056,.07671,0,.81777],110:[0,.43056,.07671,0,.56222],111:[0,.43056,.06312,0,.51111],112:[.19444,.43056,.06312,0,.51111],113:[.19444,.43056,.08847,0,.46],114:[0,.43056,.10764,0,.42166],115:[0,.43056,.08208,0,.40889],116:[0,.61508,.09486,0,.33222],117:[0,.43056,.07671,0,.53666],118:[0,.43056,.10764,0,.46],119:[0,.43056,.10764,0,.66444],120:[0,.43056,.12042,0,.46389],121:[.19444,.43056,.08847,0,.48555],122:[0,.43056,.12292,0,.40889],126:[.35,.31786,.11585,0,.51111],160:[0,0,0,0,.25],168:[0,.66786,.10474,0,.51111],176:[0,.69444,0,0,.83129],184:[.17014,0,0,0,.46],198:[0,.68333,.12028,0,.88277],216:[.04861,.73194,.09403,0,.76666],223:[.19444,.69444,.10514,0,.53666],230:[0,.43056,.07514,0,.71555],248:[.09722,.52778,.09194,0,.51111],338:[0,.68333,.12028,0,.98499],339:[0,.43056,.07514,0,.71555],710:[0,.69444,.06646,0,.51111],711:[0,.62847,.08295,0,.51111],713:[0,.56167,.10333,0,.51111],714:[0,.69444,.09694,0,.51111],715:[0,.69444,0,0,.51111],728:[0,.69444,.10806,0,.51111],729:[0,.66786,.11752,0,.30667],730:[0,.69444,0,0,.83129],732:[0,.66786,.11585,0,.51111],733:[0,.69444,.1225,0,.51111],915:[0,.68333,.13305,0,.62722],916:[0,.68333,0,0,.81777],920:[0,.68333,.09403,0,.76666],923:[0,.68333,0,0,.69222],926:[0,.68333,.15294,0,.66444],928:[0,.68333,.16389,0,.74333],931:[0,.68333,.12028,0,.71555],933:[0,.68333,.11111,0,.76666],934:[0,.68333,.05986,0,.71555],936:[0,.68333,.11111,0,.76666],937:[0,.68333,.10257,0,.71555],8211:[0,.43056,.09208,0,.51111],8212:[0,.43056,.09208,0,1.02222],8216:[0,.69444,.12417,0,.30667],8217:[0,.69444,.12417,0,.30667],8220:[0,.69444,.1685,0,.51444],8221:[0,.69444,.06961,0,.51444],8463:[0,.68889,0,0,.54028]},"Main-Regular":{32:[0,0,0,0,.25],33:[0,.69444,0,0,.27778],34:[0,.69444,0,0,.5],35:[.19444,.69444,0,0,.83334],36:[.05556,.75,0,0,.5],37:[.05556,.75,0,0,.83334],38:[0,.69444,0,0,.77778],39:[0,.69444,0,0,.27778],40:[.25,.75,0,0,.38889],41:[.25,.75,0,0,.38889],42:[0,.75,0,0,.5],43:[.08333,.58333,0,0,.77778],44:[.19444,.10556,0,0,.27778],45:[0,.43056,0,0,.33333],46:[0,.10556,0,0,.27778],47:[.25,.75,0,0,.5],48:[0,.64444,0,0,.5],49:[0,.64444,0,0,.5],50:[0,.64444,0,0,.5],51:[0,.64444,0,0,.5],52:[0,.64444,0,0,.5],53:[0,.64444,0,0,.5],54:[0,.64444,0,0,.5],55:[0,.64444,0,0,.5],56:[0,.64444,0,0,.5],57:[0,.64444,0,0,.5],58:[0,.43056,0,0,.27778],59:[.19444,.43056,0,0,.27778],60:[.0391,.5391,0,0,.77778],61:[-.13313,.36687,0,0,.77778],62:[.0391,.5391,0,0,.77778],63:[0,.69444,0,0,.47222],64:[0,.69444,0,0,.77778],65:[0,.68333,0,0,.75],66:[0,.68333,0,0,.70834],67:[0,.68333,0,0,.72222],68:[0,.68333,0,0,.76389],69:[0,.68333,0,0,.68056],70:[0,.68333,0,0,.65278],71:[0,.68333,0,0,.78472],72:[0,.68333,0,0,.75],73:[0,.68333,0,0,.36111],74:[0,.68333,0,0,.51389],75:[0,.68333,0,0,.77778],76:[0,.68333,0,0,.625],77:[0,.68333,0,0,.91667],78:[0,.68333,0,0,.75],79:[0,.68333,0,0,.77778],80:[0,.68333,0,0,.68056],81:[.19444,.68333,0,0,.77778],82:[0,.68333,0,0,.73611],83:[0,.68333,0,0,.55556],84:[0,.68333,0,0,.72222],85:[0,.68333,0,0,.75],86:[0,.68333,.01389,0,.75],87:[0,.68333,.01389,0,1.02778],88:[0,.68333,0,0,.75],89:[0,.68333,.025,0,.75],90:[0,.68333,0,0,.61111],91:[.25,.75,0,0,.27778],92:[.25,.75,0,0,.5],93:[.25,.75,0,0,.27778],94:[0,.69444,0,0,.5],95:[.31,.12056,.02778,0,.5],97:[0,.43056,0,0,.5],98:[0,.69444,0,0,.55556],99:[0,.43056,0,0,.44445],100:[0,.69444,0,0,.55556],101:[0,.43056,0,0,.44445],102:[0,.69444,.07778,0,.30556],103:[.19444,.43056,.01389,0,.5],104:[0,.69444,0,0,.55556],105:[0,.66786,0,0,.27778],106:[.19444,.66786,0,0,.30556],107:[0,.69444,0,0,.52778],108:[0,.69444,0,0,.27778],109:[0,.43056,0,0,.83334],110:[0,.43056,0,0,.55556],111:[0,.43056,0,0,.5],112:[.19444,.43056,0,0,.55556],113:[.19444,.43056,0,0,.52778],114:[0,.43056,0,0,.39167],115:[0,.43056,0,0,.39445],116:[0,.61508,0,0,.38889],117:[0,.43056,0,0,.55556],118:[0,.43056,.01389,0,.52778],119:[0,.43056,.01389,0,.72222],120:[0,.43056,0,0,.52778],121:[.19444,.43056,.01389,0,.52778],122:[0,.43056,0,0,.44445],123:[.25,.75,0,0,.5],124:[.25,.75,0,0,.27778],125:[.25,.75,0,0,.5],126:[.35,.31786,0,0,.5],160:[0,0,0,0,.25],163:[0,.69444,0,0,.76909],167:[.19444,.69444,0,0,.44445],168:[0,.66786,0,0,.5],172:[0,.43056,0,0,.66667],176:[0,.69444,0,0,.75],177:[.08333,.58333,0,0,.77778],182:[.19444,.69444,0,0,.61111],184:[.17014,0,0,0,.44445],198:[0,.68333,0,0,.90278],215:[.08333,.58333,0,0,.77778],216:[.04861,.73194,0,0,.77778],223:[0,.69444,0,0,.5],230:[0,.43056,0,0,.72222],247:[.08333,.58333,0,0,.77778],248:[.09722,.52778,0,0,.5],305:[0,.43056,0,0,.27778],338:[0,.68333,0,0,1.01389],339:[0,.43056,0,0,.77778],567:[.19444,.43056,0,0,.30556],710:[0,.69444,0,0,.5],711:[0,.62847,0,0,.5],713:[0,.56778,0,0,.5],714:[0,.69444,0,0,.5],715:[0,.69444,0,0,.5],728:[0,.69444,0,0,.5],729:[0,.66786,0,0,.27778],730:[0,.69444,0,0,.75],732:[0,.66786,0,0,.5],733:[0,.69444,0,0,.5],915:[0,.68333,0,0,.625],916:[0,.68333,0,0,.83334],920:[0,.68333,0,0,.77778],923:[0,.68333,0,0,.69445],926:[0,.68333,0,0,.66667],928:[0,.68333,0,0,.75],931:[0,.68333,0,0,.72222],933:[0,.68333,0,0,.77778],934:[0,.68333,0,0,.72222],936:[0,.68333,0,0,.77778],937:[0,.68333,0,0,.72222],8211:[0,.43056,.02778,0,.5],8212:[0,.43056,.02778,0,1],8216:[0,.69444,0,0,.27778],8217:[0,.69444,0,0,.27778],8220:[0,.69444,0,0,.5],8221:[0,.69444,0,0,.5],8224:[.19444,.69444,0,0,.44445],8225:[.19444,.69444,0,0,.44445],8230:[0,.123,0,0,1.172],8242:[0,.55556,0,0,.275],8407:[0,.71444,.15382,0,.5],8463:[0,.68889,0,0,.54028],8465:[0,.69444,0,0,.72222],8467:[0,.69444,0,.11111,.41667],8472:[.19444,.43056,0,.11111,.63646],8476:[0,.69444,0,0,.72222],8501:[0,.69444,0,0,.61111],8592:[-.13313,.36687,0,0,1],8593:[.19444,.69444,0,0,.5],8594:[-.13313,.36687,0,0,1],8595:[.19444,.69444,0,0,.5],8596:[-.13313,.36687,0,0,1],8597:[.25,.75,0,0,.5],8598:[.19444,.69444,0,0,1],8599:[.19444,.69444,0,0,1],8600:[.19444,.69444,0,0,1],8601:[.19444,.69444,0,0,1],8614:[.011,.511,0,0,1],8617:[.011,.511,0,0,1.126],8618:[.011,.511,0,0,1.126],8636:[-.13313,.36687,0,0,1],8637:[-.13313,.36687,0,0,1],8640:[-.13313,.36687,0,0,1],8641:[-.13313,.36687,0,0,1],8652:[.011,.671,0,0,1],8656:[-.13313,.36687,0,0,1],8657:[.19444,.69444,0,0,.61111],8658:[-.13313,.36687,0,0,1],8659:[.19444,.69444,0,0,.61111],8660:[-.13313,.36687,0,0,1],8661:[.25,.75,0,0,.61111],8704:[0,.69444,0,0,.55556],8706:[0,.69444,.05556,.08334,.5309],8707:[0,.69444,0,0,.55556],8709:[.05556,.75,0,0,.5],8711:[0,.68333,0,0,.83334],8712:[.0391,.5391,0,0,.66667],8715:[.0391,.5391,0,0,.66667],8722:[.08333,.58333,0,0,.77778],8723:[.08333,.58333,0,0,.77778],8725:[.25,.75,0,0,.5],8726:[.25,.75,0,0,.5],8727:[-.03472,.46528,0,0,.5],8728:[-.05555,.44445,0,0,.5],8729:[-.05555,.44445,0,0,.5],8730:[.2,.8,0,0,.83334],8733:[0,.43056,0,0,.77778],8734:[0,.43056,0,0,1],8736:[0,.69224,0,0,.72222],8739:[.25,.75,0,0,.27778],8741:[.25,.75,0,0,.5],8743:[0,.55556,0,0,.66667],8744:[0,.55556,0,0,.66667],8745:[0,.55556,0,0,.66667],8746:[0,.55556,0,0,.66667],8747:[.19444,.69444,.11111,0,.41667],8764:[-.13313,.36687,0,0,.77778],8768:[.19444,.69444,0,0,.27778],8771:[-.03625,.46375,0,0,.77778],8773:[-.022,.589,0,0,.778],8776:[-.01688,.48312,0,0,.77778],8781:[-.03625,.46375,0,0,.77778],8784:[-.133,.673,0,0,.778],8801:[-.03625,.46375,0,0,.77778],8804:[.13597,.63597,0,0,.77778],8805:[.13597,.63597,0,0,.77778],8810:[.0391,.5391,0,0,1],8811:[.0391,.5391,0,0,1],8826:[.0391,.5391,0,0,.77778],8827:[.0391,.5391,0,0,.77778],8834:[.0391,.5391,0,0,.77778],8835:[.0391,.5391,0,0,.77778],8838:[.13597,.63597,0,0,.77778],8839:[.13597,.63597,0,0,.77778],8846:[0,.55556,0,0,.66667],8849:[.13597,.63597,0,0,.77778],8850:[.13597,.63597,0,0,.77778],8851:[0,.55556,0,0,.66667],8852:[0,.55556,0,0,.66667],8853:[.08333,.58333,0,0,.77778],8854:[.08333,.58333,0,0,.77778],8855:[.08333,.58333,0,0,.77778],8856:[.08333,.58333,0,0,.77778],8857:[.08333,.58333,0,0,.77778],8866:[0,.69444,0,0,.61111],8867:[0,.69444,0,0,.61111],8868:[0,.69444,0,0,.77778],8869:[0,.69444,0,0,.77778],8872:[.249,.75,0,0,.867],8900:[-.05555,.44445,0,0,.5],8901:[-.05555,.44445,0,0,.27778],8902:[-.03472,.46528,0,0,.5],8904:[.005,.505,0,0,.9],8942:[.03,.903,0,0,.278],8943:[-.19,.313,0,0,1.172],8945:[-.1,.823,0,0,1.282],8968:[.25,.75,0,0,.44445],8969:[.25,.75,0,0,.44445],8970:[.25,.75,0,0,.44445],8971:[.25,.75,0,0,.44445],8994:[-.14236,.35764,0,0,1],8995:[-.14236,.35764,0,0,1],9136:[.244,.744,0,0,.412],9137:[.244,.745,0,0,.412],9651:[.19444,.69444,0,0,.88889],9657:[-.03472,.46528,0,0,.5],9661:[.19444,.69444,0,0,.88889],9667:[-.03472,.46528,0,0,.5],9711:[.19444,.69444,0,0,1],9824:[.12963,.69444,0,0,.77778],9825:[.12963,.69444,0,0,.77778],9826:[.12963,.69444,0,0,.77778],9827:[.12963,.69444,0,0,.77778],9837:[0,.75,0,0,.38889],9838:[.19444,.69444,0,0,.38889],9839:[.19444,.69444,0,0,.38889],10216:[.25,.75,0,0,.38889],10217:[.25,.75,0,0,.38889],10222:[.244,.744,0,0,.412],10223:[.244,.745,0,0,.412],10229:[.011,.511,0,0,1.609],10230:[.011,.511,0,0,1.638],10231:[.011,.511,0,0,1.859],10232:[.024,.525,0,0,1.609],10233:[.024,.525,0,0,1.638],10234:[.024,.525,0,0,1.858],10236:[.011,.511,0,0,1.638],10815:[0,.68333,0,0,.75],10927:[.13597,.63597,0,0,.77778],10928:[.13597,.63597,0,0,.77778],57376:[.19444,.69444,0,0,0]},"Math-BoldItalic":{32:[0,0,0,0,.25],48:[0,.44444,0,0,.575],49:[0,.44444,0,0,.575],50:[0,.44444,0,0,.575],51:[.19444,.44444,0,0,.575],52:[.19444,.44444,0,0,.575],53:[.19444,.44444,0,0,.575],54:[0,.64444,0,0,.575],55:[.19444,.44444,0,0,.575],56:[0,.64444,0,0,.575],57:[.19444,.44444,0,0,.575],65:[0,.68611,0,0,.86944],66:[0,.68611,.04835,0,.8664],67:[0,.68611,.06979,0,.81694],68:[0,.68611,.03194,0,.93812],69:[0,.68611,.05451,0,.81007],70:[0,.68611,.15972,0,.68889],71:[0,.68611,0,0,.88673],72:[0,.68611,.08229,0,.98229],73:[0,.68611,.07778,0,.51111],74:[0,.68611,.10069,0,.63125],75:[0,.68611,.06979,0,.97118],76:[0,.68611,0,0,.75555],77:[0,.68611,.11424,0,1.14201],78:[0,.68611,.11424,0,.95034],79:[0,.68611,.03194,0,.83666],80:[0,.68611,.15972,0,.72309],81:[.19444,.68611,0,0,.86861],82:[0,.68611,.00421,0,.87235],83:[0,.68611,.05382,0,.69271],84:[0,.68611,.15972,0,.63663],85:[0,.68611,.11424,0,.80027],86:[0,.68611,.25555,0,.67778],87:[0,.68611,.15972,0,1.09305],88:[0,.68611,.07778,0,.94722],89:[0,.68611,.25555,0,.67458],90:[0,.68611,.06979,0,.77257],97:[0,.44444,0,0,.63287],98:[0,.69444,0,0,.52083],99:[0,.44444,0,0,.51342],100:[0,.69444,0,0,.60972],101:[0,.44444,0,0,.55361],102:[.19444,.69444,.11042,0,.56806],103:[.19444,.44444,.03704,0,.5449],104:[0,.69444,0,0,.66759],105:[0,.69326,0,0,.4048],106:[.19444,.69326,.0622,0,.47083],107:[0,.69444,.01852,0,.6037],108:[0,.69444,.0088,0,.34815],109:[0,.44444,0,0,1.0324],110:[0,.44444,0,0,.71296],111:[0,.44444,0,0,.58472],112:[.19444,.44444,0,0,.60092],113:[.19444,.44444,.03704,0,.54213],114:[0,.44444,.03194,0,.5287],115:[0,.44444,0,0,.53125],116:[0,.63492,0,0,.41528],117:[0,.44444,0,0,.68102],118:[0,.44444,.03704,0,.56666],119:[0,.44444,.02778,0,.83148],120:[0,.44444,0,0,.65903],121:[.19444,.44444,.03704,0,.59028],122:[0,.44444,.04213,0,.55509],160:[0,0,0,0,.25],915:[0,.68611,.15972,0,.65694],916:[0,.68611,0,0,.95833],920:[0,.68611,.03194,0,.86722],923:[0,.68611,0,0,.80555],926:[0,.68611,.07458,0,.84125],928:[0,.68611,.08229,0,.98229],931:[0,.68611,.05451,0,.88507],933:[0,.68611,.15972,0,.67083],934:[0,.68611,0,0,.76666],936:[0,.68611,.11653,0,.71402],937:[0,.68611,.04835,0,.8789],945:[0,.44444,0,0,.76064],946:[.19444,.69444,.03403,0,.65972],947:[.19444,.44444,.06389,0,.59003],948:[0,.69444,.03819,0,.52222],949:[0,.44444,0,0,.52882],950:[.19444,.69444,.06215,0,.50833],951:[.19444,.44444,.03704,0,.6],952:[0,.69444,.03194,0,.5618],953:[0,.44444,0,0,.41204],954:[0,.44444,0,0,.66759],955:[0,.69444,0,0,.67083],956:[.19444,.44444,0,0,.70787],957:[0,.44444,.06898,0,.57685],958:[.19444,.69444,.03021,0,.50833],959:[0,.44444,0,0,.58472],960:[0,.44444,.03704,0,.68241],961:[.19444,.44444,0,0,.6118],962:[.09722,.44444,.07917,0,.42361],963:[0,.44444,.03704,0,.68588],964:[0,.44444,.13472,0,.52083],965:[0,.44444,.03704,0,.63055],966:[.19444,.44444,0,0,.74722],967:[.19444,.44444,0,0,.71805],968:[.19444,.69444,.03704,0,.75833],969:[0,.44444,.03704,0,.71782],977:[0,.69444,0,0,.69155],981:[.19444,.69444,0,0,.7125],982:[0,.44444,.03194,0,.975],1009:[.19444,.44444,0,0,.6118],1013:[0,.44444,0,0,.48333],57649:[0,.44444,0,0,.39352],57911:[.19444,.44444,0,0,.43889]},"Math-Italic":{32:[0,0,0,0,.25],48:[0,.43056,0,0,.5],49:[0,.43056,0,0,.5],50:[0,.43056,0,0,.5],51:[.19444,.43056,0,0,.5],52:[.19444,.43056,0,0,.5],53:[.19444,.43056,0,0,.5],54:[0,.64444,0,0,.5],55:[.19444,.43056,0,0,.5],56:[0,.64444,0,0,.5],57:[.19444,.43056,0,0,.5],65:[0,.68333,0,.13889,.75],66:[0,.68333,.05017,.08334,.75851],67:[0,.68333,.07153,.08334,.71472],68:[0,.68333,.02778,.05556,.82792],69:[0,.68333,.05764,.08334,.7382],70:[0,.68333,.13889,.08334,.64306],71:[0,.68333,0,.08334,.78625],72:[0,.68333,.08125,.05556,.83125],73:[0,.68333,.07847,.11111,.43958],74:[0,.68333,.09618,.16667,.55451],75:[0,.68333,.07153,.05556,.84931],76:[0,.68333,0,.02778,.68056],77:[0,.68333,.10903,.08334,.97014],78:[0,.68333,.10903,.08334,.80347],79:[0,.68333,.02778,.08334,.76278],80:[0,.68333,.13889,.08334,.64201],81:[.19444,.68333,0,.08334,.79056],82:[0,.68333,.00773,.08334,.75929],83:[0,.68333,.05764,.08334,.6132],84:[0,.68333,.13889,.08334,.58438],85:[0,.68333,.10903,.02778,.68278],86:[0,.68333,.22222,0,.58333],87:[0,.68333,.13889,0,.94445],88:[0,.68333,.07847,.08334,.82847],89:[0,.68333,.22222,0,.58056],90:[0,.68333,.07153,.08334,.68264],97:[0,.43056,0,0,.52859],98:[0,.69444,0,0,.42917],99:[0,.43056,0,.05556,.43276],100:[0,.69444,0,.16667,.52049],101:[0,.43056,0,.05556,.46563],102:[.19444,.69444,.10764,.16667,.48959],103:[.19444,.43056,.03588,.02778,.47697],104:[0,.69444,0,0,.57616],105:[0,.65952,0,0,.34451],106:[.19444,.65952,.05724,0,.41181],107:[0,.69444,.03148,0,.5206],108:[0,.69444,.01968,.08334,.29838],109:[0,.43056,0,0,.87801],110:[0,.43056,0,0,.60023],111:[0,.43056,0,.05556,.48472],112:[.19444,.43056,0,.08334,.50313],113:[.19444,.43056,.03588,.08334,.44641],114:[0,.43056,.02778,.05556,.45116],115:[0,.43056,0,.05556,.46875],116:[0,.61508,0,.08334,.36111],117:[0,.43056,0,.02778,.57246],118:[0,.43056,.03588,.02778,.48472],119:[0,.43056,.02691,.08334,.71592],120:[0,.43056,0,.02778,.57153],121:[.19444,.43056,.03588,.05556,.49028],122:[0,.43056,.04398,.05556,.46505],160:[0,0,0,0,.25],915:[0,.68333,.13889,.08334,.61528],916:[0,.68333,0,.16667,.83334],920:[0,.68333,.02778,.08334,.76278],923:[0,.68333,0,.16667,.69445],926:[0,.68333,.07569,.08334,.74236],928:[0,.68333,.08125,.05556,.83125],931:[0,.68333,.05764,.08334,.77986],933:[0,.68333,.13889,.05556,.58333],934:[0,.68333,0,.08334,.66667],936:[0,.68333,.11,.05556,.61222],937:[0,.68333,.05017,.08334,.7724],945:[0,.43056,.0037,.02778,.6397],946:[.19444,.69444,.05278,.08334,.56563],947:[.19444,.43056,.05556,0,.51773],948:[0,.69444,.03785,.05556,.44444],949:[0,.43056,0,.08334,.46632],950:[.19444,.69444,.07378,.08334,.4375],951:[.19444,.43056,.03588,.05556,.49653],952:[0,.69444,.02778,.08334,.46944],953:[0,.43056,0,.05556,.35394],954:[0,.43056,0,0,.57616],955:[0,.69444,0,0,.58334],956:[.19444,.43056,0,.02778,.60255],957:[0,.43056,.06366,.02778,.49398],958:[.19444,.69444,.04601,.11111,.4375],959:[0,.43056,0,.05556,.48472],960:[0,.43056,.03588,0,.57003],961:[.19444,.43056,0,.08334,.51702],962:[.09722,.43056,.07986,.08334,.36285],963:[0,.43056,.03588,0,.57141],964:[0,.43056,.1132,.02778,.43715],965:[0,.43056,.03588,.02778,.54028],966:[.19444,.43056,0,.08334,.65417],967:[.19444,.43056,0,.05556,.62569],968:[.19444,.69444,.03588,.11111,.65139],969:[0,.43056,.03588,0,.62245],977:[0,.69444,0,.08334,.59144],981:[.19444,.69444,0,.08334,.59583],982:[0,.43056,.02778,0,.82813],1009:[.19444,.43056,0,.08334,.51702],1013:[0,.43056,0,.05556,.4059],57649:[0,.43056,0,.02778,.32246],57911:[.19444,.43056,0,.08334,.38403]},"SansSerif-Bold":{32:[0,0,0,0,.25],33:[0,.69444,0,0,.36667],34:[0,.69444,0,0,.55834],35:[.19444,.69444,0,0,.91667],36:[.05556,.75,0,0,.55],37:[.05556,.75,0,0,1.02912],38:[0,.69444,0,0,.83056],39:[0,.69444,0,0,.30556],40:[.25,.75,0,0,.42778],41:[.25,.75,0,0,.42778],42:[0,.75,0,0,.55],43:[.11667,.61667,0,0,.85556],44:[.10556,.13056,0,0,.30556],45:[0,.45833,0,0,.36667],46:[0,.13056,0,0,.30556],47:[.25,.75,0,0,.55],48:[0,.69444,0,0,.55],49:[0,.69444,0,0,.55],50:[0,.69444,0,0,.55],51:[0,.69444,0,0,.55],52:[0,.69444,0,0,.55],53:[0,.69444,0,0,.55],54:[0,.69444,0,0,.55],55:[0,.69444,0,0,.55],56:[0,.69444,0,0,.55],57:[0,.69444,0,0,.55],58:[0,.45833,0,0,.30556],59:[.10556,.45833,0,0,.30556],61:[-.09375,.40625,0,0,.85556],63:[0,.69444,0,0,.51945],64:[0,.69444,0,0,.73334],65:[0,.69444,0,0,.73334],66:[0,.69444,0,0,.73334],67:[0,.69444,0,0,.70278],68:[0,.69444,0,0,.79445],69:[0,.69444,0,0,.64167],70:[0,.69444,0,0,.61111],71:[0,.69444,0,0,.73334],72:[0,.69444,0,0,.79445],73:[0,.69444,0,0,.33056],74:[0,.69444,0,0,.51945],75:[0,.69444,0,0,.76389],76:[0,.69444,0,0,.58056],77:[0,.69444,0,0,.97778],78:[0,.69444,0,0,.79445],79:[0,.69444,0,0,.79445],80:[0,.69444,0,0,.70278],81:[.10556,.69444,0,0,.79445],82:[0,.69444,0,0,.70278],83:[0,.69444,0,0,.61111],84:[0,.69444,0,0,.73334],85:[0,.69444,0,0,.76389],86:[0,.69444,.01528,0,.73334],87:[0,.69444,.01528,0,1.03889],88:[0,.69444,0,0,.73334],89:[0,.69444,.0275,0,.73334],90:[0,.69444,0,0,.67223],91:[.25,.75,0,0,.34306],93:[.25,.75,0,0,.34306],94:[0,.69444,0,0,.55],95:[.35,.10833,.03056,0,.55],97:[0,.45833,0,0,.525],98:[0,.69444,0,0,.56111],99:[0,.45833,0,0,.48889],100:[0,.69444,0,0,.56111],101:[0,.45833,0,0,.51111],102:[0,.69444,.07639,0,.33611],103:[.19444,.45833,.01528,0,.55],104:[0,.69444,0,0,.56111],105:[0,.69444,0,0,.25556],106:[.19444,.69444,0,0,.28611],107:[0,.69444,0,0,.53056],108:[0,.69444,0,0,.25556],109:[0,.45833,0,0,.86667],110:[0,.45833,0,0,.56111],111:[0,.45833,0,0,.55],112:[.19444,.45833,0,0,.56111],113:[.19444,.45833,0,0,.56111],114:[0,.45833,.01528,0,.37222],115:[0,.45833,0,0,.42167],116:[0,.58929,0,0,.40417],117:[0,.45833,0,0,.56111],118:[0,.45833,.01528,0,.5],119:[0,.45833,.01528,0,.74445],120:[0,.45833,0,0,.5],121:[.19444,.45833,.01528,0,.5],122:[0,.45833,0,0,.47639],126:[.35,.34444,0,0,.55],160:[0,0,0,0,.25],168:[0,.69444,0,0,.55],176:[0,.69444,0,0,.73334],180:[0,.69444,0,0,.55],184:[.17014,0,0,0,.48889],305:[0,.45833,0,0,.25556],567:[.19444,.45833,0,0,.28611],710:[0,.69444,0,0,.55],711:[0,.63542,0,0,.55],713:[0,.63778,0,0,.55],728:[0,.69444,0,0,.55],729:[0,.69444,0,0,.30556],730:[0,.69444,0,0,.73334],732:[0,.69444,0,0,.55],733:[0,.69444,0,0,.55],915:[0,.69444,0,0,.58056],916:[0,.69444,0,0,.91667],920:[0,.69444,0,0,.85556],923:[0,.69444,0,0,.67223],926:[0,.69444,0,0,.73334],928:[0,.69444,0,0,.79445],931:[0,.69444,0,0,.79445],933:[0,.69444,0,0,.85556],934:[0,.69444,0,0,.79445],936:[0,.69444,0,0,.85556],937:[0,.69444,0,0,.79445],8211:[0,.45833,.03056,0,.55],8212:[0,.45833,.03056,0,1.10001],8216:[0,.69444,0,0,.30556],8217:[0,.69444,0,0,.30556],8220:[0,.69444,0,0,.55834],8221:[0,.69444,0,0,.55834]},"SansSerif-Italic":{32:[0,0,0,0,.25],33:[0,.69444,.05733,0,.31945],34:[0,.69444,.00316,0,.5],35:[.19444,.69444,.05087,0,.83334],36:[.05556,.75,.11156,0,.5],37:[.05556,.75,.03126,0,.83334],38:[0,.69444,.03058,0,.75834],39:[0,.69444,.07816,0,.27778],40:[.25,.75,.13164,0,.38889],41:[.25,.75,.02536,0,.38889],42:[0,.75,.11775,0,.5],43:[.08333,.58333,.02536,0,.77778],44:[.125,.08333,0,0,.27778],45:[0,.44444,.01946,0,.33333],46:[0,.08333,0,0,.27778],47:[.25,.75,.13164,0,.5],48:[0,.65556,.11156,0,.5],49:[0,.65556,.11156,0,.5],50:[0,.65556,.11156,0,.5],51:[0,.65556,.11156,0,.5],52:[0,.65556,.11156,0,.5],53:[0,.65556,.11156,0,.5],54:[0,.65556,.11156,0,.5],55:[0,.65556,.11156,0,.5],56:[0,.65556,.11156,0,.5],57:[0,.65556,.11156,0,.5],58:[0,.44444,.02502,0,.27778],59:[.125,.44444,.02502,0,.27778],61:[-.13,.37,.05087,0,.77778],63:[0,.69444,.11809,0,.47222],64:[0,.69444,.07555,0,.66667],65:[0,.69444,0,0,.66667],66:[0,.69444,.08293,0,.66667],67:[0,.69444,.11983,0,.63889],68:[0,.69444,.07555,0,.72223],69:[0,.69444,.11983,0,.59722],70:[0,.69444,.13372,0,.56945],71:[0,.69444,.11983,0,.66667],72:[0,.69444,.08094,0,.70834],73:[0,.69444,.13372,0,.27778],74:[0,.69444,.08094,0,.47222],75:[0,.69444,.11983,0,.69445],76:[0,.69444,0,0,.54167],77:[0,.69444,.08094,0,.875],78:[0,.69444,.08094,0,.70834],79:[0,.69444,.07555,0,.73611],80:[0,.69444,.08293,0,.63889],81:[.125,.69444,.07555,0,.73611],82:[0,.69444,.08293,0,.64584],83:[0,.69444,.09205,0,.55556],84:[0,.69444,.13372,0,.68056],85:[0,.69444,.08094,0,.6875],86:[0,.69444,.1615,0,.66667],87:[0,.69444,.1615,0,.94445],88:[0,.69444,.13372,0,.66667],89:[0,.69444,.17261,0,.66667],90:[0,.69444,.11983,0,.61111],91:[.25,.75,.15942,0,.28889],93:[.25,.75,.08719,0,.28889],94:[0,.69444,.0799,0,.5],95:[.35,.09444,.08616,0,.5],97:[0,.44444,.00981,0,.48056],98:[0,.69444,.03057,0,.51667],99:[0,.44444,.08336,0,.44445],100:[0,.69444,.09483,0,.51667],101:[0,.44444,.06778,0,.44445],102:[0,.69444,.21705,0,.30556],103:[.19444,.44444,.10836,0,.5],104:[0,.69444,.01778,0,.51667],105:[0,.67937,.09718,0,.23889],106:[.19444,.67937,.09162,0,.26667],107:[0,.69444,.08336,0,.48889],108:[0,.69444,.09483,0,.23889],109:[0,.44444,.01778,0,.79445],110:[0,.44444,.01778,0,.51667],111:[0,.44444,.06613,0,.5],112:[.19444,.44444,.0389,0,.51667],113:[.19444,.44444,.04169,0,.51667],114:[0,.44444,.10836,0,.34167],115:[0,.44444,.0778,0,.38333],116:[0,.57143,.07225,0,.36111],117:[0,.44444,.04169,0,.51667],118:[0,.44444,.10836,0,.46111],119:[0,.44444,.10836,0,.68334],120:[0,.44444,.09169,0,.46111],121:[.19444,.44444,.10836,0,.46111],122:[0,.44444,.08752,0,.43472],126:[.35,.32659,.08826,0,.5],160:[0,0,0,0,.25],168:[0,.67937,.06385,0,.5],176:[0,.69444,0,0,.73752],184:[.17014,0,0,0,.44445],305:[0,.44444,.04169,0,.23889],567:[.19444,.44444,.04169,0,.26667],710:[0,.69444,.0799,0,.5],711:[0,.63194,.08432,0,.5],713:[0,.60889,.08776,0,.5],714:[0,.69444,.09205,0,.5],715:[0,.69444,0,0,.5],728:[0,.69444,.09483,0,.5],729:[0,.67937,.07774,0,.27778],730:[0,.69444,0,0,.73752],732:[0,.67659,.08826,0,.5],733:[0,.69444,.09205,0,.5],915:[0,.69444,.13372,0,.54167],916:[0,.69444,0,0,.83334],920:[0,.69444,.07555,0,.77778],923:[0,.69444,0,0,.61111],926:[0,.69444,.12816,0,.66667],928:[0,.69444,.08094,0,.70834],931:[0,.69444,.11983,0,.72222],933:[0,.69444,.09031,0,.77778],934:[0,.69444,.04603,0,.72222],936:[0,.69444,.09031,0,.77778],937:[0,.69444,.08293,0,.72222],8211:[0,.44444,.08616,0,.5],8212:[0,.44444,.08616,0,1],8216:[0,.69444,.07816,0,.27778],8217:[0,.69444,.07816,0,.27778],8220:[0,.69444,.14205,0,.5],8221:[0,.69444,.00316,0,.5]},"SansSerif-Regular":{32:[0,0,0,0,.25],33:[0,.69444,0,0,.31945],34:[0,.69444,0,0,.5],35:[.19444,.69444,0,0,.83334],36:[.05556,.75,0,0,.5],37:[.05556,.75,0,0,.83334],38:[0,.69444,0,0,.75834],39:[0,.69444,0,0,.27778],40:[.25,.75,0,0,.38889],41:[.25,.75,0,0,.38889],42:[0,.75,0,0,.5],43:[.08333,.58333,0,0,.77778],44:[.125,.08333,0,0,.27778],45:[0,.44444,0,0,.33333],46:[0,.08333,0,0,.27778],47:[.25,.75,0,0,.5],48:[0,.65556,0,0,.5],49:[0,.65556,0,0,.5],50:[0,.65556,0,0,.5],51:[0,.65556,0,0,.5],52:[0,.65556,0,0,.5],53:[0,.65556,0,0,.5],54:[0,.65556,0,0,.5],55:[0,.65556,0,0,.5],56:[0,.65556,0,0,.5],57:[0,.65556,0,0,.5],58:[0,.44444,0,0,.27778],59:[.125,.44444,0,0,.27778],61:[-.13,.37,0,0,.77778],63:[0,.69444,0,0,.47222],64:[0,.69444,0,0,.66667],65:[0,.69444,0,0,.66667],66:[0,.69444,0,0,.66667],67:[0,.69444,0,0,.63889],68:[0,.69444,0,0,.72223],69:[0,.69444,0,0,.59722],70:[0,.69444,0,0,.56945],71:[0,.69444,0,0,.66667],72:[0,.69444,0,0,.70834],73:[0,.69444,0,0,.27778],74:[0,.69444,0,0,.47222],75:[0,.69444,0,0,.69445],76:[0,.69444,0,0,.54167],77:[0,.69444,0,0,.875],78:[0,.69444,0,0,.70834],79:[0,.69444,0,0,.73611],80:[0,.69444,0,0,.63889],81:[.125,.69444,0,0,.73611],82:[0,.69444,0,0,.64584],83:[0,.69444,0,0,.55556],84:[0,.69444,0,0,.68056],85:[0,.69444,0,0,.6875],86:[0,.69444,.01389,0,.66667],87:[0,.69444,.01389,0,.94445],88:[0,.69444,0,0,.66667],89:[0,.69444,.025,0,.66667],90:[0,.69444,0,0,.61111],91:[.25,.75,0,0,.28889],93:[.25,.75,0,0,.28889],94:[0,.69444,0,0,.5],95:[.35,.09444,.02778,0,.5],97:[0,.44444,0,0,.48056],98:[0,.69444,0,0,.51667],99:[0,.44444,0,0,.44445],100:[0,.69444,0,0,.51667],101:[0,.44444,0,0,.44445],102:[0,.69444,.06944,0,.30556],103:[.19444,.44444,.01389,0,.5],104:[0,.69444,0,0,.51667],105:[0,.67937,0,0,.23889],106:[.19444,.67937,0,0,.26667],107:[0,.69444,0,0,.48889],108:[0,.69444,0,0,.23889],109:[0,.44444,0,0,.79445],110:[0,.44444,0,0,.51667],111:[0,.44444,0,0,.5],112:[.19444,.44444,0,0,.51667],113:[.19444,.44444,0,0,.51667],114:[0,.44444,.01389,0,.34167],115:[0,.44444,0,0,.38333],116:[0,.57143,0,0,.36111],117:[0,.44444,0,0,.51667],118:[0,.44444,.01389,0,.46111],119:[0,.44444,.01389,0,.68334],120:[0,.44444,0,0,.46111],121:[.19444,.44444,.01389,0,.46111],122:[0,.44444,0,0,.43472],126:[.35,.32659,0,0,.5],160:[0,0,0,0,.25],168:[0,.67937,0,0,.5],176:[0,.69444,0,0,.66667],184:[.17014,0,0,0,.44445],305:[0,.44444,0,0,.23889],567:[.19444,.44444,0,0,.26667],710:[0,.69444,0,0,.5],711:[0,.63194,0,0,.5],713:[0,.60889,0,0,.5],714:[0,.69444,0,0,.5],715:[0,.69444,0,0,.5],728:[0,.69444,0,0,.5],729:[0,.67937,0,0,.27778],730:[0,.69444,0,0,.66667],732:[0,.67659,0,0,.5],733:[0,.69444,0,0,.5],915:[0,.69444,0,0,.54167],916:[0,.69444,0,0,.83334],920:[0,.69444,0,0,.77778],923:[0,.69444,0,0,.61111],926:[0,.69444,0,0,.66667],928:[0,.69444,0,0,.70834],931:[0,.69444,0,0,.72222],933:[0,.69444,0,0,.77778],934:[0,.69444,0,0,.72222],936:[0,.69444,0,0,.77778],937:[0,.69444,0,0,.72222],8211:[0,.44444,.02778,0,.5],8212:[0,.44444,.02778,0,1],8216:[0,.69444,0,0,.27778],8217:[0,.69444,0,0,.27778],8220:[0,.69444,0,0,.5],8221:[0,.69444,0,0,.5]},"Script-Regular":{32:[0,0,0,0,.25],65:[0,.7,.22925,0,.80253],66:[0,.7,.04087,0,.90757],67:[0,.7,.1689,0,.66619],68:[0,.7,.09371,0,.77443],69:[0,.7,.18583,0,.56162],70:[0,.7,.13634,0,.89544],71:[0,.7,.17322,0,.60961],72:[0,.7,.29694,0,.96919],73:[0,.7,.19189,0,.80907],74:[.27778,.7,.19189,0,1.05159],75:[0,.7,.31259,0,.91364],76:[0,.7,.19189,0,.87373],77:[0,.7,.15981,0,1.08031],78:[0,.7,.3525,0,.9015],79:[0,.7,.08078,0,.73787],80:[0,.7,.08078,0,1.01262],81:[0,.7,.03305,0,.88282],82:[0,.7,.06259,0,.85],83:[0,.7,.19189,0,.86767],84:[0,.7,.29087,0,.74697],85:[0,.7,.25815,0,.79996],86:[0,.7,.27523,0,.62204],87:[0,.7,.27523,0,.80532],88:[0,.7,.26006,0,.94445],89:[0,.7,.2939,0,.70961],90:[0,.7,.24037,0,.8212],160:[0,0,0,0,.25]},"Size1-Regular":{32:[0,0,0,0,.25],40:[.35001,.85,0,0,.45834],41:[.35001,.85,0,0,.45834],47:[.35001,.85,0,0,.57778],91:[.35001,.85,0,0,.41667],92:[.35001,.85,0,0,.57778],93:[.35001,.85,0,0,.41667],123:[.35001,.85,0,0,.58334],125:[.35001,.85,0,0,.58334],160:[0,0,0,0,.25],710:[0,.72222,0,0,.55556],732:[0,.72222,0,0,.55556],770:[0,.72222,0,0,.55556],771:[0,.72222,0,0,.55556],8214:[-99e-5,.601,0,0,.77778],8593:[1e-5,.6,0,0,.66667],8595:[1e-5,.6,0,0,.66667],8657:[1e-5,.6,0,0,.77778],8659:[1e-5,.6,0,0,.77778],8719:[.25001,.75,0,0,.94445],8720:[.25001,.75,0,0,.94445],8721:[.25001,.75,0,0,1.05556],8730:[.35001,.85,0,0,1],8739:[-.00599,.606,0,0,.33333],8741:[-.00599,.606,0,0,.55556],8747:[.30612,.805,.19445,0,.47222],8748:[.306,.805,.19445,0,.47222],8749:[.306,.805,.19445,0,.47222],8750:[.30612,.805,.19445,0,.47222],8896:[.25001,.75,0,0,.83334],8897:[.25001,.75,0,0,.83334],8898:[.25001,.75,0,0,.83334],8899:[.25001,.75,0,0,.83334],8968:[.35001,.85,0,0,.47222],8969:[.35001,.85,0,0,.47222],8970:[.35001,.85,0,0,.47222],8971:[.35001,.85,0,0,.47222],9168:[-99e-5,.601,0,0,.66667],10216:[.35001,.85,0,0,.47222],10217:[.35001,.85,0,0,.47222],10752:[.25001,.75,0,0,1.11111],10753:[.25001,.75,0,0,1.11111],10754:[.25001,.75,0,0,1.11111],10756:[.25001,.75,0,0,.83334],10758:[.25001,.75,0,0,.83334]},"Size2-Regular":{32:[0,0,0,0,.25],40:[.65002,1.15,0,0,.59722],41:[.65002,1.15,0,0,.59722],47:[.65002,1.15,0,0,.81111],91:[.65002,1.15,0,0,.47222],92:[.65002,1.15,0,0,.81111],93:[.65002,1.15,0,0,.47222],123:[.65002,1.15,0,0,.66667],125:[.65002,1.15,0,0,.66667],160:[0,0,0,0,.25],710:[0,.75,0,0,1],732:[0,.75,0,0,1],770:[0,.75,0,0,1],771:[0,.75,0,0,1],8719:[.55001,1.05,0,0,1.27778],8720:[.55001,1.05,0,0,1.27778],8721:[.55001,1.05,0,0,1.44445],8730:[.65002,1.15,0,0,1],8747:[.86225,1.36,.44445,0,.55556],8748:[.862,1.36,.44445,0,.55556],8749:[.862,1.36,.44445,0,.55556],8750:[.86225,1.36,.44445,0,.55556],8896:[.55001,1.05,0,0,1.11111],8897:[.55001,1.05,0,0,1.11111],8898:[.55001,1.05,0,0,1.11111],8899:[.55001,1.05,0,0,1.11111],8968:[.65002,1.15,0,0,.52778],8969:[.65002,1.15,0,0,.52778],8970:[.65002,1.15,0,0,.52778],8971:[.65002,1.15,0,0,.52778],10216:[.65002,1.15,0,0,.61111],10217:[.65002,1.15,0,0,.61111],10752:[.55001,1.05,0,0,1.51112],10753:[.55001,1.05,0,0,1.51112],10754:[.55001,1.05,0,0,1.51112],10756:[.55001,1.05,0,0,1.11111],10758:[.55001,1.05,0,0,1.11111]},"Size3-Regular":{32:[0,0,0,0,.25],40:[.95003,1.45,0,0,.73611],41:[.95003,1.45,0,0,.73611],47:[.95003,1.45,0,0,1.04445],91:[.95003,1.45,0,0,.52778],92:[.95003,1.45,0,0,1.04445],93:[.95003,1.45,0,0,.52778],123:[.95003,1.45,0,0,.75],125:[.95003,1.45,0,0,.75],160:[0,0,0,0,.25],710:[0,.75,0,0,1.44445],732:[0,.75,0,0,1.44445],770:[0,.75,0,0,1.44445],771:[0,.75,0,0,1.44445],8730:[.95003,1.45,0,0,1],8968:[.95003,1.45,0,0,.58334],8969:[.95003,1.45,0,0,.58334],8970:[.95003,1.45,0,0,.58334],8971:[.95003,1.45,0,0,.58334],10216:[.95003,1.45,0,0,.75],10217:[.95003,1.45,0,0,.75]},"Size4-Regular":{32:[0,0,0,0,.25],40:[1.25003,1.75,0,0,.79167],41:[1.25003,1.75,0,0,.79167],47:[1.25003,1.75,0,0,1.27778],91:[1.25003,1.75,0,0,.58334],92:[1.25003,1.75,0,0,1.27778],93:[1.25003,1.75,0,0,.58334],123:[1.25003,1.75,0,0,.80556],125:[1.25003,1.75,0,0,.80556],160:[0,0,0,0,.25],710:[0,.825,0,0,1.8889],732:[0,.825,0,0,1.8889],770:[0,.825,0,0,1.8889],771:[0,.825,0,0,1.8889],8730:[1.25003,1.75,0,0,1],8968:[1.25003,1.75,0,0,.63889],8969:[1.25003,1.75,0,0,.63889],8970:[1.25003,1.75,0,0,.63889],8971:[1.25003,1.75,0,0,.63889],9115:[.64502,1.155,0,0,.875],9116:[1e-5,.6,0,0,.875],9117:[.64502,1.155,0,0,.875],9118:[.64502,1.155,0,0,.875],9119:[1e-5,.6,0,0,.875],9120:[.64502,1.155,0,0,.875],9121:[.64502,1.155,0,0,.66667],9122:[-99e-5,.601,0,0,.66667],9123:[.64502,1.155,0,0,.66667],9124:[.64502,1.155,0,0,.66667],9125:[-99e-5,.601,0,0,.66667],9126:[.64502,1.155,0,0,.66667],9127:[1e-5,.9,0,0,.88889],9128:[.65002,1.15,0,0,.88889],9129:[.90001,0,0,0,.88889],9130:[0,.3,0,0,.88889],9131:[1e-5,.9,0,0,.88889],9132:[.65002,1.15,0,0,.88889],9133:[.90001,0,0,0,.88889],9143:[.88502,.915,0,0,1.05556],10216:[1.25003,1.75,0,0,.80556],10217:[1.25003,1.75,0,0,.80556],57344:[-.00499,.605,0,0,1.05556],57345:[-.00499,.605,0,0,1.05556],57680:[0,.12,0,0,.45],57681:[0,.12,0,0,.45],57682:[0,.12,0,0,.45],57683:[0,.12,0,0,.45]},"Typewriter-Regular":{32:[0,0,0,0,.525],33:[0,.61111,0,0,.525],34:[0,.61111,0,0,.525],35:[0,.61111,0,0,.525],36:[.08333,.69444,0,0,.525],37:[.08333,.69444,0,0,.525],38:[0,.61111,0,0,.525],39:[0,.61111,0,0,.525],40:[.08333,.69444,0,0,.525],41:[.08333,.69444,0,0,.525],42:[0,.52083,0,0,.525],43:[-.08056,.53055,0,0,.525],44:[.13889,.125,0,0,.525],45:[-.08056,.53055,0,0,.525],46:[0,.125,0,0,.525],47:[.08333,.69444,0,0,.525],48:[0,.61111,0,0,.525],49:[0,.61111,0,0,.525],50:[0,.61111,0,0,.525],51:[0,.61111,0,0,.525],52:[0,.61111,0,0,.525],53:[0,.61111,0,0,.525],54:[0,.61111,0,0,.525],55:[0,.61111,0,0,.525],56:[0,.61111,0,0,.525],57:[0,.61111,0,0,.525],58:[0,.43056,0,0,.525],59:[.13889,.43056,0,0,.525],60:[-.05556,.55556,0,0,.525],61:[-.19549,.41562,0,0,.525],62:[-.05556,.55556,0,0,.525],63:[0,.61111,0,0,.525],64:[0,.61111,0,0,.525],65:[0,.61111,0,0,.525],66:[0,.61111,0,0,.525],67:[0,.61111,0,0,.525],68:[0,.61111,0,0,.525],69:[0,.61111,0,0,.525],70:[0,.61111,0,0,.525],71:[0,.61111,0,0,.525],72:[0,.61111,0,0,.525],73:[0,.61111,0,0,.525],74:[0,.61111,0,0,.525],75:[0,.61111,0,0,.525],76:[0,.61111,0,0,.525],77:[0,.61111,0,0,.525],78:[0,.61111,0,0,.525],79:[0,.61111,0,0,.525],80:[0,.61111,0,0,.525],81:[.13889,.61111,0,0,.525],82:[0,.61111,0,0,.525],83:[0,.61111,0,0,.525],84:[0,.61111,0,0,.525],85:[0,.61111,0,0,.525],86:[0,.61111,0,0,.525],87:[0,.61111,0,0,.525],88:[0,.61111,0,0,.525],89:[0,.61111,0,0,.525],90:[0,.61111,0,0,.525],91:[.08333,.69444,0,0,.525],92:[.08333,.69444,0,0,.525],93:[.08333,.69444,0,0,.525],94:[0,.61111,0,0,.525],95:[.09514,0,0,0,.525],96:[0,.61111,0,0,.525],97:[0,.43056,0,0,.525],98:[0,.61111,0,0,.525],99:[0,.43056,0,0,.525],100:[0,.61111,0,0,.525],101:[0,.43056,0,0,.525],102:[0,.61111,0,0,.525],103:[.22222,.43056,0,0,.525],104:[0,.61111,0,0,.525],105:[0,.61111,0,0,.525],106:[.22222,.61111,0,0,.525],107:[0,.61111,0,0,.525],108:[0,.61111,0,0,.525],109:[0,.43056,0,0,.525],110:[0,.43056,0,0,.525],111:[0,.43056,0,0,.525],112:[.22222,.43056,0,0,.525],113:[.22222,.43056,0,0,.525],114:[0,.43056,0,0,.525],115:[0,.43056,0,0,.525],116:[0,.55358,0,0,.525],117:[0,.43056,0,0,.525],118:[0,.43056,0,0,.525],119:[0,.43056,0,0,.525],120:[0,.43056,0,0,.525],121:[.22222,.43056,0,0,.525],122:[0,.43056,0,0,.525],123:[.08333,.69444,0,0,.525],124:[.08333,.69444,0,0,.525],125:[.08333,.69444,0,0,.525],126:[0,.61111,0,0,.525],127:[0,.61111,0,0,.525],160:[0,0,0,0,.525],176:[0,.61111,0,0,.525],184:[.19445,0,0,0,.525],305:[0,.43056,0,0,.525],567:[.22222,.43056,0,0,.525],711:[0,.56597,0,0,.525],713:[0,.56555,0,0,.525],714:[0,.61111,0,0,.525],715:[0,.61111,0,0,.525],728:[0,.61111,0,0,.525],730:[0,.61111,0,0,.525],770:[0,.61111,0,0,.525],771:[0,.61111,0,0,.525],776:[0,.61111,0,0,.525],915:[0,.61111,0,0,.525],916:[0,.61111,0,0,.525],920:[0,.61111,0,0,.525],923:[0,.61111,0,0,.525],926:[0,.61111,0,0,.525],928:[0,.61111,0,0,.525],931:[0,.61111,0,0,.525],933:[0,.61111,0,0,.525],934:[0,.61111,0,0,.525],936:[0,.61111,0,0,.525],937:[0,.61111,0,0,.525],8216:[0,.61111,0,0,.525],8217:[0,.61111,0,0,.525],8242:[0,.61111,0,0,.525],9251:[.11111,.21944,0,0,.525]}},B={slant:[.25,.25,.25],space:[0,0,0],stretch:[0,0,0],shrink:[0,0,0],xHeight:[.431,.431,.431],quad:[1,1.171,1.472],extraSpace:[0,0,0],num1:[.677,.732,.925],num2:[.394,.384,.387],num3:[.444,.471,.504],denom1:[.686,.752,1.025],denom2:[.345,.344,.532],sup1:[.413,.503,.504],sup2:[.363,.431,.404],sup3:[.289,.286,.294],sub1:[.15,.143,.2],sub2:[.247,.286,.4],supDrop:[.386,.353,.494],subDrop:[.05,.071,.1],delim1:[2.39,1.7,1.98],delim2:[1.01,1.157,1.42],axisHeight:[.25,.25,.25],defaultRuleThickness:[.04,.049,.049],bigOpSpacing1:[.111,.111,.111],bigOpSpacing2:[.166,.166,.166],bigOpSpacing3:[.2,.2,.2],bigOpSpacing4:[.6,.611,.611],bigOpSpacing5:[.1,.143,.143],sqrtRuleThickness:[.04,.04,.04],ptPerEm:[10,10,10],doubleRuleSep:[.2,.2,.2],arrayRuleWidth:[.04,.04,.04],fboxsep:[.3,.3,.3],fboxrule:[.04,.04,.04]},C={"\xc5":"A","\xd0":"D","\xde":"o","\xe5":"a","\xf0":"d","\xfe":"o","\u0410":"A","\u0411":"B","\u0412":"B","\u0413":"F","\u0414":"A","\u0415":"E","\u0416":"K","\u0417":"3","\u0418":"N","\u0419":"N","\u041a":"K","\u041b":"N","\u041c":"M","\u041d":"H","\u041e":"O","\u041f":"N","\u0420":"P","\u0421":"C","\u0422":"T","\u0423":"y","\u0424":"O","\u0425":"X","\u0426":"U","\u0427":"h","\u0428":"W","\u0429":"W","\u042a":"B","\u042b":"X","\u042c":"B","\u042d":"3","\u042e":"X","\u042f":"R","\u0430":"a","\u0431":"b","\u0432":"a","\u0433":"r","\u0434":"y","\u0435":"e","\u0436":"m","\u0437":"e","\u0438":"n","\u0439":"n","\u043a":"n","\u043b":"n","\u043c":"m","\u043d":"n","\u043e":"o","\u043f":"n","\u0440":"p","\u0441":"c","\u0442":"o","\u0443":"y","\u0444":"b","\u0445":"x","\u0446":"n","\u0447":"n","\u0448":"w","\u0449":"w","\u044a":"a","\u044b":"m","\u044c":"a","\u044d":"e","\u044e":"m","\u044f":"r"};function N(e,t,r){if(!T[t])throw new Error("Font metrics not found for font: "+t+".");var n=e.charCodeAt(0),a=T[t][n];if(!a&&e[0]in C&&(n=C[e[0]].charCodeAt(0),a=T[t][n]),a||"text"!==r||S(n)&&(a=T[t][77]),a)return{depth:a[0],height:a[1],italic:a[2],skew:a[3],width:a[4]}}var q={};var I=[[1,1,1],[2,1,1],[3,1,1],[4,2,1],[5,2,1],[6,3,1],[7,4,2],[8,6,3],[9,7,6],[10,8,7],[11,10,9]],R=[.5,.6,.7,.8,.9,1,1.2,1.44,1.728,2.074,2.488],H=function(e,t){return t.size<2?e:I[e-1][t.size-1]},O=function(){function e(t){this.style=void 0,this.color=void 0,this.size=void 0,this.textSize=void 0,this.phantom=void 0,this.font=void 0,this.fontFamily=void 0,this.fontWeight=void 0,this.fontShape=void 0,this.sizeMultiplier=void 0,this.maxSize=void 0,this.minRuleThickness=void 0,this._fontMetrics=void 0,this.style=t.style,this.color=t.color,this.size=t.size||e.BASESIZE,this.textSize=t.textSize||this.size,this.phantom=!!t.phantom,this.font=t.font||"",this.fontFamily=t.fontFamily||"",this.fontWeight=t.fontWeight||"",this.fontShape=t.fontShape||"",this.sizeMultiplier=R[this.size-1],this.maxSize=t.maxSize,this.minRuleThickness=t.minRuleThickness,this._fontMetrics=void 0}var t=e.prototype;return t.extend=function(t){var r={style:this.style,size:this.size,textSize:this.textSize,color:this.color,phantom:this.phantom,font:this.font,fontFamily:this.fontFamily,fontWeight:this.fontWeight,fontShape:this.fontShape,maxSize:this.maxSize,minRuleThickness:this.minRuleThickness};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);return new e(r)},t.havingStyle=function(e){return this.style===e?this:this.extend({style:e,size:H(this.textSize,e)})},t.havingCrampedStyle=function(){return this.havingStyle(this.style.cramp())},t.havingSize=function(e){return this.size===e&&this.textSize===e?this:this.extend({style:this.style.text(),size:e,textSize:e,sizeMultiplier:R[e-1]})},t.havingBaseStyle=function(t){t=t||this.style.text();var r=H(e.BASESIZE,t);return this.size===r&&this.textSize===e.BASESIZE&&this.style===t?this:this.extend({style:t,size:r})},t.havingBaseSizing=function(){var e;switch(this.style.id){case 4:case 5:e=3;break;case 6:case 7:e=1;break;default:e=6}return this.extend({style:this.style.text(),size:e})},t.withColor=function(e){return this.extend({color:e})},t.withPhantom=function(){return this.extend({phantom:!0})},t.withFont=function(e){return this.extend({font:e})},t.withTextFontFamily=function(e){return this.extend({fontFamily:e,font:""})},t.withTextFontWeight=function(e){return this.extend({fontWeight:e,font:""})},t.withTextFontShape=function(e){return this.extend({fontShape:e,font:""})},t.sizingClasses=function(e){return e.size!==this.size?["sizing","reset-size"+e.size,"size"+this.size]:[]},t.baseSizingClasses=function(){return this.size!==e.BASESIZE?["sizing","reset-size"+this.size,"size"+e.BASESIZE]:[]},t.fontMetrics=function(){return this._fontMetrics||(this._fontMetrics=function(e){var t;if(!q[t=e>=5?0:e>=3?1:2]){var r=q[t]={cssEmPerMu:B.quad[t]/18};for(var n in B)B.hasOwnProperty(n)&&(r[n]=B[n][t])}return q[t]}(this.size)),this._fontMetrics},t.getColor=function(){return this.phantom?"transparent":this.color},e}();O.BASESIZE=6;var E=O,L={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:1.00375,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:1.00375},D={ex:!0,em:!0,mu:!0},V=function(e){return"string"!=typeof e&&(e=e.unit),e in L||e in D||"ex"===e},P=function(e,t){var r;if(e.unit in L)r=L[e.unit]/t.fontMetrics().ptPerEm/t.sizeMultiplier;else if("mu"===e.unit)r=t.fontMetrics().cssEmPerMu;else{var a;if(a=t.style.isTight()?t.havingStyle(t.style.text()):t,"ex"===e.unit)r=a.fontMetrics().xHeight;else{if("em"!==e.unit)throw new n("Invalid unit: '"+e.unit+"'");r=a.fontMetrics().quad}a!==t&&(r*=a.sizeMultiplier/t.sizeMultiplier)}return Math.min(e.number*r,t.maxSize)},F=function(e){return+e.toFixed(4)+"em"},G=function(e){return e.filter((function(e){return e})).join(" ")},U=function(e,t,r){if(this.classes=e||[],this.attributes={},this.height=0,this.depth=0,this.maxFontSize=0,this.style=r||{},t){t.style.isTight()&&this.classes.push("mtight");var n=t.getColor();n&&(this.style.color=n)}},Y=function(e){var t=document.createElement(e);for(var r in t.className=G(this.classes),this.style)this.style.hasOwnProperty(r)&&(t.style[r]=this.style[r]);for(var n in this.attributes)this.attributes.hasOwnProperty(n)&&t.setAttribute(n,this.attributes[n]);for(var a=0;a<this.children.length;a++)t.appendChild(this.children[a].toNode());return t},X=function(e){var t="<"+e;this.classes.length&&(t+=' class="'+l.escape(G(this.classes))+'"');var r="";for(var n in this.style)this.style.hasOwnProperty(n)&&(r+=l.hyphenate(n)+":"+this.style[n]+";");for(var a in r&&(t+=' style="'+l.escape(r)+'"'),this.attributes)this.attributes.hasOwnProperty(a)&&(t+=" "+a+'="'+l.escape(this.attributes[a])+'"');t+=">";for(var i=0;i<this.children.length;i++)t+=this.children[i].toMarkup();return t+="</"+e+">"},W=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,U.call(this,e,r,n),this.children=t||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return Y.call(this,"span")},t.toMarkup=function(){return X.call(this,"span")},e}(),_=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,U.call(this,t,n),this.children=r||[],this.setAttribute("href",e)}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return Y.call(this,"a")},t.toMarkup=function(){return X.call(this,"a")},e}(),j=function(){function e(e,t,r){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=r}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createElement("img");for(var t in e.src=this.src,e.alt=this.alt,e.className="mord",this.style)this.style.hasOwnProperty(t)&&(e.style[t]=this.style[t]);return e},t.toMarkup=function(){var e="<img src='"+this.src+" 'alt='"+this.alt+"' ",t="";for(var r in this.style)this.style.hasOwnProperty(r)&&(t+=l.hyphenate(r)+":"+this.style[r]+";");return t&&(e+=' style="'+l.escape(t)+'"'),e+="'/>"},e}(),$={"\xee":"\u0131\u0302","\xef":"\u0131\u0308","\xed":"\u0131\u0301","\xec":"\u0131\u0300"},Z=function(){function e(e,t,r,n,a,i,o,s){this.text=void 0,this.height=void 0,this.depth=void 0,this.italic=void 0,this.skew=void 0,this.width=void 0,this.maxFontSize=void 0,this.classes=void 0,this.style=void 0,this.text=e,this.height=t||0,this.depth=r||0,this.italic=n||0,this.skew=a||0,this.width=i||0,this.classes=o||[],this.style=s||{},this.maxFontSize=0;var l=function(e){for(var t=0;t<w.length;t++)for(var r=w[t],n=0;n<r.blocks.length;n++){var a=r.blocks[n];if(e>=a[0]&&e<=a[1])return r.name}return null}(this.text.charCodeAt(0));l&&this.classes.push(l+"_fallback"),/[\xee\xef\xed\xec]/.test(this.text)&&(this.text=$[this.text])}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createTextNode(this.text),t=null;for(var r in this.italic>0&&((t=document.createElement("span")).style.marginRight=F(this.italic)),this.classes.length>0&&((t=t||document.createElement("span")).className=G(this.classes)),this.style)this.style.hasOwnProperty(r)&&((t=t||document.createElement("span")).style[r]=this.style[r]);return t?(t.appendChild(e),t):e},t.toMarkup=function(){var e=!1,t="<span";this.classes.length&&(e=!0,t+=' class="',t+=l.escape(G(this.classes)),t+='"');var r="";for(var n in this.italic>0&&(r+="margin-right:"+this.italic+"em;"),this.style)this.style.hasOwnProperty(n)&&(r+=l.hyphenate(n)+":"+this.style[n]+";");r&&(e=!0,t+=' style="'+l.escape(r)+'"');var a=l.escape(this.text);return e?(t+=">",t+=a,t+="</span>"):a},e}(),K=function(){function e(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);for(var r=0;r<this.children.length;r++)e.appendChild(this.children[r].toNode());return e},t.toMarkup=function(){var e='<svg xmlns="http://www.w3.org/2000/svg"';for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&(e+=" "+t+"='"+this.attributes[t]+"'");e+=">";for(var r=0;r<this.children.length;r++)e+=this.children[r].toMarkup();return e+="</svg>"},e}(),J=function(){function e(e,t){this.pathName=void 0,this.alternate=void 0,this.pathName=e,this.alternate=t}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","path");return this.alternate?e.setAttribute("d",this.alternate):e.setAttribute("d",z[this.pathName]),e},t.toMarkup=function(){return this.alternate?"<path d='"+this.alternate+"'/>":"<path d='"+z[this.pathName]+"'/>"},e}(),Q=function(){function e(e){this.attributes=void 0,this.attributes=e||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","line");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);return e},t.toMarkup=function(){var e="<line";for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&(e+=" "+t+"='"+this.attributes[t]+"'");return e+="/>"},e}();function ee(e){if(e instanceof Z)return e;throw new Error("Expected symbolNode but got "+String(e)+".")}var te={bin:1,close:1,inner:1,open:1,punct:1,rel:1},re={"accent-token":1,mathord:1,"op-token":1,spacing:1,textord:1},ne={math:{},text:{}},ae=ne;function ie(e,t,r,n,a,i){ne[e][a]={font:t,group:r,replace:n},i&&n&&(ne[e][n]=ne[e][a])}var oe="math",se="text",le="main",he="ams",ce="accent-token",me="bin",ue="close",pe="inner",de="mathord",fe="op-token",ge="open",ve="punct",be="rel",ye="spacing",xe="textord";ie(oe,le,be,"\u2261","\\equiv",!0),ie(oe,le,be,"\u227a","\\prec",!0),ie(oe,le,be,"\u227b","\\succ",!0),ie(oe,le,be,"\u223c","\\sim",!0),ie(oe,le,be,"\u22a5","\\perp"),ie(oe,le,be,"\u2aaf","\\preceq",!0),ie(oe,le,be,"\u2ab0","\\succeq",!0),ie(oe,le,be,"\u2243","\\simeq",!0),ie(oe,le,be,"\u2223","\\mid",!0),ie(oe,le,be,"\u226a","\\ll",!0),ie(oe,le,be,"\u226b","\\gg",!0),ie(oe,le,be,"\u224d","\\asymp",!0),ie(oe,le,be,"\u2225","\\parallel"),ie(oe,le,be,"\u22c8","\\bowtie",!0),ie(oe,le,be,"\u2323","\\smile",!0),ie(oe,le,be,"\u2291","\\sqsubseteq",!0),ie(oe,le,be,"\u2292","\\sqsupseteq",!0),ie(oe,le,be,"\u2250","\\doteq",!0),ie(oe,le,be,"\u2322","\\frown",!0),ie(oe,le,be,"\u220b","\\ni",!0),ie(oe,le,be,"\u221d","\\propto",!0),ie(oe,le,be,"\u22a2","\\vdash",!0),ie(oe,le,be,"\u22a3","\\dashv",!0),ie(oe,le,be,"\u220b","\\owns"),ie(oe,le,ve,".","\\ldotp"),ie(oe,le,ve,"\u22c5","\\cdotp"),ie(oe,le,xe,"#","\\#"),ie(se,le,xe,"#","\\#"),ie(oe,le,xe,"&","\\&"),ie(se,le,xe,"&","\\&"),ie(oe,le,xe,"\u2135","\\aleph",!0),ie(oe,le,xe,"\u2200","\\forall",!0),ie(oe,le,xe,"\u210f","\\hbar",!0),ie(oe,le,xe,"\u2203","\\exists",!0),ie(oe,le,xe,"\u2207","\\nabla",!0),ie(oe,le,xe,"\u266d","\\flat",!0),ie(oe,le,xe,"\u2113","\\ell",!0),ie(oe,le,xe,"\u266e","\\natural",!0),ie(oe,le,xe,"\u2663","\\clubsuit",!0),ie(oe,le,xe,"\u2118","\\wp",!0),ie(oe,le,xe,"\u266f","\\sharp",!0),ie(oe,le,xe,"\u2662","\\diamondsuit",!0),ie(oe,le,xe,"\u211c","\\Re",!0),ie(oe,le,xe,"\u2661","\\heartsuit",!0),ie(oe,le,xe,"\u2111","\\Im",!0),ie(oe,le,xe,"\u2660","\\spadesuit",!0),ie(oe,le,xe,"\xa7","\\S",!0),ie(se,le,xe,"\xa7","\\S"),ie(oe,le,xe,"\xb6","\\P",!0),ie(se,le,xe,"\xb6","\\P"),ie(oe,le,xe,"\u2020","\\dag"),ie(se,le,xe,"\u2020","\\dag"),ie(se,le,xe,"\u2020","\\textdagger"),ie(oe,le,xe,"\u2021","\\ddag"),ie(se,le,xe,"\u2021","\\ddag"),ie(se,le,xe,"\u2021","\\textdaggerdbl"),ie(oe,le,ue,"\u23b1","\\rmoustache",!0),ie(oe,le,ge,"\u23b0","\\lmoustache",!0),ie(oe,le,ue,"\u27ef","\\rgroup",!0),ie(oe,le,ge,"\u27ee","\\lgroup",!0),ie(oe,le,me,"\u2213","\\mp",!0),ie(oe,le,me,"\u2296","\\ominus",!0),ie(oe,le,me,"\u228e","\\uplus",!0),ie(oe,le,me,"\u2293","\\sqcap",!0),ie(oe,le,me,"\u2217","\\ast"),ie(oe,le,me,"\u2294","\\sqcup",!0),ie(oe,le,me,"\u25ef","\\bigcirc",!0),ie(oe,le,me,"\u2219","\\bullet",!0),ie(oe,le,me,"\u2021","\\ddagger"),ie(oe,le,me,"\u2240","\\wr",!0),ie(oe,le,me,"\u2a3f","\\amalg"),ie(oe,le,me,"&","\\And"),ie(oe,le,be,"\u27f5","\\longleftarrow",!0),ie(oe,le,be,"\u21d0","\\Leftarrow",!0),ie(oe,le,be,"\u27f8","\\Longleftarrow",!0),ie(oe,le,be,"\u27f6","\\longrightarrow",!0),ie(oe,le,be,"\u21d2","\\Rightarrow",!0),ie(oe,le,be,"\u27f9","\\Longrightarrow",!0),ie(oe,le,be,"\u2194","\\leftrightarrow",!0),ie(oe,le,be,"\u27f7","\\longleftrightarrow",!0),ie(oe,le,be,"\u21d4","\\Leftrightarrow",!0),ie(oe,le,be,"\u27fa","\\Longleftrightarrow",!0),ie(oe,le,be,"\u21a6","\\mapsto",!0),ie(oe,le,be,"\u27fc","\\longmapsto",!0),ie(oe,le,be,"\u2197","\\nearrow",!0),ie(oe,le,be,"\u21a9","\\hookleftarrow",!0),ie(oe,le,be,"\u21aa","\\hookrightarrow",!0),ie(oe,le,be,"\u2198","\\searrow",!0),ie(oe,le,be,"\u21bc","\\leftharpoonup",!0),ie(oe,le,be,"\u21c0","\\rightharpoonup",!0),ie(oe,le,be,"\u2199","\\swarrow",!0),ie(oe,le,be,"\u21bd","\\leftharpoondown",!0),ie(oe,le,be,"\u21c1","\\rightharpoondown",!0),ie(oe,le,be,"\u2196","\\nwarrow",!0),ie(oe,le,be,"\u21cc","\\rightleftharpoons",!0),ie(oe,he,be,"\u226e","\\nless",!0),ie(oe,he,be,"\ue010","\\@nleqslant"),ie(oe,he,be,"\ue011","\\@nleqq"),ie(oe,he,be,"\u2a87","\\lneq",!0),ie(oe,he,be,"\u2268","\\lneqq",!0),ie(oe,he,be,"\ue00c","\\@lvertneqq"),ie(oe,he,be,"\u22e6","\\lnsim",!0),ie(oe,he,be,"\u2a89","\\lnapprox",!0),ie(oe,he,be,"\u2280","\\nprec",!0),ie(oe,he,be,"\u22e0","\\npreceq",!0),ie(oe,he,be,"\u22e8","\\precnsim",!0),ie(oe,he,be,"\u2ab9","\\precnapprox",!0),ie(oe,he,be,"\u2241","\\nsim",!0),ie(oe,he,be,"\ue006","\\@nshortmid"),ie(oe,he,be,"\u2224","\\nmid",!0),ie(oe,he,be,"\u22ac","\\nvdash",!0),ie(oe,he,be,"\u22ad","\\nvDash",!0),ie(oe,he,be,"\u22ea","\\ntriangleleft"),ie(oe,he,be,"\u22ec","\\ntrianglelefteq",!0),ie(oe,he,be,"\u228a","\\subsetneq",!0),ie(oe,he,be,"\ue01a","\\@varsubsetneq"),ie(oe,he,be,"\u2acb","\\subsetneqq",!0),ie(oe,he,be,"\ue017","\\@varsubsetneqq"),ie(oe,he,be,"\u226f","\\ngtr",!0),ie(oe,he,be,"\ue00f","\\@ngeqslant"),ie(oe,he,be,"\ue00e","\\@ngeqq"),ie(oe,he,be,"\u2a88","\\gneq",!0),ie(oe,he,be,"\u2269","\\gneqq",!0),ie(oe,he,be,"\ue00d","\\@gvertneqq"),ie(oe,he,be,"\u22e7","\\gnsim",!0),ie(oe,he,be,"\u2a8a","\\gnapprox",!0),ie(oe,he,be,"\u2281","\\nsucc",!0),ie(oe,he,be,"\u22e1","\\nsucceq",!0),ie(oe,he,be,"\u22e9","\\succnsim",!0),ie(oe,he,be,"\u2aba","\\succnapprox",!0),ie(oe,he,be,"\u2246","\\ncong",!0),ie(oe,he,be,"\ue007","\\@nshortparallel"),ie(oe,he,be,"\u2226","\\nparallel",!0),ie(oe,he,be,"\u22af","\\nVDash",!0),ie(oe,he,be,"\u22eb","\\ntriangleright"),ie(oe,he,be,"\u22ed","\\ntrianglerighteq",!0),ie(oe,he,be,"\ue018","\\@nsupseteqq"),ie(oe,he,be,"\u228b","\\supsetneq",!0),ie(oe,he,be,"\ue01b","\\@varsupsetneq"),ie(oe,he,be,"\u2acc","\\supsetneqq",!0),ie(oe,he,be,"\ue019","\\@varsupsetneqq"),ie(oe,he,be,"\u22ae","\\nVdash",!0),ie(oe,he,be,"\u2ab5","\\precneqq",!0),ie(oe,he,be,"\u2ab6","\\succneqq",!0),ie(oe,he,be,"\ue016","\\@nsubseteqq"),ie(oe,he,me,"\u22b4","\\unlhd"),ie(oe,he,me,"\u22b5","\\unrhd"),ie(oe,he,be,"\u219a","\\nleftarrow",!0),ie(oe,he,be,"\u219b","\\nrightarrow",!0),ie(oe,he,be,"\u21cd","\\nLeftarrow",!0),ie(oe,he,be,"\u21cf","\\nRightarrow",!0),ie(oe,he,be,"\u21ae","\\nleftrightarrow",!0),ie(oe,he,be,"\u21ce","\\nLeftrightarrow",!0),ie(oe,he,be,"\u25b3","\\vartriangle"),ie(oe,he,xe,"\u210f","\\hslash"),ie(oe,he,xe,"\u25bd","\\triangledown"),ie(oe,he,xe,"\u25ca","\\lozenge"),ie(oe,he,xe,"\u24c8","\\circledS"),ie(oe,he,xe,"\xae","\\circledR"),ie(se,he,xe,"\xae","\\circledR"),ie(oe,he,xe,"\u2221","\\measuredangle",!0),ie(oe,he,xe,"\u2204","\\nexists"),ie(oe,he,xe,"\u2127","\\mho"),ie(oe,he,xe,"\u2132","\\Finv",!0),ie(oe,he,xe,"\u2141","\\Game",!0),ie(oe,he,xe,"\u2035","\\backprime"),ie(oe,he,xe,"\u25b2","\\blacktriangle"),ie(oe,he,xe,"\u25bc","\\blacktriangledown"),ie(oe,he,xe,"\u25a0","\\blacksquare"),ie(oe,he,xe,"\u29eb","\\blacklozenge"),ie(oe,he,xe,"\u2605","\\bigstar"),ie(oe,he,xe,"\u2222","\\sphericalangle",!0),ie(oe,he,xe,"\u2201","\\complement",!0),ie(oe,he,xe,"\xf0","\\eth",!0),ie(se,le,xe,"\xf0","\xf0"),ie(oe,he,xe,"\u2571","\\diagup"),ie(oe,he,xe,"\u2572","\\diagdown"),ie(oe,he,xe,"\u25a1","\\square"),ie(oe,he,xe,"\u25a1","\\Box"),ie(oe,he,xe,"\u25ca","\\Diamond"),ie(oe,he,xe,"\xa5","\\yen",!0),ie(se,he,xe,"\xa5","\\yen",!0),ie(oe,he,xe,"\u2713","\\checkmark",!0),ie(se,he,xe,"\u2713","\\checkmark"),ie(oe,he,xe,"\u2136","\\beth",!0),ie(oe,he,xe,"\u2138","\\daleth",!0),ie(oe,he,xe,"\u2137","\\gimel",!0),ie(oe,he,xe,"\u03dd","\\digamma",!0),ie(oe,he,xe,"\u03f0","\\varkappa"),ie(oe,he,ge,"\u250c","\\@ulcorner",!0),ie(oe,he,ue,"\u2510","\\@urcorner",!0),ie(oe,he,ge,"\u2514","\\@llcorner",!0),ie(oe,he,ue,"\u2518","\\@lrcorner",!0),ie(oe,he,be,"\u2266","\\leqq",!0),ie(oe,he,be,"\u2a7d","\\leqslant",!0),ie(oe,he,be,"\u2a95","\\eqslantless",!0),ie(oe,he,be,"\u2272","\\lesssim",!0),ie(oe,he,be,"\u2a85","\\lessapprox",!0),ie(oe,he,be,"\u224a","\\approxeq",!0),ie(oe,he,me,"\u22d6","\\lessdot"),ie(oe,he,be,"\u22d8","\\lll",!0),ie(oe,he,be,"\u2276","\\lessgtr",!0),ie(oe,he,be,"\u22da","\\lesseqgtr",!0),ie(oe,he,be,"\u2a8b","\\lesseqqgtr",!0),ie(oe,he,be,"\u2251","\\doteqdot"),ie(oe,he,be,"\u2253","\\risingdotseq",!0),ie(oe,he,be,"\u2252","\\fallingdotseq",!0),ie(oe,he,be,"\u223d","\\backsim",!0),ie(oe,he,be,"\u22cd","\\backsimeq",!0),ie(oe,he,be,"\u2ac5","\\subseteqq",!0),ie(oe,he,be,"\u22d0","\\Subset",!0),ie(oe,he,be,"\u228f","\\sqsubset",!0),ie(oe,he,be,"\u227c","\\preccurlyeq",!0),ie(oe,he,be,"\u22de","\\curlyeqprec",!0),ie(oe,he,be,"\u227e","\\precsim",!0),ie(oe,he,be,"\u2ab7","\\precapprox",!0),ie(oe,he,be,"\u22b2","\\vartriangleleft"),ie(oe,he,be,"\u22b4","\\trianglelefteq"),ie(oe,he,be,"\u22a8","\\vDash",!0),ie(oe,he,be,"\u22aa","\\Vvdash",!0),ie(oe,he,be,"\u2323","\\smallsmile"),ie(oe,he,be,"\u2322","\\smallfrown"),ie(oe,he,be,"\u224f","\\bumpeq",!0),ie(oe,he,be,"\u224e","\\Bumpeq",!0),ie(oe,he,be,"\u2267","\\geqq",!0),ie(oe,he,be,"\u2a7e","\\geqslant",!0),ie(oe,he,be,"\u2a96","\\eqslantgtr",!0),ie(oe,he,be,"\u2273","\\gtrsim",!0),ie(oe,he,be,"\u2a86","\\gtrapprox",!0),ie(oe,he,me,"\u22d7","\\gtrdot"),ie(oe,he,be,"\u22d9","\\ggg",!0),ie(oe,he,be,"\u2277","\\gtrless",!0),ie(oe,he,be,"\u22db","\\gtreqless",!0),ie(oe,he,be,"\u2a8c","\\gtreqqless",!0),ie(oe,he,be,"\u2256","\\eqcirc",!0),ie(oe,he,be,"\u2257","\\circeq",!0),ie(oe,he,be,"\u225c","\\triangleq",!0),ie(oe,he,be,"\u223c","\\thicksim"),ie(oe,he,be,"\u2248","\\thickapprox"),ie(oe,he,be,"\u2ac6","\\supseteqq",!0),ie(oe,he,be,"\u22d1","\\Supset",!0),ie(oe,he,be,"\u2290","\\sqsupset",!0),ie(oe,he,be,"\u227d","\\succcurlyeq",!0),ie(oe,he,be,"\u22df","\\curlyeqsucc",!0),ie(oe,he,be,"\u227f","\\succsim",!0),ie(oe,he,be,"\u2ab8","\\succapprox",!0),ie(oe,he,be,"\u22b3","\\vartriangleright"),ie(oe,he,be,"\u22b5","\\trianglerighteq"),ie(oe,he,be,"\u22a9","\\Vdash",!0),ie(oe,he,be,"\u2223","\\shortmid"),ie(oe,he,be,"\u2225","\\shortparallel"),ie(oe,he,be,"\u226c","\\between",!0),ie(oe,he,be,"\u22d4","\\pitchfork",!0),ie(oe,he,be,"\u221d","\\varpropto"),ie(oe,he,be,"\u25c0","\\blacktriangleleft"),ie(oe,he,be,"\u2234","\\therefore",!0),ie(oe,he,be,"\u220d","\\backepsilon"),ie(oe,he,be,"\u25b6","\\blacktriangleright"),ie(oe,he,be,"\u2235","\\because",!0),ie(oe,he,be,"\u22d8","\\llless"),ie(oe,he,be,"\u22d9","\\gggtr"),ie(oe,he,me,"\u22b2","\\lhd"),ie(oe,he,me,"\u22b3","\\rhd"),ie(oe,he,be,"\u2242","\\eqsim",!0),ie(oe,le,be,"\u22c8","\\Join"),ie(oe,he,be,"\u2251","\\Doteq",!0),ie(oe,he,me,"\u2214","\\dotplus",!0),ie(oe,he,me,"\u2216","\\smallsetminus"),ie(oe,he,me,"\u22d2","\\Cap",!0),ie(oe,he,me,"\u22d3","\\Cup",!0),ie(oe,he,me,"\u2a5e","\\doublebarwedge",!0),ie(oe,he,me,"\u229f","\\boxminus",!0),ie(oe,he,me,"\u229e","\\boxplus",!0),ie(oe,he,me,"\u22c7","\\divideontimes",!0),ie(oe,he,me,"\u22c9","\\ltimes",!0),ie(oe,he,me,"\u22ca","\\rtimes",!0),ie(oe,he,me,"\u22cb","\\leftthreetimes",!0),ie(oe,he,me,"\u22cc","\\rightthreetimes",!0),ie(oe,he,me,"\u22cf","\\curlywedge",!0),ie(oe,he,me,"\u22ce","\\curlyvee",!0),ie(oe,he,me,"\u229d","\\circleddash",!0),ie(oe,he,me,"\u229b","\\circledast",!0),ie(oe,he,me,"\u22c5","\\centerdot"),ie(oe,he,me,"\u22ba","\\intercal",!0),ie(oe,he,me,"\u22d2","\\doublecap"),ie(oe,he,me,"\u22d3","\\doublecup"),ie(oe,he,me,"\u22a0","\\boxtimes",!0),ie(oe,he,be,"\u21e2","\\dashrightarrow",!0),ie(oe,he,be,"\u21e0","\\dashleftarrow",!0),ie(oe,he,be,"\u21c7","\\leftleftarrows",!0),ie(oe,he,be,"\u21c6","\\leftrightarrows",!0),ie(oe,he,be,"\u21da","\\Lleftarrow",!0),ie(oe,he,be,"\u219e","\\twoheadleftarrow",!0),ie(oe,he,be,"\u21a2","\\leftarrowtail",!0),ie(oe,he,be,"\u21ab","\\looparrowleft",!0),ie(oe,he,be,"\u21cb","\\leftrightharpoons",!0),ie(oe,he,be,"\u21b6","\\curvearrowleft",!0),ie(oe,he,be,"\u21ba","\\circlearrowleft",!0),ie(oe,he,be,"\u21b0","\\Lsh",!0),ie(oe,he,be,"\u21c8","\\upuparrows",!0),ie(oe,he,be,"\u21bf","\\upharpoonleft",!0),ie(oe,he,be,"\u21c3","\\downharpoonleft",!0),ie(oe,le,be,"\u22b6","\\origof",!0),ie(oe,le,be,"\u22b7","\\imageof",!0),ie(oe,he,be,"\u22b8","\\multimap",!0),ie(oe,he,be,"\u21ad","\\leftrightsquigarrow",!0),ie(oe,he,be,"\u21c9","\\rightrightarrows",!0),ie(oe,he,be,"\u21c4","\\rightleftarrows",!0),ie(oe,he,be,"\u21a0","\\twoheadrightarrow",!0),ie(oe,he,be,"\u21a3","\\rightarrowtail",!0),ie(oe,he,be,"\u21ac","\\looparrowright",!0),ie(oe,he,be,"\u21b7","\\curvearrowright",!0),ie(oe,he,be,"\u21bb","\\circlearrowright",!0),ie(oe,he,be,"\u21b1","\\Rsh",!0),ie(oe,he,be,"\u21ca","\\downdownarrows",!0),ie(oe,he,be,"\u21be","\\upharpoonright",!0),ie(oe,he,be,"\u21c2","\\downharpoonright",!0),ie(oe,he,be,"\u21dd","\\rightsquigarrow",!0),ie(oe,he,be,"\u21dd","\\leadsto"),ie(oe,he,be,"\u21db","\\Rrightarrow",!0),ie(oe,he,be,"\u21be","\\restriction"),ie(oe,le,xe,"\u2018","`"),ie(oe,le,xe,"$","\\$"),ie(se,le,xe,"$","\\$"),ie(se,le,xe,"$","\\textdollar"),ie(oe,le,xe,"%","\\%"),ie(se,le,xe,"%","\\%"),ie(oe,le,xe,"_","\\_"),ie(se,le,xe,"_","\\_"),ie(se,le,xe,"_","\\textunderscore"),ie(oe,le,xe,"\u2220","\\angle",!0),ie(oe,le,xe,"\u221e","\\infty",!0),ie(oe,le,xe,"\u2032","\\prime"),ie(oe,le,xe,"\u25b3","\\triangle"),ie(oe,le,xe,"\u0393","\\Gamma",!0),ie(oe,le,xe,"\u0394","\\Delta",!0),ie(oe,le,xe,"\u0398","\\Theta",!0),ie(oe,le,xe,"\u039b","\\Lambda",!0),ie(oe,le,xe,"\u039e","\\Xi",!0),ie(oe,le,xe,"\u03a0","\\Pi",!0),ie(oe,le,xe,"\u03a3","\\Sigma",!0),ie(oe,le,xe,"\u03a5","\\Upsilon",!0),ie(oe,le,xe,"\u03a6","\\Phi",!0),ie(oe,le,xe,"\u03a8","\\Psi",!0),ie(oe,le,xe,"\u03a9","\\Omega",!0),ie(oe,le,xe,"A","\u0391"),ie(oe,le,xe,"B","\u0392"),ie(oe,le,xe,"E","\u0395"),ie(oe,le,xe,"Z","\u0396"),ie(oe,le,xe,"H","\u0397"),ie(oe,le,xe,"I","\u0399"),ie(oe,le,xe,"K","\u039a"),ie(oe,le,xe,"M","\u039c"),ie(oe,le,xe,"N","\u039d"),ie(oe,le,xe,"O","\u039f"),ie(oe,le,xe,"P","\u03a1"),ie(oe,le,xe,"T","\u03a4"),ie(oe,le,xe,"X","\u03a7"),ie(oe,le,xe,"\xac","\\neg",!0),ie(oe,le,xe,"\xac","\\lnot"),ie(oe,le,xe,"\u22a4","\\top"),ie(oe,le,xe,"\u22a5","\\bot"),ie(oe,le,xe,"\u2205","\\emptyset"),ie(oe,he,xe,"\u2205","\\varnothing"),ie(oe,le,de,"\u03b1","\\alpha",!0),ie(oe,le,de,"\u03b2","\\beta",!0),ie(oe,le,de,"\u03b3","\\gamma",!0),ie(oe,le,de,"\u03b4","\\delta",!0),ie(oe,le,de,"\u03f5","\\epsilon",!0),ie(oe,le,de,"\u03b6","\\zeta",!0),ie(oe,le,de,"\u03b7","\\eta",!0),ie(oe,le,de,"\u03b8","\\theta",!0),ie(oe,le,de,"\u03b9","\\iota",!0),ie(oe,le,de,"\u03ba","\\kappa",!0),ie(oe,le,de,"\u03bb","\\lambda",!0),ie(oe,le,de,"\u03bc","\\mu",!0),ie(oe,le,de,"\u03bd","\\nu",!0),ie(oe,le,de,"\u03be","\\xi",!0),ie(oe,le,de,"\u03bf","\\omicron",!0),ie(oe,le,de,"\u03c0","\\pi",!0),ie(oe,le,de,"\u03c1","\\rho",!0),ie(oe,le,de,"\u03c3","\\sigma",!0),ie(oe,le,de,"\u03c4","\\tau",!0),ie(oe,le,de,"\u03c5","\\upsilon",!0),ie(oe,le,de,"\u03d5","\\phi",!0),ie(oe,le,de,"\u03c7","\\chi",!0),ie(oe,le,de,"\u03c8","\\psi",!0),ie(oe,le,de,"\u03c9","\\omega",!0),ie(oe,le,de,"\u03b5","\\varepsilon",!0),ie(oe,le,de,"\u03d1","\\vartheta",!0),ie(oe,le,de,"\u03d6","\\varpi",!0),ie(oe,le,de,"\u03f1","\\varrho",!0),ie(oe,le,de,"\u03c2","\\varsigma",!0),ie(oe,le,de,"\u03c6","\\varphi",!0),ie(oe,le,me,"\u2217","*",!0),ie(oe,le,me,"+","+"),ie(oe,le,me,"\u2212","-",!0),ie(oe,le,me,"\u22c5","\\cdot",!0),ie(oe,le,me,"\u2218","\\circ",!0),ie(oe,le,me,"\xf7","\\div",!0),ie(oe,le,me,"\xb1","\\pm",!0),ie(oe,le,me,"\xd7","\\times",!0),ie(oe,le,me,"\u2229","\\cap",!0),ie(oe,le,me,"\u222a","\\cup",!0),ie(oe,le,me,"\u2216","\\setminus",!0),ie(oe,le,me,"\u2227","\\land"),ie(oe,le,me,"\u2228","\\lor"),ie(oe,le,me,"\u2227","\\wedge",!0),ie(oe,le,me,"\u2228","\\vee",!0),ie(oe,le,xe,"\u221a","\\surd"),ie(oe,le,ge,"\u27e8","\\langle",!0),ie(oe,le,ge,"\u2223","\\lvert"),ie(oe,le,ge,"\u2225","\\lVert"),ie(oe,le,ue,"?","?"),ie(oe,le,ue,"!","!"),ie(oe,le,ue,"\u27e9","\\rangle",!0),ie(oe,le,ue,"\u2223","\\rvert"),ie(oe,le,ue,"\u2225","\\rVert"),ie(oe,le,be,"=","="),ie(oe,le,be,":",":"),ie(oe,le,be,"\u2248","\\approx",!0),ie(oe,le,be,"\u2245","\\cong",!0),ie(oe,le,be,"\u2265","\\ge"),ie(oe,le,be,"\u2265","\\geq",!0),ie(oe,le,be,"\u2190","\\gets"),ie(oe,le,be,">","\\gt",!0),ie(oe,le,be,"\u2208","\\in",!0),ie(oe,le,be,"\ue020","\\@not"),ie(oe,le,be,"\u2282","\\subset",!0),ie(oe,le,be,"\u2283","\\supset",!0),ie(oe,le,be,"\u2286","\\subseteq",!0),ie(oe,le,be,"\u2287","\\supseteq",!0),ie(oe,he,be,"\u2288","\\nsubseteq",!0),ie(oe,he,be,"\u2289","\\nsupseteq",!0),ie(oe,le,be,"\u22a8","\\models"),ie(oe,le,be,"\u2190","\\leftarrow",!0),ie(oe,le,be,"\u2264","\\le"),ie(oe,le,be,"\u2264","\\leq",!0),ie(oe,le,be,"<","\\lt",!0),ie(oe,le,be,"\u2192","\\rightarrow",!0),ie(oe,le,be,"\u2192","\\to"),ie(oe,he,be,"\u2271","\\ngeq",!0),ie(oe,he,be,"\u2270","\\nleq",!0),ie(oe,le,ye,"\xa0","\\ "),ie(oe,le,ye,"\xa0","\\space"),ie(oe,le,ye,"\xa0","\\nobreakspace"),ie(se,le,ye,"\xa0","\\ "),ie(se,le,ye,"\xa0"," "),ie(se,le,ye,"\xa0","\\space"),ie(se,le,ye,"\xa0","\\nobreakspace"),ie(oe,le,ye,null,"\\nobreak"),ie(oe,le,ye,null,"\\allowbreak"),ie(oe,le,ve,",",","),ie(oe,le,ve,";",";"),ie(oe,he,me,"\u22bc","\\barwedge",!0),ie(oe,he,me,"\u22bb","\\veebar",!0),ie(oe,le,me,"\u2299","\\odot",!0),ie(oe,le,me,"\u2295","\\oplus",!0),ie(oe,le,me,"\u2297","\\otimes",!0),ie(oe,le,xe,"\u2202","\\partial",!0),ie(oe,le,me,"\u2298","\\oslash",!0),ie(oe,he,me,"\u229a","\\circledcirc",!0),ie(oe,he,me,"\u22a1","\\boxdot",!0),ie(oe,le,me,"\u25b3","\\bigtriangleup"),ie(oe,le,me,"\u25bd","\\bigtriangledown"),ie(oe,le,me,"\u2020","\\dagger"),ie(oe,le,me,"\u22c4","\\diamond"),ie(oe,le,me,"\u22c6","\\star"),ie(oe,le,me,"\u25c3","\\triangleleft"),ie(oe,le,me,"\u25b9","\\triangleright"),ie(oe,le,ge,"{","\\{"),ie(se,le,xe,"{","\\{"),ie(se,le,xe,"{","\\textbraceleft"),ie(oe,le,ue,"}","\\}"),ie(se,le,xe,"}","\\}"),ie(se,le,xe,"}","\\textbraceright"),ie(oe,le,ge,"{","\\lbrace"),ie(oe,le,ue,"}","\\rbrace"),ie(oe,le,ge,"[","\\lbrack",!0),ie(se,le,xe,"[","\\lbrack",!0),ie(oe,le,ue,"]","\\rbrack",!0),ie(se,le,xe,"]","\\rbrack",!0),ie(oe,le,ge,"(","\\lparen",!0),ie(oe,le,ue,")","\\rparen",!0),ie(se,le,xe,"<","\\textless",!0),ie(se,le,xe,">","\\textgreater",!0),ie(oe,le,ge,"\u230a","\\lfloor",!0),ie(oe,le,ue,"\u230b","\\rfloor",!0),ie(oe,le,ge,"\u2308","\\lceil",!0),ie(oe,le,ue,"\u2309","\\rceil",!0),ie(oe,le,xe,"\\","\\backslash"),ie(oe,le,xe,"\u2223","|"),ie(oe,le,xe,"\u2223","\\vert"),ie(se,le,xe,"|","\\textbar",!0),ie(oe,le,xe,"\u2225","\\|"),ie(oe,le,xe,"\u2225","\\Vert"),ie(se,le,xe,"\u2225","\\textbardbl"),ie(se,le,xe,"~","\\textasciitilde"),ie(se,le,xe,"\\","\\textbackslash"),ie(se,le,xe,"^","\\textasciicircum"),ie(oe,le,be,"\u2191","\\uparrow",!0),ie(oe,le,be,"\u21d1","\\Uparrow",!0),ie(oe,le,be,"\u2193","\\downarrow",!0),ie(oe,le,be,"\u21d3","\\Downarrow",!0),ie(oe,le,be,"\u2195","\\updownarrow",!0),ie(oe,le,be,"\u21d5","\\Updownarrow",!0),ie(oe,le,fe,"\u2210","\\coprod"),ie(oe,le,fe,"\u22c1","\\bigvee"),ie(oe,le,fe,"\u22c0","\\bigwedge"),ie(oe,le,fe,"\u2a04","\\biguplus"),ie(oe,le,fe,"\u22c2","\\bigcap"),ie(oe,le,fe,"\u22c3","\\bigcup"),ie(oe,le,fe,"\u222b","\\int"),ie(oe,le,fe,"\u222b","\\intop"),ie(oe,le,fe,"\u222c","\\iint"),ie(oe,le,fe,"\u222d","\\iiint"),ie(oe,le,fe,"\u220f","\\prod"),ie(oe,le,fe,"\u2211","\\sum"),ie(oe,le,fe,"\u2a02","\\bigotimes"),ie(oe,le,fe,"\u2a01","\\bigoplus"),ie(oe,le,fe,"\u2a00","\\bigodot"),ie(oe,le,fe,"\u222e","\\oint"),ie(oe,le,fe,"\u222f","\\oiint"),ie(oe,le,fe,"\u2230","\\oiiint"),ie(oe,le,fe,"\u2a06","\\bigsqcup"),ie(oe,le,fe,"\u222b","\\smallint"),ie(se,le,pe,"\u2026","\\textellipsis"),ie(oe,le,pe,"\u2026","\\mathellipsis"),ie(se,le,pe,"\u2026","\\ldots",!0),ie(oe,le,pe,"\u2026","\\ldots",!0),ie(oe,le,pe,"\u22ef","\\@cdots",!0),ie(oe,le,pe,"\u22f1","\\ddots",!0),ie(oe,le,xe,"\u22ee","\\varvdots"),ie(oe,le,ce,"\u02ca","\\acute"),ie(oe,le,ce,"\u02cb","\\grave"),ie(oe,le,ce,"\xa8","\\ddot"),ie(oe,le,ce,"~","\\tilde"),ie(oe,le,ce,"\u02c9","\\bar"),ie(oe,le,ce,"\u02d8","\\breve"),ie(oe,le,ce,"\u02c7","\\check"),ie(oe,le,ce,"^","\\hat"),ie(oe,le,ce,"\u20d7","\\vec"),ie(oe,le,ce,"\u02d9","\\dot"),ie(oe,le,ce,"\u02da","\\mathring"),ie(oe,le,de,"\ue131","\\@imath"),ie(oe,le,de,"\ue237","\\@jmath"),ie(oe,le,xe,"\u0131","\u0131"),ie(oe,le,xe,"\u0237","\u0237"),ie(se,le,xe,"\u0131","\\i",!0),ie(se,le,xe,"\u0237","\\j",!0),ie(se,le,xe,"\xdf","\\ss",!0),ie(se,le,xe,"\xe6","\\ae",!0),ie(se,le,xe,"\u0153","\\oe",!0),ie(se,le,xe,"\xf8","\\o",!0),ie(se,le,xe,"\xc6","\\AE",!0),ie(se,le,xe,"\u0152","\\OE",!0),ie(se,le,xe,"\xd8","\\O",!0),ie(se,le,ce,"\u02ca","\\'"),ie(se,le,ce,"\u02cb","\\`"),ie(se,le,ce,"\u02c6","\\^"),ie(se,le,ce,"\u02dc","\\~"),ie(se,le,ce,"\u02c9","\\="),ie(se,le,ce,"\u02d8","\\u"),ie(se,le,ce,"\u02d9","\\."),ie(se,le,ce,"\xb8","\\c"),ie(se,le,ce,"\u02da","\\r"),ie(se,le,ce,"\u02c7","\\v"),ie(se,le,ce,"\xa8",'\\"'),ie(se,le,ce,"\u02dd","\\H"),ie(se,le,ce,"\u25ef","\\textcircled");var we={"--":!0,"---":!0,"``":!0,"''":!0};ie(se,le,xe,"\u2013","--",!0),ie(se,le,xe,"\u2013","\\textendash"),ie(se,le,xe,"\u2014","---",!0),ie(se,le,xe,"\u2014","\\textemdash"),ie(se,le,xe,"\u2018","`",!0),ie(se,le,xe,"\u2018","\\textquoteleft"),ie(se,le,xe,"\u2019","'",!0),ie(se,le,xe,"\u2019","\\textquoteright"),ie(se,le,xe,"\u201c","``",!0),ie(se,le,xe,"\u201c","\\textquotedblleft"),ie(se,le,xe,"\u201d","''",!0),ie(se,le,xe,"\u201d","\\textquotedblright"),ie(oe,le,xe,"\xb0","\\degree",!0),ie(se,le,xe,"\xb0","\\degree"),ie(se,le,xe,"\xb0","\\textdegree",!0),ie(oe,le,xe,"\xa3","\\pounds"),ie(oe,le,xe,"\xa3","\\mathsterling",!0),ie(se,le,xe,"\xa3","\\pounds"),ie(se,le,xe,"\xa3","\\textsterling",!0),ie(oe,he,xe,"\u2720","\\maltese"),ie(se,he,xe,"\u2720","\\maltese");for(var ke='0123456789/@."',Se=0;Se<ke.length;Se++){var Me=ke.charAt(Se);ie(oe,le,xe,Me,Me)}for(var ze='0123456789!@*()-=+";:?/.,',Ae=0;Ae<ze.length;Ae++){var Te=ze.charAt(Ae);ie(se,le,xe,Te,Te)}for(var Be="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Ce=0;Ce<Be.length;Ce++){var Ne=Be.charAt(Ce);ie(oe,le,de,Ne,Ne),ie(se,le,xe,Ne,Ne)}ie(oe,he,xe,"C","\u2102"),ie(se,he,xe,"C","\u2102"),ie(oe,he,xe,"H","\u210d"),ie(se,he,xe,"H","\u210d"),ie(oe,he,xe,"N","\u2115"),ie(se,he,xe,"N","\u2115"),ie(oe,he,xe,"P","\u2119"),ie(se,he,xe,"P","\u2119"),ie(oe,he,xe,"Q","\u211a"),ie(se,he,xe,"Q","\u211a"),ie(oe,he,xe,"R","\u211d"),ie(se,he,xe,"R","\u211d"),ie(oe,he,xe,"Z","\u2124"),ie(se,he,xe,"Z","\u2124"),ie(oe,le,de,"h","\u210e"),ie(se,le,de,"h","\u210e");for(var qe="",Ie=0;Ie<Be.length;Ie++){var Re=Be.charAt(Ie);ie(oe,le,de,Re,qe=String.fromCharCode(55349,56320+Ie)),ie(se,le,xe,Re,qe),ie(oe,le,de,Re,qe=String.fromCharCode(55349,56372+Ie)),ie(se,le,xe,Re,qe),ie(oe,le,de,Re,qe=String.fromCharCode(55349,56424+Ie)),ie(se,le,xe,Re,qe),ie(oe,le,de,Re,qe=String.fromCharCode(55349,56580+Ie)),ie(se,le,xe,Re,qe),ie(oe,le,de,Re,qe=String.fromCharCode(55349,56736+Ie)),ie(se,le,xe,Re,qe),ie(oe,le,de,Re,qe=String.fromCharCode(55349,56788+Ie)),ie(se,le,xe,Re,qe),ie(oe,le,de,Re,qe=String.fromCharCode(55349,56840+Ie)),ie(se,le,xe,Re,qe),ie(oe,le,de,Re,qe=String.fromCharCode(55349,56944+Ie)),ie(se,le,xe,Re,qe),Ie<26&&(ie(oe,le,de,Re,qe=String.fromCharCode(55349,56632+Ie)),ie(se,le,xe,Re,qe),ie(oe,le,de,Re,qe=String.fromCharCode(55349,56476+Ie)),ie(se,le,xe,Re,qe))}ie(oe,le,de,"k",qe=String.fromCharCode(55349,56668)),ie(se,le,xe,"k",qe);for(var He=0;He<10;He++){var Oe=He.toString();ie(oe,le,de,Oe,qe=String.fromCharCode(55349,57294+He)),ie(se,le,xe,Oe,qe),ie(oe,le,de,Oe,qe=String.fromCharCode(55349,57314+He)),ie(se,le,xe,Oe,qe),ie(oe,le,de,Oe,qe=String.fromCharCode(55349,57324+He)),ie(se,le,xe,Oe,qe),ie(oe,le,de,Oe,qe=String.fromCharCode(55349,57334+He)),ie(se,le,xe,Oe,qe)}for(var Ee="\xd0\xde\xfe",Le=0;Le<Ee.length;Le++){var De=Ee.charAt(Le);ie(oe,le,de,De,De),ie(se,le,xe,De,De)}var Ve=[["mathbf","textbf","Main-Bold"],["mathbf","textbf","Main-Bold"],["mathnormal","textit","Math-Italic"],["mathnormal","textit","Math-Italic"],["boldsymbol","boldsymbol","Main-BoldItalic"],["boldsymbol","boldsymbol","Main-BoldItalic"],["mathscr","textscr","Script-Regular"],["","",""],["","",""],["","",""],["mathfrak","textfrak","Fraktur-Regular"],["mathfrak","textfrak","Fraktur-Regular"],["mathbb","textbb","AMS-Regular"],["mathbb","textbb","AMS-Regular"],["","",""],["","",""],["mathsf","textsf","SansSerif-Regular"],["mathsf","textsf","SansSerif-Regular"],["mathboldsf","textboldsf","SansSerif-Bold"],["mathboldsf","textboldsf","SansSerif-Bold"],["mathitsf","textitsf","SansSerif-Italic"],["mathitsf","textitsf","SansSerif-Italic"],["","",""],["","",""],["mathtt","texttt","Typewriter-Regular"],["mathtt","texttt","Typewriter-Regular"]],Pe=[["mathbf","textbf","Main-Bold"],["","",""],["mathsf","textsf","SansSerif-Regular"],["mathboldsf","textboldsf","SansSerif-Bold"],["mathtt","texttt","Typewriter-Regular"]],Fe=function(e,t,r){return ae[r][e]&&ae[r][e].replace&&(e=ae[r][e].replace),{value:e,metrics:N(e,t,r)}},Ge=function(e,t,r,n,a){var i,o=Fe(e,t,r),s=o.metrics;if(e=o.value,s){var l=s.italic;("text"===r||n&&"mathit"===n.font)&&(l=0),i=new Z(e,s.height,s.depth,l,s.skew,s.width,a)}else"undefined"!=typeof console&&console.warn("No character metrics for '"+e+"' in style '"+t+"' and mode '"+r+"'"),i=new Z(e,0,0,0,0,0,a);if(n){i.maxFontSize=n.sizeMultiplier,n.style.isTight()&&i.classes.push("mtight");var h=n.getColor();h&&(i.style.color=h)}return i},Ue=function(e,t){if(G(e.classes)!==G(t.classes)||e.skew!==t.skew||e.maxFontSize!==t.maxFontSize)return!1;if(1===e.classes.length){var r=e.classes[0];if("mbin"===r||"mord"===r)return!1}for(var n in e.style)if(e.style.hasOwnProperty(n)&&e.style[n]!==t.style[n])return!1;for(var a in t.style)if(t.style.hasOwnProperty(a)&&e.style[a]!==t.style[a])return!1;return!0},Ye=function(e){for(var t=0,r=0,n=0,a=0;a<e.children.length;a++){var i=e.children[a];i.height>t&&(t=i.height),i.depth>r&&(r=i.depth),i.maxFontSize>n&&(n=i.maxFontSize)}e.height=t,e.depth=r,e.maxFontSize=n},Xe=function(e,t,r,n){var a=new W(e,t,r,n);return Ye(a),a},We=function(e,t,r,n){return new W(e,t,r,n)},_e=function(e){var t=new A(e);return Ye(t),t},je=function(e,t,r){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}return n+"-"+("textbf"===t&&"textit"===r?"BoldItalic":"textbf"===t?"Bold":"textit"===t?"Italic":"Regular")},$e={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},Ze={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},Ke={fontMap:$e,makeSymbol:Ge,mathsym:function(e,t,r,n){return void 0===n&&(n=[]),"boldsymbol"===r.font&&Fe(e,"Main-Bold",t).metrics?Ge(e,"Main-Bold",t,r,n.concat(["mathbf"])):"\\"===e||"main"===ae[t][e].font?Ge(e,"Main-Regular",t,r,n):Ge(e,"AMS-Regular",t,r,n.concat(["amsrm"]))},makeSpan:Xe,makeSvgSpan:We,makeLineSpan:function(e,t,r){var n=Xe([e],[],t);return n.height=Math.max(r||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),n.style.borderBottomWidth=F(n.height),n.maxFontSize=1,n},makeAnchor:function(e,t,r,n){var a=new _(e,t,r,n);return Ye(a),a},makeFragment:_e,wrapFragment:function(e,t){return e instanceof A?Xe([],[e],t):e},makeVList:function(e,t){for(var r=function(e){if("individualShift"===e.positionType){for(var t=e.children,r=[t[0]],n=-t[0].shift-t[0].elem.depth,a=n,i=1;i<t.length;i++){var o=-t[i].shift-a-t[i].elem.depth,s=o-(t[i-1].elem.height+t[i-1].elem.depth);a+=o,r.push({type:"kern",size:s}),r.push(t[i])}return{children:r,depth:n}}var l;if("top"===e.positionType){for(var h=e.positionData,c=0;c<e.children.length;c++){var m=e.children[c];h-="kern"===m.type?m.size:m.elem.height+m.elem.depth}l=h}else if("bottom"===e.positionType)l=-e.positionData;else{var u=e.children[0];if("elem"!==u.type)throw new Error('First child must have type "elem".');if("shift"===e.positionType)l=-u.elem.depth-e.positionData;else{if("firstBaseline"!==e.positionType)throw new Error("Invalid positionType "+e.positionType+".");l=-u.elem.depth}}return{children:e.children,depth:l}}(e),n=r.children,a=r.depth,i=0,o=0;o<n.length;o++){var s=n[o];if("elem"===s.type){var l=s.elem;i=Math.max(i,l.maxFontSize,l.height)}}i+=2;var h=Xe(["pstrut"],[]);h.style.height=F(i);for(var c=[],m=a,u=a,p=a,d=0;d<n.length;d++){var f=n[d];if("kern"===f.type)p+=f.size;else{var g=f.elem,v=f.wrapperClasses||[],b=f.wrapperStyle||{},y=Xe(v,[h,g],void 0,b);y.style.top=F(-i-p-g.depth),f.marginLeft&&(y.style.marginLeft=f.marginLeft),f.marginRight&&(y.style.marginRight=f.marginRight),c.push(y),p+=g.height+g.depth}m=Math.min(m,p),u=Math.max(u,p)}var x,w=Xe(["vlist"],c);if(w.style.height=F(u),m<0){var k=Xe([],[]),S=Xe(["vlist"],[k]);S.style.height=F(-m);var M=Xe(["vlist-s"],[new Z("\u200b")]);x=[Xe(["vlist-r"],[w,M]),Xe(["vlist-r"],[S])]}else x=[Xe(["vlist-r"],[w])];var z=Xe(["vlist-t"],x);return 2===x.length&&z.classes.push("vlist-t2"),z.height=u,z.depth=-m,z},makeOrd:function(e,t,r){var a=e.mode,i=e.text,o=["mord"],s="math"===a||"text"===a&&t.font,l=s?t.font:t.fontFamily;if(55349===i.charCodeAt(0)){var h=function(e,t){var r=1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536,a="math"===t?0:1;if(119808<=r&&r<120484){var i=Math.floor((r-119808)/26);return[Ve[i][2],Ve[i][a]]}if(120782<=r&&r<=120831){var o=Math.floor((r-120782)/10);return[Pe[o][2],Pe[o][a]]}if(120485===r||120486===r)return[Ve[0][2],Ve[0][a]];if(120486<r&&r<120782)return["",""];throw new n("Unsupported character: "+e)}(i,a),c=h[0],m=h[1];return Ge(i,c,a,t,o.concat(m))}if(l){var u,p;if("boldsymbol"===l){var d=function(e,t,r,n,a){return"textord"!==a&&Fe(e,"Math-BoldItalic",t).metrics?{fontName:"Math-BoldItalic",fontClass:"boldsymbol"}:{fontName:"Main-Bold",fontClass:"mathbf"}}(i,a,0,0,r);u=d.fontName,p=[d.fontClass]}else s?(u=$e[l].fontName,p=[l]):(u=je(l,t.fontWeight,t.fontShape),p=[l,t.fontWeight,t.fontShape]);if(Fe(i,u,a).metrics)return Ge(i,u,a,t,o.concat(p));if(we.hasOwnProperty(i)&&"Typewriter"===u.slice(0,10)){for(var f=[],g=0;g<i.length;g++)f.push(Ge(i[g],u,a,t,o.concat(p)));return _e(f)}}if("mathord"===r)return Ge(i,"Math-Italic",a,t,o.concat(["mathnormal"]));if("textord"===r){var v=ae[a][i]&&ae[a][i].font;if("ams"===v){var b=je("amsrm",t.fontWeight,t.fontShape);return Ge(i,b,a,t,o.concat("amsrm",t.fontWeight,t.fontShape))}if("main"!==v&&v){var y=je(v,t.fontWeight,t.fontShape);return Ge(i,y,a,t,o.concat(y,t.fontWeight,t.fontShape))}var x=je("textrm",t.fontWeight,t.fontShape);return Ge(i,x,a,t,o.concat(t.fontWeight,t.fontShape))}throw new Error("unexpected type: "+r+" in makeOrd")},makeGlue:function(e,t){var r=Xe(["mspace"],[],t),n=P(e,t);return r.style.marginRight=F(n),r},staticSvg:function(e,t){var r=Ze[e],n=r[0],a=r[1],i=r[2],o=new J(n),s=new K([o],{width:F(a),height:F(i),style:"width:"+F(a),viewBox:"0 0 "+1e3*a+" "+1e3*i,preserveAspectRatio:"xMinYMin"}),l=We(["overlay"],[s],t);return l.height=i,l.style.height=F(i),l.style.width=F(a),l},svgData:Ze,tryCombineChars:function(e){for(var t=0;t<e.length-1;t++){var r=e[t],n=e[t+1];r instanceof Z&&n instanceof Z&&Ue(r,n)&&(r.text+=n.text,r.height=Math.max(r.height,n.height),r.depth=Math.max(r.depth,n.depth),r.italic=n.italic,e.splice(t+1,1),t--)}return e}},Je={number:3,unit:"mu"},Qe={number:4,unit:"mu"},et={number:5,unit:"mu"},tt={mord:{mop:Je,mbin:Qe,mrel:et,minner:Je},mop:{mord:Je,mop:Je,mrel:et,minner:Je},mbin:{mord:Qe,mop:Qe,mopen:Qe,minner:Qe},mrel:{mord:et,mop:et,mopen:et,minner:et},mopen:{},mclose:{mop:Je,mbin:Qe,mrel:et,minner:Je},mpunct:{mord:Je,mop:Je,mrel:et,mopen:Je,mclose:Je,mpunct:Je,minner:Je},minner:{mord:Je,mop:Je,mbin:Qe,mrel:et,mopen:Je,mpunct:Je,minner:Je}},rt={mord:{mop:Je},mop:{mord:Je,mop:Je},mbin:{},mrel:{},mopen:{},mclose:{mop:Je},mpunct:{},minner:{mop:Je}},nt={},at={},it={};function ot(e){for(var t=e.type,r=e.names,n=e.props,a=e.handler,i=e.htmlBuilder,o=e.mathmlBuilder,s={type:t,numArgs:n.numArgs,argTypes:n.argTypes,allowedInArgument:!!n.allowedInArgument,allowedInText:!!n.allowedInText,allowedInMath:void 0===n.allowedInMath||n.allowedInMath,numOptionalArgs:n.numOptionalArgs||0,infix:!!n.infix,primitive:!!n.primitive,handler:a},l=0;l<r.length;++l)nt[r[l]]=s;t&&(i&&(at[t]=i),o&&(it[t]=o))}function st(e){ot({type:e.type,names:[],props:{numArgs:0},handler:function(){throw new Error("Should never be called.")},htmlBuilder:e.htmlBuilder,mathmlBuilder:e.mathmlBuilder})}var lt=function(e){return"ordgroup"===e.type&&1===e.body.length?e.body[0]:e},ht=function(e){return"ordgroup"===e.type?e.body:[e]},ct=Ke.makeSpan,mt=["leftmost","mbin","mopen","mrel","mop","mpunct"],ut=["rightmost","mrel","mclose","mpunct"],pt={display:x.DISPLAY,text:x.TEXT,script:x.SCRIPT,scriptscript:x.SCRIPTSCRIPT},dt={mord:"mord",mop:"mop",mbin:"mbin",mrel:"mrel",mopen:"mopen",mclose:"mclose",mpunct:"mpunct",minner:"minner"},ft=function(e,t,r,n){void 0===n&&(n=[null,null]);for(var a=[],i=0;i<e.length;i++){var o=wt(e[i],t);if(o instanceof A){var s=o.children;a.push.apply(a,s)}else a.push(o)}if(Ke.tryCombineChars(a),!r)return a;var h=t;if(1===e.length){var c=e[0];"sizing"===c.type?h=t.havingSize(c.size):"styling"===c.type&&(h=t.havingStyle(pt[c.style]))}var m=ct([n[0]||"leftmost"],[],t),u=ct([n[1]||"rightmost"],[],t),p="root"===r;return gt(a,(function(e,t){var r=t.classes[0],n=e.classes[0];"mbin"===r&&l.contains(ut,n)?t.classes[0]="mord":"mbin"===n&&l.contains(mt,r)&&(e.classes[0]="mord")}),{node:m},u,p),gt(a,(function(e,t){var r=yt(t),n=yt(e),a=r&&n?e.hasClass("mtight")?rt[r][n]:tt[r][n]:null;if(a)return Ke.makeGlue(a,h)}),{node:m},u,p),a},gt=function e(t,r,n,a,i){a&&t.push(a);for(var o=0;o<t.length;o++){var s=t[o],l=vt(s);if(l)e(l.children,r,n,null,i);else{var h=!s.hasClass("mspace");if(h){var c=r(s,n.node);c&&(n.insertAfter?n.insertAfter(c):(t.unshift(c),o++))}h?n.node=s:i&&s.hasClass("newline")&&(n.node=ct(["leftmost"])),n.insertAfter=function(e){return function(r){t.splice(e+1,0,r),o++}}(o)}}a&&t.pop()},vt=function(e){return e instanceof A||e instanceof _||e instanceof W&&e.hasClass("enclosing")?e:null},bt=function e(t,r){var n=vt(t);if(n){var a=n.children;if(a.length){if("right"===r)return e(a[a.length-1],"right");if("left"===r)return e(a[0],"left")}}return t},yt=function(e,t){return e?(t&&(e=bt(e,t)),dt[e.classes[0]]||null):null},xt=function(e,t){var r=["nulldelimiter"].concat(e.baseSizingClasses());return ct(t.concat(r))},wt=function(e,t,r){if(!e)return ct();if(at[e.type]){var a=at[e.type](e,t);if(r&&t.size!==r.size){a=ct(t.sizingClasses(r),[a],t);var i=t.sizeMultiplier/r.sizeMultiplier;a.height*=i,a.depth*=i}return a}throw new n("Got group of unknown type: '"+e.type+"'")};function kt(e,t){var r=ct(["base"],e,t),n=ct(["strut"]);return n.style.height=F(r.height+r.depth),r.depth&&(n.style.verticalAlign=F(-r.depth)),r.children.unshift(n),r}function St(e,t){var r=null;1===e.length&&"tag"===e[0].type&&(r=e[0].tag,e=e[0].body);var n,a=ft(e,t,"root");2===a.length&&a[1].hasClass("tag")&&(n=a.pop());for(var i,o=[],s=[],l=0;l<a.length;l++)if(s.push(a[l]),a[l].hasClass("mbin")||a[l].hasClass("mrel")||a[l].hasClass("allowbreak")){for(var h=!1;l<a.length-1&&a[l+1].hasClass("mspace")&&!a[l+1].hasClass("newline");)l++,s.push(a[l]),a[l].hasClass("nobreak")&&(h=!0);h||(o.push(kt(s,t)),s=[])}else a[l].hasClass("newline")&&(s.pop(),s.length>0&&(o.push(kt(s,t)),s=[]),o.push(a[l]));s.length>0&&o.push(kt(s,t)),r?((i=kt(ft(r,t,!0))).classes=["tag"],o.push(i)):n&&o.push(n);var c=ct(["katex-html"],o);if(c.setAttribute("aria-hidden","true"),i){var m=i.children[0];m.style.height=F(c.height+c.depth),c.depth&&(m.style.verticalAlign=F(-c.depth))}return c}function Mt(e){return new A(e)}var zt=function(){function e(e,t,r){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=r||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.getAttribute=function(e){return this.attributes[e]},t.toNode=function(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);this.classes.length>0&&(e.className=G(this.classes));for(var r=0;r<this.children.length;r++)e.appendChild(this.children[r].toNode());return e},t.toMarkup=function(){var e="<"+this.type;for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&(e+=" "+t+'="',e+=l.escape(this.attributes[t]),e+='"');this.classes.length>0&&(e+=' class ="'+l.escape(G(this.classes))+'"'),e+=">";for(var r=0;r<this.children.length;r++)e+=this.children[r].toMarkup();return e+="</"+this.type+">"},t.toText=function(){return this.children.map((function(e){return e.toText()})).join("")},e}(),At=function(){function e(e){this.text=void 0,this.text=e}var t=e.prototype;return t.toNode=function(){return document.createTextNode(this.text)},t.toMarkup=function(){return l.escape(this.toText())},t.toText=function(){return this.text},e}(),Tt={MathNode:zt,TextNode:At,SpaceNode:function(){function e(e){this.width=void 0,this.character=void 0,this.width=e,this.character=e>=.05555&&e<=.05556?"\u200a":e>=.1666&&e<=.1667?"\u2009":e>=.2222&&e<=.2223?"\u2005":e>=.2777&&e<=.2778?"\u2005\u200a":e>=-.05556&&e<=-.05555?"\u200a\u2063":e>=-.1667&&e<=-.1666?"\u2009\u2063":e>=-.2223&&e<=-.2222?"\u205f\u2063":e>=-.2778&&e<=-.2777?"\u2005\u2063":null}var t=e.prototype;return t.toNode=function(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",F(this.width)),e},t.toMarkup=function(){return this.character?"<mtext>"+this.character+"</mtext>":'<mspace width="'+F(this.width)+'"/>'},t.toText=function(){return this.character?this.character:" "},e}(),newDocumentFragment:Mt},Bt=function(e,t,r){return!ae[t][e]||!ae[t][e].replace||55349===e.charCodeAt(0)||we.hasOwnProperty(e)&&r&&(r.fontFamily&&"tt"===r.fontFamily.slice(4,6)||r.font&&"tt"===r.font.slice(4,6))||(e=ae[t][e].replace),new Tt.TextNode(e)},Ct=function(e){return 1===e.length?e[0]:new Tt.MathNode("mrow",e)},Nt=function(e,t){if("texttt"===t.fontFamily)return"monospace";if("textsf"===t.fontFamily)return"textit"===t.fontShape&&"textbf"===t.fontWeight?"sans-serif-bold-italic":"textit"===t.fontShape?"sans-serif-italic":"textbf"===t.fontWeight?"bold-sans-serif":"sans-serif";if("textit"===t.fontShape&&"textbf"===t.fontWeight)return"bold-italic";if("textit"===t.fontShape)return"italic";if("textbf"===t.fontWeight)return"bold";var r=t.font;if(!r||"mathnormal"===r)return null;var n=e.mode;if("mathit"===r)return"italic";if("boldsymbol"===r)return"textord"===e.type?"bold":"bold-italic";if("mathbf"===r)return"bold";if("mathbb"===r)return"double-struck";if("mathfrak"===r)return"fraktur";if("mathscr"===r||"mathcal"===r)return"script";if("mathsf"===r)return"sans-serif";if("mathtt"===r)return"monospace";var a=e.text;return l.contains(["\\imath","\\jmath"],a)?null:(ae[n][a]&&ae[n][a].replace&&(a=ae[n][a].replace),N(a,Ke.fontMap[r].fontName,n)?Ke.fontMap[r].variant:null)},qt=function(e,t,r){if(1===e.length){var n=Rt(e[0],t);return r&&n instanceof zt&&"mo"===n.type&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}for(var a,i=[],o=0;o<e.length;o++){var s=Rt(e[o],t);if(s instanceof zt&&a instanceof zt){if("mtext"===s.type&&"mtext"===a.type&&s.getAttribute("mathvariant")===a.getAttribute("mathvariant")){var l;(l=a.children).push.apply(l,s.children);continue}if("mn"===s.type&&"mn"===a.type){var h;(h=a.children).push.apply(h,s.children);continue}if("mi"===s.type&&1===s.children.length&&"mn"===a.type){var c=s.children[0];if(c instanceof At&&"."===c.text){var m;(m=a.children).push.apply(m,s.children);continue}}else if("mi"===a.type&&1===a.children.length){var u=a.children[0];if(u instanceof At&&"\u0338"===u.text&&("mo"===s.type||"mi"===s.type||"mn"===s.type)){var p=s.children[0];p instanceof At&&p.text.length>0&&(p.text=p.text.slice(0,1)+"\u0338"+p.text.slice(1),i.pop())}}}i.push(s),a=s}return i},It=function(e,t,r){return Ct(qt(e,t,r))},Rt=function(e,t){if(!e)return new Tt.MathNode("mrow");if(it[e.type])return it[e.type](e,t);throw new n("Got group of unknown type: '"+e.type+"'")};function Ht(e,t,r,n,a){var i,o=qt(e,r);i=1===o.length&&o[0]instanceof zt&&l.contains(["mrow","mtable"],o[0].type)?o[0]:new Tt.MathNode("mrow",o);var s=new Tt.MathNode("annotation",[new Tt.TextNode(t)]);s.setAttribute("encoding","application/x-tex");var h=new Tt.MathNode("semantics",[i,s]),c=new Tt.MathNode("math",[h]);c.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n&&c.setAttribute("display","block");var m=a?"katex":"katex-mathml";return Ke.makeSpan([m],[c])}var Ot=function(e){return new E({style:e.displayMode?x.DISPLAY:x.TEXT,maxSize:e.maxSize,minRuleThickness:e.minRuleThickness})},Et=function(e,t){if(t.displayMode){var r=["katex-display"];t.leqno&&r.push("leqno"),t.fleqn&&r.push("fleqn"),e=Ke.makeSpan(r,[e])}return e},Lt=function(e,t,r){var n,a=Ot(r);if("mathml"===r.output)return Ht(e,t,a,r.displayMode,!0);if("html"===r.output){var i=St(e,a);n=Ke.makeSpan(["katex"],[i])}else{var o=Ht(e,t,a,r.displayMode,!1),s=St(e,a);n=Ke.makeSpan(["katex"],[o,s])}return Et(n,r)},Dt={widehat:"^",widecheck:"\u02c7",widetilde:"~",utilde:"~",overleftarrow:"\u2190",underleftarrow:"\u2190",xleftarrow:"\u2190",overrightarrow:"\u2192",underrightarrow:"\u2192",xrightarrow:"\u2192",underbrace:"\u23df",overbrace:"\u23de",overgroup:"\u23e0",undergroup:"\u23e1",overleftrightarrow:"\u2194",underleftrightarrow:"\u2194",xleftrightarrow:"\u2194",Overrightarrow:"\u21d2",xRightarrow:"\u21d2",overleftharpoon:"\u21bc",xleftharpoonup:"\u21bc",overrightharpoon:"\u21c0",xrightharpoonup:"\u21c0",xLeftarrow:"\u21d0",xLeftrightarrow:"\u21d4",xhookleftarrow:"\u21a9",xhookrightarrow:"\u21aa",xmapsto:"\u21a6",xrightharpoondown:"\u21c1",xleftharpoondown:"\u21bd",xrightleftharpoons:"\u21cc",xleftrightharpoons:"\u21cb",xtwoheadleftarrow:"\u219e",xtwoheadrightarrow:"\u21a0",xlongequal:"=",xtofrom:"\u21c4",xrightleftarrows:"\u21c4",xrightequilibrium:"\u21cc",xleftequilibrium:"\u21cb","\\cdrightarrow":"\u2192","\\cdleftarrow":"\u2190","\\cdlongequal":"="},Vt={overrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],overleftarrow:[["leftarrow"],.888,522,"xMinYMin"],underrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],underleftarrow:[["leftarrow"],.888,522,"xMinYMin"],xrightarrow:[["rightarrow"],1.469,522,"xMaxYMin"],"\\cdrightarrow":[["rightarrow"],3,522,"xMaxYMin"],xleftarrow:[["leftarrow"],1.469,522,"xMinYMin"],"\\cdleftarrow":[["leftarrow"],3,522,"xMinYMin"],Overrightarrow:[["doublerightarrow"],.888,560,"xMaxYMin"],xRightarrow:[["doublerightarrow"],1.526,560,"xMaxYMin"],xLeftarrow:[["doubleleftarrow"],1.526,560,"xMinYMin"],overleftharpoon:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoonup:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoondown:[["leftharpoondown"],.888,522,"xMinYMin"],overrightharpoon:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoonup:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoondown:[["rightharpoondown"],.888,522,"xMaxYMin"],xlongequal:[["longequal"],.888,334,"xMinYMin"],"\\cdlongequal":[["longequal"],3,334,"xMinYMin"],xtwoheadleftarrow:[["twoheadleftarrow"],.888,334,"xMinYMin"],xtwoheadrightarrow:[["twoheadrightarrow"],.888,334,"xMaxYMin"],overleftrightarrow:[["leftarrow","rightarrow"],.888,522],overbrace:[["leftbrace","midbrace","rightbrace"],1.6,548],underbrace:[["leftbraceunder","midbraceunder","rightbraceunder"],1.6,548],underleftrightarrow:[["leftarrow","rightarrow"],.888,522],xleftrightarrow:[["leftarrow","rightarrow"],1.75,522],xLeftrightarrow:[["doubleleftarrow","doublerightarrow"],1.75,560],xrightleftharpoons:[["leftharpoondownplus","rightharpoonplus"],1.75,716],xleftrightharpoons:[["leftharpoonplus","rightharpoondownplus"],1.75,716],xhookleftarrow:[["leftarrow","righthook"],1.08,522],xhookrightarrow:[["lefthook","rightarrow"],1.08,522],overlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],underlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],overgroup:[["leftgroup","rightgroup"],.888,342],undergroup:[["leftgroupunder","rightgroupunder"],.888,342],xmapsto:[["leftmapsto","rightarrow"],1.5,522],xtofrom:[["leftToFrom","rightToFrom"],1.75,528],xrightleftarrows:[["baraboveleftarrow","rightarrowabovebar"],1.75,901],xrightequilibrium:[["baraboveshortleftharpoon","rightharpoonaboveshortbar"],1.75,716],xleftequilibrium:[["shortbaraboveleftharpoon","shortrightharpoonabovebar"],1.75,716]},Pt=function(e,t,r,n,a){var i,o=e.height+e.depth+r+n;if(/fbox|color|angl/.test(t)){if(i=Ke.makeSpan(["stretchy",t],[],a),"fbox"===t){var s=a.color&&a.getColor();s&&(i.style.borderColor=s)}}else{var l=[];/^[bx]cancel$/.test(t)&&l.push(new Q({x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})),/^x?cancel$/.test(t)&&l.push(new Q({x1:"0",y1:"100%",x2:"100%",y2:"0","stroke-width":"0.046em"}));var h=new K(l,{width:"100%",height:F(o)});i=Ke.makeSvgSpan([],[h],a)}return i.height=o,i.style.height=F(o),i},Ft=function(e){var t=new Tt.MathNode("mo",[new Tt.TextNode(Dt[e.replace(/^\\/,"")])]);return t.setAttribute("stretchy","true"),t},Gt=function(e,t){var r=function(){var r=4e5,n=e.label.slice(1);if(l.contains(["widehat","widecheck","widetilde","utilde"],n)){var a,i,o,s="ordgroup"===(d=e.base).type?d.body.length:1;if(s>5)"widehat"===n||"widecheck"===n?(a=420,r=2364,o=.42,i=n+"4"):(a=312,r=2340,o=.34,i="tilde4");else{var h=[1,1,2,2,3,3][s];"widehat"===n||"widecheck"===n?(r=[0,1062,2364,2364,2364][h],a=[0,239,300,360,420][h],o=[0,.24,.3,.3,.36,.42][h],i=n+h):(r=[0,600,1033,2339,2340][h],a=[0,260,286,306,312][h],o=[0,.26,.286,.3,.306,.34][h],i="tilde"+h)}var c=new J(i),m=new K([c],{width:"100%",height:F(o),viewBox:"0 0 "+r+" "+a,preserveAspectRatio:"none"});return{span:Ke.makeSvgSpan([],[m],t),minWidth:0,height:o}}var u,p,d,f=[],g=Vt[n],v=g[0],b=g[1],y=g[2],x=y/1e3,w=v.length;if(1===w)u=["hide-tail"],p=[g[3]];else if(2===w)u=["halfarrow-left","halfarrow-right"],p=["xMinYMin","xMaxYMin"];else{if(3!==w)throw new Error("Correct katexImagesData or update code here to support\n "+w+" children.");u=["brace-left","brace-center","brace-right"],p=["xMinYMin","xMidYMin","xMaxYMin"]}for(var k=0;k<w;k++){var S=new J(v[k]),M=new K([S],{width:"400em",height:F(x),viewBox:"0 0 "+r+" "+y,preserveAspectRatio:p[k]+" slice"}),z=Ke.makeSvgSpan([u[k]],[M],t);if(1===w)return{span:z,minWidth:b,height:x};z.style.height=F(x),f.push(z)}return{span:Ke.makeSpan(["stretchy"],f,t),minWidth:b,height:x}}(),n=r.span,a=r.minWidth,i=r.height;return n.height=i,n.style.height=F(i),a>0&&(n.style.minWidth=F(a)),n};function Ut(e,t){if(!e||e.type!==t)throw new Error("Expected node of type "+t+", but got "+(e?"node of type "+e.type:String(e)));return e}function Yt(e){var t=Xt(e);if(!t)throw new Error("Expected node of symbol group type, but got "+(e?"node of type "+e.type:String(e)));return t}function Xt(e){return e&&("atom"===e.type||re.hasOwnProperty(e.type))?e:null}var Wt=function(e,t){var r,n,a;e&&"supsub"===e.type?(r=(n=Ut(e.base,"accent")).base,e.base=r,a=function(e){if(e instanceof W)return e;throw new Error("Expected span<HtmlDomNode> but got "+String(e)+".")}(wt(e,t)),e.base=n):r=(n=Ut(e,"accent")).base;var i=wt(r,t.havingCrampedStyle()),o=0;if(n.isShifty&&l.isCharacterBox(r)){var s=l.getBaseElem(r);o=ee(wt(s,t.havingCrampedStyle())).skew}var h,c="\\c"===n.label,m=c?i.height+i.depth:Math.min(i.height,t.fontMetrics().xHeight);if(n.isStretchy)h=Gt(n,t),h=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"elem",elem:h,wrapperClasses:["svg-align"],wrapperStyle:o>0?{width:"calc(100% - "+F(2*o)+")",marginLeft:F(2*o)}:void 0}]},t);else{var u,p;"\\vec"===n.label?(u=Ke.staticSvg("vec",t),p=Ke.svgData.vec[1]):((u=ee(u=Ke.makeOrd({mode:n.mode,text:n.label},t,"textord"))).italic=0,p=u.width,c&&(m+=u.depth)),h=Ke.makeSpan(["accent-body"],[u]);var d="\\textcircled"===n.label;d&&(h.classes.push("accent-full"),m=i.height);var f=o;d||(f-=p/2),h.style.left=F(f),"\\textcircled"===n.label&&(h.style.top=".2em"),h=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"kern",size:-m},{type:"elem",elem:h}]},t)}var g=Ke.makeSpan(["mord","accent"],[h],t);return a?(a.children[0]=g,a.height=Math.max(g.height,a.height),a.classes[0]="mord",a):g},_t=function(e,t){var r=e.isStretchy?Ft(e.label):new Tt.MathNode("mo",[Bt(e.label,e.mode)]),n=new Tt.MathNode("mover",[Rt(e.base,t),r]);return n.setAttribute("accent","true"),n},jt=new RegExp(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map((function(e){return"\\"+e})).join("|"));ot({type:"accent",names:["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\widecheck","\\widehat","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overlinesegment","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:function(e,t){var r=lt(t[0]),n=!jt.test(e.funcName),a=!n||"\\widehat"===e.funcName||"\\widetilde"===e.funcName||"\\widecheck"===e.funcName;return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:n,isShifty:a,base:r}},htmlBuilder:Wt,mathmlBuilder:_t}),ot({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\u","\\.",'\\"',"\\c","\\r","\\H","\\v","\\textcircled"],props:{numArgs:1,allowedInText:!0,allowedInMath:!0,argTypes:["primitive"]},handler:function(e,t){var r=t[0],n=e.parser.mode;return"math"===n&&(e.parser.settings.reportNonstrict("mathVsTextAccents","LaTeX's accent "+e.funcName+" works only in text mode"),n="text"),{type:"accent",mode:n,label:e.funcName,isStretchy:!1,isShifty:!0,base:r}},htmlBuilder:Wt,mathmlBuilder:_t}),ot({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underlinesegment","\\utilde"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"accentUnder",mode:r.mode,label:n,base:a}},htmlBuilder:function(e,t){var r=wt(e.base,t),n=Gt(e,t),a="\\utilde"===e.label?.12:0,i=Ke.makeVList({positionType:"top",positionData:r.height,children:[{type:"elem",elem:n,wrapperClasses:["svg-align"]},{type:"kern",size:a},{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord","accentunder"],[i],t)},mathmlBuilder:function(e,t){var r=Ft(e.label),n=new Tt.MathNode("munder",[Rt(e.base,t),r]);return n.setAttribute("accentunder","true"),n}});var $t=function(e){var t=new Tt.MathNode("mpadded",e?[e]:[]);return t.setAttribute("width","+0.6em"),t.setAttribute("lspace","0.3em"),t};ot({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xrightleftharpoons","\\xleftrightharpoons","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\xtofrom","\\xrightleftarrows","\\xrightequilibrium","\\xleftequilibrium","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler:function(e,t,r){var n=e.parser,a=e.funcName;return{type:"xArrow",mode:n.mode,label:a,body:t[0],below:r[0]}},htmlBuilder:function(e,t){var r,n=t.style,a=t.havingStyle(n.sup()),i=Ke.wrapFragment(wt(e.body,a,t),t),o="\\x"===e.label.slice(0,2)?"x":"cd";i.classes.push(o+"-arrow-pad"),e.below&&(a=t.havingStyle(n.sub()),(r=Ke.wrapFragment(wt(e.below,a,t),t)).classes.push(o+"-arrow-pad"));var s,l=Gt(e,t),h=-t.fontMetrics().axisHeight+.5*l.height,c=-t.fontMetrics().axisHeight-.5*l.height-.111;if((i.depth>.25||"\\xleftequilibrium"===e.label)&&(c-=i.depth),r){var m=-t.fontMetrics().axisHeight+r.height+.5*l.height+.111;s=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:c},{type:"elem",elem:l,shift:h},{type:"elem",elem:r,shift:m}]},t)}else s=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:c},{type:"elem",elem:l,shift:h}]},t);return s.children[0].children[0].children[1].classes.push("svg-align"),Ke.makeSpan(["mrel","x-arrow"],[s],t)},mathmlBuilder:function(e,t){var r,n=Ft(e.label);if(n.setAttribute("minsize","x"===e.label.charAt(0)?"1.75em":"3.0em"),e.body){var a=$t(Rt(e.body,t));if(e.below){var i=$t(Rt(e.below,t));r=new Tt.MathNode("munderover",[n,i,a])}else r=new Tt.MathNode("mover",[n,a])}else if(e.below){var o=$t(Rt(e.below,t));r=new Tt.MathNode("munder",[n,o])}else r=$t(),r=new Tt.MathNode("mover",[n,r]);return r}});var Zt=Ke.makeSpan;function Kt(e,t){var r=ft(e.body,t,!0);return Zt([e.mclass],r,t)}function Jt(e,t){var r,n=qt(e.body,t);return"minner"===e.mclass?r=new Tt.MathNode("mpadded",n):"mord"===e.mclass?e.isCharacterBox?(r=n[0]).type="mi":r=new Tt.MathNode("mi",n):(e.isCharacterBox?(r=n[0]).type="mo":r=new Tt.MathNode("mo",n),"mbin"===e.mclass?(r.attributes.lspace="0.22em",r.attributes.rspace="0.22em"):"mpunct"===e.mclass?(r.attributes.lspace="0em",r.attributes.rspace="0.17em"):"mopen"===e.mclass||"mclose"===e.mclass?(r.attributes.lspace="0em",r.attributes.rspace="0em"):"minner"===e.mclass&&(r.attributes.lspace="0.0556em",r.attributes.width="+0.1111em")),r}ot({type:"mclass",names:["\\mathord","\\mathbin","\\mathrel","\\mathopen","\\mathclose","\\mathpunct","\\mathinner"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"mclass",mode:r.mode,mclass:"m"+n.slice(5),body:ht(a),isCharacterBox:l.isCharacterBox(a)}},htmlBuilder:Kt,mathmlBuilder:Jt});var Qt=function(e){var t="ordgroup"===e.type&&e.body.length?e.body[0]:e;return"atom"!==t.type||"bin"!==t.family&&"rel"!==t.family?"mord":"m"+t.family};ot({type:"mclass",names:["\\@binrel"],props:{numArgs:2},handler:function(e,t){return{type:"mclass",mode:e.parser.mode,mclass:Qt(t[0]),body:ht(t[1]),isCharacterBox:l.isCharacterBox(t[1])}}}),ot({type:"mclass",names:["\\stackrel","\\overset","\\underset"],props:{numArgs:2},handler:function(e,t){var r,n=e.parser,a=e.funcName,i=t[1],o=t[0];r="\\stackrel"!==a?Qt(i):"mrel";var s={type:"op",mode:i.mode,limits:!0,alwaysHandleSupSub:!0,parentIsSupSub:!1,symbol:!1,suppressBaseShift:"\\stackrel"!==a,body:ht(i)},h={type:"supsub",mode:o.mode,base:s,sup:"\\underset"===a?null:o,sub:"\\underset"===a?o:null};return{type:"mclass",mode:n.mode,mclass:r,body:[h],isCharacterBox:l.isCharacterBox(h)}},htmlBuilder:Kt,mathmlBuilder:Jt}),ot({type:"pmb",names:["\\pmb"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"pmb",mode:e.parser.mode,mclass:Qt(t[0]),body:ht(t[0])}},htmlBuilder:function(e,t){var r=ft(e.body,t,!0),n=Ke.makeSpan([e.mclass],r,t);return n.style.textShadow="0.02em 0.01em 0.04px",n},mathmlBuilder:function(e,t){var r=qt(e.body,t),n=new Tt.MathNode("mstyle",r);return n.setAttribute("style","text-shadow: 0.02em 0.01em 0.04px"),n}});var er={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},tr=function(e){return"textord"===e.type&&"@"===e.text};function rr(e,t,r){var n=er[e];switch(n){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return r.callFunction(n,[t[0]],[t[1]]);case"\\uparrow":case"\\downarrow":var a={type:"atom",text:n,mode:"math",family:"rel"},i={type:"ordgroup",mode:"math",body:[r.callFunction("\\\\cdleft",[t[0]],[]),r.callFunction("\\Big",[a],[]),r.callFunction("\\\\cdright",[t[1]],[])]};return r.callFunction("\\\\cdparent",[i],[]);case"\\\\cdlongequal":return r.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":return r.callFunction("\\Big",[{type:"textord",text:"\\Vert",mode:"math"}],[]);default:return{type:"textord",text:" ",mode:"math"}}}ot({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"cdlabel",mode:r.mode,side:n.slice(4),label:t[0]}},htmlBuilder:function(e,t){var r=t.havingStyle(t.style.sup()),n=Ke.wrapFragment(wt(e.label,r,t),t);return n.classes.push("cd-label-"+e.side),n.style.bottom=F(.8-n.depth),n.height=0,n.depth=0,n},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mrow",[Rt(e.label,t)]);return(r=new Tt.MathNode("mpadded",[r])).setAttribute("width","0"),"left"===e.side&&r.setAttribute("lspace","-1width"),r.setAttribute("voffset","0.7em"),(r=new Tt.MathNode("mstyle",[r])).setAttribute("displaystyle","false"),r.setAttribute("scriptlevel","1"),r}}),ot({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:function(e,t){return{type:"cdlabelparent",mode:e.parser.mode,fragment:t[0]}},htmlBuilder:function(e,t){var r=Ke.wrapFragment(wt(e.fragment,t),t);return r.classes.push("cd-vert-arrow"),r},mathmlBuilder:function(e,t){return new Tt.MathNode("mrow",[Rt(e.fragment,t)])}}),ot({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){for(var r=e.parser,a=Ut(t[0],"ordgroup").body,i="",o=0;o<a.length;o++){i+=Ut(a[o],"textord").text}var s,l=parseInt(i);if(isNaN(l))throw new n("\\@char has non-numeric argument "+i);if(l<0||l>=1114111)throw new n("\\@char with invalid code point "+i);return l<=65535?s=String.fromCharCode(l):(l-=65536,s=String.fromCharCode(55296+(l>>10),56320+(1023&l))),{type:"textord",mode:r.mode,text:s}}});var nr=function(e,t){var r=ft(e.body,t.withColor(e.color),!1);return Ke.makeFragment(r)},ar=function(e,t){var r=qt(e.body,t.withColor(e.color)),n=new Tt.MathNode("mstyle",r);return n.setAttribute("mathcolor",e.color),n};ot({type:"color",names:["\\textcolor"],props:{numArgs:2,allowedInText:!0,argTypes:["color","original"]},handler:function(e,t){var r=e.parser,n=Ut(t[0],"color-token").color,a=t[1];return{type:"color",mode:r.mode,color:n,body:ht(a)}},htmlBuilder:nr,mathmlBuilder:ar}),ot({type:"color",names:["\\color"],props:{numArgs:1,allowedInText:!0,argTypes:["color"]},handler:function(e,t){var r=e.parser,n=e.breakOnTokenText,a=Ut(t[0],"color-token").color;r.gullet.macros.set("\\current@color",a);var i=r.parseExpression(!0,n);return{type:"color",mode:r.mode,color:a,body:i}},htmlBuilder:nr,mathmlBuilder:ar}),ot({type:"cr",names:["\\\\"],props:{numArgs:0,numOptionalArgs:0,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a="["===n.gullet.future().text?n.parseSizeGroup(!0):null,i=!n.settings.displayMode||!n.settings.useStrictBehavior("newLineInDisplayMode","In LaTeX, \\\\ or \\newline does nothing in display mode");return{type:"cr",mode:n.mode,newLine:i,size:a&&Ut(a,"size").value}},htmlBuilder:function(e,t){var r=Ke.makeSpan(["mspace"],[],t);return e.newLine&&(r.classes.push("newline"),e.size&&(r.style.marginTop=F(P(e.size,t)))),r},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mspace");return e.newLine&&(r.setAttribute("linebreak","newline"),e.size&&r.setAttribute("height",F(P(e.size,t)))),r}});var ir={"\\global":"\\global","\\long":"\\\\globallong","\\\\globallong":"\\\\globallong","\\def":"\\gdef","\\gdef":"\\gdef","\\edef":"\\xdef","\\xdef":"\\xdef","\\let":"\\\\globallet","\\futurelet":"\\\\globalfuture"},or=function(e){var t=e.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(t))throw new n("Expected a control sequence",e);return t},sr=function(e,t,r,n){var a=e.gullet.macros.get(r.text);null==a&&(r.noexpand=!0,a={tokens:[r],numArgs:0,unexpandable:!e.gullet.isExpandable(r.text)}),e.gullet.macros.set(t,a,n)};ot({type:"internal",names:["\\global","\\long","\\\\globallong"],props:{numArgs:0,allowedInText:!0},handler:function(e){var t=e.parser,r=e.funcName;t.consumeSpaces();var a=t.fetch();if(ir[a.text])return"\\global"!==r&&"\\\\globallong"!==r||(a.text=ir[a.text]),Ut(t.parseFunction(),"internal");throw new n("Invalid token after macro prefix",a)}}),ot({type:"internal",names:["\\def","\\gdef","\\edef","\\xdef"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,a=t.gullet.popToken(),i=a.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(i))throw new n("Expected a control sequence",a);for(var o,s=0,l=[[]];"{"!==t.gullet.future().text;)if("#"===(a=t.gullet.popToken()).text){if("{"===t.gullet.future().text){o=t.gullet.future(),l[s].push("{");break}if(a=t.gullet.popToken(),!/^[1-9]$/.test(a.text))throw new n('Invalid argument number "'+a.text+'"');if(parseInt(a.text)!==s+1)throw new n('Argument number "'+a.text+'" out of order');s++,l.push([])}else{if("EOF"===a.text)throw new n("Expected a macro definition");l[s].push(a.text)}var h=t.gullet.consumeArg().tokens;return o&&h.unshift(o),"\\edef"!==r&&"\\xdef"!==r||(h=t.gullet.expandTokens(h)).reverse(),t.gullet.macros.set(i,{tokens:h,numArgs:s,delimiters:l},r===ir[r]),{type:"internal",mode:t.mode}}}),ot({type:"internal",names:["\\let","\\\\globallet"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=or(t.gullet.popToken());t.gullet.consumeSpaces();var a=function(e){var t=e.gullet.popToken();return"="===t.text&&" "===(t=e.gullet.popToken()).text&&(t=e.gullet.popToken()),t}(t);return sr(t,n,a,"\\\\globallet"===r),{type:"internal",mode:t.mode}}}),ot({type:"internal",names:["\\futurelet","\\\\globalfuture"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=or(t.gullet.popToken()),a=t.gullet.popToken(),i=t.gullet.popToken();return sr(t,n,i,"\\\\globalfuture"===r),t.gullet.pushToken(i),t.gullet.pushToken(a),{type:"internal",mode:t.mode}}});var lr=function(e,t,r){var n=N(ae.math[e]&&ae.math[e].replace||e,t,r);if(!n)throw new Error("Unsupported symbol "+e+" and font size "+t+".");return n},hr=function(e,t,r,n){var a=r.havingBaseStyle(t),i=Ke.makeSpan(n.concat(a.sizingClasses(r)),[e],r),o=a.sizeMultiplier/r.sizeMultiplier;return i.height*=o,i.depth*=o,i.maxFontSize=a.sizeMultiplier,i},cr=function(e,t,r){var n=t.havingBaseStyle(r),a=(1-t.sizeMultiplier/n.sizeMultiplier)*t.fontMetrics().axisHeight;e.classes.push("delimcenter"),e.style.top=F(a),e.height-=a,e.depth+=a},mr=function(e,t,r,n,a,i){var o=function(e,t,r,n){return Ke.makeSymbol(e,"Size"+t+"-Regular",r,n)}(e,t,a,n),s=hr(Ke.makeSpan(["delimsizing","size"+t],[o],n),x.TEXT,n,i);return r&&cr(s,n,x.TEXT),s},ur=function(e,t,r){var n;return n="Size1-Regular"===t?"delim-size1":"delim-size4",{type:"elem",elem:Ke.makeSpan(["delimsizinginner",n],[Ke.makeSpan([],[Ke.makeSymbol(e,t,r)])])}},pr=function(e,t,r){var n=T["Size4-Regular"][e.charCodeAt(0)]?T["Size4-Regular"][e.charCodeAt(0)][4]:T["Size1-Regular"][e.charCodeAt(0)][4],a=new J("inner",function(e,t){switch(e){case"\u239c":return"M291 0 H417 V"+t+" H291z M291 0 H417 V"+t+" H291z";case"\u2223":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145z";case"\u2225":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145zM367 0 H410 V"+t+" H367z M367 0 H410 V"+t+" H367z";case"\u239f":return"M457 0 H583 V"+t+" H457z M457 0 H583 V"+t+" H457z";case"\u23a2":return"M319 0 H403 V"+t+" H319z M319 0 H403 V"+t+" H319z";case"\u23a5":return"M263 0 H347 V"+t+" H263z M263 0 H347 V"+t+" H263z";case"\u23aa":return"M384 0 H504 V"+t+" H384z M384 0 H504 V"+t+" H384z";case"\u23d0":return"M312 0 H355 V"+t+" H312z M312 0 H355 V"+t+" H312z";case"\u2016":return"M257 0 H300 V"+t+" H257z M257 0 H300 V"+t+" H257zM478 0 H521 V"+t+" H478z M478 0 H521 V"+t+" H478z";default:return""}}(e,Math.round(1e3*t))),i=new K([a],{width:F(n),height:F(t),style:"width:"+F(n),viewBox:"0 0 "+1e3*n+" "+Math.round(1e3*t),preserveAspectRatio:"xMinYMin"}),o=Ke.makeSvgSpan([],[i],r);return o.height=t,o.style.height=F(t),o.style.width=F(n),{type:"elem",elem:o}},dr={type:"kern",size:-.008},fr=["|","\\lvert","\\rvert","\\vert"],gr=["\\|","\\lVert","\\rVert","\\Vert"],vr=function(e,t,r,n,a,i){var o,s,h,c,m="",u=0;o=h=c=e,s=null;var p="Size1-Regular";"\\uparrow"===e?h=c="\u23d0":"\\Uparrow"===e?h=c="\u2016":"\\downarrow"===e?o=h="\u23d0":"\\Downarrow"===e?o=h="\u2016":"\\updownarrow"===e?(o="\\uparrow",h="\u23d0",c="\\downarrow"):"\\Updownarrow"===e?(o="\\Uparrow",h="\u2016",c="\\Downarrow"):l.contains(fr,e)?(h="\u2223",m="vert",u=333):l.contains(gr,e)?(h="\u2225",m="doublevert",u=556):"["===e||"\\lbrack"===e?(o="\u23a1",h="\u23a2",c="\u23a3",p="Size4-Regular",m="lbrack",u=667):"]"===e||"\\rbrack"===e?(o="\u23a4",h="\u23a5",c="\u23a6",p="Size4-Regular",m="rbrack",u=667):"\\lfloor"===e||"\u230a"===e?(h=o="\u23a2",c="\u23a3",p="Size4-Regular",m="lfloor",u=667):"\\lceil"===e||"\u2308"===e?(o="\u23a1",h=c="\u23a2",p="Size4-Regular",m="lceil",u=667):"\\rfloor"===e||"\u230b"===e?(h=o="\u23a5",c="\u23a6",p="Size4-Regular",m="rfloor",u=667):"\\rceil"===e||"\u2309"===e?(o="\u23a4",h=c="\u23a5",p="Size4-Regular",m="rceil",u=667):"("===e||"\\lparen"===e?(o="\u239b",h="\u239c",c="\u239d",p="Size4-Regular",m="lparen",u=875):")"===e||"\\rparen"===e?(o="\u239e",h="\u239f",c="\u23a0",p="Size4-Regular",m="rparen",u=875):"\\{"===e||"\\lbrace"===e?(o="\u23a7",s="\u23a8",c="\u23a9",h="\u23aa",p="Size4-Regular"):"\\}"===e||"\\rbrace"===e?(o="\u23ab",s="\u23ac",c="\u23ad",h="\u23aa",p="Size4-Regular"):"\\lgroup"===e||"\u27ee"===e?(o="\u23a7",c="\u23a9",h="\u23aa",p="Size4-Regular"):"\\rgroup"===e||"\u27ef"===e?(o="\u23ab",c="\u23ad",h="\u23aa",p="Size4-Regular"):"\\lmoustache"===e||"\u23b0"===e?(o="\u23a7",c="\u23ad",h="\u23aa",p="Size4-Regular"):"\\rmoustache"!==e&&"\u23b1"!==e||(o="\u23ab",c="\u23a9",h="\u23aa",p="Size4-Regular");var d=lr(o,p,a),f=d.height+d.depth,g=lr(h,p,a),v=g.height+g.depth,b=lr(c,p,a),y=b.height+b.depth,w=0,k=1;if(null!==s){var S=lr(s,p,a);w=S.height+S.depth,k=2}var M=f+y+w,z=M+Math.max(0,Math.ceil((t-M)/(k*v)))*k*v,A=n.fontMetrics().axisHeight;r&&(A*=n.sizeMultiplier);var T=z/2-A,B=[];if(m.length>0){var C=z-f-y,N=Math.round(1e3*z),q=function(e,t){switch(e){case"lbrack":return"M403 1759 V84 H666 V0 H319 V1759 v"+t+" v1759 h347 v-84\nH403z M403 1759 V0 H319 V1759 v"+t+" v1759 h84z";case"rbrack":return"M347 1759 V0 H0 V84 H263 V1759 v"+t+" v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v"+t+" v1759 h84z";case"vert":return"M145 15 v585 v"+t+" v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v"+-t+" v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v"+t+" v585 h43z";case"doublevert":return"M145 15 v585 v"+t+" v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v"+-t+" v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v"+t+" v585 h43z\nM367 15 v585 v"+t+" v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v"+-t+" v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M410 15 H367 v585 v"+t+" v585 h43z";case"lfloor":return"M319 602 V0 H403 V602 v"+t+" v1715 h263 v84 H319z\nMM319 602 V0 H403 V602 v"+t+" v1715 H319z";case"rfloor":return"M319 602 V0 H403 V602 v"+t+" v1799 H0 v-84 H319z\nMM319 602 V0 H403 V602 v"+t+" v1715 H319z";case"lceil":return"M403 1759 V84 H666 V0 H319 V1759 v"+t+" v602 h84z\nM403 1759 V0 H319 V1759 v"+t+" v602 h84z";case"rceil":return"M347 1759 V0 H0 V84 H263 V1759 v"+t+" v602 h84z\nM347 1759 V0 h-84 V1759 v"+t+" v602 h84z";case"lparen":return"M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1\nc-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,\n-36,557 l0,"+(t+84)+"c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,\n949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9\nc0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,\n-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189\nl0,-"+(t+92)+"c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,\n-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z";case"rparen":return"M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,\n63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5\nc11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0,"+(t+9)+"\nc-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664\nc-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11\nc0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17\nc242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558\nl0,-"+(t+144)+"c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,\n-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z";default:throw new Error("Unknown stretchy delimiter.")}}(m,Math.round(1e3*C)),I=new J(m,q),R=(u/1e3).toFixed(3)+"em",H=(N/1e3).toFixed(3)+"em",O=new K([I],{width:R,height:H,viewBox:"0 0 "+u+" "+N}),E=Ke.makeSvgSpan([],[O],n);E.height=N/1e3,E.style.width=R,E.style.height=H,B.push({type:"elem",elem:E})}else{if(B.push(ur(c,p,a)),B.push(dr),null===s){var L=z-f-y+.016;B.push(pr(h,L,n))}else{var D=(z-f-y-w)/2+.016;B.push(pr(h,D,n)),B.push(dr),B.push(ur(s,p,a)),B.push(dr),B.push(pr(h,D,n))}B.push(dr),B.push(ur(o,p,a))}var V=n.havingBaseStyle(x.TEXT),P=Ke.makeVList({positionType:"bottom",positionData:T,children:B},V);return hr(Ke.makeSpan(["delimsizing","mult"],[P],V),x.TEXT,n,i)},br=.08,yr=function(e,t,r,n,a){var i=function(e,t,r){t*=1e3;var n="";switch(e){case"sqrtMain":n=function(e,t){return"M95,"+(622+e+t)+"\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl"+e/2.075+" -"+e+"\nc5.3,-9.3,12,-14,20,-14\nH400000v"+(40+e)+"H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM"+(834+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize1":n=function(e,t){return"M263,"+(601+e+t)+"c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl"+e/2.084+" -"+e+"\nc4.7,-7.3,11,-11,19,-11\nH40000v"+(40+e)+"H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize2":n=function(e,t){return"M983 "+(10+e+t)+"\nl"+e/3.13+" -"+e+"\nc4,-6.7,10,-10,18,-10 H400000v"+(40+e)+"\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize3":n=function(e,t){return"M424,"+(2398+e+t)+"\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl"+e/4.223+" -"+e+"c4,-6.7,10,-10,18,-10 H400000\nv"+(40+e)+"H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M"+(1001+e)+" "+t+"\nh400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize4":n=function(e,t){return"M473,"+(2713+e+t)+"\nc339.3,-1799.3,509.3,-2700,510,-2702 l"+e/5.298+" -"+e+"\nc3.3,-7.3,9.3,-11,18,-11 H400000v"+(40+e)+"H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM"+(1001+e)+" "+t+"h400000v"+(40+e)+"H1017.7z"}(t,M);break;case"sqrtTall":n=function(e,t,r){return"M702 "+(e+t)+"H400000"+(40+e)+"\nH742v"+(r-54-t-e)+"l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 "+t+"H400000v"+(40+e)+"H742z"}(t,M,r)}return n}(e,n,r),o=new J(e,i),s=new K([o],{width:"400em",height:F(t),viewBox:"0 0 400000 "+r,preserveAspectRatio:"xMinYMin slice"});return Ke.makeSvgSpan(["hide-tail"],[s],a)},xr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","\\surd"],wr=["\\uparrow","\\downarrow","\\updownarrow","\\Uparrow","\\Downarrow","\\Updownarrow","|","\\|","\\vert","\\Vert","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1"],kr=["<",">","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],Sr=[0,1.2,1.8,2.4,3],Mr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],zr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"stack"}],Ar=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],Tr=function(e){if("small"===e.type)return"Main-Regular";if("large"===e.type)return"Size"+e.size+"-Regular";if("stack"===e.type)return"Size4-Regular";throw new Error("Add support for delim type '"+e.type+"' here.")},Br=function(e,t,r,n){for(var a=Math.min(2,3-n.style.size);a<r.length&&"stack"!==r[a].type;a++){var i=lr(e,Tr(r[a]),"math"),o=i.height+i.depth;if("small"===r[a].type&&(o*=n.havingBaseStyle(r[a].style).sizeMultiplier),o>t)return r[a]}return r[r.length-1]},Cr=function(e,t,r,n,a,i){var o;"<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),o=l.contains(kr,e)?Mr:l.contains(xr,e)?Ar:zr;var s=Br(e,t,o,n);return"small"===s.type?function(e,t,r,n,a,i){var o=Ke.makeSymbol(e,"Main-Regular",a,n),s=hr(o,t,n,i);return r&&cr(s,n,t),s}(e,s.style,r,n,a,i):"large"===s.type?mr(e,s.size,r,n,a,i):vr(e,t,r,n,a,i)},Nr={sqrtImage:function(e,t){var r,n,a=t.havingBaseSizing(),i=Br("\\surd",e*a.sizeMultiplier,Ar,a),o=a.sizeMultiplier,s=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),l=0,h=0,c=0;return"small"===i.type?(e<1?o=1:e<1.4&&(o=.7),h=(1+s)/o,(r=yr("sqrtMain",l=(1+s+br)/o,c=1e3+1e3*s+80,s,t)).style.minWidth="0.853em",n=.833/o):"large"===i.type?(c=1080*Sr[i.size],h=(Sr[i.size]+s)/o,l=(Sr[i.size]+s+br)/o,(r=yr("sqrtSize"+i.size,l,c,s,t)).style.minWidth="1.02em",n=1/o):(l=e+s+br,h=e+s,c=Math.floor(1e3*e+s)+80,(r=yr("sqrtTall",l,c,s,t)).style.minWidth="0.742em",n=1.056),r.height=h,r.style.height=F(l),{span:r,advanceWidth:n,ruleWidth:(t.fontMetrics().sqrtRuleThickness+s)*o}},sizedDelim:function(e,t,r,a,i){if("<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),l.contains(xr,e)||l.contains(kr,e))return mr(e,t,!1,r,a,i);if(l.contains(wr,e))return vr(e,Sr[t],!1,r,a,i);throw new n("Illegal delimiter: '"+e+"'")},sizeToMaxHeight:Sr,customSizedDelim:Cr,leftRightDelim:function(e,t,r,n,a,i){var o=n.fontMetrics().axisHeight*n.sizeMultiplier,s=5/n.fontMetrics().ptPerEm,l=Math.max(t-o,r+o),h=Math.max(l/500*901,2*l-s);return Cr(e,h,!0,n,a,i)}},qr={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},Ir=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","<",">","\\langle","\u27e8","\\rangle","\u27e9","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function Rr(e,t){var r=Xt(e);if(r&&l.contains(Ir,r.text))return r;throw new n(r?"Invalid delimiter '"+r.text+"' after '"+t.funcName+"'":"Invalid delimiter type '"+e.type+"'",e)}function Hr(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}ot({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:function(e,t){var r=Rr(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:qr[e.funcName].size,mclass:qr[e.funcName].mclass,delim:r.text}},htmlBuilder:function(e,t){return"."===e.delim?Ke.makeSpan([e.mclass]):Nr.sizedDelim(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[];"."!==e.delim&&t.push(Bt(e.delim,e.mode));var r=new Tt.MathNode("mo",t);"mopen"===e.mclass||"mclose"===e.mclass?r.setAttribute("fence","true"):r.setAttribute("fence","false"),r.setAttribute("stretchy","true");var n=F(Nr.sizeToMaxHeight[e.size]);return r.setAttribute("minsize",n),r.setAttribute("maxsize",n),r}}),ot({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get("\\current@color");if(r&&"string"!=typeof r)throw new n("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:e.parser.mode,delim:Rr(t[0],e).text,color:r}}}),ot({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=Rr(t[0],e),n=e.parser;++n.leftrightDepth;var a=n.parseExpression(!1);--n.leftrightDepth,n.expect("\\right",!1);var i=Ut(n.parseFunction(),"leftright-right");return{type:"leftright",mode:n.mode,body:a,left:r.text,right:i.delim,rightColor:i.color}},htmlBuilder:function(e,t){Hr(e);for(var r,n,a=ft(e.body,t,!0,["mopen","mclose"]),i=0,o=0,s=!1,l=0;l<a.length;l++)a[l].isMiddle?s=!0:(i=Math.max(a[l].height,i),o=Math.max(a[l].depth,o));if(i*=t.sizeMultiplier,o*=t.sizeMultiplier,r="."===e.left?xt(t,["mopen"]):Nr.leftRightDelim(e.left,i,o,t,e.mode,["mopen"]),a.unshift(r),s)for(var h=1;h<a.length;h++){var c=a[h].isMiddle;c&&(a[h]=Nr.leftRightDelim(c.delim,i,o,c.options,e.mode,[]))}if("."===e.right)n=xt(t,["mclose"]);else{var m=e.rightColor?t.withColor(e.rightColor):t;n=Nr.leftRightDelim(e.right,i,o,m,e.mode,["mclose"])}return a.push(n),Ke.makeSpan(["minner"],a,t)},mathmlBuilder:function(e,t){Hr(e);var r=qt(e.body,t);if("."!==e.left){var n=new Tt.MathNode("mo",[Bt(e.left,e.mode)]);n.setAttribute("fence","true"),r.unshift(n)}if("."!==e.right){var a=new Tt.MathNode("mo",[Bt(e.right,e.mode)]);a.setAttribute("fence","true"),e.rightColor&&a.setAttribute("mathcolor",e.rightColor),r.push(a)}return Ct(r)}}),ot({type:"middle",names:["\\middle"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=Rr(t[0],e);if(!e.parser.leftrightDepth)throw new n("\\middle without preceding \\left",r);return{type:"middle",mode:e.parser.mode,delim:r.text}},htmlBuilder:function(e,t){var r;if("."===e.delim)r=xt(t,[]);else{r=Nr.sizedDelim(e.delim,1,t,e.mode,[]);var n={delim:e.delim,options:t};r.isMiddle=n}return r},mathmlBuilder:function(e,t){var r="\\vert"===e.delim||"|"===e.delim?Bt("|","text"):Bt(e.delim,e.mode),n=new Tt.MathNode("mo",[r]);return n.setAttribute("fence","true"),n.setAttribute("lspace","0.05em"),n.setAttribute("rspace","0.05em"),n}});var Or=function(e,t){var r,n,a,i=Ke.wrapFragment(wt(e.body,t),t),o=e.label.slice(1),s=t.sizeMultiplier,h=0,c=l.isCharacterBox(e.body);if("sout"===o)(r=Ke.makeSpan(["stretchy","sout"])).height=t.fontMetrics().defaultRuleThickness/s,h=-.5*t.fontMetrics().xHeight;else if("phase"===o){var m=P({number:.6,unit:"pt"},t),u=P({number:.35,unit:"ex"},t);s/=t.havingBaseSizing().sizeMultiplier;var p=i.height+i.depth+m+u;i.style.paddingLeft=F(p/2+m);var d=Math.floor(1e3*p*s),f="M400000 "+(n=d)+" H0 L"+n/2+" 0 l65 45 L145 "+(n-80)+" H400000z",g=new K([new J("phase",f)],{width:"400em",height:F(d/1e3),viewBox:"0 0 400000 "+d,preserveAspectRatio:"xMinYMin slice"});(r=Ke.makeSvgSpan(["hide-tail"],[g],t)).style.height=F(p),h=i.depth+m+u}else{/cancel/.test(o)?c||i.classes.push("cancel-pad"):"angl"===o?i.classes.push("anglpad"):i.classes.push("boxpad");var v=0,b=0,y=0;/box/.test(o)?(y=Math.max(t.fontMetrics().fboxrule,t.minRuleThickness),b=v=t.fontMetrics().fboxsep+("colorbox"===o?0:y)):"angl"===o?(v=4*(y=Math.max(t.fontMetrics().defaultRuleThickness,t.minRuleThickness)),b=Math.max(0,.25-i.depth)):b=v=c?.2:0,r=Pt(i,o,v,b,t),/fbox|boxed|fcolorbox/.test(o)?(r.style.borderStyle="solid",r.style.borderWidth=F(y)):"angl"===o&&.049!==y&&(r.style.borderTopWidth=F(y),r.style.borderRightWidth=F(y)),h=i.depth+b,e.backgroundColor&&(r.style.backgroundColor=e.backgroundColor,e.borderColor&&(r.style.borderColor=e.borderColor))}if(e.backgroundColor)a=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:r,shift:h},{type:"elem",elem:i,shift:0}]},t);else{var x=/cancel|phase/.test(o)?["svg-align"]:[];a=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:0},{type:"elem",elem:r,shift:h,wrapperClasses:x}]},t)}return/cancel/.test(o)&&(a.height=i.height,a.depth=i.depth),/cancel/.test(o)&&!c?Ke.makeSpan(["mord","cancel-lap"],[a],t):Ke.makeSpan(["mord"],[a],t)},Er=function(e,t){var r=0,n=new Tt.MathNode(e.label.indexOf("colorbox")>-1?"mpadded":"menclose",[Rt(e.body,t)]);switch(e.label){case"\\cancel":n.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":n.setAttribute("notation","downdiagonalstrike");break;case"\\phase":n.setAttribute("notation","phasorangle");break;case"\\sout":n.setAttribute("notation","horizontalstrike");break;case"\\fbox":n.setAttribute("notation","box");break;case"\\angl":n.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":if(r=t.fontMetrics().fboxsep*t.fontMetrics().ptPerEm,n.setAttribute("width","+"+2*r+"pt"),n.setAttribute("height","+"+2*r+"pt"),n.setAttribute("lspace",r+"pt"),n.setAttribute("voffset",r+"pt"),"\\fcolorbox"===e.label){var a=Math.max(t.fontMetrics().fboxrule,t.minRuleThickness);n.setAttribute("style","border: "+a+"em solid "+String(e.borderColor))}break;case"\\xcancel":n.setAttribute("notation","updiagonalstrike downdiagonalstrike")}return e.backgroundColor&&n.setAttribute("mathbackground",e.backgroundColor),n};ot({type:"enclose",names:["\\colorbox"],props:{numArgs:2,allowedInText:!0,argTypes:["color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ut(t[0],"color-token").color,o=t[1];return{type:"enclose",mode:n.mode,label:a,backgroundColor:i,body:o}},htmlBuilder:Or,mathmlBuilder:Er}),ot({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,allowedInText:!0,argTypes:["color","color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ut(t[0],"color-token").color,o=Ut(t[1],"color-token").color,s=t[2];return{type:"enclose",mode:n.mode,label:a,backgroundColor:o,borderColor:i,body:s}},htmlBuilder:Or,mathmlBuilder:Er}),ot({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\fbox",body:t[0]}}}),ot({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\phase"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"enclose",mode:r.mode,label:n,body:a}},htmlBuilder:Or,mathmlBuilder:Er}),ot({type:"enclose",names:["\\angl"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!1},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\angl",body:t[0]}}});var Lr={};function Dr(e){for(var t=e.type,r=e.names,n=e.props,a=e.handler,i=e.htmlBuilder,o=e.mathmlBuilder,s={type:t,numArgs:n.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:a},l=0;l<r.length;++l)Lr[r[l]]=s;i&&(at[t]=i),o&&(it[t]=o)}var Vr={};function Pr(e,t){Vr[e]=t}var Fr=function(){function e(e,t,r){this.lexer=void 0,this.start=void 0,this.end=void 0,this.lexer=e,this.start=t,this.end=r}return e.range=function(t,r){return r?t&&t.loc&&r.loc&&t.loc.lexer===r.loc.lexer?new e(t.loc.lexer,t.loc.start,r.loc.end):null:t&&t.loc},e}(),Gr=function(){function e(e,t){this.text=void 0,this.loc=void 0,this.noexpand=void 0,this.treatAsRelax=void 0,this.text=e,this.loc=t}return e.prototype.range=function(t,r){return new e(r,Fr.range(this,t))},e}();function Ur(e){var t=[];e.consumeSpaces();var r=e.fetch().text;for("\\relax"===r&&(e.consume(),e.consumeSpaces(),r=e.fetch().text);"\\hline"===r||"\\hdashline"===r;)e.consume(),t.push("\\hdashline"===r),e.consumeSpaces(),r=e.fetch().text;return t}var Yr=function(e){if(!e.parser.settings.displayMode)throw new n("{"+e.envName+"} can be used only in display mode.")};function Xr(e){if(-1===e.indexOf("ed"))return-1===e.indexOf("*")}function Wr(e,t,r){var a=t.hskipBeforeAndAfter,i=t.addJot,o=t.cols,s=t.arraystretch,l=t.colSeparationType,h=t.autoTag,c=t.singleRow,m=t.emptySingleRow,u=t.maxNumCols,p=t.leqno;if(e.gullet.beginGroup(),c||e.gullet.macros.set("\\cr","\\\\\\relax"),!s){var d=e.gullet.expandMacroAsText("\\arraystretch");if(null==d)s=1;else if(!(s=parseFloat(d))||s<0)throw new n("Invalid \\arraystretch: "+d)}e.gullet.beginGroup();var f=[],g=[f],v=[],b=[],y=null!=h?[]:void 0;function x(){h&&e.gullet.macros.set("\\@eqnsw","1",!0)}function w(){y&&(e.gullet.macros.get("\\df@tag")?(y.push(e.subparse([new Gr("\\df@tag")])),e.gullet.macros.set("\\df@tag",void 0,!0)):y.push(Boolean(h)&&"1"===e.gullet.macros.get("\\@eqnsw")))}for(x(),b.push(Ur(e));;){var k=e.parseExpression(!1,c?"\\end":"\\\\");e.gullet.endGroup(),e.gullet.beginGroup(),k={type:"ordgroup",mode:e.mode,body:k},r&&(k={type:"styling",mode:e.mode,style:r,body:[k]}),f.push(k);var S=e.fetch().text;if("&"===S){if(u&&f.length===u){if(c||l)throw new n("Too many tab characters: &",e.nextToken);e.settings.reportNonstrict("textEnv","Too few columns specified in the {array} column argument.")}e.consume()}else{if("\\end"===S){w(),1===f.length&&"styling"===k.type&&0===k.body[0].body.length&&(g.length>1||!m)&&g.pop(),b.length<g.length+1&&b.push([]);break}if("\\\\"!==S)throw new n("Expected & or \\\\ or \\cr or \\end",e.nextToken);e.consume();var M=void 0;" "!==e.gullet.future().text&&(M=e.parseSizeGroup(!0)),v.push(M?M.value:null),w(),b.push(Ur(e)),f=[],g.push(f),x()}}return e.gullet.endGroup(),e.gullet.endGroup(),{type:"array",mode:e.mode,addJot:i,arraystretch:s,body:g,cols:o,rowGaps:v,hskipBeforeAndAfter:a,hLinesBeforeRow:b,colSeparationType:l,tags:y,leqno:p}}function _r(e){return"d"===e.slice(0,1)?"display":"text"}var jr=function(e,t){var r,a,i=e.body.length,o=e.hLinesBeforeRow,s=0,h=new Array(i),c=[],m=Math.max(t.fontMetrics().arrayRuleWidth,t.minRuleThickness),u=1/t.fontMetrics().ptPerEm,p=5*u;e.colSeparationType&&"small"===e.colSeparationType&&(p=t.havingStyle(x.SCRIPT).sizeMultiplier/t.sizeMultiplier*.2778);var d="CD"===e.colSeparationType?P({number:3,unit:"ex"},t):12*u,f=3*u,g=e.arraystretch*d,v=.7*g,b=.3*g,y=0;function w(e){for(var t=0;t<e.length;++t)t>0&&(y+=.25),c.push({pos:y,isDashed:e[t]})}for(w(o[0]),r=0;r<e.body.length;++r){var k=e.body[r],S=v,M=b;s<k.length&&(s=k.length);var z=new Array(k.length);for(a=0;a<k.length;++a){var A=wt(k[a],t);M<A.depth&&(M=A.depth),S<A.height&&(S=A.height),z[a]=A}var T=e.rowGaps[r],B=0;T&&(B=P(T,t))>0&&(M<(B+=b)&&(M=B),B=0),e.addJot&&(M+=f),z.height=S,z.depth=M,y+=S,z.pos=y,y+=M+B,h[r]=z,w(o[r+1])}var C,N,q=y/2+t.fontMetrics().axisHeight,I=e.cols||[],R=[],H=[];if(e.tags&&e.tags.some((function(e){return e})))for(r=0;r<i;++r){var O=h[r],E=O.pos-q,L=e.tags[r],D=void 0;(D=!0===L?Ke.makeSpan(["eqn-num"],[],t):!1===L?Ke.makeSpan([],[],t):Ke.makeSpan([],ft(L,t,!0),t)).depth=O.depth,D.height=O.height,H.push({type:"elem",elem:D,shift:E})}for(a=0,N=0;a<s||N<I.length;++a,++N){for(var V=I[N]||{},G=!0;"separator"===V.type;){if(G||((C=Ke.makeSpan(["arraycolsep"],[])).style.width=F(t.fontMetrics().doubleRuleSep),R.push(C)),"|"!==V.separator&&":"!==V.separator)throw new n("Invalid separator type: "+V.separator);var U="|"===V.separator?"solid":"dashed",Y=Ke.makeSpan(["vertical-separator"],[],t);Y.style.height=F(y),Y.style.borderRightWidth=F(m),Y.style.borderRightStyle=U,Y.style.margin="0 "+F(-m/2);var X=y-q;X&&(Y.style.verticalAlign=F(-X)),R.push(Y),V=I[++N]||{},G=!1}if(!(a>=s)){var W=void 0;(a>0||e.hskipBeforeAndAfter)&&0!==(W=l.deflt(V.pregap,p))&&((C=Ke.makeSpan(["arraycolsep"],[])).style.width=F(W),R.push(C));var _=[];for(r=0;r<i;++r){var j=h[r],$=j[a];if($){var Z=j.pos-q;$.depth=j.depth,$.height=j.height,_.push({type:"elem",elem:$,shift:Z})}}_=Ke.makeVList({positionType:"individualShift",children:_},t),_=Ke.makeSpan(["col-align-"+(V.align||"c")],[_]),R.push(_),(a<s-1||e.hskipBeforeAndAfter)&&0!==(W=l.deflt(V.postgap,p))&&((C=Ke.makeSpan(["arraycolsep"],[])).style.width=F(W),R.push(C))}}if(h=Ke.makeSpan(["mtable"],R),c.length>0){for(var K=Ke.makeLineSpan("hline",t,m),J=Ke.makeLineSpan("hdashline",t,m),Q=[{type:"elem",elem:h,shift:0}];c.length>0;){var ee=c.pop(),te=ee.pos-q;ee.isDashed?Q.push({type:"elem",elem:J,shift:te}):Q.push({type:"elem",elem:K,shift:te})}h=Ke.makeVList({positionType:"individualShift",children:Q},t)}if(0===H.length)return Ke.makeSpan(["mord"],[h],t);var re=Ke.makeVList({positionType:"individualShift",children:H},t);return re=Ke.makeSpan(["tag"],[re],t),Ke.makeFragment([h,re])},$r={c:"center ",l:"left ",r:"right "},Zr=function(e,t){for(var r=[],n=new Tt.MathNode("mtd",[],["mtr-glue"]),a=new Tt.MathNode("mtd",[],["mml-eqn-num"]),i=0;i<e.body.length;i++){for(var o=e.body[i],s=[],l=0;l<o.length;l++)s.push(new Tt.MathNode("mtd",[Rt(o[l],t)]));e.tags&&e.tags[i]&&(s.unshift(n),s.push(n),e.leqno?s.unshift(a):s.push(a)),r.push(new Tt.MathNode("mtr",s))}var h=new Tt.MathNode("mtable",r),c=.5===e.arraystretch?.1:.16+e.arraystretch-1+(e.addJot?.09:0);h.setAttribute("rowspacing",F(c));var m="",u="";if(e.cols&&e.cols.length>0){var p=e.cols,d="",f=!1,g=0,v=p.length;"separator"===p[0].type&&(m+="top ",g=1),"separator"===p[p.length-1].type&&(m+="bottom ",v-=1);for(var b=g;b<v;b++)"align"===p[b].type?(u+=$r[p[b].align],f&&(d+="none "),f=!0):"separator"===p[b].type&&f&&(d+="|"===p[b].separator?"solid ":"dashed ",f=!1);h.setAttribute("columnalign",u.trim()),/[sd]/.test(d)&&h.setAttribute("columnlines",d.trim())}if("align"===e.colSeparationType){for(var y=e.cols||[],x="",w=1;w<y.length;w++)x+=w%2?"0em ":"1em ";h.setAttribute("columnspacing",x.trim())}else"alignat"===e.colSeparationType||"gather"===e.colSeparationType?h.setAttribute("columnspacing","0em"):"small"===e.colSeparationType?h.setAttribute("columnspacing","0.2778em"):"CD"===e.colSeparationType?h.setAttribute("columnspacing","0.5em"):h.setAttribute("columnspacing","1em");var k="",S=e.hLinesBeforeRow;m+=S[0].length>0?"left ":"",m+=S[S.length-1].length>0?"right ":"";for(var M=1;M<S.length-1;M++)k+=0===S[M].length?"none ":S[M][0]?"dashed ":"solid ";return/[sd]/.test(k)&&h.setAttribute("rowlines",k.trim()),""!==m&&(h=new Tt.MathNode("menclose",[h])).setAttribute("notation",m.trim()),e.arraystretch&&e.arraystretch<1&&(h=new Tt.MathNode("mstyle",[h])).setAttribute("scriptlevel","1"),h},Kr=function(e,t){-1===e.envName.indexOf("ed")&&Yr(e);var r,a=[],i=e.envName.indexOf("at")>-1?"alignat":"align",o="split"===e.envName,s=Wr(e.parser,{cols:a,addJot:!0,autoTag:o?void 0:Xr(e.envName),emptySingleRow:!0,colSeparationType:i,maxNumCols:o?2:void 0,leqno:e.parser.settings.leqno},"display"),l=0,h={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&"ordgroup"===t[0].type){for(var c="",m=0;m<t[0].body.length;m++){c+=Ut(t[0].body[m],"textord").text}r=Number(c),l=2*r}var u=!l;s.body.forEach((function(e){for(var t=1;t<e.length;t+=2){var a=Ut(e[t],"styling");Ut(a.body[0],"ordgroup").body.unshift(h)}if(u)l<e.length&&(l=e.length);else{var i=e.length/2;if(r<i)throw new n("Too many math in a row: expected "+r+", but got "+i,e[0])}}));for(var p=0;p<l;++p){var d="r",f=0;p%2==1?d="l":p>0&&u&&(f=1),a[p]={type:"align",align:d,pregap:f,postgap:0}}return s.colSeparationType=u?"align":"alignat",s};Dr({type:"array",names:["array","darray"],props:{numArgs:1},handler:function(e,t){var r=(Xt(t[0])?[t[0]]:Ut(t[0],"ordgroup").body).map((function(e){var t=Yt(e).text;if(-1!=="lcr".indexOf(t))return{type:"align",align:t};if("|"===t)return{type:"separator",separator:"|"};if(":"===t)return{type:"separator",separator:":"};throw new n("Unknown column alignment: "+t,e)})),a={cols:r,hskipBeforeAndAfter:!0,maxNumCols:r.length};return Wr(e.parser,a,_r(e.envName))},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler:function(e){var t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName.replace("*","")],r="c",a={hskipBeforeAndAfter:!1,cols:[{type:"align",align:r}]};if("*"===e.envName.charAt(e.envName.length-1)){var i=e.parser;if(i.consumeSpaces(),"["===i.fetch().text){if(i.consume(),i.consumeSpaces(),r=i.fetch().text,-1==="lcr".indexOf(r))throw new n("Expected l or c or r",i.nextToken);i.consume(),i.consumeSpaces(),i.expect("]"),i.consume(),a.cols=[{type:"align",align:r}]}}var o=Wr(e.parser,a,_r(e.envName)),s=Math.max.apply(Math,[0].concat(o.body.map((function(e){return e.length}))));return o.cols=new Array(s).fill({type:"align",align:r}),t?{type:"leftright",mode:e.mode,body:[o],left:t[0],right:t[1],rightColor:void 0}:o},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["smallmatrix"],props:{numArgs:0},handler:function(e){var t=Wr(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["subarray"],props:{numArgs:1},handler:function(e,t){var r=(Xt(t[0])?[t[0]]:Ut(t[0],"ordgroup").body).map((function(e){var t=Yt(e).text;if(-1!=="lc".indexOf(t))return{type:"align",align:t};throw new n("Unknown column alignment: "+t,e)}));if(r.length>1)throw new n("{subarray} can contain only one column");var a={cols:r,hskipBeforeAndAfter:!1,arraystretch:.5};if((a=Wr(e.parser,a,"script")).body.length>0&&a.body[0].length>1)throw new n("{subarray} can contain only one column");return a},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler:function(e){var t=Wr(e.parser,{arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},_r(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:Kr,htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler:function(e){l.contains(["gather","gather*"],e.envName)&&Yr(e);var t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",autoTag:Xr(e.envName),emptySingleRow:!0,leqno:e.parser.settings.leqno};return Wr(e.parser,t,"display")},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:Kr,htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["equation","equation*"],props:{numArgs:0},handler:function(e){Yr(e);var t={autoTag:Xr(e.envName),emptySingleRow:!0,singleRow:!0,maxNumCols:1,leqno:e.parser.settings.leqno};return Wr(e.parser,t,"display")},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["CD"],props:{numArgs:0},handler:function(e){return Yr(e),function(e){var t=[];for(e.gullet.beginGroup(),e.gullet.macros.set("\\cr","\\\\\\relax"),e.gullet.beginGroup();;){t.push(e.parseExpression(!1,"\\\\")),e.gullet.endGroup(),e.gullet.beginGroup();var r=e.fetch().text;if("&"!==r&&"\\\\"!==r){if("\\end"===r){0===t[t.length-1].length&&t.pop();break}throw new n("Expected \\\\ or \\cr or \\end",e.nextToken)}e.consume()}for(var a,i,o=[],s=[o],l=0;l<t.length;l++){for(var h=t[l],c={type:"styling",body:[],mode:"math",style:"display"},m=0;m<h.length;m++)if(tr(h[m])){o.push(c);var u=Yt(h[m+=1]).text,p=new Array(2);if(p[0]={type:"ordgroup",mode:"math",body:[]},p[1]={type:"ordgroup",mode:"math",body:[]},"=|.".indexOf(u)>-1);else{if(!("<>AV".indexOf(u)>-1))throw new n('Expected one of "<>AV=|." after @',h[m]);for(var d=0;d<2;d++){for(var f=!0,g=m+1;g<h.length;g++){if(i=u,("mathord"===(a=h[g]).type||"atom"===a.type)&&a.text===i){f=!1,m=g;break}if(tr(h[g]))throw new n("Missing a "+u+" character to complete a CD arrow.",h[g]);p[d].body.push(h[g])}if(f)throw new n("Missing a "+u+" character to complete a CD arrow.",h[m])}}var v={type:"styling",body:[rr(u,p,e)],mode:"math",style:"display"};o.push(v),c={type:"styling",body:[],mode:"math",style:"display"}}else c.body.push(h[m]);l%2==0?o.push(c):o.shift(),o=[],s.push(o)}return e.gullet.endGroup(),e.gullet.endGroup(),{type:"array",mode:"math",body:s,arraystretch:1,addJot:!0,rowGaps:[null],cols:new Array(s[0].length).fill({type:"align",align:"c",pregap:.25,postgap:.25}),colSeparationType:"CD",hLinesBeforeRow:new Array(s.length+1).fill([])}}(e.parser)},htmlBuilder:jr,mathmlBuilder:Zr}),Pr("\\nonumber","\\gdef\\@eqnsw{0}"),Pr("\\notag","\\nonumber"),ot({type:"text",names:["\\hline","\\hdashline"],props:{numArgs:0,allowedInText:!0,allowedInMath:!0},handler:function(e,t){throw new n(e.funcName+" valid only within array environment")}});var Jr=Lr;ot({type:"environment",names:["\\begin","\\end"],props:{numArgs:1,argTypes:["text"]},handler:function(e,t){var r=e.parser,a=e.funcName,i=t[0];if("ordgroup"!==i.type)throw new n("Invalid environment name",i);for(var o="",s=0;s<i.body.length;++s)o+=Ut(i.body[s],"textord").text;if("\\begin"===a){if(!Jr.hasOwnProperty(o))throw new n("No such environment: "+o,i);var l=Jr[o],h=r.parseArguments("\\begin{"+o+"}",l),c=h.args,m=h.optArgs,u={mode:r.mode,envName:o,parser:r},p=l.handler(u,c,m);r.expect("\\end",!1);var d=r.nextToken,f=Ut(r.parseFunction(),"environment");if(f.name!==o)throw new n("Mismatch: \\begin{"+o+"} matched by \\end{"+f.name+"}",d);return p}return{type:"environment",mode:r.mode,name:o,nameGroup:i}}});var Qr=function(e,t){var r=e.font,n=t.withFont(r);return wt(e.body,n)},en=function(e,t){var r=e.font,n=t.withFont(r);return Rt(e.body,n)},tn={"\\Bbb":"\\mathbb","\\bold":"\\mathbf","\\frak":"\\mathfrak","\\bm":"\\boldsymbol"};ot({type:"font",names:["\\mathrm","\\mathit","\\mathbf","\\mathnormal","\\mathbb","\\mathcal","\\mathfrak","\\mathscr","\\mathsf","\\mathtt","\\Bbb","\\bold","\\frak"],props:{numArgs:1,allowedInArgument:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=lt(t[0]),i=n;return i in tn&&(i=tn[i]),{type:"font",mode:r.mode,font:i.slice(1),body:a}},htmlBuilder:Qr,mathmlBuilder:en}),ot({type:"mclass",names:["\\boldsymbol","\\bm"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=t[0],a=l.isCharacterBox(n);return{type:"mclass",mode:r.mode,mclass:Qt(n),body:[{type:"font",mode:r.mode,font:"boldsymbol",body:n}],isCharacterBox:a}}}),ot({type:"font",names:["\\rm","\\sf","\\tt","\\bf","\\it","\\cal"],props:{numArgs:0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=e.breakOnTokenText,i=r.mode,o=r.parseExpression(!0,a);return{type:"font",mode:i,font:"math"+n.slice(1),body:{type:"ordgroup",mode:r.mode,body:o}}},htmlBuilder:Qr,mathmlBuilder:en});var rn=function(e,t){var r=t;return"display"===e?r=r.id>=x.SCRIPT.id?r.text():x.DISPLAY:"text"===e&&r.size===x.DISPLAY.size?r=x.TEXT:"script"===e?r=x.SCRIPT:"scriptscript"===e&&(r=x.SCRIPTSCRIPT),r},nn=function(e,t){var r,n=rn(e.size,t.style),a=n.fracNum(),i=n.fracDen();r=t.havingStyle(a);var o=wt(e.numer,r,t);if(e.continued){var s=8.5/t.fontMetrics().ptPerEm,l=3.5/t.fontMetrics().ptPerEm;o.height=o.height<s?s:o.height,o.depth=o.depth<l?l:o.depth}r=t.havingStyle(i);var h,c,m,u,p,d,f,g,v,b,y=wt(e.denom,r,t);if(e.hasBarLine?(e.barSize?(c=P(e.barSize,t),h=Ke.makeLineSpan("frac-line",t,c)):h=Ke.makeLineSpan("frac-line",t),c=h.height,m=h.height):(h=null,c=0,m=t.fontMetrics().defaultRuleThickness),n.size===x.DISPLAY.size||"display"===e.size?(u=t.fontMetrics().num1,p=c>0?3*m:7*m,d=t.fontMetrics().denom1):(c>0?(u=t.fontMetrics().num2,p=m):(u=t.fontMetrics().num3,p=3*m),d=t.fontMetrics().denom2),h){var w=t.fontMetrics().axisHeight;u-o.depth-(w+.5*c)<p&&(u+=p-(u-o.depth-(w+.5*c))),w-.5*c-(y.height-d)<p&&(d+=p-(w-.5*c-(y.height-d)));var k=-(w-.5*c);f=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:y,shift:d},{type:"elem",elem:h,shift:k},{type:"elem",elem:o,shift:-u}]},t)}else{var S=u-o.depth-(y.height-d);S<p&&(u+=.5*(p-S),d+=.5*(p-S)),f=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:y,shift:d},{type:"elem",elem:o,shift:-u}]},t)}return r=t.havingStyle(n),f.height*=r.sizeMultiplier/t.sizeMultiplier,f.depth*=r.sizeMultiplier/t.sizeMultiplier,g=n.size===x.DISPLAY.size?t.fontMetrics().delim1:n.size===x.SCRIPTSCRIPT.size?t.havingStyle(x.SCRIPT).fontMetrics().delim2:t.fontMetrics().delim2,v=null==e.leftDelim?xt(t,["mopen"]):Nr.customSizedDelim(e.leftDelim,g,!0,t.havingStyle(n),e.mode,["mopen"]),b=e.continued?Ke.makeSpan([]):null==e.rightDelim?xt(t,["mclose"]):Nr.customSizedDelim(e.rightDelim,g,!0,t.havingStyle(n),e.mode,["mclose"]),Ke.makeSpan(["mord"].concat(r.sizingClasses(t)),[v,Ke.makeSpan(["mfrac"],[f]),b],t)},an=function(e,t){var r=new Tt.MathNode("mfrac",[Rt(e.numer,t),Rt(e.denom,t)]);if(e.hasBarLine){if(e.barSize){var n=P(e.barSize,t);r.setAttribute("linethickness",F(n))}}else r.setAttribute("linethickness","0px");var a=rn(e.size,t.style);if(a.size!==t.style.size){r=new Tt.MathNode("mstyle",[r]);var i=a.size===x.DISPLAY.size?"true":"false";r.setAttribute("displaystyle",i),r.setAttribute("scriptlevel","0")}if(null!=e.leftDelim||null!=e.rightDelim){var o=[];if(null!=e.leftDelim){var s=new Tt.MathNode("mo",[new Tt.TextNode(e.leftDelim.replace("\\",""))]);s.setAttribute("fence","true"),o.push(s)}if(o.push(r),null!=e.rightDelim){var l=new Tt.MathNode("mo",[new Tt.TextNode(e.rightDelim.replace("\\",""))]);l.setAttribute("fence","true"),o.push(l)}return Ct(o)}return r};ot({type:"genfrac",names:["\\dfrac","\\frac","\\tfrac","\\dbinom","\\binom","\\tbinom","\\\\atopfrac","\\\\bracefrac","\\\\brackfrac"],props:{numArgs:2,allowedInArgument:!0},handler:function(e,t){var r,n=e.parser,a=e.funcName,i=t[0],o=t[1],s=null,l=null,h="auto";switch(a){case"\\dfrac":case"\\frac":case"\\tfrac":r=!0;break;case"\\\\atopfrac":r=!1;break;case"\\dbinom":case"\\binom":case"\\tbinom":r=!1,s="(",l=")";break;case"\\\\bracefrac":r=!1,s="\\{",l="\\}";break;case"\\\\brackfrac":r=!1,s="[",l="]";break;default:throw new Error("Unrecognized genfrac command")}switch(a){case"\\dfrac":case"\\dbinom":h="display";break;case"\\tfrac":case"\\tbinom":h="text"}return{type:"genfrac",mode:n.mode,continued:!1,numer:i,denom:o,hasBarLine:r,leftDelim:s,rightDelim:l,size:h,barSize:null}},htmlBuilder:nn,mathmlBuilder:an}),ot({type:"genfrac",names:["\\cfrac"],props:{numArgs:2},handler:function(e,t){var r=e.parser,n=(e.funcName,t[0]),a=t[1];return{type:"genfrac",mode:r.mode,continued:!0,numer:n,denom:a,hasBarLine:!0,leftDelim:null,rightDelim:null,size:"display",barSize:null}}}),ot({type:"infix",names:["\\over","\\choose","\\atop","\\brace","\\brack"],props:{numArgs:0,infix:!0},handler:function(e){var t,r=e.parser,n=e.funcName,a=e.token;switch(n){case"\\over":t="\\frac";break;case"\\choose":t="\\binom";break;case"\\atop":t="\\\\atopfrac";break;case"\\brace":t="\\\\bracefrac";break;case"\\brack":t="\\\\brackfrac";break;default:throw new Error("Unrecognized infix genfrac command")}return{type:"infix",mode:r.mode,replaceWith:t,token:a}}});var on=["display","text","script","scriptscript"],sn=function(e){var t=null;return e.length>0&&(t="."===(t=e)?null:t),t};ot({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler:function(e,t){var r,n=e.parser,a=t[4],i=t[5],o=lt(t[0]),s="atom"===o.type&&"open"===o.family?sn(o.text):null,l=lt(t[1]),h="atom"===l.type&&"close"===l.family?sn(l.text):null,c=Ut(t[2],"size"),m=null;r=!!c.isBlank||(m=c.value).number>0;var u="auto",p=t[3];if("ordgroup"===p.type){if(p.body.length>0){var d=Ut(p.body[0],"textord");u=on[Number(d.text)]}}else p=Ut(p,"textord"),u=on[Number(p.text)];return{type:"genfrac",mode:n.mode,numer:a,denom:i,continued:!1,hasBarLine:r,barSize:m,leftDelim:s,rightDelim:h,size:u}},htmlBuilder:nn,mathmlBuilder:an}),ot({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(e,t){var r=e.parser,n=(e.funcName,e.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Ut(t[0],"size").value,token:n}}}),ot({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(e,t){var r=e.parser,n=(e.funcName,t[0]),a=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(Ut(t[1],"infix").size),i=t[2],o=a.number>0;return{type:"genfrac",mode:r.mode,numer:n,denom:i,continued:!1,hasBarLine:o,barSize:a,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:nn,mathmlBuilder:an});var ln=function(e,t){var r,n,a=t.style;"supsub"===e.type?(r=e.sup?wt(e.sup,t.havingStyle(a.sup()),t):wt(e.sub,t.havingStyle(a.sub()),t),n=Ut(e.base,"horizBrace")):n=Ut(e,"horizBrace");var i,o=wt(n.base,t.havingBaseStyle(x.DISPLAY)),s=Gt(n,t);if(n.isOver?(i=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:o},{type:"kern",size:.1},{type:"elem",elem:s}]},t)).children[0].children[0].children[1].classes.push("svg-align"):(i=Ke.makeVList({positionType:"bottom",positionData:o.depth+.1+s.height,children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:o}]},t)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=Ke.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t);i=n.isOver?Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},t):Ke.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},t)}return Ke.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t)};ot({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"horizBrace",mode:r.mode,label:n,isOver:/^\\over/.test(n),base:t[0]}},htmlBuilder:ln,mathmlBuilder:function(e,t){var r=Ft(e.label);return new Tt.MathNode(e.isOver?"mover":"munder",[Rt(e.base,t),r])}}),ot({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[1],a=Ut(t[0],"url").url;return r.settings.isTrusted({command:"\\href",url:a})?{type:"href",mode:r.mode,href:a,body:ht(n)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(e,t){var r=ft(e.body,t,!1);return Ke.makeAnchor(e.href,[],r,t)},mathmlBuilder:function(e,t){var r=It(e.body,t);return r instanceof zt||(r=new zt("mrow",[r])),r.setAttribute("href",e.href),r}}),ot({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=Ut(t[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:n}))return r.formatUnsupportedCmd("\\url");for(var a=[],i=0;i<n.length;i++){var o=n[i];"~"===o&&(o="\\textasciitilde"),a.push({type:"textord",mode:"text",text:o})}var s={type:"text",mode:r.mode,font:"\\texttt",body:a};return{type:"href",mode:r.mode,href:n,body:ht(s)}}}),ot({type:"hbox",names:["\\hbox"],props:{numArgs:1,argTypes:["text"],allowedInText:!0,primitive:!0},handler:function(e,t){return{type:"hbox",mode:e.parser.mode,body:ht(t[0])}},htmlBuilder:function(e,t){var r=ft(e.body,t,!1);return Ke.makeFragment(r)},mathmlBuilder:function(e,t){return new Tt.MathNode("mrow",qt(e.body,t))}}),ot({type:"html",names:["\\htmlClass","\\htmlId","\\htmlStyle","\\htmlData"],props:{numArgs:2,argTypes:["raw","original"],allowedInText:!0},handler:function(e,t){var r,a=e.parser,i=e.funcName,o=(e.token,Ut(t[0],"raw").string),s=t[1];a.settings.strict&&a.settings.reportNonstrict("htmlExtension","HTML extension is disabled on strict mode");var l={};switch(i){case"\\htmlClass":l.class=o,r={command:"\\htmlClass",class:o};break;case"\\htmlId":l.id=o,r={command:"\\htmlId",id:o};break;case"\\htmlStyle":l.style=o,r={command:"\\htmlStyle",style:o};break;case"\\htmlData":for(var h=o.split(","),c=0;c<h.length;c++){var m=h[c].split("=");if(2!==m.length)throw new n("Error parsing key-value for \\htmlData");l["data-"+m[0].trim()]=m[1].trim()}r={command:"\\htmlData",attributes:l};break;default:throw new Error("Unrecognized html command")}return a.settings.isTrusted(r)?{type:"html",mode:a.mode,attributes:l,body:ht(s)}:a.formatUnsupportedCmd(i)},htmlBuilder:function(e,t){var r=ft(e.body,t,!1),n=["enclosing"];e.attributes.class&&n.push.apply(n,e.attributes.class.trim().split(/\s+/));var a=Ke.makeSpan(n,r,t);for(var i in e.attributes)"class"!==i&&e.attributes.hasOwnProperty(i)&&a.setAttribute(i,e.attributes[i]);return a},mathmlBuilder:function(e,t){return It(e.body,t)}}),ot({type:"htmlmathml",names:["\\html@mathml"],props:{numArgs:2,allowedInText:!0},handler:function(e,t){return{type:"htmlmathml",mode:e.parser.mode,html:ht(t[0]),mathml:ht(t[1])}},htmlBuilder:function(e,t){var r=ft(e.html,t,!1);return Ke.makeFragment(r)},mathmlBuilder:function(e,t){return It(e.mathml,t)}});var hn=function(e){if(/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(e))return{number:+e,unit:"bp"};var t=/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(e);if(!t)throw new n("Invalid size: '"+e+"' in \\includegraphics");var r={number:+(t[1]+t[2]),unit:t[3]};if(!V(r))throw new n("Invalid unit: '"+r.unit+"' in \\includegraphics.");return r};ot({type:"includegraphics",names:["\\includegraphics"],props:{numArgs:1,numOptionalArgs:1,argTypes:["raw","url"],allowedInText:!1},handler:function(e,t,r){var a=e.parser,i={number:0,unit:"em"},o={number:.9,unit:"em"},s={number:0,unit:"em"},l="";if(r[0])for(var h=Ut(r[0],"raw").string.split(","),c=0;c<h.length;c++){var m=h[c].split("=");if(2===m.length){var u=m[1].trim();switch(m[0].trim()){case"alt":l=u;break;case"width":i=hn(u);break;case"height":o=hn(u);break;case"totalheight":s=hn(u);break;default:throw new n("Invalid key: '"+m[0]+"' in \\includegraphics.")}}}var p=Ut(t[0],"url").url;return""===l&&(l=(l=(l=p).replace(/^.*[\\/]/,"")).substring(0,l.lastIndexOf("."))),a.settings.isTrusted({command:"\\includegraphics",url:p})?{type:"includegraphics",mode:a.mode,alt:l,width:i,height:o,totalheight:s,src:p}:a.formatUnsupportedCmd("\\includegraphics")},htmlBuilder:function(e,t){var r=P(e.height,t),n=0;e.totalheight.number>0&&(n=P(e.totalheight,t)-r);var a=0;e.width.number>0&&(a=P(e.width,t));var i={height:F(r+n)};a>0&&(i.width=F(a)),n>0&&(i.verticalAlign=F(-n));var o=new j(e.src,e.alt,i);return o.height=r,o.depth=n,o},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mglyph",[]);r.setAttribute("alt",e.alt);var n=P(e.height,t),a=0;if(e.totalheight.number>0&&(a=P(e.totalheight,t)-n,r.setAttribute("valign",F(-a))),r.setAttribute("height",F(n+a)),e.width.number>0){var i=P(e.width,t);r.setAttribute("width",F(i))}return r.setAttribute("src",e.src),r}}),ot({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=Ut(t[0],"size");if(r.settings.strict){var i="m"===n[1],o="mu"===a.value.unit;i?(o||r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" supports only mu units, not "+a.value.unit+" units"),"math"!==r.mode&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" works only in math mode")):o&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" doesn't support mu units")}return{type:"kern",mode:r.mode,dimension:a.value}},htmlBuilder:function(e,t){return Ke.makeGlue(e.dimension,t)},mathmlBuilder:function(e,t){var r=P(e.dimension,t);return new Tt.SpaceNode(r)}}),ot({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"lap",mode:r.mode,alignment:n.slice(5),body:a}},htmlBuilder:function(e,t){var r;"clap"===e.alignment?(r=Ke.makeSpan([],[wt(e.body,t)]),r=Ke.makeSpan(["inner"],[r],t)):r=Ke.makeSpan(["inner"],[wt(e.body,t)]);var n=Ke.makeSpan(["fix"],[]),a=Ke.makeSpan([e.alignment],[r,n],t),i=Ke.makeSpan(["strut"]);return i.style.height=F(a.height+a.depth),a.depth&&(i.style.verticalAlign=F(-a.depth)),a.children.unshift(i),a=Ke.makeSpan(["thinbox"],[a],t),Ke.makeSpan(["mord","vbox"],[a],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mpadded",[Rt(e.body,t)]);if("rlap"!==e.alignment){var n="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",n+"width")}return r.setAttribute("width","0px"),r}}),ot({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){var r=e.funcName,n=e.parser,a=n.mode;n.switchMode("math");var i="\\("===r?"\\)":"$",o=n.parseExpression(!1,i);return n.expect(i),n.switchMode(a),{type:"styling",mode:n.mode,style:"text",body:o}}}),ot({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){throw new n("Mismatched "+e.funcName)}});var cn=function(e,t){switch(t.style.size){case x.DISPLAY.size:return e.display;case x.TEXT.size:return e.text;case x.SCRIPT.size:return e.script;case x.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};ot({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:function(e,t){return{type:"mathchoice",mode:e.parser.mode,display:ht(t[0]),text:ht(t[1]),script:ht(t[2]),scriptscript:ht(t[3])}},htmlBuilder:function(e,t){var r=cn(e,t),n=ft(r,t,!1);return Ke.makeFragment(n)},mathmlBuilder:function(e,t){var r=cn(e,t);return It(r,t)}});var mn=function(e,t,r,n,a,i,o){e=Ke.makeSpan([],[e]);var s,h,c,m=r&&l.isCharacterBox(r);if(t){var u=wt(t,n.havingStyle(a.sup()),n);h={elem:u,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-u.depth)}}if(r){var p=wt(r,n.havingStyle(a.sub()),n);s={elem:p,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-p.height)}}if(h&&s){var d=n.fontMetrics().bigOpSpacing5+s.elem.height+s.elem.depth+s.kern+e.depth+o;c=Ke.makeVList({positionType:"bottom",positionData:d,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:F(-i)},{type:"kern",size:s.kern},{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:F(i)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(s){var f=e.height-o;c=Ke.makeVList({positionType:"top",positionData:f,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:F(-i)},{type:"kern",size:s.kern},{type:"elem",elem:e}]},n)}else{if(!h)return e;var g=e.depth+o;c=Ke.makeVList({positionType:"bottom",positionData:g,children:[{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:F(i)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}var v=[c];if(s&&0!==i&&!m){var b=Ke.makeSpan(["mspace"],[],n);b.style.marginRight=F(i),v.unshift(b)}return Ke.makeSpan(["mop","op-limits"],v,n)},un=["\\smallint"],pn=function(e,t){var r,n,a,i=!1;"supsub"===e.type?(r=e.sup,n=e.sub,a=Ut(e.base,"op"),i=!0):a=Ut(e,"op");var o,s=t.style,h=!1;if(s.size===x.DISPLAY.size&&a.symbol&&!l.contains(un,a.name)&&(h=!0),a.symbol){var c=h?"Size2-Regular":"Size1-Regular",m="";if("\\oiint"!==a.name&&"\\oiiint"!==a.name||(m=a.name.slice(1),a.name="oiint"===m?"\\iint":"\\iiint"),o=Ke.makeSymbol(a.name,c,"math",t,["mop","op-symbol",h?"large-op":"small-op"]),m.length>0){var u=o.italic,p=Ke.staticSvg(m+"Size"+(h?"2":"1"),t);o=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:o,shift:0},{type:"elem",elem:p,shift:h?.08:0}]},t),a.name="\\"+m,o.classes.unshift("mop"),o.italic=u}}else if(a.body){var d=ft(a.body,t,!0);1===d.length&&d[0]instanceof Z?(o=d[0]).classes[0]="mop":o=Ke.makeSpan(["mop"],d,t)}else{for(var f=[],g=1;g<a.name.length;g++)f.push(Ke.mathsym(a.name[g],a.mode,t));o=Ke.makeSpan(["mop"],f,t)}var v=0,b=0;return(o instanceof Z||"\\oiint"===a.name||"\\oiiint"===a.name)&&!a.suppressBaseShift&&(v=(o.height-o.depth)/2-t.fontMetrics().axisHeight,b=o.italic),i?mn(o,r,n,t,s,b,v):(v&&(o.style.position="relative",o.style.top=F(v)),o)},dn=function(e,t){var r;if(e.symbol)r=new zt("mo",[Bt(e.name,e.mode)]),l.contains(un,e.name)&&r.setAttribute("largeop","false");else if(e.body)r=new zt("mo",qt(e.body,t));else{r=new zt("mi",[new At(e.name.slice(1))]);var n=new zt("mo",[Bt("\u2061","text")]);r=e.parentIsSupSub?new zt("mrow",[r,n]):Mt([r,n])}return r},fn={"\u220f":"\\prod","\u2210":"\\coprod","\u2211":"\\sum","\u22c0":"\\bigwedge","\u22c1":"\\bigvee","\u22c2":"\\bigcap","\u22c3":"\\bigcup","\u2a00":"\\bigodot","\u2a01":"\\bigoplus","\u2a02":"\\bigotimes","\u2a04":"\\biguplus","\u2a06":"\\bigsqcup"};ot({type:"op",names:["\\coprod","\\bigvee","\\bigwedge","\\biguplus","\\bigcap","\\bigcup","\\intop","\\prod","\\sum","\\bigotimes","\\bigoplus","\\bigodot","\\bigsqcup","\\smallint","\u220f","\u2210","\u2211","\u22c0","\u22c1","\u22c2","\u22c3","\u2a00","\u2a01","\u2a02","\u2a04","\u2a06"],props:{numArgs:0},handler:function(e,t){var r=e.parser,n=e.funcName;return 1===n.length&&(n=fn[n]),{type:"op",mode:r.mode,limits:!0,parentIsSupSub:!1,symbol:!0,name:n}},htmlBuilder:pn,mathmlBuilder:dn}),ot({type:"op",names:["\\mathop"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser,n=t[0];return{type:"op",mode:r.mode,limits:!1,parentIsSupSub:!1,symbol:!1,body:ht(n)}},htmlBuilder:pn,mathmlBuilder:dn});var gn={"\u222b":"\\int","\u222c":"\\iint","\u222d":"\\iiint","\u222e":"\\oint","\u222f":"\\oiint","\u2230":"\\oiiint"};ot({type:"op",names:["\\arcsin","\\arccos","\\arctan","\\arctg","\\arcctg","\\arg","\\ch","\\cos","\\cosec","\\cosh","\\cot","\\cotg","\\coth","\\csc","\\ctg","\\cth","\\deg","\\dim","\\exp","\\hom","\\ker","\\lg","\\ln","\\log","\\sec","\\sin","\\sinh","\\sh","\\tan","\\tanh","\\tg","\\th"],props:{numArgs:0},handler:function(e){var t=e.parser,r=e.funcName;return{type:"op",mode:t.mode,limits:!1,parentIsSupSub:!1,symbol:!1,name:r}},htmlBuilder:pn,mathmlBuilder:dn}),ot({type:"op",names:["\\det","\\gcd","\\inf","\\lim","\\max","\\min","\\Pr","\\sup"],props:{numArgs:0},handler:function(e){var t=e.parser,r=e.funcName;return{type:"op",mode:t.mode,limits:!0,parentIsSupSub:!1,symbol:!1,name:r}},htmlBuilder:pn,mathmlBuilder:dn}),ot({type:"op",names:["\\int","\\iint","\\iiint","\\oint","\\oiint","\\oiiint","\u222b","\u222c","\u222d","\u222e","\u222f","\u2230"],props:{numArgs:0},handler:function(e){var t=e.parser,r=e.funcName;return 1===r.length&&(r=gn[r]),{type:"op",mode:t.mode,limits:!1,parentIsSupSub:!1,symbol:!0,name:r}},htmlBuilder:pn,mathmlBuilder:dn});var vn=function(e,t){var r,n,a,i,o=!1;if("supsub"===e.type?(r=e.sup,n=e.sub,a=Ut(e.base,"operatorname"),o=!0):a=Ut(e,"operatorname"),a.body.length>0){for(var s=a.body.map((function(e){var t=e.text;return"string"==typeof t?{type:"textord",mode:e.mode,text:t}:e})),l=ft(s,t.withFont("mathrm"),!0),h=0;h<l.length;h++){var c=l[h];c instanceof Z&&(c.text=c.text.replace(/\u2212/,"-").replace(/\u2217/,"*"))}i=Ke.makeSpan(["mop"],l,t)}else i=Ke.makeSpan(["mop"],[],t);return o?mn(i,r,n,t,t.style,0,0):i};function bn(e,t,r){for(var n=ft(e,t,!1),a=t.sizeMultiplier/r.sizeMultiplier,i=0;i<n.length;i++){var o=n[i].classes.indexOf("sizing");o<0?Array.prototype.push.apply(n[i].classes,t.sizingClasses(r)):n[i].classes[o+1]==="reset-size"+t.size&&(n[i].classes[o+1]="reset-size"+r.size),n[i].height*=a,n[i].depth*=a}return Ke.makeFragment(n)}ot({type:"operatorname",names:["\\operatorname@","\\operatornamewithlimits"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"operatorname",mode:r.mode,body:ht(a),alwaysHandleSupSub:"\\operatornamewithlimits"===n,limits:!1,parentIsSupSub:!1}},htmlBuilder:vn,mathmlBuilder:function(e,t){for(var r=qt(e.body,t.withFont("mathrm")),n=!0,a=0;a<r.length;a++){var i=r[a];if(i instanceof Tt.SpaceNode);else if(i instanceof Tt.MathNode)switch(i.type){case"mi":case"mn":case"ms":case"mspace":case"mtext":break;case"mo":var o=i.children[0];1===i.children.length&&o instanceof Tt.TextNode?o.text=o.text.replace(/\u2212/,"-").replace(/\u2217/,"*"):n=!1;break;default:n=!1}else n=!1}if(n){var s=r.map((function(e){return e.toText()})).join("");r=[new Tt.TextNode(s)]}var l=new Tt.MathNode("mi",r);l.setAttribute("mathvariant","normal");var h=new Tt.MathNode("mo",[Bt("\u2061","text")]);return e.parentIsSupSub?new Tt.MathNode("mrow",[l,h]):Tt.newDocumentFragment([l,h])}}),Pr("\\operatorname","\\@ifstar\\operatornamewithlimits\\operatorname@"),st({type:"ordgroup",htmlBuilder:function(e,t){return e.semisimple?Ke.makeFragment(ft(e.body,t,!1)):Ke.makeSpan(["mord"],ft(e.body,t,!0),t)},mathmlBuilder:function(e,t){return It(e.body,t,!0)}}),ot({type:"overline",names:["\\overline"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=t[0];return{type:"overline",mode:r.mode,body:n}},htmlBuilder:function(e,t){var r=wt(e.body,t.havingCrampedStyle()),n=Ke.makeLineSpan("overline-line",t),a=t.fontMetrics().defaultRuleThickness,i=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r},{type:"kern",size:3*a},{type:"elem",elem:n},{type:"kern",size:a}]},t);return Ke.makeSpan(["mord","overline"],[i],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[new Tt.TextNode("\u203e")]);r.setAttribute("stretchy","true");var n=new Tt.MathNode("mover",[Rt(e.body,t),r]);return n.setAttribute("accent","true"),n}}),ot({type:"phantom",names:["\\phantom"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[0];return{type:"phantom",mode:r.mode,body:ht(n)}},htmlBuilder:function(e,t){var r=ft(e.body,t.withPhantom(),!1);return Ke.makeFragment(r)},mathmlBuilder:function(e,t){var r=qt(e.body,t);return new Tt.MathNode("mphantom",r)}}),ot({type:"hphantom",names:["\\hphantom"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[0];return{type:"hphantom",mode:r.mode,body:n}},htmlBuilder:function(e,t){var r=Ke.makeSpan([],[wt(e.body,t.withPhantom())]);if(r.height=0,r.depth=0,r.children)for(var n=0;n<r.children.length;n++)r.children[n].height=0,r.children[n].depth=0;return r=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r}]},t),Ke.makeSpan(["mord"],[r],t)},mathmlBuilder:function(e,t){var r=qt(ht(e.body),t),n=new Tt.MathNode("mphantom",r),a=new Tt.MathNode("mpadded",[n]);return a.setAttribute("height","0px"),a.setAttribute("depth","0px"),a}}),ot({type:"vphantom",names:["\\vphantom"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[0];return{type:"vphantom",mode:r.mode,body:n}},htmlBuilder:function(e,t){var r=Ke.makeSpan(["inner"],[wt(e.body,t.withPhantom())]),n=Ke.makeSpan(["fix"],[]);return Ke.makeSpan(["mord","rlap"],[r,n],t)},mathmlBuilder:function(e,t){var r=qt(ht(e.body),t),n=new Tt.MathNode("mphantom",r),a=new Tt.MathNode("mpadded",[n]);return a.setAttribute("width","0px"),a}}),ot({type:"raisebox",names:["\\raisebox"],props:{numArgs:2,argTypes:["size","hbox"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=Ut(t[0],"size").value,a=t[1];return{type:"raisebox",mode:r.mode,dy:n,body:a}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=P(e.dy,t);return Ke.makeVList({positionType:"shift",positionData:-n,children:[{type:"elem",elem:r}]},t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mpadded",[Rt(e.body,t)]),n=e.dy.number+e.dy.unit;return r.setAttribute("voffset",n),r}}),ot({type:"internal",names:["\\relax"],props:{numArgs:0,allowedInText:!0},handler:function(e){return{type:"internal",mode:e.parser.mode}}}),ot({type:"rule",names:["\\rule"],props:{numArgs:2,numOptionalArgs:1,argTypes:["size","size","size"]},handler:function(e,t,r){var n=e.parser,a=r[0],i=Ut(t[0],"size"),o=Ut(t[1],"size");return{type:"rule",mode:n.mode,shift:a&&Ut(a,"size").value,width:i.value,height:o.value}},htmlBuilder:function(e,t){var r=Ke.makeSpan(["mord","rule"],[],t),n=P(e.width,t),a=P(e.height,t),i=e.shift?P(e.shift,t):0;return r.style.borderRightWidth=F(n),r.style.borderTopWidth=F(a),r.style.bottom=F(i),r.width=n,r.height=a+i,r.depth=-i,r.maxFontSize=1.125*a*t.sizeMultiplier,r},mathmlBuilder:function(e,t){var r=P(e.width,t),n=P(e.height,t),a=e.shift?P(e.shift,t):0,i=t.color&&t.getColor()||"black",o=new Tt.MathNode("mspace");o.setAttribute("mathbackground",i),o.setAttribute("width",F(r)),o.setAttribute("height",F(n));var s=new Tt.MathNode("mpadded",[o]);return a>=0?s.setAttribute("height",F(a)):(s.setAttribute("height",F(a)),s.setAttribute("depth",F(-a))),s.setAttribute("voffset",F(a)),s}});var yn=["\\tiny","\\sixptsize","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];ot({type:"sizing",names:yn,props:{numArgs:0,allowedInText:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!1,r);return{type:"sizing",mode:a.mode,size:yn.indexOf(n)+1,body:i}},htmlBuilder:function(e,t){var r=t.havingSize(e.size);return bn(e.body,r,t)},mathmlBuilder:function(e,t){var r=t.havingSize(e.size),n=qt(e.body,r),a=new Tt.MathNode("mstyle",n);return a.setAttribute("mathsize",F(r.sizeMultiplier)),a}}),ot({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=!1,i=!1,o=r[0]&&Ut(r[0],"ordgroup");if(o)for(var s="",l=0;l<o.body.length;++l){if("t"===(s=o.body[l].text))a=!0;else{if("b"!==s){a=!1,i=!1;break}i=!0}}else a=!0,i=!0;var h=t[0];return{type:"smash",mode:n.mode,body:h,smashHeight:a,smashDepth:i}},htmlBuilder:function(e,t){var r=Ke.makeSpan([],[wt(e.body,t)]);if(!e.smashHeight&&!e.smashDepth)return r;if(e.smashHeight&&(r.height=0,r.children))for(var n=0;n<r.children.length;n++)r.children[n].height=0;if(e.smashDepth&&(r.depth=0,r.children))for(var a=0;a<r.children.length;a++)r.children[a].depth=0;var i=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord"],[i],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mpadded",[Rt(e.body,t)]);return e.smashHeight&&r.setAttribute("height","0px"),e.smashDepth&&r.setAttribute("depth","0px"),r}}),ot({type:"sqrt",names:["\\sqrt"],props:{numArgs:1,numOptionalArgs:1},handler:function(e,t,r){var n=e.parser,a=r[0],i=t[0];return{type:"sqrt",mode:n.mode,body:i,index:a}},htmlBuilder:function(e,t){var r=wt(e.body,t.havingCrampedStyle());0===r.height&&(r.height=t.fontMetrics().xHeight),r=Ke.wrapFragment(r,t);var n=t.fontMetrics().defaultRuleThickness,a=n;t.style.id<x.TEXT.id&&(a=t.fontMetrics().xHeight);var i=n+a/4,o=r.height+r.depth+i+n,s=Nr.sqrtImage(o,t),l=s.span,h=s.ruleWidth,c=s.advanceWidth,m=l.height-h;m>r.height+r.depth+i&&(i=(i+m-r.height-r.depth)/2);var u=l.height-r.height-i-h;r.style.paddingLeft=F(c);var p=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+u)},{type:"elem",elem:l},{type:"kern",size:h}]},t);if(e.index){var d=t.havingStyle(x.SCRIPTSCRIPT),f=wt(e.index,d,t),g=.6*(p.height-p.depth),v=Ke.makeVList({positionType:"shift",positionData:-g,children:[{type:"elem",elem:f}]},t),b=Ke.makeSpan(["root"],[v]);return Ke.makeSpan(["mord","sqrt"],[b,p],t)}return Ke.makeSpan(["mord","sqrt"],[p],t)},mathmlBuilder:function(e,t){var r=e.body,n=e.index;return n?new Tt.MathNode("mroot",[Rt(r,t),Rt(n,t)]):new Tt.MathNode("msqrt",[Rt(r,t)])}});var xn={display:x.DISPLAY,text:x.TEXT,script:x.SCRIPT,scriptscript:x.SCRIPTSCRIPT};ot({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!0,r),o=n.slice(1,n.length-5);return{type:"styling",mode:a.mode,style:o,body:i}},htmlBuilder:function(e,t){var r=xn[e.style],n=t.havingStyle(r).withFont("");return bn(e.body,n,t)},mathmlBuilder:function(e,t){var r=xn[e.style],n=t.havingStyle(r),a=qt(e.body,n),i=new Tt.MathNode("mstyle",a),o={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return i.setAttribute("scriptlevel",o[0]),i.setAttribute("displaystyle",o[1]),i}});var wn=function(e,t){var r=e.base;return r?"op"===r.type?r.limits&&(t.style.size===x.DISPLAY.size||r.alwaysHandleSupSub)?pn:null:"operatorname"===r.type?r.alwaysHandleSupSub&&(t.style.size===x.DISPLAY.size||r.limits)?vn:null:"accent"===r.type?l.isCharacterBox(r.base)?Wt:null:"horizBrace"===r.type&&!e.sub===r.isOver?ln:null:null};st({type:"supsub",htmlBuilder:function(e,t){var r=wn(e,t);if(r)return r(e,t);var n,a,i,o=e.base,s=e.sup,h=e.sub,c=wt(o,t),m=t.fontMetrics(),u=0,p=0,d=o&&l.isCharacterBox(o);if(s){var f=t.havingStyle(t.style.sup());n=wt(s,f,t),d||(u=c.height-f.fontMetrics().supDrop*f.sizeMultiplier/t.sizeMultiplier)}if(h){var g=t.havingStyle(t.style.sub());a=wt(h,g,t),d||(p=c.depth+g.fontMetrics().subDrop*g.sizeMultiplier/t.sizeMultiplier)}i=t.style===x.DISPLAY?m.sup1:t.style.cramped?m.sup3:m.sup2;var v,b=t.sizeMultiplier,y=F(.5/m.ptPerEm/b),w=null;if(a){var k=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name);(c instanceof Z||k)&&(w=F(-c.italic))}if(n&&a){u=Math.max(u,i,n.depth+.25*m.xHeight),p=Math.max(p,m.sub2);var S=4*m.defaultRuleThickness;if(u-n.depth-(a.height-p)<S){p=S-(u-n.depth)+a.height;var M=.8*m.xHeight-(u-n.depth);M>0&&(u+=M,p-=M)}var z=[{type:"elem",elem:a,shift:p,marginRight:y,marginLeft:w},{type:"elem",elem:n,shift:-u,marginRight:y}];v=Ke.makeVList({positionType:"individualShift",children:z},t)}else if(a){p=Math.max(p,m.sub1,a.height-.8*m.xHeight);var A=[{type:"elem",elem:a,marginLeft:w,marginRight:y}];v=Ke.makeVList({positionType:"shift",positionData:p,children:A},t)}else{if(!n)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,n.depth+.25*m.xHeight),v=Ke.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:n,marginRight:y}]},t)}var T=yt(c,"right")||"mord";return Ke.makeSpan([T],[c,Ke.makeSpan(["msupsub"],[v])],t)},mathmlBuilder:function(e,t){var r,n=!1;e.base&&"horizBrace"===e.base.type&&!!e.sup===e.base.isOver&&(n=!0,r=e.base.isOver),!e.base||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0);var a,i=[Rt(e.base,t)];if(e.sub&&i.push(Rt(e.sub,t)),e.sup&&i.push(Rt(e.sup,t)),n)a=r?"mover":"munder";else if(e.sub)if(e.sup){var o=e.base;a=o&&"op"===o.type&&o.limits&&t.style===x.DISPLAY||o&&"operatorname"===o.type&&o.alwaysHandleSupSub&&(t.style===x.DISPLAY||o.limits)?"munderover":"msubsup"}else{var s=e.base;a=s&&"op"===s.type&&s.limits&&(t.style===x.DISPLAY||s.alwaysHandleSupSub)||s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(s.limits||t.style===x.DISPLAY)?"munder":"msub"}else{var l=e.base;a=l&&"op"===l.type&&l.limits&&(t.style===x.DISPLAY||l.alwaysHandleSupSub)||l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||t.style===x.DISPLAY)?"mover":"msup"}return new Tt.MathNode(a,i)}}),st({type:"atom",htmlBuilder:function(e,t){return Ke.mathsym(e.text,e.mode,t,["m"+e.family])},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[Bt(e.text,e.mode)]);if("bin"===e.family){var n=Nt(e,t);"bold-italic"===n&&r.setAttribute("mathvariant",n)}else"punct"===e.family?r.setAttribute("separator","true"):"open"!==e.family&&"close"!==e.family||r.setAttribute("stretchy","false");return r}});var kn={mi:"italic",mn:"normal",mtext:"normal"};st({type:"mathord",htmlBuilder:function(e,t){return Ke.makeOrd(e,t,"mathord")},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mi",[Bt(e.text,e.mode,t)]),n=Nt(e,t)||"italic";return n!==kn[r.type]&&r.setAttribute("mathvariant",n),r}}),st({type:"textord",htmlBuilder:function(e,t){return Ke.makeOrd(e,t,"textord")},mathmlBuilder:function(e,t){var r,n=Bt(e.text,e.mode,t),a=Nt(e,t)||"normal";return r="text"===e.mode?new Tt.MathNode("mtext",[n]):/[0-9]/.test(e.text)?new Tt.MathNode("mn",[n]):"\\prime"===e.text?new Tt.MathNode("mo",[n]):new Tt.MathNode("mi",[n]),a!==kn[r.type]&&r.setAttribute("mathvariant",a),r}});var Sn={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},Mn={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};st({type:"spacing",htmlBuilder:function(e,t){if(Mn.hasOwnProperty(e.text)){var r=Mn[e.text].className||"";if("text"===e.mode){var a=Ke.makeOrd(e,t,"textord");return a.classes.push(r),a}return Ke.makeSpan(["mspace",r],[Ke.mathsym(e.text,e.mode,t)],t)}if(Sn.hasOwnProperty(e.text))return Ke.makeSpan(["mspace",Sn[e.text]],[],t);throw new n('Unknown type of space "'+e.text+'"')},mathmlBuilder:function(e,t){if(!Mn.hasOwnProperty(e.text)){if(Sn.hasOwnProperty(e.text))return new Tt.MathNode("mspace");throw new n('Unknown type of space "'+e.text+'"')}return new Tt.MathNode("mtext",[new Tt.TextNode("\xa0")])}});var zn=function(){var e=new Tt.MathNode("mtd",[]);return e.setAttribute("width","50%"),e};st({type:"tag",mathmlBuilder:function(e,t){var r=new Tt.MathNode("mtable",[new Tt.MathNode("mtr",[zn(),new Tt.MathNode("mtd",[It(e.body,t)]),zn(),new Tt.MathNode("mtd",[It(e.tag,t)])])]);return r.setAttribute("width","100%"),r}});var An={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},Tn={"\\textbf":"textbf","\\textmd":"textmd"},Bn={"\\textit":"textit","\\textup":"textup"},Cn=function(e,t){var r=e.font;return r?An[r]?t.withTextFontFamily(An[r]):Tn[r]?t.withTextFontWeight(Tn[r]):t.withTextFontShape(Bn[r]):t};ot({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"text",mode:r.mode,body:ht(a),font:n}},htmlBuilder:function(e,t){var r=Cn(e,t),n=ft(e.body,r,!0);return Ke.makeSpan(["mord","text"],n,r)},mathmlBuilder:function(e,t){var r=Cn(e,t);return It(e.body,r)}}),ot({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"underline",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=Ke.makeLineSpan("underline-line",t),a=t.fontMetrics().defaultRuleThickness,i=Ke.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:a},{type:"elem",elem:n},{type:"kern",size:3*a},{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord","underline"],[i],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[new Tt.TextNode("\u203e")]);r.setAttribute("stretchy","true");var n=new Tt.MathNode("munder",[Rt(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),ot({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler:function(e,t){return{type:"vcenter",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=t.fontMetrics().axisHeight,a=.5*(r.height-n-(r.depth+n));return Ke.makeVList({positionType:"shift",positionData:a,children:[{type:"elem",elem:r}]},t)},mathmlBuilder:function(e,t){return new Tt.MathNode("mpadded",[Rt(e.body,t)],["vcenter"])}}),ot({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(e,t,r){throw new n("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(e,t){for(var r=Nn(e),n=[],a=t.havingStyle(t.style.text()),i=0;i<r.length;i++){var o=r[i];"~"===o&&(o="\\textasciitilde"),n.push(Ke.makeSymbol(o,"Typewriter-Regular",e.mode,a,["mord","texttt"]))}return Ke.makeSpan(["mord","text"].concat(a.sizingClasses(t)),Ke.tryCombineChars(n),a)},mathmlBuilder:function(e,t){var r=new Tt.TextNode(Nn(e)),n=new Tt.MathNode("mtext",[r]);return n.setAttribute("mathvariant","monospace"),n}});var Nn=function(e){return e.body.replace(/ /g,e.star?"\u2423":"\xa0")},qn=nt,In="[ \r\n\t]",Rn="(\\\\[a-zA-Z@]+)"+In+"*",Hn="[\u0300-\u036f]",On=new RegExp(Hn+"+$"),En="("+In+"+)|\\\\(\n|[ \r\t]+\n?)[ \r\t]*|([!-\\[\\]-\u2027\u202a-\ud7ff\uf900-\uffff]"+Hn+"*|[\ud800-\udbff][\udc00-\udfff]"+Hn+"*|\\\\verb\\*([^]).*?\\4|\\\\verb([^*a-zA-Z]).*?\\5|"+Rn+"|\\\\[^\ud800-\udfff])",Ln=function(){function e(e,t){this.input=void 0,this.settings=void 0,this.tokenRegex=void 0,this.catcodes=void 0,this.input=e,this.settings=t,this.tokenRegex=new RegExp(En,"g"),this.catcodes={"%":14,"~":13}}var t=e.prototype;return t.setCatcode=function(e,t){this.catcodes[e]=t},t.lex=function(){var e=this.input,t=this.tokenRegex.lastIndex;if(t===e.length)return new Gr("EOF",new Fr(this,t,t));var r=this.tokenRegex.exec(e);if(null===r||r.index!==t)throw new n("Unexpected character: '"+e[t]+"'",new Gr(e[t],new Fr(this,t,t+1)));var a=r[6]||r[3]||(r[2]?"\\ ":" ");if(14===this.catcodes[a]){var i=e.indexOf("\n",this.tokenRegex.lastIndex);return-1===i?(this.tokenRegex.lastIndex=e.length,this.settings.reportNonstrict("commentAtEnd","% comment has no terminating newline; LaTeX would fail because of commenting the end of math mode (e.g. $)")):this.tokenRegex.lastIndex=i+1,this.lex()}return new Gr(a,new Fr(this,t,this.tokenRegex.lastIndex))},e}(),Dn=function(){function e(e,t){void 0===e&&(e={}),void 0===t&&(t={}),this.current=void 0,this.builtins=void 0,this.undefStack=void 0,this.current=t,this.builtins=e,this.undefStack=[]}var t=e.prototype;return t.beginGroup=function(){this.undefStack.push({})},t.endGroup=function(){if(0===this.undefStack.length)throw new n("Unbalanced namespace destruction: attempt to pop global namespace; please report this as a bug");var e=this.undefStack.pop();for(var t in e)e.hasOwnProperty(t)&&(null==e[t]?delete this.current[t]:this.current[t]=e[t])},t.endGroups=function(){for(;this.undefStack.length>0;)this.endGroup()},t.has=function(e){return this.current.hasOwnProperty(e)||this.builtins.hasOwnProperty(e)},t.get=function(e){return this.current.hasOwnProperty(e)?this.current[e]:this.builtins[e]},t.set=function(e,t,r){if(void 0===r&&(r=!1),r){for(var n=0;n<this.undefStack.length;n++)delete this.undefStack[n][e];this.undefStack.length>0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{var a=this.undefStack[this.undefStack.length-1];a&&!a.hasOwnProperty(e)&&(a[e]=this.current[e])}null==t?delete this.current[e]:this.current[e]=t},e}(),Vn=Vr;Pr("\\noexpand",(function(e){var t=e.popToken();return e.isExpandable(t.text)&&(t.noexpand=!0,t.treatAsRelax=!0),{tokens:[t],numArgs:0}})),Pr("\\expandafter",(function(e){var t=e.popToken();return e.expandOnce(!0),{tokens:[t],numArgs:0}})),Pr("\\@firstoftwo",(function(e){return{tokens:e.consumeArgs(2)[0],numArgs:0}})),Pr("\\@secondoftwo",(function(e){return{tokens:e.consumeArgs(2)[1],numArgs:0}})),Pr("\\@ifnextchar",(function(e){var t=e.consumeArgs(3);e.consumeSpaces();var r=e.future();return 1===t[0].length&&t[0][0].text===r.text?{tokens:t[1],numArgs:0}:{tokens:t[2],numArgs:0}})),Pr("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}"),Pr("\\TextOrMath",(function(e){var t=e.consumeArgs(2);return"text"===e.mode?{tokens:t[0],numArgs:0}:{tokens:t[1],numArgs:0}}));var Pn={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15};Pr("\\char",(function(e){var t,r=e.popToken(),a="";if("'"===r.text)t=8,r=e.popToken();else if('"'===r.text)t=16,r=e.popToken();else if("`"===r.text)if("\\"===(r=e.popToken()).text[0])a=r.text.charCodeAt(1);else{if("EOF"===r.text)throw new n("\\char` missing argument");a=r.text.charCodeAt(0)}else t=10;if(t){if(null==(a=Pn[r.text])||a>=t)throw new n("Invalid base-"+t+" digit "+r.text);for(var i;null!=(i=Pn[e.future().text])&&i<t;)a*=t,a+=i,e.popToken()}return"\\@char{"+a+"}"}));var Fn=function(e,t,r){var a=e.consumeArg().tokens;if(1!==a.length)throw new n("\\newcommand's first argument must be a macro name");var i=a[0].text,o=e.isDefined(i);if(o&&!t)throw new n("\\newcommand{"+i+"} attempting to redefine "+i+"; use \\renewcommand");if(!o&&!r)throw new n("\\renewcommand{"+i+"} when command "+i+" does not yet exist; use \\newcommand");var s=0;if(1===(a=e.consumeArg().tokens).length&&"["===a[0].text){for(var l="",h=e.expandNextToken();"]"!==h.text&&"EOF"!==h.text;)l+=h.text,h=e.expandNextToken();if(!l.match(/^\s*[0-9]+\s*$/))throw new n("Invalid number of arguments: "+l);s=parseInt(l),a=e.consumeArg().tokens}return e.macros.set(i,{tokens:a,numArgs:s}),""};Pr("\\newcommand",(function(e){return Fn(e,!1,!0)})),Pr("\\renewcommand",(function(e){return Fn(e,!0,!1)})),Pr("\\providecommand",(function(e){return Fn(e,!0,!0)})),Pr("\\message",(function(e){var t=e.consumeArgs(1)[0];return console.log(t.reverse().map((function(e){return e.text})).join("")),""})),Pr("\\errmessage",(function(e){var t=e.consumeArgs(1)[0];return console.error(t.reverse().map((function(e){return e.text})).join("")),""})),Pr("\\show",(function(e){var t=e.popToken(),r=t.text;return console.log(t,e.macros.get(r),qn[r],ae.math[r],ae.text[r]),""})),Pr("\\bgroup","{"),Pr("\\egroup","}"),Pr("~","\\nobreakspace"),Pr("\\lq","`"),Pr("\\rq","'"),Pr("\\aa","\\r a"),Pr("\\AA","\\r A"),Pr("\\textcopyright","\\html@mathml{\\textcircled{c}}{\\char`\xa9}"),Pr("\\copyright","\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}"),Pr("\\textregistered","\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`\xae}"),Pr("\u212c","\\mathscr{B}"),Pr("\u2130","\\mathscr{E}"),Pr("\u2131","\\mathscr{F}"),Pr("\u210b","\\mathscr{H}"),Pr("\u2110","\\mathscr{I}"),Pr("\u2112","\\mathscr{L}"),Pr("\u2133","\\mathscr{M}"),Pr("\u211b","\\mathscr{R}"),Pr("\u212d","\\mathfrak{C}"),Pr("\u210c","\\mathfrak{H}"),Pr("\u2128","\\mathfrak{Z}"),Pr("\\Bbbk","\\Bbb{k}"),Pr("\xb7","\\cdotp"),Pr("\\llap","\\mathllap{\\textrm{#1}}"),Pr("\\rlap","\\mathrlap{\\textrm{#1}}"),Pr("\\clap","\\mathclap{\\textrm{#1}}"),Pr("\\mathstrut","\\vphantom{(}"),Pr("\\underbar","\\underline{\\text{#1}}"),Pr("\\not",'\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'),Pr("\\neq","\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`\u2260}}"),Pr("\\ne","\\neq"),Pr("\u2260","\\neq"),Pr("\\notin","\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}{\\mathrel{\\char`\u2209}}"),Pr("\u2209","\\notin"),Pr("\u2258","\\html@mathml{\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}}{\\mathrel{\\char`\u2258}}"),Pr("\u2259","\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}"),Pr("\u225a","\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225a}}"),Pr("\u225b","\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}{\\mathrel{\\char`\u225b}}"),Pr("\u225d","\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}{\\mathrel{\\char`\u225d}}"),Pr("\u225e","\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}{\\mathrel{\\char`\u225e}}"),Pr("\u225f","\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225f}}"),Pr("\u27c2","\\perp"),Pr("\u203c","\\mathclose{!\\mkern-0.8mu!}"),Pr("\u220c","\\notni"),Pr("\u231c","\\ulcorner"),Pr("\u231d","\\urcorner"),Pr("\u231e","\\llcorner"),Pr("\u231f","\\lrcorner"),Pr("\xa9","\\copyright"),Pr("\xae","\\textregistered"),Pr("\ufe0f","\\textregistered"),Pr("\\ulcorner",'\\html@mathml{\\@ulcorner}{\\mathop{\\char"231c}}'),Pr("\\urcorner",'\\html@mathml{\\@urcorner}{\\mathop{\\char"231d}}'),Pr("\\llcorner",'\\html@mathml{\\@llcorner}{\\mathop{\\char"231e}}'),Pr("\\lrcorner",'\\html@mathml{\\@lrcorner}{\\mathop{\\char"231f}}'),Pr("\\vdots","\\mathord{\\varvdots\\rule{0pt}{15pt}}"),Pr("\u22ee","\\vdots"),Pr("\\varGamma","\\mathit{\\Gamma}"),Pr("\\varDelta","\\mathit{\\Delta}"),Pr("\\varTheta","\\mathit{\\Theta}"),Pr("\\varLambda","\\mathit{\\Lambda}"),Pr("\\varXi","\\mathit{\\Xi}"),Pr("\\varPi","\\mathit{\\Pi}"),Pr("\\varSigma","\\mathit{\\Sigma}"),Pr("\\varUpsilon","\\mathit{\\Upsilon}"),Pr("\\varPhi","\\mathit{\\Phi}"),Pr("\\varPsi","\\mathit{\\Psi}"),Pr("\\varOmega","\\mathit{\\Omega}"),Pr("\\substack","\\begin{subarray}{c}#1\\end{subarray}"),Pr("\\colon","\\nobreak\\mskip2mu\\mathpunct{}\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"),Pr("\\boxed","\\fbox{$\\displaystyle{#1}$}"),Pr("\\iff","\\DOTSB\\;\\Longleftrightarrow\\;"),Pr("\\implies","\\DOTSB\\;\\Longrightarrow\\;"),Pr("\\impliedby","\\DOTSB\\;\\Longleftarrow\\;");var Gn={",":"\\dotsc","\\not":"\\dotsb","+":"\\dotsb","=":"\\dotsb","<":"\\dotsb",">":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};Pr("\\dots",(function(e){var t="\\dotso",r=e.expandAfterFuture().text;return r in Gn?t=Gn[r]:("\\not"===r.slice(0,4)||r in ae.math&&l.contains(["bin","rel"],ae.math[r].group))&&(t="\\dotsb"),t}));var Un={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};Pr("\\dotso",(function(e){return e.future().text in Un?"\\ldots\\,":"\\ldots"})),Pr("\\dotsc",(function(e){var t=e.future().text;return t in Un&&","!==t?"\\ldots\\,":"\\ldots"})),Pr("\\cdots",(function(e){return e.future().text in Un?"\\@cdots\\,":"\\@cdots"})),Pr("\\dotsb","\\cdots"),Pr("\\dotsm","\\cdots"),Pr("\\dotsi","\\!\\cdots"),Pr("\\dotsx","\\ldots\\,"),Pr("\\DOTSI","\\relax"),Pr("\\DOTSB","\\relax"),Pr("\\DOTSX","\\relax"),Pr("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),Pr("\\,","\\tmspace+{3mu}{.1667em}"),Pr("\\thinspace","\\,"),Pr("\\>","\\mskip{4mu}"),Pr("\\:","\\tmspace+{4mu}{.2222em}"),Pr("\\medspace","\\:"),Pr("\\;","\\tmspace+{5mu}{.2777em}"),Pr("\\thickspace","\\;"),Pr("\\!","\\tmspace-{3mu}{.1667em}"),Pr("\\negthinspace","\\!"),Pr("\\negmedspace","\\tmspace-{4mu}{.2222em}"),Pr("\\negthickspace","\\tmspace-{5mu}{.277em}"),Pr("\\enspace","\\kern.5em "),Pr("\\enskip","\\hskip.5em\\relax"),Pr("\\quad","\\hskip1em\\relax"),Pr("\\qquad","\\hskip2em\\relax"),Pr("\\tag","\\@ifstar\\tag@literal\\tag@paren"),Pr("\\tag@paren","\\tag@literal{({#1})}"),Pr("\\tag@literal",(function(e){if(e.macros.get("\\df@tag"))throw new n("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"})),Pr("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),Pr("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),Pr("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),Pr("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),Pr("\\newline","\\\\\\relax"),Pr("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");var Yn=F(T["Main-Regular"]["T".charCodeAt(0)][1]-.7*T["Main-Regular"]["A".charCodeAt(0)][1]);Pr("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+Yn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),Pr("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+Yn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),Pr("\\hspace","\\@ifstar\\@hspacer\\@hspace"),Pr("\\@hspace","\\hskip #1\\relax"),Pr("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),Pr("\\ordinarycolon",":"),Pr("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),Pr("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),Pr("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),Pr("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),Pr("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),Pr("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),Pr("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),Pr("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),Pr("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),Pr("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),Pr("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),Pr("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),Pr("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),Pr("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),Pr("\u2237","\\dblcolon"),Pr("\u2239","\\eqcolon"),Pr("\u2254","\\coloneqq"),Pr("\u2255","\\eqqcolon"),Pr("\u2a74","\\Coloneqq"),Pr("\\ratio","\\vcentcolon"),Pr("\\coloncolon","\\dblcolon"),Pr("\\colonequals","\\coloneqq"),Pr("\\coloncolonequals","\\Coloneqq"),Pr("\\equalscolon","\\eqqcolon"),Pr("\\equalscoloncolon","\\Eqqcolon"),Pr("\\colonminus","\\coloneq"),Pr("\\coloncolonminus","\\Coloneq"),Pr("\\minuscolon","\\eqcolon"),Pr("\\minuscoloncolon","\\Eqcolon"),Pr("\\coloncolonapprox","\\Colonapprox"),Pr("\\coloncolonsim","\\Colonsim"),Pr("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Pr("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Pr("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Pr("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Pr("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"),Pr("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),Pr("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),Pr("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),Pr("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),Pr("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),Pr("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),Pr("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),Pr("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),Pr("\\gvertneqq","\\html@mathml{\\@gvertneqq}{\u2269}"),Pr("\\lvertneqq","\\html@mathml{\\@lvertneqq}{\u2268}"),Pr("\\ngeqq","\\html@mathml{\\@ngeqq}{\u2271}"),Pr("\\ngeqslant","\\html@mathml{\\@ngeqslant}{\u2271}"),Pr("\\nleqq","\\html@mathml{\\@nleqq}{\u2270}"),Pr("\\nleqslant","\\html@mathml{\\@nleqslant}{\u2270}"),Pr("\\nshortmid","\\html@mathml{\\@nshortmid}{\u2224}"),Pr("\\nshortparallel","\\html@mathml{\\@nshortparallel}{\u2226}"),Pr("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{\u2288}"),Pr("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{\u2289}"),Pr("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{\u228a}"),Pr("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{\u2acb}"),Pr("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{\u228b}"),Pr("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{\u2acc}"),Pr("\\imath","\\html@mathml{\\@imath}{\u0131}"),Pr("\\jmath","\\html@mathml{\\@jmath}{\u0237}"),Pr("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"),Pr("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"),Pr("\u27e6","\\llbracket"),Pr("\u27e7","\\rrbracket"),Pr("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"),Pr("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"),Pr("\u2983","\\lBrace"),Pr("\u2984","\\rBrace"),Pr("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"),Pr("\u29b5","\\minuso"),Pr("\\darr","\\downarrow"),Pr("\\dArr","\\Downarrow"),Pr("\\Darr","\\Downarrow"),Pr("\\lang","\\langle"),Pr("\\rang","\\rangle"),Pr("\\uarr","\\uparrow"),Pr("\\uArr","\\Uparrow"),Pr("\\Uarr","\\Uparrow"),Pr("\\N","\\mathbb{N}"),Pr("\\R","\\mathbb{R}"),Pr("\\Z","\\mathbb{Z}"),Pr("\\alef","\\aleph"),Pr("\\alefsym","\\aleph"),Pr("\\Alpha","\\mathrm{A}"),Pr("\\Beta","\\mathrm{B}"),Pr("\\bull","\\bullet"),Pr("\\Chi","\\mathrm{X}"),Pr("\\clubs","\\clubsuit"),Pr("\\cnums","\\mathbb{C}"),Pr("\\Complex","\\mathbb{C}"),Pr("\\Dagger","\\ddagger"),Pr("\\diamonds","\\diamondsuit"),Pr("\\empty","\\emptyset"),Pr("\\Epsilon","\\mathrm{E}"),Pr("\\Eta","\\mathrm{H}"),Pr("\\exist","\\exists"),Pr("\\harr","\\leftrightarrow"),Pr("\\hArr","\\Leftrightarrow"),Pr("\\Harr","\\Leftrightarrow"),Pr("\\hearts","\\heartsuit"),Pr("\\image","\\Im"),Pr("\\infin","\\infty"),Pr("\\Iota","\\mathrm{I}"),Pr("\\isin","\\in"),Pr("\\Kappa","\\mathrm{K}"),Pr("\\larr","\\leftarrow"),Pr("\\lArr","\\Leftarrow"),Pr("\\Larr","\\Leftarrow"),Pr("\\lrarr","\\leftrightarrow"),Pr("\\lrArr","\\Leftrightarrow"),Pr("\\Lrarr","\\Leftrightarrow"),Pr("\\Mu","\\mathrm{M}"),Pr("\\natnums","\\mathbb{N}"),Pr("\\Nu","\\mathrm{N}"),Pr("\\Omicron","\\mathrm{O}"),Pr("\\plusmn","\\pm"),Pr("\\rarr","\\rightarrow"),Pr("\\rArr","\\Rightarrow"),Pr("\\Rarr","\\Rightarrow"),Pr("\\real","\\Re"),Pr("\\reals","\\mathbb{R}"),Pr("\\Reals","\\mathbb{R}"),Pr("\\Rho","\\mathrm{P}"),Pr("\\sdot","\\cdot"),Pr("\\sect","\\S"),Pr("\\spades","\\spadesuit"),Pr("\\sub","\\subset"),Pr("\\sube","\\subseteq"),Pr("\\supe","\\supseteq"),Pr("\\Tau","\\mathrm{T}"),Pr("\\thetasym","\\vartheta"),Pr("\\weierp","\\wp"),Pr("\\Zeta","\\mathrm{Z}"),Pr("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),Pr("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),Pr("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),Pr("\\bra","\\mathinner{\\langle{#1}|}"),Pr("\\ket","\\mathinner{|{#1}\\rangle}"),Pr("\\braket","\\mathinner{\\langle{#1}\\rangle}"),Pr("\\Bra","\\left\\langle#1\\right|"),Pr("\\Ket","\\left|#1\\right\\rangle");var Xn=function(e){return function(t){var r=t.consumeArg().tokens,n=t.consumeArg().tokens,a=t.consumeArg().tokens,i=t.consumeArg().tokens,o=t.macros.get("|"),s=t.macros.get("\\|");t.macros.beginGroup();var l=function(t){return function(r){e&&(r.macros.set("|",o),a.length&&r.macros.set("\\|",s));var i=t;!t&&a.length&&("|"===r.future().text&&(r.popToken(),i=!0));return{tokens:i?a:n,numArgs:0}}};t.macros.set("|",l(!1)),a.length&&t.macros.set("\\|",l(!0));var h=t.consumeArg().tokens,c=t.expandTokens([].concat(i,h,r));return t.macros.endGroup(),{tokens:c.reverse(),numArgs:0}}};Pr("\\bra@ket",Xn(!1)),Pr("\\bra@set",Xn(!0)),Pr("\\Braket","\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"),Pr("\\Set","\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"),Pr("\\set","\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"),Pr("\\angln","{\\angl n}"),Pr("\\blue","\\textcolor{##6495ed}{#1}"),Pr("\\orange","\\textcolor{##ffa500}{#1}"),Pr("\\pink","\\textcolor{##ff00af}{#1}"),Pr("\\red","\\textcolor{##df0030}{#1}"),Pr("\\green","\\textcolor{##28ae7b}{#1}"),Pr("\\gray","\\textcolor{gray}{#1}"),Pr("\\purple","\\textcolor{##9d38bd}{#1}"),Pr("\\blueA","\\textcolor{##ccfaff}{#1}"),Pr("\\blueB","\\textcolor{##80f6ff}{#1}"),Pr("\\blueC","\\textcolor{##63d9ea}{#1}"),Pr("\\blueD","\\textcolor{##11accd}{#1}"),Pr("\\blueE","\\textcolor{##0c7f99}{#1}"),Pr("\\tealA","\\textcolor{##94fff5}{#1}"),Pr("\\tealB","\\textcolor{##26edd5}{#1}"),Pr("\\tealC","\\textcolor{##01d1c1}{#1}"),Pr("\\tealD","\\textcolor{##01a995}{#1}"),Pr("\\tealE","\\textcolor{##208170}{#1}"),Pr("\\greenA","\\textcolor{##b6ffb0}{#1}"),Pr("\\greenB","\\textcolor{##8af281}{#1}"),Pr("\\greenC","\\textcolor{##74cf70}{#1}"),Pr("\\greenD","\\textcolor{##1fab54}{#1}"),Pr("\\greenE","\\textcolor{##0d923f}{#1}"),Pr("\\goldA","\\textcolor{##ffd0a9}{#1}"),Pr("\\goldB","\\textcolor{##ffbb71}{#1}"),Pr("\\goldC","\\textcolor{##ff9c39}{#1}"),Pr("\\goldD","\\textcolor{##e07d10}{#1}"),Pr("\\goldE","\\textcolor{##a75a05}{#1}"),Pr("\\redA","\\textcolor{##fca9a9}{#1}"),Pr("\\redB","\\textcolor{##ff8482}{#1}"),Pr("\\redC","\\textcolor{##f9685d}{#1}"),Pr("\\redD","\\textcolor{##e84d39}{#1}"),Pr("\\redE","\\textcolor{##bc2612}{#1}"),Pr("\\maroonA","\\textcolor{##ffbde0}{#1}"),Pr("\\maroonB","\\textcolor{##ff92c6}{#1}"),Pr("\\maroonC","\\textcolor{##ed5fa6}{#1}"),Pr("\\maroonD","\\textcolor{##ca337c}{#1}"),Pr("\\maroonE","\\textcolor{##9e034e}{#1}"),Pr("\\purpleA","\\textcolor{##ddd7ff}{#1}"),Pr("\\purpleB","\\textcolor{##c6b9fc}{#1}"),Pr("\\purpleC","\\textcolor{##aa87ff}{#1}"),Pr("\\purpleD","\\textcolor{##7854ab}{#1}"),Pr("\\purpleE","\\textcolor{##543b78}{#1}"),Pr("\\mintA","\\textcolor{##f5f9e8}{#1}"),Pr("\\mintB","\\textcolor{##edf2df}{#1}"),Pr("\\mintC","\\textcolor{##e0e5cc}{#1}"),Pr("\\grayA","\\textcolor{##f6f7f7}{#1}"),Pr("\\grayB","\\textcolor{##f0f1f2}{#1}"),Pr("\\grayC","\\textcolor{##e3e5e6}{#1}"),Pr("\\grayD","\\textcolor{##d6d8da}{#1}"),Pr("\\grayE","\\textcolor{##babec2}{#1}"),Pr("\\grayF","\\textcolor{##888d93}{#1}"),Pr("\\grayG","\\textcolor{##626569}{#1}"),Pr("\\grayH","\\textcolor{##3b3e40}{#1}"),Pr("\\grayI","\\textcolor{##21242c}{#1}"),Pr("\\kaBlue","\\textcolor{##314453}{#1}"),Pr("\\kaGreen","\\textcolor{##71B307}{#1}");var Wn={"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0},_n=function(){function e(e,t,r){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new Dn(Vn,t.macros),this.mode=r,this.stack=[]}var t=e.prototype;return t.feed=function(e){this.lexer=new Ln(e,this.settings)},t.switchMode=function(e){this.mode=e},t.beginGroup=function(){this.macros.beginGroup()},t.endGroup=function(){this.macros.endGroup()},t.endGroups=function(){this.macros.endGroups()},t.future=function(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]},t.popToken=function(){return this.future(),this.stack.pop()},t.pushToken=function(e){this.stack.push(e)},t.pushTokens=function(e){var t;(t=this.stack).push.apply(t,e)},t.scanArgument=function(e){var t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken();var a=this.consumeArg(["]"]);n=a.tokens,r=a.end}else{var i=this.consumeArg();n=i.tokens,t=i.start,r=i.end}return this.pushToken(new Gr("EOF",r.loc)),this.pushTokens(n),t.range(r,"")},t.consumeSpaces=function(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}},t.consumeArg=function(e){var t=[],r=e&&e.length>0;r||this.consumeSpaces();var a,i=this.future(),o=0,s=0;do{if(a=this.popToken(),t.push(a),"{"===a.text)++o;else if("}"===a.text){if(-1===--o)throw new n("Extra }",a)}else if("EOF"===a.text)throw new n("Unexpected end of input in a macro argument, expected '"+(e&&r?e[s]:"}")+"'",a);if(e&&r)if((0===o||1===o&&"{"===e[s])&&a.text===e[s]){if(++s===e.length){t.splice(-s,s);break}}else s=0}while(0!==o||r);return"{"===i.text&&"}"===t[t.length-1].text&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:i,end:a}},t.consumeArgs=function(e,t){if(t){if(t.length!==e+1)throw new n("The length of delimiters doesn't match the number of args!");for(var r=t[0],a=0;a<r.length;a++){var i=this.popToken();if(r[a]!==i.text)throw new n("Use of the macro doesn't match its definition",i)}}for(var o=[],s=0;s<e;s++)o.push(this.consumeArg(t&&t[s+1]).tokens);return o},t.expandOnce=function(e){var t=this.popToken(),r=t.text,a=t.noexpand?null:this._getExpansion(r);if(null==a||e&&a.unexpandable){if(e&&null==a&&"\\"===r[0]&&!this.isDefined(r))throw new n("Undefined control sequence: "+r);return this.pushToken(t),!1}if(this.expansionCount++,this.expansionCount>this.settings.maxExpand)throw new n("Too many expansions: infinite loop or need to increase maxExpand setting");var i=a.tokens,o=this.consumeArgs(a.numArgs,a.delimiters);if(a.numArgs)for(var s=(i=i.slice()).length-1;s>=0;--s){var l=i[s];if("#"===l.text){if(0===s)throw new n("Incomplete placeholder at end of macro body",l);if("#"===(l=i[--s]).text)i.splice(s+1,1);else{if(!/^[1-9]$/.test(l.text))throw new n("Not a valid argument number",l);var h;(h=i).splice.apply(h,[s,2].concat(o[+l.text-1]))}}}return this.pushTokens(i),i.length},t.expandAfterFuture=function(){return this.expandOnce(),this.future()},t.expandNextToken=function(){for(;;)if(!1===this.expandOnce()){var e=this.stack.pop();return e.treatAsRelax&&(e.text="\\relax"),e}throw new Error},t.expandMacro=function(e){return this.macros.has(e)?this.expandTokens([new Gr(e)]):void 0},t.expandTokens=function(e){var t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;)if(!1===this.expandOnce(!0)){var n=this.stack.pop();n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(n)}return t},t.expandMacroAsText=function(e){var t=this.expandMacro(e);return t?t.map((function(e){return e.text})).join(""):t},t._getExpansion=function(e){var t=this.macros.get(e);if(null==t)return t;if(1===e.length){var r=this.lexer.catcodes[e];if(null!=r&&13!==r)return}var n="function"==typeof t?t(this):t;if("string"==typeof n){var a=0;if(-1!==n.indexOf("#"))for(var i=n.replace(/##/g,"");-1!==i.indexOf("#"+(a+1));)++a;for(var o=new Ln(n,this.settings),s=[],l=o.lex();"EOF"!==l.text;)s.push(l),l=o.lex();return s.reverse(),{tokens:s,numArgs:a}}return n},t.isDefined=function(e){return this.macros.has(e)||qn.hasOwnProperty(e)||ae.math.hasOwnProperty(e)||ae.text.hasOwnProperty(e)||Wn.hasOwnProperty(e)},t.isExpandable=function(e){var t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:qn.hasOwnProperty(e)&&!qn[e].primitive},e}(),jn=/^[\u208a\u208b\u208c\u208d\u208e\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u1d66\u1d67\u1d68\u1d69\u1d6a]/,$n=Object.freeze({"\u208a":"+","\u208b":"-","\u208c":"=","\u208d":"(","\u208e":")","\u2080":"0","\u2081":"1","\u2082":"2","\u2083":"3","\u2084":"4","\u2085":"5","\u2086":"6","\u2087":"7","\u2088":"8","\u2089":"9","\u2090":"a","\u2091":"e","\u2095":"h","\u1d62":"i","\u2c7c":"j","\u2096":"k","\u2097":"l","\u2098":"m","\u2099":"n","\u2092":"o","\u209a":"p","\u1d63":"r","\u209b":"s","\u209c":"t","\u1d64":"u","\u1d65":"v","\u2093":"x","\u1d66":"\u03b2","\u1d67":"\u03b3","\u1d68":"\u03c1","\u1d69":"\u03d5","\u1d6a":"\u03c7","\u207a":"+","\u207b":"-","\u207c":"=","\u207d":"(","\u207e":")","\u2070":"0","\xb9":"1","\xb2":"2","\xb3":"3","\u2074":"4","\u2075":"5","\u2076":"6","\u2077":"7","\u2078":"8","\u2079":"9","\u1d2c":"A","\u1d2e":"B","\u1d30":"D","\u1d31":"E","\u1d33":"G","\u1d34":"H","\u1d35":"I","\u1d36":"J","\u1d37":"K","\u1d38":"L","\u1d39":"M","\u1d3a":"N","\u1d3c":"O","\u1d3e":"P","\u1d3f":"R","\u1d40":"T","\u1d41":"U","\u2c7d":"V","\u1d42":"W","\u1d43":"a","\u1d47":"b","\u1d9c":"c","\u1d48":"d","\u1d49":"e","\u1da0":"f","\u1d4d":"g","\u02b0":"h","\u2071":"i","\u02b2":"j","\u1d4f":"k","\u02e1":"l","\u1d50":"m","\u207f":"n","\u1d52":"o","\u1d56":"p","\u02b3":"r","\u02e2":"s","\u1d57":"t","\u1d58":"u","\u1d5b":"v","\u02b7":"w","\u02e3":"x","\u02b8":"y","\u1dbb":"z","\u1d5d":"\u03b2","\u1d5e":"\u03b3","\u1d5f":"\u03b4","\u1d60":"\u03d5","\u1d61":"\u03c7","\u1dbf":"\u03b8"}),Zn={"\u0301":{text:"\\'",math:"\\acute"},"\u0300":{text:"\\`",math:"\\grave"},"\u0308":{text:'\\"',math:"\\ddot"},"\u0303":{text:"\\~",math:"\\tilde"},"\u0304":{text:"\\=",math:"\\bar"},"\u0306":{text:"\\u",math:"\\breve"},"\u030c":{text:"\\v",math:"\\check"},"\u0302":{text:"\\^",math:"\\hat"},"\u0307":{text:"\\.",math:"\\dot"},"\u030a":{text:"\\r",math:"\\mathring"},"\u030b":{text:"\\H"},"\u0327":{text:"\\c"}},Kn={"\xe1":"a\u0301","\xe0":"a\u0300","\xe4":"a\u0308","\u01df":"a\u0308\u0304","\xe3":"a\u0303","\u0101":"a\u0304","\u0103":"a\u0306","\u1eaf":"a\u0306\u0301","\u1eb1":"a\u0306\u0300","\u1eb5":"a\u0306\u0303","\u01ce":"a\u030c","\xe2":"a\u0302","\u1ea5":"a\u0302\u0301","\u1ea7":"a\u0302\u0300","\u1eab":"a\u0302\u0303","\u0227":"a\u0307","\u01e1":"a\u0307\u0304","\xe5":"a\u030a","\u01fb":"a\u030a\u0301","\u1e03":"b\u0307","\u0107":"c\u0301","\u1e09":"c\u0327\u0301","\u010d":"c\u030c","\u0109":"c\u0302","\u010b":"c\u0307","\xe7":"c\u0327","\u010f":"d\u030c","\u1e0b":"d\u0307","\u1e11":"d\u0327","\xe9":"e\u0301","\xe8":"e\u0300","\xeb":"e\u0308","\u1ebd":"e\u0303","\u0113":"e\u0304","\u1e17":"e\u0304\u0301","\u1e15":"e\u0304\u0300","\u0115":"e\u0306","\u1e1d":"e\u0327\u0306","\u011b":"e\u030c","\xea":"e\u0302","\u1ebf":"e\u0302\u0301","\u1ec1":"e\u0302\u0300","\u1ec5":"e\u0302\u0303","\u0117":"e\u0307","\u0229":"e\u0327","\u1e1f":"f\u0307","\u01f5":"g\u0301","\u1e21":"g\u0304","\u011f":"g\u0306","\u01e7":"g\u030c","\u011d":"g\u0302","\u0121":"g\u0307","\u0123":"g\u0327","\u1e27":"h\u0308","\u021f":"h\u030c","\u0125":"h\u0302","\u1e23":"h\u0307","\u1e29":"h\u0327","\xed":"i\u0301","\xec":"i\u0300","\xef":"i\u0308","\u1e2f":"i\u0308\u0301","\u0129":"i\u0303","\u012b":"i\u0304","\u012d":"i\u0306","\u01d0":"i\u030c","\xee":"i\u0302","\u01f0":"j\u030c","\u0135":"j\u0302","\u1e31":"k\u0301","\u01e9":"k\u030c","\u0137":"k\u0327","\u013a":"l\u0301","\u013e":"l\u030c","\u013c":"l\u0327","\u1e3f":"m\u0301","\u1e41":"m\u0307","\u0144":"n\u0301","\u01f9":"n\u0300","\xf1":"n\u0303","\u0148":"n\u030c","\u1e45":"n\u0307","\u0146":"n\u0327","\xf3":"o\u0301","\xf2":"o\u0300","\xf6":"o\u0308","\u022b":"o\u0308\u0304","\xf5":"o\u0303","\u1e4d":"o\u0303\u0301","\u1e4f":"o\u0303\u0308","\u022d":"o\u0303\u0304","\u014d":"o\u0304","\u1e53":"o\u0304\u0301","\u1e51":"o\u0304\u0300","\u014f":"o\u0306","\u01d2":"o\u030c","\xf4":"o\u0302","\u1ed1":"o\u0302\u0301","\u1ed3":"o\u0302\u0300","\u1ed7":"o\u0302\u0303","\u022f":"o\u0307","\u0231":"o\u0307\u0304","\u0151":"o\u030b","\u1e55":"p\u0301","\u1e57":"p\u0307","\u0155":"r\u0301","\u0159":"r\u030c","\u1e59":"r\u0307","\u0157":"r\u0327","\u015b":"s\u0301","\u1e65":"s\u0301\u0307","\u0161":"s\u030c","\u1e67":"s\u030c\u0307","\u015d":"s\u0302","\u1e61":"s\u0307","\u015f":"s\u0327","\u1e97":"t\u0308","\u0165":"t\u030c","\u1e6b":"t\u0307","\u0163":"t\u0327","\xfa":"u\u0301","\xf9":"u\u0300","\xfc":"u\u0308","\u01d8":"u\u0308\u0301","\u01dc":"u\u0308\u0300","\u01d6":"u\u0308\u0304","\u01da":"u\u0308\u030c","\u0169":"u\u0303","\u1e79":"u\u0303\u0301","\u016b":"u\u0304","\u1e7b":"u\u0304\u0308","\u016d":"u\u0306","\u01d4":"u\u030c","\xfb":"u\u0302","\u016f":"u\u030a","\u0171":"u\u030b","\u1e7d":"v\u0303","\u1e83":"w\u0301","\u1e81":"w\u0300","\u1e85":"w\u0308","\u0175":"w\u0302","\u1e87":"w\u0307","\u1e98":"w\u030a","\u1e8d":"x\u0308","\u1e8b":"x\u0307","\xfd":"y\u0301","\u1ef3":"y\u0300","\xff":"y\u0308","\u1ef9":"y\u0303","\u0233":"y\u0304","\u0177":"y\u0302","\u1e8f":"y\u0307","\u1e99":"y\u030a","\u017a":"z\u0301","\u017e":"z\u030c","\u1e91":"z\u0302","\u017c":"z\u0307","\xc1":"A\u0301","\xc0":"A\u0300","\xc4":"A\u0308","\u01de":"A\u0308\u0304","\xc3":"A\u0303","\u0100":"A\u0304","\u0102":"A\u0306","\u1eae":"A\u0306\u0301","\u1eb0":"A\u0306\u0300","\u1eb4":"A\u0306\u0303","\u01cd":"A\u030c","\xc2":"A\u0302","\u1ea4":"A\u0302\u0301","\u1ea6":"A\u0302\u0300","\u1eaa":"A\u0302\u0303","\u0226":"A\u0307","\u01e0":"A\u0307\u0304","\xc5":"A\u030a","\u01fa":"A\u030a\u0301","\u1e02":"B\u0307","\u0106":"C\u0301","\u1e08":"C\u0327\u0301","\u010c":"C\u030c","\u0108":"C\u0302","\u010a":"C\u0307","\xc7":"C\u0327","\u010e":"D\u030c","\u1e0a":"D\u0307","\u1e10":"D\u0327","\xc9":"E\u0301","\xc8":"E\u0300","\xcb":"E\u0308","\u1ebc":"E\u0303","\u0112":"E\u0304","\u1e16":"E\u0304\u0301","\u1e14":"E\u0304\u0300","\u0114":"E\u0306","\u1e1c":"E\u0327\u0306","\u011a":"E\u030c","\xca":"E\u0302","\u1ebe":"E\u0302\u0301","\u1ec0":"E\u0302\u0300","\u1ec4":"E\u0302\u0303","\u0116":"E\u0307","\u0228":"E\u0327","\u1e1e":"F\u0307","\u01f4":"G\u0301","\u1e20":"G\u0304","\u011e":"G\u0306","\u01e6":"G\u030c","\u011c":"G\u0302","\u0120":"G\u0307","\u0122":"G\u0327","\u1e26":"H\u0308","\u021e":"H\u030c","\u0124":"H\u0302","\u1e22":"H\u0307","\u1e28":"H\u0327","\xcd":"I\u0301","\xcc":"I\u0300","\xcf":"I\u0308","\u1e2e":"I\u0308\u0301","\u0128":"I\u0303","\u012a":"I\u0304","\u012c":"I\u0306","\u01cf":"I\u030c","\xce":"I\u0302","\u0130":"I\u0307","\u0134":"J\u0302","\u1e30":"K\u0301","\u01e8":"K\u030c","\u0136":"K\u0327","\u0139":"L\u0301","\u013d":"L\u030c","\u013b":"L\u0327","\u1e3e":"M\u0301","\u1e40":"M\u0307","\u0143":"N\u0301","\u01f8":"N\u0300","\xd1":"N\u0303","\u0147":"N\u030c","\u1e44":"N\u0307","\u0145":"N\u0327","\xd3":"O\u0301","\xd2":"O\u0300","\xd6":"O\u0308","\u022a":"O\u0308\u0304","\xd5":"O\u0303","\u1e4c":"O\u0303\u0301","\u1e4e":"O\u0303\u0308","\u022c":"O\u0303\u0304","\u014c":"O\u0304","\u1e52":"O\u0304\u0301","\u1e50":"O\u0304\u0300","\u014e":"O\u0306","\u01d1":"O\u030c","\xd4":"O\u0302","\u1ed0":"O\u0302\u0301","\u1ed2":"O\u0302\u0300","\u1ed6":"O\u0302\u0303","\u022e":"O\u0307","\u0230":"O\u0307\u0304","\u0150":"O\u030b","\u1e54":"P\u0301","\u1e56":"P\u0307","\u0154":"R\u0301","\u0158":"R\u030c","\u1e58":"R\u0307","\u0156":"R\u0327","\u015a":"S\u0301","\u1e64":"S\u0301\u0307","\u0160":"S\u030c","\u1e66":"S\u030c\u0307","\u015c":"S\u0302","\u1e60":"S\u0307","\u015e":"S\u0327","\u0164":"T\u030c","\u1e6a":"T\u0307","\u0162":"T\u0327","\xda":"U\u0301","\xd9":"U\u0300","\xdc":"U\u0308","\u01d7":"U\u0308\u0301","\u01db":"U\u0308\u0300","\u01d5":"U\u0308\u0304","\u01d9":"U\u0308\u030c","\u0168":"U\u0303","\u1e78":"U\u0303\u0301","\u016a":"U\u0304","\u1e7a":"U\u0304\u0308","\u016c":"U\u0306","\u01d3":"U\u030c","\xdb":"U\u0302","\u016e":"U\u030a","\u0170":"U\u030b","\u1e7c":"V\u0303","\u1e82":"W\u0301","\u1e80":"W\u0300","\u1e84":"W\u0308","\u0174":"W\u0302","\u1e86":"W\u0307","\u1e8c":"X\u0308","\u1e8a":"X\u0307","\xdd":"Y\u0301","\u1ef2":"Y\u0300","\u0178":"Y\u0308","\u1ef8":"Y\u0303","\u0232":"Y\u0304","\u0176":"Y\u0302","\u1e8e":"Y\u0307","\u0179":"Z\u0301","\u017d":"Z\u030c","\u1e90":"Z\u0302","\u017b":"Z\u0307","\u03ac":"\u03b1\u0301","\u1f70":"\u03b1\u0300","\u1fb1":"\u03b1\u0304","\u1fb0":"\u03b1\u0306","\u03ad":"\u03b5\u0301","\u1f72":"\u03b5\u0300","\u03ae":"\u03b7\u0301","\u1f74":"\u03b7\u0300","\u03af":"\u03b9\u0301","\u1f76":"\u03b9\u0300","\u03ca":"\u03b9\u0308","\u0390":"\u03b9\u0308\u0301","\u1fd2":"\u03b9\u0308\u0300","\u1fd1":"\u03b9\u0304","\u1fd0":"\u03b9\u0306","\u03cc":"\u03bf\u0301","\u1f78":"\u03bf\u0300","\u03cd":"\u03c5\u0301","\u1f7a":"\u03c5\u0300","\u03cb":"\u03c5\u0308","\u03b0":"\u03c5\u0308\u0301","\u1fe2":"\u03c5\u0308\u0300","\u1fe1":"\u03c5\u0304","\u1fe0":"\u03c5\u0306","\u03ce":"\u03c9\u0301","\u1f7c":"\u03c9\u0300","\u038e":"\u03a5\u0301","\u1fea":"\u03a5\u0300","\u03ab":"\u03a5\u0308","\u1fe9":"\u03a5\u0304","\u1fe8":"\u03a5\u0306","\u038f":"\u03a9\u0301","\u1ffa":"\u03a9\u0300"},Jn=function(){function e(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new _n(e,t,this.mode),this.settings=t,this.leftrightDepth=0}var t=e.prototype;return t.expect=function(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new n("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()},t.consume=function(){this.nextToken=null},t.fetch=function(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken},t.switchMode=function(e){this.mode=e,this.gullet.switchMode(e)},t.parse=function(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");try{var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e}finally{this.gullet.endGroups()}},t.subparse=function(e){var t=this.nextToken;this.consume(),this.gullet.pushToken(new Gr("}")),this.gullet.pushTokens(e);var r=this.parseExpression(!1);return this.expect("}"),this.nextToken=t,r},t.parseExpression=function(t,r){for(var n=[];;){"math"===this.mode&&this.consumeSpaces();var a=this.fetch();if(-1!==e.endOfExpression.indexOf(a.text))break;if(r&&a.text===r)break;if(t&&qn[a.text]&&qn[a.text].infix)break;var i=this.parseAtom(r);if(!i)break;"internal"!==i.type&&n.push(i)}return"text"===this.mode&&this.formLigatures(n),this.handleInfixNodes(n)},t.handleInfixNodes=function(e){for(var t,r=-1,a=0;a<e.length;a++)if("infix"===e[a].type){if(-1!==r)throw new n("only one infix operator per group",e[a].token);r=a,t=e[a].replaceWith}if(-1!==r&&t){var i,o,s=e.slice(0,r),l=e.slice(r+1);return i=1===s.length&&"ordgroup"===s[0].type?s[0]:{type:"ordgroup",mode:this.mode,body:s},o=1===l.length&&"ordgroup"===l[0].type?l[0]:{type:"ordgroup",mode:this.mode,body:l},["\\\\abovefrac"===t?this.callFunction(t,[i,e[r],o],[]):this.callFunction(t,[i,o],[])]}return e},t.handleSupSubscript=function(e){var t=this.fetch(),r=t.text;this.consume(),this.consumeSpaces();var a=this.parseGroup(e);if(!a)throw new n("Expected group after '"+r+"'",t);return a},t.formatUnsupportedCmd=function(e){for(var t=[],r=0;r<e.length;r++)t.push({type:"textord",mode:"text",text:e[r]});var n={type:"text",mode:this.mode,body:t};return{type:"color",mode:this.mode,color:this.settings.errorColor,body:[n]}},t.parseAtom=function(t){var r,a,i=this.parseGroup("atom",t);if("text"===this.mode)return i;for(;;){this.consumeSpaces();var o=this.fetch();if("\\limits"===o.text||"\\nolimits"===o.text){if(i&&"op"===i.type){var s="\\limits"===o.text;i.limits=s,i.alwaysHandleSupSub=!0}else{if(!i||"operatorname"!==i.type)throw new n("Limit controls must follow a math operator",o);i.alwaysHandleSupSub&&(i.limits="\\limits"===o.text)}this.consume()}else if("^"===o.text){if(r)throw new n("Double superscript",o);r=this.handleSupSubscript("superscript")}else if("_"===o.text){if(a)throw new n("Double subscript",o);a=this.handleSupSubscript("subscript")}else if("'"===o.text){if(r)throw new n("Double superscript",o);var l={type:"textord",mode:this.mode,text:"\\prime"},h=[l];for(this.consume();"'"===this.fetch().text;)h.push(l),this.consume();"^"===this.fetch().text&&h.push(this.handleSupSubscript("superscript")),r={type:"ordgroup",mode:this.mode,body:h}}else{if(!$n[o.text])break;var c=$n[o.text],m=jn.test(o.text);for(this.consume();;){var u=this.fetch().text;if(!$n[u])break;if(jn.test(u)!==m)break;this.consume(),c+=$n[u]}var p=new e(c,this.settings).parse();m?a={type:"ordgroup",mode:"math",body:p}:r={type:"ordgroup",mode:"math",body:p}}}return r||a?{type:"supsub",mode:this.mode,base:i,sup:r,sub:a}:i},t.parseFunction=function(e,t){var r=this.fetch(),a=r.text,i=qn[a];if(!i)return null;if(this.consume(),t&&"atom"!==t&&!i.allowedInArgument)throw new n("Got function '"+a+"' with no arguments"+(t?" as "+t:""),r);if("text"===this.mode&&!i.allowedInText)throw new n("Can't use function '"+a+"' in text mode",r);if("math"===this.mode&&!1===i.allowedInMath)throw new n("Can't use function '"+a+"' in math mode",r);var o=this.parseArguments(a,i),s=o.args,l=o.optArgs;return this.callFunction(a,s,l,r,e)},t.callFunction=function(e,t,r,a,i){var o={funcName:e,parser:this,token:a,breakOnTokenText:i},s=qn[e];if(s&&s.handler)return s.handler(o,t,r);throw new n("No function handler for "+e)},t.parseArguments=function(e,t){var r=t.numArgs+t.numOptionalArgs;if(0===r)return{args:[],optArgs:[]};for(var a=[],i=[],o=0;o<r;o++){var s=t.argTypes&&t.argTypes[o],l=o<t.numOptionalArgs;(t.primitive&&null==s||"sqrt"===t.type&&1===o&&null==i[0])&&(s="primitive");var h=this.parseGroupOfType("argument to '"+e+"'",s,l);if(l)i.push(h);else{if(null==h)throw new n("Null argument, please report this as a bug");a.push(h)}}return{args:a,optArgs:i}},t.parseGroupOfType=function(e,t,r){switch(t){case"color":return this.parseColorGroup(r);case"size":return this.parseSizeGroup(r);case"url":return this.parseUrlGroup(r);case"math":case"text":return this.parseArgumentGroup(r,t);case"hbox":var a=this.parseArgumentGroup(r,"text");return null!=a?{type:"styling",mode:a.mode,body:[a],style:"text"}:null;case"raw":var i=this.parseStringGroup("raw",r);return null!=i?{type:"raw",mode:"text",string:i.text}:null;case"primitive":if(r)throw new n("A primitive argument cannot be optional");var o=this.parseGroup(e);if(null==o)throw new n("Expected group as "+e,this.fetch());return o;case"original":case null:case void 0:return this.parseArgumentGroup(r);default:throw new n("Unknown group type as "+e,this.fetch())}},t.consumeSpaces=function(){for(;" "===this.fetch().text;)this.consume()},t.parseStringGroup=function(e,t){var r=this.gullet.scanArgument(t);if(null==r)return null;for(var n,a="";"EOF"!==(n=this.fetch()).text;)a+=n.text,this.consume();return this.consume(),r.text=a,r},t.parseRegexGroup=function(e,t){for(var r,a=this.fetch(),i=a,o="";"EOF"!==(r=this.fetch()).text&&e.test(o+r.text);)o+=(i=r).text,this.consume();if(""===o)throw new n("Invalid "+t+": '"+a.text+"'",a);return a.range(i,o)},t.parseColorGroup=function(e){var t=this.parseStringGroup("color",e);if(null==t)return null;var r=/^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(t.text);if(!r)throw new n("Invalid color: '"+t.text+"'",t);var a=r[0];return/^[0-9a-f]{6}$/i.test(a)&&(a="#"+a),{type:"color-token",mode:this.mode,color:a}},t.parseSizeGroup=function(e){var t,r=!1;if(this.gullet.consumeSpaces(),!(t=e||"{"===this.gullet.future().text?this.parseStringGroup("size",e):this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/,"size")))return null;e||0!==t.text.length||(t.text="0pt",r=!0);var a=/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(t.text);if(!a)throw new n("Invalid size: '"+t.text+"'",t);var i={number:+(a[1]+a[2]),unit:a[3]};if(!V(i))throw new n("Invalid unit: '"+i.unit+"'",t);return{type:"size",mode:this.mode,value:i,isBlank:r}},t.parseUrlGroup=function(e){this.gullet.lexer.setCatcode("%",13),this.gullet.lexer.setCatcode("~",12);var t=this.parseStringGroup("url",e);if(this.gullet.lexer.setCatcode("%",14),this.gullet.lexer.setCatcode("~",13),null==t)return null;var r=t.text.replace(/\\([#$%&~_^{}])/g,"$1");return{type:"url",mode:this.mode,url:r}},t.parseArgumentGroup=function(e,t){var r=this.gullet.scanArgument(e);if(null==r)return null;var n=this.mode;t&&this.switchMode(t),this.gullet.beginGroup();var a=this.parseExpression(!1,"EOF");this.expect("EOF"),this.gullet.endGroup();var i={type:"ordgroup",mode:this.mode,loc:r.loc,body:a};return t&&this.switchMode(n),i},t.parseGroup=function(e,t){var r,a=this.fetch(),i=a.text;if("{"===i||"\\begingroup"===i){this.consume();var o="{"===i?"}":"\\endgroup";this.gullet.beginGroup();var s=this.parseExpression(!1,o),l=this.fetch();this.expect(o),this.gullet.endGroup(),r={type:"ordgroup",mode:this.mode,loc:Fr.range(a,l),body:s,semisimple:"\\begingroup"===i||void 0}}else if(null==(r=this.parseFunction(t,e)||this.parseSymbol())&&"\\"===i[0]&&!Wn.hasOwnProperty(i)){if(this.settings.throwOnError)throw new n("Undefined control sequence: "+i,a);r=this.formatUnsupportedCmd(i),this.consume()}return r},t.formLigatures=function(e){for(var t=e.length-1,r=0;r<t;++r){var n=e[r],a=n.text;"-"===a&&"-"===e[r+1].text&&(r+1<t&&"-"===e[r+2].text?(e.splice(r,3,{type:"textord",mode:"text",loc:Fr.range(n,e[r+2]),text:"---"}),t-=2):(e.splice(r,2,{type:"textord",mode:"text",loc:Fr.range(n,e[r+1]),text:"--"}),t-=1)),"'"!==a&&"`"!==a||e[r+1].text!==a||(e.splice(r,2,{type:"textord",mode:"text",loc:Fr.range(n,e[r+1]),text:a+a}),t-=1)}},t.parseSymbol=function(){var e=this.fetch(),t=e.text;if(/^\\verb[^a-zA-Z]/.test(t)){this.consume();var r=t.slice(5),a="*"===r.charAt(0);if(a&&(r=r.slice(1)),r.length<2||r.charAt(0)!==r.slice(-1))throw new n("\\verb assertion failed --\n please report what input caused this bug");return{type:"verb",mode:"text",body:r=r.slice(1,-1),star:a}}Kn.hasOwnProperty(t[0])&&!ae[this.mode][t[0]]&&(this.settings.strict&&"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Accented Unicode text character "'+t[0]+'" used in math mode',e),t=Kn[t[0]]+t.slice(1));var i,o=On.exec(t);if(o&&("i"===(t=t.substring(0,o.index))?t="\u0131":"j"===t&&(t="\u0237")),ae[this.mode][t]){this.settings.strict&&"math"===this.mode&&Ee.indexOf(t)>=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);var s,l=ae[this.mode][t].group,h=Fr.range(e);if(te.hasOwnProperty(l)){var c=l;s={type:"atom",mode:this.mode,family:c,loc:h,text:t}}else s={type:l,mode:this.mode,loc:h,text:t};i=s}else{if(!(t.charCodeAt(0)>=128))return null;this.settings.strict&&(S(t.charCodeAt(0))?"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'" ('+t.charCodeAt(0)+")",e)),i={type:"textord",mode:"text",loc:Fr.range(e),text:t}}if(this.consume(),o)for(var m=0;m<o[0].length;m++){var u=o[0][m];if(!Zn[u])throw new n("Unknown accent ' "+u+"'",e);var p=Zn[u][this.mode]||Zn[u].text;if(!p)throw new n("Accent "+u+" unsupported in "+this.mode+" mode",e);i={type:"accent",mode:this.mode,loc:Fr.range(e),label:p,isStretchy:!1,isShifty:!0,base:i}}return i},e}();Jn.endOfExpression=["}","\\endgroup","\\end","\\right","&"];var Qn=function(e,t){if(!("string"==typeof e||e instanceof String))throw new TypeError("KaTeX can only parse string typed expression");var r=new Jn(e,t);delete r.gullet.macros.current["\\df@tag"];var a=r.parse();if(delete r.gullet.macros.current["\\current@color"],delete r.gullet.macros.current["\\color"],r.gullet.macros.get("\\df@tag")){if(!t.displayMode)throw new n("\\tag works only in display equations");a=[{type:"tag",mode:"text",body:a,tag:r.subparse([new Gr("\\df@tag")])}]}return a},ea=function(e,t,r){t.textContent="";var n=ra(e,r).toNode();t.appendChild(n)};"undefined"!=typeof document&&"CSS1Compat"!==document.compatMode&&("undefined"!=typeof console&&console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your website has a suitable doctype."),ea=function(){throw new n("KaTeX doesn't work in quirks mode.")});var ta=function(e,t,r){if(r.throwOnError||!(e instanceof n))throw e;var a=Ke.makeSpan(["katex-error"],[new Z(t)]);return a.setAttribute("title",e.toString()),a.setAttribute("style","color:"+r.errorColor),a},ra=function(e,t){var r=new m(t);try{var n=Qn(e,r);return Lt(n,e,r)}catch(t){return ta(t,e,r)}},na={version:"0.16.8",render:ea,renderToString:function(e,t){return ra(e,t).toMarkup()},ParseError:n,SETTINGS_SCHEMA:h,__parse:function(e,t){var r=new m(t);return Qn(e,r)},__renderToDomTree:ra,__renderToHTMLTree:function(e,t){var r=new m(t);try{return function(e,t,r){var n=St(e,Ot(r)),a=Ke.makeSpan(["katex"],[n]);return Et(a,r)}(Qn(e,r),0,r)}catch(t){return ta(t,e,r)}},__setFontMetrics:function(e,t){T[e]=t},__defineSymbol:ie,__defineFunction:ot,__defineMacro:Pr,__domTree:{Span:W,Anchor:_,SymbolNode:Z,SvgNode:K,PathNode:J,LineNode:Q}};return t=t.default}()})); \ No newline at end of file
diff --git a/source/know/concept/bb84-protocol/index.md b/source/know/concept/bb84-protocol/index.md
index 0f75930..44ea57d 100644
--- a/source/know/concept/bb84-protocol/index.md
+++ b/source/know/concept/bb84-protocol/index.md
@@ -48,7 +48,7 @@ $$\begin{aligned}
\end{aligned}$$
After Alice has sent all her qubits,
-the next step is **basis reconciliation**:
+the next step is *basis reconciliation*:
over the classical channel, Bob announces, for each bit,
which basis he chose, and Alice tells him if he was right or wrong.
Bob discards all bits where he guessed wrongly.
@@ -56,6 +56,7 @@ If their quantum channel did not have any noise or eavesdroppers,
Alice and Bob now have a perfectly correlated secret string of bits.
+
## Eavesdropper detection
But what if there is actually an eavesdropper?
@@ -99,6 +100,7 @@ that as long as the error rate is below 11%,
the BB84 protocol is fully secure, i.e. there cannot be any eavesdroppers.
+
## Error correction
In practice, even without Eve, quantum channels are imperfect,
@@ -125,11 +127,14 @@ $$\begin{aligned}
If $$A = B$$, then $$a_{n+1}$$ and $$b_{n+1}$$ are discarded to prevent
a listener on the classical channel from learning anything about the string.
-If $$A \neq B$$, all of $$a_n$$, $$b_n$$, $$a_{n+1}$$ and $$b_{n+1}$$ are discarded,
-and then Alice and Bob move on to $$n = 3$$, etc.
+If $$A \neq B$$, something went wrong,
+so all of $$a_n$$, $$b_n$$, $$a_{n+1}$$ and $$b_{n+1}$$ are discarded.
+Then Alice and Bob move on to $$n = 3$$, etc.
-Given that $$A = B$$, the probability that $$a_n = b_n$$,
-which is what we want, is given by:
+Given that $$A = B$$, the probability that $$a_n = b_n$$ is as shown below.
+Note that there are two possible explanations for $$A = B$$:
+either $$a_{n} = b_{n} \land a_{n+1} = b_{n+1}$$,
+or $$a_{n} \neq b_{n} \land a_{n+1} \neq b_{n+1}$$:
$$\begin{aligned}
P(a_{n} = b_{n} | A = B)
@@ -164,6 +169,7 @@ $$\begin{aligned}
More efficient schemes exist, which do not consume so many bits.
+
## Privacy amplification
Suppose that after the error correction step, $$p = 1$$,
@@ -177,10 +183,10 @@ $$\begin{aligned}
q = P(e_n = a_n) > \frac{1}{2}
\end{aligned}$$
-**Privacy amplification** is an optional final step of the BB84 protocol
-which aims to reduce Eve's $$q$$.
+*Privacy amplification* is an optional final step of the BB84 protocol
+that aims to reduce Eve's $$q$$.
Alice and Bob use their existing strings to generate a new one
-$$\{a_1', ..., a_M'\}$$:
+$$\{a_1', ..., a_M'\}$$ where:
$$\begin{aligned}
a_1'
@@ -225,6 +231,7 @@ Eve would only know 50% of the bits,
which is equivalent to her guessing at random.
+
## References
1. N. Brunner,
*Quantum information theory: lecture notes*,
diff --git a/source/know/concept/bell-state/index.md b/source/know/concept/bell-state/index.md
index fa289de..d4508e6 100644
--- a/source/know/concept/bell-state/index.md
+++ b/source/know/concept/bell-state/index.md
@@ -24,14 +24,14 @@ $$\begin{aligned}
}
\end{aligned}$$
-Where e.g. $$\ket{0}_A \ket{1}_B = \ket{0}_A \otimes \ket{1}_B$$
+Where e.g. $$\ket{0}_A \ket{1}_B \equiv \ket{0}_A \otimes \ket{1}_B$$
is the tensor product of qubit $$A$$ in state $$\ket{0}$$ and $$B$$ in $$\ket{1}$$.
These states form an orthonormal basis for the two-qubit
[Hilbert space](/know/concept/hilbert-space/).
More importantly, however,
-is that the Bell states are maximally entangled,
-which we prove here for $$\ket{\Phi^{+}}$$.
+is that all four Bell states are *maximally entangled*.
+For brevity, we will only show this for $$\ket{\Phi^{+}}$$ here.
Consider the following pure [density operator](/know/concept/density-operator/):
$$\begin{aligned}
@@ -40,7 +40,8 @@ $$\begin{aligned}
&= \frac{1}{2} \Big( \ket{0}_A \ket{0}_B + \ket{1}_A \ket{1}_B \Big) \Big( \bra{0}_A \bra{0}_B + \bra{1}_A \bra{1}_B \Big)
\end{aligned}$$
-The reduced density operator $$\hat{\rho}_A$$ of qubit $$A$$ is then calculated as follows:
+The *reduced* density operator $$\hat{\rho}_A$$ of qubit $$A$$
+is then calculated like so, using a partial trace:
$$\begin{aligned}
\hat{\rho}_A
@@ -54,12 +55,13 @@ $$\begin{aligned}
= \frac{1}{2} \hat{I}
\end{aligned}$$
-This result is maximally mixed, therefore $$\ket{\Phi^{+}}$$ is maximally entangled.
-The same holds for the other three Bell states,
-and is equally true for qubit $$B$$.
-
+The same holds for qubit $$B$$. This result is *maximally mixed*,
+therefore $$\ket{\Phi^{+}}$$ is maximally entangled.
This means that a measurement of qubit $$A$$
-has a 50-50 chance to yield $$\ket{0}$$ or $$\ket{1}$$.
+has a 50-50 chance to yield $$\ket{0}$$ or $$\ket{1}$$,
+or in other words, no useful information can be gathered
+from measuring just one of the qubits.
+
However, due to the entanglement,
measuring $$A$$ also has consequences for qubit $$B$$:
diff --git a/source/know/concept/bernstein-vazirani-algorithm/index.md b/source/know/concept/bernstein-vazirani-algorithm/index.md
index 884cca3..4f36d3c 100644
--- a/source/know/concept/bernstein-vazirani-algorithm/index.md
+++ b/source/know/concept/bernstein-vazirani-algorithm/index.md
@@ -24,8 +24,8 @@ of $$x$$ with an unknown $$N$$-bit string $$s$$:
$$\begin{aligned}
f(x)
- = s \cdot x \:\:(\bmod \: 2)
- = (s_1 x_1 + s_2 x_2 + \:...\: + s_N x_N) \:\:(\bmod \: 2)
+ \equiv s \cdot x \:\bmod 2
+ = (s_1 x_1 + s_2 x_2 + \:...\: + s_N x_N) \:\bmod 2
\end{aligned}$$
The goal is to find $$s$$.
diff --git a/source/know/concept/blochs-theorem/index.md b/source/know/concept/blochs-theorem/index.md
index d7fcf90..c6278f3 100644
--- a/source/know/concept/blochs-theorem/index.md
+++ b/source/know/concept/blochs-theorem/index.md
@@ -12,14 +12,14 @@ given a potential $$V(\vb{r})$$ which is periodic on a lattice,
i.e. $$V(\vb{r}) = V(\vb{r} + \vb{a})$$
for a primitive lattice vector $$\vb{a}$$,
then it follows that the solutions $$\psi(\vb{r})$$
-to the time-independent Schrödinger equation
-take the following form,
+to the time-independent Schrödinger equation take the following form,
where the function $$u(\vb{r})$$ is periodic on the same lattice,
i.e. $$u(\vb{r}) = u(\vb{r} + \vb{a})$$:
$$\begin{aligned}
\boxed{
- \psi(\vb{r}) = u(\vb{r}) e^{i \vb{k} \cdot \vb{r}}
+ \psi(\vb{r})
+ = u(\vb{r}) e^{i \vb{k} \cdot \vb{r}}
}
\end{aligned}$$
@@ -33,9 +33,11 @@ then both $$\psi(\vb{r})$$ and $$\psi(\vb{r} + \vb{a})$$
are eigenstates with the same energy:
$$\begin{aligned}
- \hat{H} \psi(\vb{r}) = E \psi(\vb{r})
- \qquad
- \hat{H} \psi(\vb{r} + \vb{a}) = E \psi(\vb{r} + \vb{a})
+ \hat{H} \psi(\vb{r})
+ = E \psi(\vb{r})
+ \qquad \qquad
+ \hat{H} \psi(\vb{r} + \vb{a})
+ = E \psi(\vb{r} + \vb{a})
\end{aligned}$$
Now define the unitary translation operator $$\hat{T}(\vb{a})$$ such that
@@ -52,18 +54,21 @@ $$\begin{aligned}
In other words, if $$\hat{H}$$ is lattice-periodic,
then it will commute with $$\hat{T}(\vb{a})$$,
i.e. $$[\hat{H}, \hat{T}(\vb{a})] = 0$$.
-Consequently, $$\hat{H}$$ and $$\hat{T}(\vb{a})$$ must share eigenstates $$\psi(\vb{r})$$:
+Consequently, $$\hat{H}$$ and $$\hat{T}(\vb{a})$$
+must share eigenstates $$\psi(\vb{r})$$:
$$\begin{aligned}
- \hat{H} \:\psi(\vb{r}) = E \:\psi(\vb{r})
+ \hat{H} \psi(\vb{r})
+ = E \psi(\vb{r})
\qquad \qquad
- \hat{T}(\vb{a}) \:\psi(\vb{r}) = \tau \:\psi(\vb{r})
+ \hat{T}(\vb{a}) \psi(\vb{r})
+ = \tau \psi(\vb{r})
\end{aligned}$$
Since $$\hat{T}$$ is unitary,
its eigenvalues $$\tau$$ must have the form $$e^{i \theta}$$, with $$\theta$$ real.
Therefore a translation by $$\vb{a}$$ causes a phase shift,
-for some vector $$\vb{k}$$:
+so there exists a vector $$\vb{k}$$ such that:
$$\begin{aligned}
\psi(\vb{r} + \vb{a})
diff --git a/source/know/concept/boltzmann-equation/index.md b/source/know/concept/boltzmann-equation/index.md
index 5f4add0..3821512 100644
--- a/source/know/concept/boltzmann-equation/index.md
+++ b/source/know/concept/boltzmann-equation/index.md
@@ -67,7 +67,7 @@ but unfortunately also quite difficult to work with.
In addition, $$f$$ is a 7-dimensional function,
so the BTE is already hard to solve without collisions!
We only present the simplest case,
-known as the **Bhatnagar-Gross-Krook approximation**:
+the **Bhatnagar-Gross-Krook approximation**:
if the equilibrium state $$f_0(\vb{r}, \vb{v})$$ is known,
then each collision brings the system closer to $$f_0$$:
@@ -90,14 +90,15 @@ $$\begin{aligned}
n(\vb{r}, t) = \int_{-\infty}^\infty f(\vb{r}, \vb{v}, t) \dd{\vb{v}}
\end{aligned}$$
-Consequently, a purely velocity-dependent quantity $$Q(\vb{v})$$ can be averaged like so:
+Consequently, a purely velocity-dependent quantity $$Q(\vb{v})$$
+can be averaged like so:
$$\begin{aligned}
- \Expval{Q}
- = \frac{1}{n} \int_{-\infty}^\infty Q(\vb{r}, \vb{v}, t) \: f(\vb{r}, \vb{v}, t) \dd{\vb{v}}
+ \Expval{Q}\!(\vb{r}, t)
+ = \frac{1}{n} \int_{-\infty}^\infty Q(\vb{v}) \: f(\vb{r}, \vb{v}, t) \dd{\vb{v}}
\end{aligned}$$
-With that in mind, we multiply the collisionless BTE equation by $$Q(\vb{v})$$ and integrate,
+With that in mind, we multiply the collisionless BTE by $$Q(\vb{v})$$ and integrate,
assuming that $$\vb{F}$$ does not depend on $$\vb{v}$$:
$$\begin{aligned}
@@ -136,7 +137,8 @@ $$\begin{aligned}
If we set $$Q = m$$, then the mass density $$\rho = n \Expval{Q}$$,
and we find that the **zeroth moment** of the BTE describes conservation of mass,
-where $$\vb{V} \equiv \Expval{\vb{v}} = \int \vb{v} f \dd{\vb{v}}$$ is the fluid velocity:
+where $$\vb{V} \equiv \Expval{\vb{v}} = n^{-1} \int \vb{v} f \dd{\vb{v}}$$
+is the fluid velocity:
$$\begin{aligned}
\boxed{
@@ -231,7 +233,8 @@ $$\begin{aligned}
{% include proof/start.html id="proof-moment2" -%}
-We insert $$Q = m |\vb{v}|^2 / 2$$ into our prototype and recognize $$\rho$$ wherever possible:
+We insert $$Q = m |\vb{v}|^2 / 2$$ into our prototype
+and recognize $$\rho$$ wherever possible:
$$\begin{aligned}
0
@@ -244,7 +247,8 @@ $$\begin{aligned}
- \frac{\vb{F}}{2} \cdot \bigg( n \Expval{\pdv{|\vb{v}|^2}{\vb{v}}} \bigg)
\end{aligned}$$
-We handle these terms one by one. Substituting $$\vb{v} = \vb{V} + \vb{w}$$ in the first gives:
+We handle these terms one by one.
+Substituting $$\vb{v} = \vb{V} + \vb{w}$$ in the first gives:
$$\begin{aligned}
\Expval{|\vb{v}|^2}
diff --git a/source/know/concept/bose-einstein-distribution/index.md b/source/know/concept/bose-einstein-distribution/index.md
index 5640e69..ea5ca68 100644
--- a/source/know/concept/bose-einstein-distribution/index.md
+++ b/source/know/concept/bose-einstein-distribution/index.md
@@ -14,19 +14,19 @@ which do not obey the [Pauli exclusion principle](/know/concept/pauli-exclusion-
distribute themselves across the available states
in a system at equilibrium.
-Consider a single-particle state $$s$$,
+Consider a single-particle state $$\ket{i}$$,
which can contain any number of bosons.
-Since the occupation number $$N$$ is variable,
+Since the occupation number $$n_i$$ is variable,
we use the [grand canonical ensemble](/know/concept/grand-canonical-ensemble/),
whose grand partition function $$\mathcal{Z}$$ is as shown below,
-where $$\varepsilon$$ is the energy per particle,
+where $$\varepsilon_i$$ is the energy per particle,
and $$\mu$$ is the chemical potential.
We evaluate the sum in $$\mathcal{Z}$$ as a geometric series:
$$\begin{aligned}
\mathcal{Z}
- = \sum_{N = 0}^\infty \Big( e^{-\beta (\varepsilon - \mu)} \Big)^{N}
- = \frac{1}{1 - e^{-\beta (\varepsilon - \mu)}}
+ = \sum_{m = 0}^\infty \Big( e^{-\beta (\varepsilon_i - \mu)} \Big)^{m}
+ = \frac{1}{1 - e^{-\beta (\varepsilon_i - \mu)}}
\end{aligned}$$
The corresponding [thermodynamic potential](/know/concept/thermodynamic-potential/)
@@ -35,42 +35,42 @@ is the Landau potential $$\Omega$$, given by:
$$\begin{aligned}
\Omega
= - k T \ln{\mathcal{Z}}
- = k T \ln\!\big( 1 - e^{-\beta (\varepsilon - \mu)} \big)
+ = k T \ln\!\big( 1 - e^{-\beta (\varepsilon_i - \mu)} \big)
\end{aligned}$$
-The average number of particles $$\expval{N}$$ in $$s$$
+The average number of particles $$\expval{n_i}$$ in $$\ket{i}$$
is then found by taking a derivative of $$\Omega$$:
$$\begin{aligned}
- \expval{N}
+ \expval{n_i}
= - \pdv{\Omega}{\mu}
= k T \pdv{\ln{\mathcal{Z}}}{\mu}
- = \frac{e^{-\beta (\varepsilon - \mu)}}{1 - e^{-\beta (\varepsilon - \mu)}}
+ = \frac{e^{-\beta (\varepsilon_i - \mu)}}{1 - e^{-\beta (\varepsilon_i - \mu)}}
\end{aligned}$$
-By multiplying both the numerator and the denominator by $$e^{\beta(\varepsilon \!-\! \mu)}$$,
+By multiplying both the numerator and the denominator by $$e^{\beta(\varepsilon_i - \mu)}$$,
we arrive at the standard form of the **Bose-Einstein distribution** $$f_B$$:
$$\begin{aligned}
\boxed{
- \expval{N}
- = f_B(\varepsilon)
- = \frac{1}{e^{\beta (\varepsilon - \mu)} - 1}
+ \expval{n_i}
+ = f_B(\varepsilon_i)
+ = \frac{1}{e^{\beta (\varepsilon_i - \mu)} - 1}
}
\end{aligned}$$
-This gives the expected occupation number $$\expval{N}$$
-of state $$s$$ with energy $$\varepsilon$$,
+This gives the expected occupation number $$\expval{n_i}$$
+of state $$\ket{i}$$ with energy $$\varepsilon_i$$,
given a temperature $$T$$ and chemical potential $$\mu$$.
{% comment %}
-The corresponding variance $$\sigma^2 \equiv \expval{N^2} - \expval{N}^2$$ is found to be:
+The corresponding variance $$\sigma^2 \equiv \expval{n_i^2} - \expval{n_i}^2$$ is found to be:
$$\begin{aligned}
\boxed{
\sigma^2
- = k T \pdv{\expval{N}}{\mu}
- = \expval{N} \big(1 + \expval{N}\!\big)
+ = k T \pdv{\expval{n_i}}{\mu}
+ = \expval{n_i} \big(1 + \expval{n_i}\!\big)
}
\end{aligned}$$
{% endcomment %}
diff --git a/source/know/concept/boussinesq-wave-theory/index.md b/source/know/concept/boussinesq-wave-theory/index.md
index e5fd433..b5f91e1 100644
--- a/source/know/concept/boussinesq-wave-theory/index.md
+++ b/source/know/concept/boussinesq-wave-theory/index.md
@@ -275,7 +275,7 @@ $$\begin{aligned}
\end{aligned}$$
The smallest term we will include is $$a h^2 / \lambda^3$$;
-anything smaller (specifically containing $$a^2 / \lambda^2$$) will be discarded.
+anything smaller (i.e. containing a factor of $$a^2 / \lambda^2$$) will be discarded.
Of course, this decision is arbitrary:
higher-order approximations exist for deeper water and/or taller waves,
but we stick with Boussinesq's original choice, leaving:
diff --git a/source/know/concept/canonical-ensemble/index.md b/source/know/concept/canonical-ensemble/index.md
index 8a96e91..da7d436 100644
--- a/source/know/concept/canonical-ensemble/index.md
+++ b/source/know/concept/canonical-ensemble/index.md
@@ -178,7 +178,7 @@ $$\begin{aligned}
\end{aligned}$$
Rearranging and substituting
-the [fundamental thermodynamic relation](/know/concept/fundamental-thermodynamic-relation/)
+the [fundamental thermodynamic relation](/know/concept/fundamental-relation-of-thermodynamics/)
then gives:
$$\begin{aligned}
diff --git a/source/know/concept/clausius-mossotti-relation/index.md b/source/know/concept/clausius-mossotti-relation/index.md
index a0f4916..03bdcac 100644
--- a/source/know/concept/clausius-mossotti-relation/index.md
+++ b/source/know/concept/clausius-mossotti-relation/index.md
@@ -55,7 +55,8 @@ the dipole term will be dominant in that case, given by:
$$\begin{aligned}
V_i(\vb{r})
- \approx \frac{1}{4 \pi \varepsilon_0} \frac{1}{|\vb{r}|^2} \int \rho_i(\vb{r}') \: |\vb{r}'| \cos{\theta} \dd{\vb{r}'}
+ \approx \frac{1}{4 \pi \varepsilon_0} \frac{1}{|\vb{r}|^2}
+ \int_{-\infty}^\infty \rho_i(\vb{r}') \: |\vb{r}'| \cos{\theta} \dd{\vb{r}'}
\end{aligned}$$
Where $$\theta$$ is the angle between $$\vb{r}$$ and $$\vb{r}'$$,
@@ -64,7 +65,8 @@ with the unit vector $$\vu{r}$$, normalized from $$\vb{r}$$:
$$\begin{aligned}
V_i(\vb{r})
- = \frac{1}{4 \pi \varepsilon_0} \frac{1}{|\vb{r}|^2} \: \vu{r} \cdot \!\!\int \vb{r}' \rho_i(\vb{r}') \dd{\vb{r}'}
+ = \frac{1}{4 \pi \varepsilon_0} \frac{1}{|\vb{r}|^2}
+ \: \vu{r} \cdot \!\!\int_{-\infty}^\infty \vb{r}' \rho_i(\vb{r}') \dd{\vb{r}'}
\end{aligned}$$
The integral is a more general definition of the dipole moment $$\vb{p}_i$$.
diff --git a/source/know/concept/convolution-theorem/index.md b/source/know/concept/convolution-theorem/index.md
index 3f9eafb..8462fcc 100644
--- a/source/know/concept/convolution-theorem/index.md
+++ b/source/know/concept/convolution-theorem/index.md
@@ -24,10 +24,10 @@ and $$A$$ and $$B$$ are the constants from its definition:
$$\begin{aligned}
\boxed{
\begin{aligned}
- A \cdot (f * g)(x)
+ A \: (f * g)(x)
&= \hat{\mathcal{F}}{}^{-1}\Big\{ \tilde{f}(k) \: \tilde{g}(k) \Big\}
\\
- B \cdot (\tilde{f} * \tilde{g})(k)
+ B \: (\tilde{f} * \tilde{g})(k)
&= \hat{\mathcal{F}}\Big\{ f(x) \: g(x) \Big\}
\end{aligned}
}
@@ -45,7 +45,7 @@ $$\begin{aligned}
\\
&= A \int_{-\infty}^\infty g(x') \: f(x - x') \dd{x'}
\\
- &= A \cdot (f * g)(x)
+ &= A \: (f * g)(x)
\end{aligned}$$
Then we do the same again,
@@ -59,7 +59,7 @@ $$\begin{aligned}
\\
&= B \int_{-\infty}^\infty \tilde{g}(k') \: \tilde{f}(k - k') \dd{k'}
\\
- &= B \cdot (\tilde{f} * \tilde{g})(k)
+ &= B \: (\tilde{f} * \tilde{g})(k)
\end{aligned}$$
{% include proof/end.html id="proof-fourier" %}
diff --git a/source/know/concept/coupled-mode-theory/index.md b/source/know/concept/coupled-mode-theory/index.md
index 6a5ec1b..23b6470 100644
--- a/source/know/concept/coupled-mode-theory/index.md
+++ b/source/know/concept/coupled-mode-theory/index.md
@@ -10,8 +10,8 @@ layout: "concept"
Given an optical resonator (e.g. a photonic crystal cavity),
consider one of its quasinormal modes
-with frequency $$\omega_0$$ and decay rate $$1 / \tau_0$$.
-Its complex amplitude $$A$$ is governed by:
+with frequency $$\omega_0$$ and decay rate $$1 / \tau_0$$ in isolation.
+Its complex amplitude $$A$$ then obeys:
$$\begin{aligned}
\dv{A}{t}
diff --git a/source/know/concept/debye-length/index.md b/source/know/concept/debye-length/index.md
index 5961c4f..063e308 100644
--- a/source/know/concept/debye-length/index.md
+++ b/source/know/concept/debye-length/index.md
@@ -12,8 +12,7 @@ If a charged object is put in a plasma,
it repels like charges and attracts opposite charges,
leading to a **Debye sheath** around the object's surface
with a net opposite charge.
-This has the effect of **shielding** the object's presence
-from the rest of the plasma.
+This has the effect of **shielding** the rest of the plasma from the object's presence.
We start from [Gauss' law](/know/concept/maxwells-equations/)
for the [electric field](/know/concept/electric-field/) $$\vb{E}$$,
@@ -23,12 +22,12 @@ and splitting the charge density into ions $$n_i$$ and electrons $$n_e$$:
$$\begin{aligned}
\nabla^2 \phi(\vb{r})
- = - \frac{1}{\varepsilon_0} \Big( q_i n_i(\vb{r}) + q_e n_e(\vb{r}) + q_t \delta(\vb{r}) \Big)
+ = - \frac{1}{\varepsilon_0} \Big( q_i n_i(\vb{r}) + q_e n_e(\vb{r}) + Q \delta(\vb{r}) \Big)
\end{aligned}$$
The last term represents a *test particle*,
which will be shielded.
-This particle is a point charge $$q_t$$,
+This particle is a point charge $$Q$$,
whose density is simply a [Dirac delta function](/know/concept/dirac-delta-function/) $$\delta(\vb{r})$$,
and is not included in $$n_i$$ or $$n_e$$.
@@ -63,10 +62,10 @@ where we have assumed quasi-neutrality such that $$q_i n_{i0} = q_e n_{e0}$$:
$$\begin{aligned}
\nabla^2 \phi
&= - \frac{1}{\varepsilon_0}
- \bigg( q_i n_{i0} - n_{i0} \frac{q_i^2 \phi}{k_B T_i} + q_e n_{e0} - n_{e0} \frac{q_e^2 \phi}{k_B T_e} + q_t \delta(\vb{r}) \bigg)
+ \bigg( q_i n_{i0} - n_{i0} \frac{q_i^2 \phi}{k_B T_i} + q_e n_{e0} - n_{e0} \frac{q_e^2 \phi}{k_B T_e} + Q \delta(\vb{r}) \bigg)
\\
&= \bigg( \frac{n_{i0} q_i^2}{\varepsilon_0 k_B T_i} + \frac{n_{e0} q_e^2}{\varepsilon_0 k_B T_e} \bigg) \phi
- - \frac{q_t}{\varepsilon_0} \delta(\vb{r})
+ - \frac{Q}{\varepsilon_0} \delta(\vb{r})
\end{aligned}$$
We now define the **ion** and **electron Debye lengths**
@@ -101,24 +100,27 @@ suggesting exponential decay:
$$\begin{aligned}
\nabla^2 \phi(\vb{r})
&= \frac{1}{\lambda_D^2} \phi(\vb{r})
- - \frac{q_t}{\varepsilon_0} \delta(\vb{r})
+ - \frac{Q}{\varepsilon_0} \delta(\vb{r})
\end{aligned}$$
-This has the following solution,
-known as the **Yukawa potential**,
-which decays exponentially,
-representing the plasma's **self-shielding**
-over a characteristic distance $$\lambda_D$$:
+This has the solution below, known as the **Yukawa potential**,
+which looks like Coulomb's law but with an extra exponential factor,
+representing the plasma's **self-shielding**:
$$\begin{aligned}
\boxed{
\phi(r)
- = \frac{q_t}{4 \pi \varepsilon_0 r} \exp\!\Big( \!-\!\frac{r}{\lambda_D} \Big)
+ = \frac{Q}{4 \pi \varepsilon_0 r} \exp\!\Big( \!-\!\frac{r}{\lambda_D} \Big)
}
\end{aligned}$$
+We call it *self*-shielding because in reality
+$$Q$$ is simply an electron or ion of the plasma.
+This explains why plasmas are macroscopically neutral,
+despite consisting of charged particles.
+
Note that $$r$$ is a scalar,
-i.e. the potential depends only on the radial distance to $$q_t$$.
+i.e. the potential depends only on the radial distance to $$Q$$.
This treatment only makes sense
if the plasma is sufficiently dense,
such that there is a large number of particles
diff --git a/source/know/concept/deutsch-jozsa-algorithm/index.md b/source/know/concept/deutsch-jozsa-algorithm/index.md
index 44b06ad..223877a 100644
--- a/source/know/concept/deutsch-jozsa-algorithm/index.md
+++ b/source/know/concept/deutsch-jozsa-algorithm/index.md
@@ -72,8 +72,8 @@ $$\begin{aligned}
+ \frac{1}{2} \Ket{1} \Big( \Ket{0 \oplus f(1)} - \Ket{1 \oplus f(1)} \Big)
\end{aligned}$$
-The parenthesized superpositions can be reduced.
-Assuming that $$f(b) = 0$$, we notice:
+The parenthesized superpositions can be reduced:
+let us suppose that $$f(b) = 0$$, then:
$$\begin{aligned}
\Ket{0 \oplus f(b)} - \Ket{1 \oplus f(b)}
@@ -91,7 +91,7 @@ $$\begin{aligned}
\end{aligned}$$
We can thus combine both cases, $$f(b) = 0$$ or $$f(b) = 1$$,
-into the following single expression:
+into the following expression:
$$\begin{aligned}
\Ket{0 \oplus f(b)} - \Ket{1 \oplus f(b)}
@@ -106,8 +106,8 @@ $$\begin{aligned}
\frac{1}{2} \Big( (-1)^{f(0)} \Ket{0} + (-1)^{f(1)} \Ket{1} \Big) \Big( \Ket{0} - \Ket{1} \Big)
\end{aligned}$$
-The second qubit in state $$\Ket{-}$$ is garbage; it is no longer of interest.
-The first qubit is given by:
+The second qubit in state $$\Ket{-}$$ is garbage (i.e. no longer of interest).
+The first qubit is:
$$\begin{aligned}
\frac{1}{\sqrt{2}} \Big( (-1)^{f(0)} \Ket{0} + (-1)^{f(1)} \Ket{1} \Big)
@@ -126,8 +126,8 @@ $$\begin{aligned}
\end{aligned}$$
Depending on whether $$f$$ is constant or balanced,
-the mearurement outcome of this state will be $$\Ket{0}$$ or $$\Ket{1}$$
-with 100\% probability. We have solved the problem!
+the measurement outcome of this state will be $$\Ket{0}$$ or $$\Ket{1}$$
+with 100% probability. We have solved the problem!
Note that we only consulted the oracle (i.e. applied $$U_f$$) once.
A classical computer would need to query it twice,
@@ -146,7 +146,7 @@ This algorithm is then implemented by the following quantum circuit:
alt="Deutsch-Jozsa circuit" %}
There are $$N$$ qubits in initial state $$\Ket{0}$$, and one in $$\Ket{1}$$.
-For clarity, the oracle $$U_f$$ works like so:
+The oracle $$U_f$$ performs this action:
$$\begin{aligned}
\Ket{x_1} \Ket{x_2} \cdots \Ket{x_N} \Ket{y}
@@ -167,7 +167,7 @@ $$\begin{aligned}
Where $$\Ket{x} = \Ket{x_1} \cdots \Ket{x_N}$$ denotes a classical binary state.
For example, if $$x = 5 = 2^0 + 2^2$$ in the summation,
then $$\Ket{x} = \Ket{1} \Ket{0} \Ket{1} \Ket{0}^{\otimes N-3}$$
-(from least to most significant).
+(from least to most significant digit).
We give this state to the oracle,
and, by the same logic as for the Deutsch algorithm,
@@ -217,8 +217,8 @@ we only need to measure the $$N$$ qubits once;
$$f$$ is constant if and only if all are zero.
The Deutsch-Jozsa algorithm needs only one oracle query to give an error-free result,
-whereas a classical computer needs $$2^{N-1} + 1$$ queries in the worst case;
-a revolutionary discovery.
+whereas a classical computer needs $$2^{N-1} + 1$$ queries in the worst case.
+A revolutionary discovery!
## References
diff --git a/source/know/concept/diffie-hellman-key-exchange/index.md b/source/know/concept/diffie-hellman-key-exchange/index.md
index 3525881..a6e0894 100644
--- a/source/know/concept/diffie-hellman-key-exchange/index.md
+++ b/source/know/concept/diffie-hellman-key-exchange/index.md
@@ -32,19 +32,22 @@ there is no efficient algorithm to recover $$n$$.
Suppose that Alice and Bob want to exchange encrypted data in the future,
so they need to agree on an encryption key to use.
-However, they can only exchange messages with each other over
+However, they can only exchange messages over
an insecure channel, which is being eavesdropped.
After they publicly agree on the values of $$g$$ and $$p$$,
-Alice and Bob each choose a secret number from $$\{0, ..., p \!-\! 2\}$$, respectively $$a$$ and $$b$$,
+Alice and Bob each choose a secret number from $$\{0, ..., p \!-\! 2\}$$,
+respectively $$a$$ and $$b$$,
and then privately calculate $$A$$ and $$B$$ as follows:
$$\begin{aligned}
A
- \equiv g^a \bmod p
- \qquad \qquad
+ &\equiv f(a)
+ = g^a \bmod p
+ \\
B
- \equiv g^b \bmod p
+ &\equiv f(b)
+ = g^b \bmod p
\end{aligned}$$
Finally, they transmit these numbers $$A$$ and $$B$$
@@ -69,8 +72,7 @@ but cannot recover $$a$$ or $$b$$.
This assumption is just that: an assumption.
So far, nobody has been able to prove or disprove it
for classical computation.
-However, for quantum computers,
-it has already been *dis*proven!
+However, for quantum computers, it has already been *dis*proven!
In this case, another method must be used,
for example the [BB84 protocol](/know/concept/bb84-protocol/).
diff --git a/source/know/concept/dirac-notation/index.md b/source/know/concept/dirac-notation/index.md
index 2830a33..bbf31e5 100644
--- a/source/know/concept/dirac-notation/index.md
+++ b/source/know/concept/dirac-notation/index.md
@@ -27,7 +27,8 @@ that maps kets $$\ket{V}$$ to other kets $$\ket{V'}$$.
Recall that by definition the Hilbert inner product must satisfy:
$$\begin{aligned}
- \inprod{V}{W} = \inprod{W}{V}^*
+ \inprod{V}{W}
+ = \inprod{W}{V}^*
\end{aligned}$$
So far, nothing has been said about the actual representation of bras or kets.
@@ -36,12 +37,14 @@ the corresponding bras are given by the kets' adjoints,
i.e. their transpose conjugates:
$$\begin{aligned}
- \ket{V} =
+ \ket{V}
+ =
\begin{bmatrix}
v_1 \\ \vdots \\ v_N
\end{bmatrix}
- \quad \implies \quad
- \bra{V} =
+ \qquad \implies \qquad
+ \bra{V}
+ =
\begin{bmatrix}
v_1^* & \cdots & v_N^*
\end{bmatrix}
@@ -88,8 +91,9 @@ then the bras are *functionals* $$F[u(x)]$$
that take an arbitrary function $$u(x)$$ as an argument and return a scalar:
$$\begin{aligned}
- \ket{f} = f(x)
- \quad \implies \quad
+ \ket{f}
+ = f(x)
+ \qquad \implies \qquad
\bra{f}
= F[u(x)]
= \int_a^b f^*(x) \: u(x) \dd{x}
diff --git a/source/know/concept/discrete-spectrum-summation/index.md b/source/know/concept/discrete-spectrum-summation/index.md
new file mode 100644
index 0000000..dbbd5f9
--- /dev/null
+++ b/source/know/concept/discrete-spectrum-summation/index.md
@@ -0,0 +1,77 @@
+---
+title: "Discrete spectrum summation"
+sort_title: "Discrete spectrum summation"
+date: 2026-09-02
+categories:
+- Physics
+- Quantum mechanics
+layout: "concept"
+---
+
+This article is about a trick used in many calculations,
+especially in condensed matter physics and advanced quantum mechanics,
+which, as far as I know, does not have a specific name
+(this is the best I could come up with),
+but is so common and useful that it deserves attention.
+
+Often, we find ourselves doing calculations
+about a $$D$$-dimensional system with periodic boundary conditions.
+Generally, there are two sources of such boundary conditions:
+an inherent periodicity of the system (e.g. crystals),
+and/or a need to chop up an infinite system into finite pieces
+to prevent mathematical problems (e.g. divergences).
+
+In the second case, if studying the whole infinity directly is not possible,
+we restrict ourselves to a hypercube with side $$L$$
+and $$D$$-dimensional volume $$V = L^D$$,
+with the intention to let $$L \to \infty$$ at the end.
+We then often impose periodic boundary conditions on the hypercube,
+in order to be able to use [Fourier transforms](/know/concept/fourier-transform/)
+on such a finite domain, and/or to study transport phenomena.
+This idea is trivial to generalize to "hyperrectangles"
+with different side lengths $$L_x$$, $$L_y$$, etc.
+
+In both cases, we might end up expanding functions
+from a [Hilbert space](/know/concept/hilbert-space/) defined on the hypercube
+in a basis of plane waves $$\ket{\psi_\vb{k}}$$ with wavevectors $$\vb{k}$$,
+often as the result of a Fourier transform.
+But due to the hypercube's finite size and its boundary conditions,
+those plane waves occupy a discrete set of allowed $$\vb{k}$$-values
+(whereas in an infinite system, $$\vb{k}$$ would be a continuous variable).
+
+Hence, those normalized basis waves $$\ket{\psi_\vb{k}}$$ are as follows
+in $$\vb{r}$$-space (modulo a constant phase):
+
+$$\begin{aligned}
+ \inprod{\vb{r}}{\psi_{\vb{k}}}
+ = \psi_{\vb{k}}(\vb{r})
+ = \frac{1}{\sqrt{L^D}} \exp(i \vb{k} \cdot \vb{r})
+ \qquad \qquad
+ \vb{k} = \frac{2 \pi}{L} (n_1, ..., n_D)
+\end{aligned}$$
+
+Where $$n_1, ..., n_D \in \mathbb{Z}$$.
+The discreteness is typically an artifact of our mathematical setup,
+and then disappears into the true continuous spectrum for $$L \to \infty$$.
+Until then, every plane wave occupies a nonzero volume
+$$(2 \pi)^D / L^D$$ in $$\vb{k}$$-space.
+
+Here is the key: as $$L$$ increases, the allowed $$\vb{k}$$-values become denser,
+until any sum over those $$\vb{k}$$ turns into a Riemann integral:
+
+$$\begin{aligned}
+ \lim_{L \to \infty} \frac{(2 \pi)^D}{L^D} \sum_{\vb{k}} f(\vb{k})
+ = \int_{-\infty}^\infty f(\vb{k}) \dd{\vb{k}}
+\end{aligned}$$
+
+Where $$(2 \pi) / L$$ is the spacing between $$\vb{k}$$-values.
+This trick to convert nasty sums to easier integrals
+is used all over physics because it is so powerful.
+We can even get away with postponing taking the limit,
+and doing the conversion as an exact equality in the middle of our calculation,
+on the condition that we take $$L \to \infty$$ at the end.
+
+Actually, this trick is not exclusive to periodic boundary conditions,
+but is also valid for Dirichlet ("particle in a box") boundaries,
+in which case the wavevector spectrum is discrete too,
+also with constant spacing between allowed $$\vb{k}$$-values.
diff --git a/source/know/concept/dyson-equation/index.md b/source/know/concept/dyson-equation/index.md
index ae9eb35..03be06f 100644
--- a/source/know/concept/dyson-equation/index.md
+++ b/source/know/concept/dyson-equation/index.md
@@ -25,8 +25,8 @@ $$\begin{aligned}
= \delta(\vb{r} - \vb{r}') \: \delta(t - t')
\end{aligned}$$
-From this, we define the inverse $$\hat{G}{}_0^{-1}(\vb{r}, t)$$
-as follows, so that $$\hat{G}{}_0^{-1} G_0 = \delta(\vb{r} \!-\! \vb{r}') \: \delta(t \!-\! t')$$:
+From this, we define the inverse $$\hat{G}{}_0^{-1}(\vb{r}, t)$$ as follows,
+so that $$\hat{G}{}_0^{-1} G_0 = \delta(\vb{r} \!-\! \vb{r}') \: \delta(t \!-\! t')$$:
$$\begin{aligned}
\hat{G}{}_0^{-1}(\vb{r}, t)
@@ -35,16 +35,15 @@ $$\begin{aligned}
Note that $$\hat{G}{}_0^{-1}$$ is an operator, while $$G_0$$ is a function.
For the sake of consistency, we thus define
-the operator $$\hat{G}_0(\vb{r}, t)$$
-as a multiplication by $$G_0$$
-and integration over $$\vb{r}'$$ and $$t'$$:
+its operator version $$\hat{G}_0(\vb{r}, t)$$
+as a multiplication by $$G_0$$ and integration over $$\vb{r}'$$ and $$t'$$:
$$\begin{aligned}
\hat{G}_0(\vb{r}, t) \: f
- \equiv \iint_{-\infty}^\infty G_0(\vb{r}, t; \vb{r}', t') \: f(\vb{r}', t') \: \dd{\vb{r}}' \dd{t'}
+ \equiv \iint_{-\infty}^\infty G_0(\vb{r}, t; \vb{r}', t') \: f(\vb{r}', t') \dd{\vb{r}}' \dd{t'}
\end{aligned}$$
-For an arbitrary function $$f(\vb{r}, t)$$,
+Where $$f(\vb{r}, t)$$ is an arbitrary function,
so that $$\hat{G}{}_0^{-1} \hat{G}_0 = \hat{G}_0 \hat{G}{}_0^{-1} = 1$$.
Moving on, the Schrödinger equation can be rewritten like so,
using $$\hat{G}{}_0^{-1}$$:
@@ -61,7 +60,7 @@ by solving the defining equation above.
Suppose we now add a more complicated and
possibly time-dependent term $$\hat{H}_1(\vb{r}, t)$$,
in which case the corresponding fundamental solution
-$$G(\vb{r}, \vb{r}', t, t')$$ satisfies:
+$$G(\vb{r}, \vb{r}', t, t')$$ (note the lack of a $$0$$ subscript) satisfies:
$$\begin{aligned}
\delta(\vb{r} - \vb{r}') \: \delta(t - t')
@@ -72,7 +71,7 @@ $$\begin{aligned}
This equation is typically too complicated to solve,
so we would like an easier way to calculate this new $$G$$.
-The perturbed wavefunction $$\Psi(\vb{r}, t)$$
+Clearly, the perturbed wavefunction $$\Psi(\vb{r}, t)$$
satisfies the Schrödinger equation:
$$\begin{aligned}
@@ -80,9 +79,8 @@ $$\begin{aligned}
= 0
\end{aligned}$$
-We know that $$\hat{G}{}_0^{-1} \Psi_0 = 0$$,
-which we put on the right,
-and then we apply $$\hat{G}_0$$ in front:
+We know that $$\hat{G}{}_0^{-1} \Psi_0 = 0$$ from earlier,
+which we put on the right, and then apply $$\hat{G}_0$$ to it:
$$\begin{aligned}
\hat{G}_0^{-1} \Psi - \hat{H}_1 \Psi
@@ -110,7 +108,8 @@ $$\begin{aligned}
\end{aligned}$$
The parenthesized expression clearly has the same recursive pattern,
-so we denote it by $$\hat{G}$$ and write the so-called **Dyson equation**:
+so we denote it by $$\hat{G}$$ (an operator, not the function $$G$$)
+and write the so-called **Dyson equation**:
$$\begin{aligned}
\boxed{
@@ -133,8 +132,8 @@ $$\begin{aligned}
This relation is equivalent to the Schrödinger equation.
So now we have the operator $$\hat{G}(\vb{r}, t)$$,
but what about the fundamental solution function $$G(\vb{r}, t; \vb{r}', t')$$?
-Let us take its definition, multiply it by an arbitrary $$f(\vb{r}, t)$$,
-and integrate over $$G$$'s second argument pair:
+Let us take the latter's definition and multiply it by an arbitrary $$f(\vb{r}, t)$$,
+and then integrate over $$G$$'s second argument pair:
$$\begin{aligned}
\iint \big( \hat{G}{}_0^{-1} \!-\! \hat{H}_1 \big) G(\vb{r}', t') \: f(\vb{r}', t') \dd{\vb{r}'} \dd{t'}
@@ -143,8 +142,7 @@ $$\begin{aligned}
\end{aligned}$$
Where we have hidden the arguments $$(\vb{r}, t)$$ for brevity.
-We now apply $$\hat{G}_0(\vb{r}, t)$$ to this equation
-(which contains an integral over $$t''$$ independent of $$t'$$):
+We apply $$\hat{G}_0(\vb{r}, t)$$ to this equation:
$$\begin{aligned}
\hat{G}_0 f
@@ -154,8 +152,10 @@ $$\begin{aligned}
\end{aligned}$$
Here, the shape of Dyson's equation is clearly recognizable,
-so we conclude that, as expected, the operator $$\hat{G}$$
-is defined as multiplication by the function $$G$$ followed by integration:
+so we conclude that the operator $$\hat{G}$$
+is defined as multiplication by the function $$G$$ followed by integration,
+exactly analogously to $$\hat{G}_0$$ and $$G_0$$,
+which should not be a big surprise:
$$\begin{aligned}
\hat{G}(\vb{r}, t) \: f(\vb{r}, t)
diff --git a/source/know/concept/electric-dipole-approximation/index.md b/source/know/concept/electric-dipole-approximation/index.md
index 06f0f45..393b875 100644
--- a/source/know/concept/electric-dipole-approximation/index.md
+++ b/source/know/concept/electric-dipole-approximation/index.md
@@ -138,10 +138,10 @@ $$\begin{aligned}
\\
&= - (- i i) q \omega_0 \vu{x} \cdot \vb{A}_0 \exp(- i \omega t)
\\
- &\approx - \vu{d} \cdot \vb{E}_0 \exp(- i \omega t)
+ &\approx - \vu{p} \cdot \vb{E}_0 \exp(- i \omega t)
\end{aligned}$$
-Where $$\vu{d} \equiv q \vu{x}$$ is
+Where $$\vu{p} \equiv q \vu{x}$$ is
the **transition dipole moment operator** of the electron,
hence the name *electric dipole approximation*.
Finally, we take the real part, yielding:
@@ -150,7 +150,7 @@ $$\begin{aligned}
\boxed{
\begin{aligned}
\hat{H}_1(t)
- &= - \vu{d} \cdot \vb{E}(t)
+ &= - \vu{p} \cdot \vb{E}(t)
\\
&= - q \vu{x} \cdot \vb{E}_0 \cos(\omega t)
\end{aligned}
diff --git a/source/know/concept/electromagnetic-wave-equation/index.md b/source/know/concept/electromagnetic-wave-equation/index.md
index a27fe6f..559d943 100644
--- a/source/know/concept/electromagnetic-wave-equation/index.md
+++ b/source/know/concept/electromagnetic-wave-equation/index.md
@@ -1,7 +1,7 @@
---
title: "Electromagnetic wave equation"
sort_title: "Electromagnetic wave equation"
-date: 2021-09-09
+date: 2024-09-08 # Originally 2021-09-09, major rewrite
categories:
- Physics
- Electromagnetism
@@ -9,236 +9,281 @@ categories:
layout: "concept"
---
-The electromagnetic wave equation describes
-the propagation of light through various media.
-Since an electromagnetic (light) wave consists of
+Light, i.e. **electromagnetic waves**, consist of
an [electric field](/know/concept/electric-field/)
and a [magnetic field](/know/concept/magnetic-field/),
-we need [Maxwell's equations](/know/concept/maxwells-equations/)
-in order to derive the wave equation.
+one inducing the other and vice versa.
+The existence and classical behavior of such waves
+can be derived using only [Maxwell's equations](/know/concept/maxwells-equations/),
+as we will demonstrate here.
-
-## Uniform medium
-
-We will use all of Maxwell's equations,
-but we start with Ampère's circuital law for the "free" fields $$\vb{H}$$ and $$\vb{D}$$,
-in the absence of a free current $$\vb{J}_\mathrm{free} = 0$$:
-
-$$\begin{aligned}
- \nabla \cross \vb{H}
- = \pdv{\vb{D}}{t}
-\end{aligned}$$
-
-We assume that the medium is isotropic, linear,
-and uniform in all of space, such that:
+We start from Faraday's law of induction,
+where we assume that the system consists of materials
+with well-known (linear) relative magnetic permeabilities $$\mu_r(\vb{r})$$,
+such that $$\vb{B} = \mu_0 \mu_r \vb{H}$$:
$$\begin{aligned}
- \vb{D} = \varepsilon_0 \varepsilon_r \vb{E}
- \qquad \quad
- \vb{H} = \frac{1}{\mu_0 \mu_r} \vb{B}
+ \nabla \cross \vb{E}
+ = - \pdv{\vb{B}}{t}
+ = - \mu_0 \mu_r \pdv{\vb{H}}{t}
\end{aligned}$$
-Which, upon insertion into Ampère's law,
-yields an equation relating $$\vb{B}$$ and $$\vb{E}$$.
-This may seem to contradict Ampère's "total" law,
-but keep in mind that $$\vb{J}_\mathrm{bound} \neq 0$$ here:
+We move $$\mu_r(\vb{r})$$ to the other side,
+take the curl, and insert Ampère's circuital law:
$$\begin{aligned}
- \nabla \cross \vb{B}
- = \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdv{\vb{E}}{t}
+ \nabla \cross \bigg( \frac{1}{\mu_r} \nabla \cross \vb{E} \bigg)
+ &= - \mu_0 \pdv{}{t} \big( \nabla \cross \vb{H} \big)
+ \\
+ &= - \mu_0 \bigg( \pdv{\vb{J}_\mathrm{free}}{t} + \pdvn{2}{\vb{D}}{t} \bigg)
\end{aligned}$$
-Now we take the curl, rearrange,
-and substitute $$\nabla \cross \vb{E}$$ according to Faraday's law:
+For simplicity, we only consider insulating materials,
+since light propagation in conductors is a complex beast.
+We thus assume that there are no free currents $$\vb{J}_\mathrm{free} = 0$$, leaving:
$$\begin{aligned}
- \nabla \cross (\nabla \cross \vb{B})
- = \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdv{}{t}(\nabla \cross \vb{E})
- = - \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{B}}{t}
+ \nabla \cross \bigg( \frac{1}{\mu_r} \nabla \cross \vb{E} \bigg)
+ &= - \mu_0 \pdvn{2}{\vb{D}}{t}
\end{aligned}$$
-Using a vector identity, we rewrite the leftmost expression,
-which can then be reduced thanks to Gauss' law for magnetism $$\nabla \cdot \vb{B} = 0$$:
+Having $$\vb{E}$$ and $$\vb{D}$$ in the same equation is not ideal,
+so we should make a choice:
+do we restrict ourselves to linear media
+(so $$\vb{D} = \varepsilon_0 \varepsilon_r \vb{E}$$),
+or do we allow materials with more complicated responses
+(so $$\vb{D} = \varepsilon_0 \vb{E} + \vb{P}$$, with $$\vb{P}$$ unspecified)?
+The former is usually sufficient:
$$\begin{aligned}
- - \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{B}}{t}
- &= \nabla (\nabla \cdot \vb{B}) - \nabla^2 \vb{B}
- = - \nabla^2 \vb{B}
+ \boxed{
+ \nabla \cross \bigg( \frac{1}{\mu_r} \nabla \cross \vb{E} \bigg)
+ = - \mu_0 \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{E}}{t}
+ }
\end{aligned}$$
-This describes $$\vb{B}$$.
-Next, we repeat the process for $$\vb{E}$$:
-taking the curl of Faraday's law yields:
+This is the general linear form of the **electromagnetic wave equation**,
+where $$\mu_r$$ and $$\varepsilon_r$$
+both depend on $$\vb{r}$$ in order to describe the structure of the system.
+We can obtain a similar equation for $$\vb{H}$$,
+by starting from Ampère's law under the same assumptions:
$$\begin{aligned}
- \nabla \cross (\nabla \cross \vb{E})
- = - \pdv{}{t}(\nabla \cross \vb{B})
- = - \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{E}}{t}
+ \nabla \cross \vb{H}
+ = \pdv{\vb{D}}{t}
+ = \varepsilon_0 \varepsilon_r \pdv{\vb{E}}{t}
\end{aligned}$$
-Which can be rewritten using same vector identity as before,
-and then reduced by assuming that there is no net charge density $$\rho = 0$$
-in Gauss' law, such that $$\nabla \cdot \vb{E} = 0$$:
+Taking the curl and substituting Faraday's law on the right yields:
$$\begin{aligned}
- - \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{E}}{t}
- &= \nabla (\nabla \cdot \vb{E}) - \nabla^2 \vb{E}
- = - \nabla^2 \vb{E}
+ \nabla \cross \bigg( \frac{1}{\varepsilon_r} \nabla \cross \vb{H} \bigg)
+ &= \varepsilon_0 \pdv{}{t} \big( \nabla \cross \vb{E} \big)
+ = - \varepsilon_0 \pdvn{2}{\vb{B}}{t}
\end{aligned}$$
-We thus arrive at the following two (implicitly coupled)
-wave equations for $$\vb{E}$$ and $$\vb{B}$$,
-where we have defined the phase velocity $$v \equiv 1 / \sqrt{\mu_0 \mu_r \varepsilon_0 \varepsilon_r}$$:
+And then we insert $$\vb{B} = \mu_0 \mu_r \vb{H}$$ to get the analogous
+electromagnetic wave equation for $$\vb{H}$$:
$$\begin{aligned}
\boxed{
- \pdvn{2}{\vb{E}}{t} - \frac{1}{v^2} \nabla^2 \vb{E}
- = 0
- }
- \qquad \quad
- \boxed{
- \pdvn{2}{\vb{B}}{t} - \frac{1}{v^2} \nabla^2 \vb{B}
- = 0
+ \nabla \cross \bigg( \frac{1}{\varepsilon_r} \nabla \cross \vb{H} \bigg)
+ = - \mu_0 \varepsilon_0 \mu_r \pdvn{2}{\vb{H}}{t}
}
\end{aligned}$$
-Traditionally, it is said that the solutions are as follows,
-where the wavenumber $$|\vb{k}| = \omega / v$$:
+This is equivalent to the problem for $$\vb{E}$$,
+since they are coupled by Maxwell's equations.
+By solving either, subject to Gauss's laws
+$$\nabla \cdot (\varepsilon_r \vb{E}) = 0$$ and $$\nabla \cdot (\mu_r \vb{H}) = 0$$,
+the behavior of light in a given system can be deduced.
+Note that Gauss's laws enforce that the wave's fields are transverse,
+i.e. they must be perpendicular to the propagation direction.
-$$\begin{aligned}
- \vb{E}(\vb{r}, t)
- &= \vb{E}_0 \exp(i \vb{k} \cdot \vb{r} - i \omega t)
- \\
- \vb{B}(\vb{r}, t)
- &= \vb{B}_0 \exp(i \vb{k} \cdot \vb{r} - i \omega t)
-\end{aligned}$$
-In fact, thanks to linearity, these **plane waves** can be treated as
-terms in a Fourier series, meaning that virtually
-*any* function $$f(\vb{k} \cdot \vb{r} - \omega t)$$ is a valid solution.
-Keep in mind that in reality $$\vb{E}$$ and $$\vb{B}$$ are real,
-so although it is mathematically convenient to use plane waves,
-in the end you will need to take the real part.
+## Homogeneous linear media
+In the special case where the medium is completely uniform,
+$$\mu_r$$ and $$\varepsilon_r$$ no longer depend on $$\vb{r}$$,
+so they can be moved to the other side:
-## Non-uniform medium
+$$\begin{aligned}
+ \nabla \cross \big( \nabla \cross \vb{E} \big)
+ &= - \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{E}}{t}
+ \\
+ \nabla \cross \big( \nabla \cross \vb{H} \big)
+ &= - \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{H}}{t}
+\end{aligned}$$
-A useful generalization is to allow spatial change
-in the relative permittivity $$\varepsilon_r(\vb{r})$$
-and the relative permeability $$\mu_r(\vb{r})$$.
-We still assume that the medium is linear and isotropic, so:
+This can be rewritten using the vector identity
+$$\nabla \cross (\nabla \cross \vb{V}) = \nabla (\nabla \cdot \vb{V}) - \nabla^2 \vb{V}$$:
$$\begin{aligned}
- \vb{D}
- = \varepsilon_0 \varepsilon_r(\vb{r}) \vb{E}
- \qquad \quad
- \vb{B}
- = \mu_0 \mu_r(\vb{r}) \vb{H}
+ \nabla (\nabla \cdot \vb{E}) - \nabla^2 \vb{E}
+ &= - \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{E}}{t}
+ \\
+ \nabla (\nabla \cdot \vb{H}) - \nabla^2 \vb{H}
+ &= - \mu_0 \mu_r \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{H}}{t}
\end{aligned}$$
-Inserting these expressions into Faraday's and Ampère's laws
-respectively yields:
+Which can be reduced using Gauss's laws
+$$\nabla \cdot \vb{E} = 0$$ and $$\nabla \cdot \vb{H} = 0$$
+thanks to the fact that $$\varepsilon_r$$ and $$\mu_r$$ are constants in this case.
+We therefore arrive at:
$$\begin{aligned}
- \nabla \cross \vb{E}
- = - \mu_0 \mu_r(\vb{r}) \pdv{\vb{H}}{t}
- \qquad \quad
- \nabla \cross \vb{H}
- = \varepsilon_0 \varepsilon_r(\vb{r}) \pdv{\vb{E}}{t}
+ \boxed{
+ \nabla^2 \vb{E} - \frac{n^2}{c^2} \pdvn{2}{\vb{E}}{t}
+ = 0
+ }
\end{aligned}$$
-We then divide Ampère's law by $$\varepsilon_r(\vb{r})$$,
-take the curl, and substitute Faraday's law, giving:
-
$$\begin{aligned}
- \nabla \cross \Big( \frac{1}{\varepsilon_r} \nabla \cross \vb{H} \Big)
- = \varepsilon_0 \pdv{}{t}(\nabla \cross \vb{E})
- = - \mu_0 \mu_r \varepsilon_0 \pdvn{2}{\vb{H}}{t}
+ \boxed{
+ \nabla^2 \vb{H} - \frac{n^2}{c^2} \pdvn{2}{\vb{H}}{t}
+ = 0
+ }
\end{aligned}$$
-Next, we exploit linearity by decomposing $$\vb{H}$$ and $$\vb{E}$$
-into Fourier series, with terms given by:
+Where $$c = 1 / \sqrt{\mu_0 \varepsilon_0}$$ is the speed of light in a vacuum,
+and $$n = \sqrt{\mu_0 \varepsilon_0}$$ is the refractive index of the medium.
+Note that most authors write the magnetic equation with $$\vb{B}$$ instead of $$\vb{H}$$;
+both are correct thanks to linearity.
+
+In a vacuum, where $$n = 1$$, these equations are sometimes written as
+$$\square \vb{E} = 0$$ and $$\square \vb{H} = 0$$,
+where $$\square$$ is the **d'Alembert operator**, defined as follows:
$$\begin{aligned}
- \vb{H}(\vb{r}, t)
- = \vb{H}(\vb{r}) \exp(- i \omega t)
- \qquad \quad
- \vb{E}(\vb{r}, t)
- = \vb{E}(\vb{r}) \exp(- i \omega t)
+ \boxed{
+ \square
+ \equiv \nabla^2 - \frac{1}{c^2} \pdvn{2}{}{t}
+ }
\end{aligned}$$
-By inserting this ansatz into the equation,
-we can remove the explicit time dependence:
+Note that some authors define it with the opposite sign.
+In any case, the d'Alembert operator is important for special relativity.
+
+The solution to the homogeneous electromagnetic wave equation
+are traditionally said to be the so-called **plane waves** given by:
$$\begin{aligned}
- \nabla \cross \Big( \frac{1}{\varepsilon_r} \nabla \cross \vb{H} \Big) \exp(- i \omega t)
- = \mu_0 \varepsilon_0 \omega^2 \mu_r \vb{H} \exp(- i \omega t)
+ \vb{E}(\vb{r}, t)
+ &= \vb{E}_0 e^{i \vb{k} \cdot \vb{r} - i \omega t}
+ \\
+ \vb{B}(\vb{r}, t)
+ &= \vb{B}_0 e^{i \vb{k} \cdot \vb{r} - i \omega t}
\end{aligned}$$
-Dividing out $$\exp(- i \omega t)$$,
-we arrive at an eigenvalue problem for $$\omega^2$$,
-with $$c = 1 / \sqrt{\mu_0 \varepsilon_0}$$:
+Where the wavevector $$\vb{k}$$ is arbitrary,
+and the angular frequency $$\omega = c |\vb{k}| / n$$.
+We also often talk about the wavelength, which is $$\lambda = 2 \pi / |\vb{k}|$$.
+The appearance of $$\vb{k}$$ in the exponent
+tells us that these waves are propagating through space,
+as you would expect.
+
+In fact, because the wave equations are linear,
+any superposition of plane waves,
+i.e. any function of the form $$f(\vb{k} \cdot \vb{r} - \omega t)$$,
+is in fact a valid solution.
+Just remember that $$\vb{E}$$ and $$\vb{H}$$ are real-valued,
+so it may be necessary to take the real part at the end of a calculation.
+
+
+
+## Inhomogeneous linear media
+
+But suppose the medium is not uniform, i.e. it contains structures
+described by $$\varepsilon_r(\vb{r})$$ and $$\mu_r(\vb{r})$$.
+If the structures are much larger than the light's wavelength,
+the homogeneous equation is still a very good approximation
+away from any material boundaries;
+anywhere else, however, they will break down.
+Recall the general equations from before we assumed homogeneity:
$$\begin{aligned}
- \boxed{
- \nabla \cross \Big( \frac{1}{\varepsilon_r(\vb{r})} \nabla \cross \vb{H}(\vb{r}) \Big)
- = \Big( \frac{\omega}{c} \Big)^2 \mu_r(\vb{r}) \vb{H}(\vb{r})
- }
+ \nabla \cross \bigg( \frac{1}{\mu_r} \nabla \cross \vb{E} \bigg)
+ &= - \frac{\varepsilon_r}{c^2} \pdvn{2}{\vb{E}}{t}
+ \\
+ \nabla \cross \bigg( \frac{1}{\varepsilon_r} \nabla \cross \vb{H} \bigg)
+ &= - \frac{\mu_r}{c^2} \pdvn{2}{\vb{H}}{t}
\end{aligned}$$
-Compared to a uniform medium, $$\omega$$ is often not arbitrary here:
-there are discrete eigenvalues $$\omega$$,
-corresponding to discrete **modes** $$\vb{H}(\vb{r})$$.
+In theory, this is everything we need,
+but in most cases a better approach is possible:
+the trick is that we only rarely need to explicitly calculate
+the $$t$$-dependence of $$\vb{E}$$ or $$\vb{H}$$.
+Instead, we can first solve an easier time-independent version
+of this problem, and then approximate the dynamics
+with [coupled mode theory](/know/concept/coupled-mode-theory/) later.
-Next, we go through the same process to find an equation for $$\vb{E}$$.
-Starting from Faraday's law, we divide by $$\mu_r(\vb{r})$$,
-take the curl, and insert Ampère's law:
+To eliminate $$t$$, we make an ansatz for $$\vb{E}$$ and $$\vb{H}$$, shown below.
+No generality is lost by doing this;
+this is effectively a kind of [Fourier transform](/know/concept/fourier-transform/):
$$\begin{aligned}
- \nabla \cross \Big( \frac{1}{\mu_r} \nabla \cross \vb{E} \Big)
- = - \mu_0 \pdv{}{t}(\nabla \cross \vb{H})
- = - \mu_0 \varepsilon_0 \varepsilon_r \pdvn{2}{\vb{E}}{t}
+ \vb{E}(\vb{r}, t)
+ &= \vb{E}(\vb{r}) e^{- i \omega t}
+ \\
+ \vb{H}(\vb{r}, t)
+ &= \vb{H}(\vb{r}) e^{- i \omega t}
\end{aligned}$$
-Then, by replacing $$\vb{E}(\vb{r}, t)$$ with our plane-wave ansatz,
-we remove the time dependence:
+Inserting this ansatz and dividing out $$e^{-i \omega t}$$
+yields the time-independent forms:
$$\begin{aligned}
- \nabla \cross \Big( \frac{1}{\mu_r} \nabla \cross \vb{E} \Big) \exp(- i \omega t)
- = - \mu_0 \varepsilon_0 \omega^2 \varepsilon_r \vb{E} \exp(- i \omega t)
+ \boxed{
+ \nabla \cross \bigg( \frac{1}{\mu_r} \nabla \cross \vb{E} \bigg)
+ = \Big( \frac{\omega}{c} \Big)^2 \varepsilon_r \vb{E}
+ }
\end{aligned}$$
-Which, after dividing out $$\exp(- i \omega t)$$,
-yields an analogous eigenvalue problem with $$\vb{E}(r)$$:
-
$$\begin{aligned}
\boxed{
- \nabla \cross \Big( \frac{1}{\mu_r(\vb{r})} \nabla \cross \vb{E}(\vb{r}) \Big)
- = \Big( \frac{\omega}{c} \Big)^2 \varepsilon_r(\vb{r}) \vb{E}(\vb{r})
+ \nabla \cross \bigg( \frac{1}{\varepsilon_r} \nabla \cross \vb{H} \bigg)
+ = \Big( \frac{\omega}{c} \Big)^2 \mu_r \vb{H}
}
\end{aligned}$$
-Usually, it is a reasonable approximation
-to say $$\mu_r(\vb{r}) = 1$$,
-in which case the equation for $$\vb{H}(\vb{r})$$
-becomes a Hermitian eigenvalue problem,
-and is thus easier to solve than for $$\vb{E}(\vb{r})$$.
+These are eigenvalue problems for $$\omega^2$$,
+which can be solved subject to Gauss's laws and suitable boundary conditions.
+The resulting allowed values of $$\omega$$ may consist of
+continuous ranges and/or discrete resonances,
+analogous to *scattering* and *bound* quantum states, respectively.
+It can be shown that the operators on both sides of each equation
+are Hermitian, meaning these are well-behaved problems
+yielding real eigenvalues and orthogonal eigenfields.
-Keep in mind, however, that in any case,
-the solutions $$\vb{H}(\vb{r})$$ and/or $$\vb{E}(\vb{r})$$
-must satisfy the two Maxwell's equations that were not explicitly used:
+Both equations are still equivalent:
+we only need to solve one. But which one?
+In practice, one is usually easier than the other,
+due to the common approximation that $$\mu_r \approx 1$$ for many dielectric materials,
+in which case the equations reduce to:
$$\begin{aligned}
- \nabla \cdot (\varepsilon_r \vb{E}) = 0
- \qquad \quad
- \nabla \cdot (\mu_r \vb{H}) = 0
+ \nabla \cross \big( \nabla \cross \vb{E} \big)
+ &= \Big( \frac{\omega}{c} \Big)^2 \varepsilon_r \vb{E}
+ \\
+ \nabla \cross \bigg( \frac{1}{\varepsilon_r} \nabla \cross \vb{H} \bigg)
+ &= \Big( \frac{\omega}{c} \Big)^2 \vb{H}
\end{aligned}$$
-This is equivalent to demanding that the resulting waves are *transverse*,
-or in other words,
-the wavevector $$\vb{k}$$ must be perpendicular to
-the amplitudes $$\vb{H}_0$$ and $$\vb{E}_0$$.
+Now the equation for $$\vb{H}$$ is starting to look simpler,
+because it only has an operator on *one* side.
+We could "fix" the equation for $$\vb{E}$$ by dividing it by $$\varepsilon_r$$,
+but the resulting operator would no longer be Hermitian,
+and hence not well-behaved.
+To get an idea of how to handle $$\varepsilon_r$$ in the $$\vb{E}$$-equation,
+notice its similarity to the weight function $$w$$
+in [Sturm-Liouville theory](/know/concept/sturm-liouville-theory/).
+
+Gauss's magnetic law $$\nabla \cdot \vb{H} = 0$$
+is also significantly easier for numerical calculations
+than its electric counterpart $$\nabla \cdot (\varepsilon_r \vb{E}) = 0$$,
+so we usually prefer to solve the equation for $$\vb{H}$$.
+
## References
diff --git a/source/know/concept/equation-of-motion-theory/index.md b/source/know/concept/equation-of-motion-theory/index.md
index c1ed8da..76cee81 100644
--- a/source/know/concept/equation-of-motion-theory/index.md
+++ b/source/know/concept/equation-of-motion-theory/index.md
@@ -100,7 +100,8 @@ $$\begin{aligned}
\\
&= \sum_{\nu' \nu''} u_{\nu' \nu''} \Big( \delta_{\nu \nu'} \hat{f}_{\!\nu''}
- 2 \acomm{\hat{f}_{\!\nu'}^\dagger}{\hat{f}_{\!\nu}} \hat{f}_{\!\nu''} \Big)
- = - \sum_{\nu''} u_{\nu \nu''} \hat{f}_{\!\nu''}
+ \\
+ &= - \sum_{\nu''} u_{\nu \nu''} \hat{f}_{\!\nu''}
\end{aligned}$$
{% include proof/end.html id="proof-commutator" %}
@@ -160,7 +161,7 @@ $$\begin{aligned}
\end{aligned}$$
We take the [Fourier transform](/know/concept/fourier-transform/)
-$$(t \!-\! t') \to (\omega + i \eta)$$, where $$\eta \to 0^+$$ ensures convergence:
+$$(t - t') \to (\omega + i \eta)$$, where $$\eta \to 0^+$$ ensures convergence:
$$\begin{aligned}
\sum_{\nu''} \Big( \hbar \delta_{\nu \nu''} (\omega + i \eta) - u_{\nu \nu''} \Big) G^R_{\nu'' \nu'}(\omega)
@@ -178,7 +179,7 @@ $$\begin{aligned}
\end{aligned}$$
For a non-interacting, time-independent Hamiltonian,
-we therefore arrive at:
+we thus arrive at the famous result:
$$\begin{aligned}
\boxed{
diff --git a/source/know/concept/euler-equations/index.md b/source/know/concept/euler-equations/index.md
index 2654d2b..415e2f1 100644
--- a/source/know/concept/euler-equations/index.md
+++ b/source/know/concept/euler-equations/index.md
@@ -146,7 +146,7 @@ When the fluid gets compressed in a certain location, thermodynamics
states that the pressure, temperature and/or entropy must increase there.
For simplicity, let us assume an *isothermal* and *isentropic* fluid,
such that only $$p$$ is affected by compression, and the
-[fundamental thermodynamic relation](/know/concept/fundamental-thermodynamic-relation/)
+[fundamental thermodynamic relation](/know/concept/fundamental-relation-of-thermodynamics/)
reduces to $$\dd{E} = - p \dd{V}$$.
Then the pressure is given by a thermodynamic equation of state $$p(\rho, T)$$,
diff --git a/source/know/concept/fabry-perot-cavity/index.md b/source/know/concept/fabry-perot-cavity/index.md
index d5ea0ea..c648549 100644
--- a/source/know/concept/fabry-perot-cavity/index.md
+++ b/source/know/concept/fabry-perot-cavity/index.md
@@ -10,11 +10,13 @@ layout: "concept"
---
In its simplest form, a **Fabry-Pérot cavity**
-is a region of light-transmitting medium surrounded by two mirrors,
-which may transmit some of the incoming light.
-Such a setup can be used as e.g. an interferometer or a laser cavity.
+is a region of light-transmitting medium surrounded by two parallel mirrors,
+which may let some of the light escape.
+Such a setup can be used as e.g. a laser cavity or an interferometer.
+Below, we treat this simple system as an exercise
+for calculating *quasinormal modes* in 1D,
+i.e. modes with complex resonances.
-Below, we calculate its quasinormal modes in 1D.
We divide the $$x$$-axis into three domains: left $$L$$, center $$C$$, and right $$R$$.
The cavity $$C$$ has length $$\ell$$ and is centered on $$x = 0$$.
Let $$n_L$$, $$n_C$$ and $$n_R$$ be the respective domains' refractive indices:
@@ -95,8 +97,8 @@ $$\begin{aligned}
\end{bmatrix}
\end{aligned}$$
-We do not want to simply satisfy this equation
-by setting $$A_1$$, $$A_2$$, $$A_3$$ and $$A_4$$,
+We do not want to satisfy this equation
+by simply setting $$A_1$$, $$A_2$$, $$A_3$$ and $$A_4$$,
so we demand that the system matrix is not invertible,
i.e. its determinant is zero:
@@ -116,7 +118,9 @@ $$\begin{aligned}
- 2 n_C (n_L + n_R) \cos(k_m n_C \ell)
\end{aligned}$$
-Finally, some further rearranging gives a convenient transcendental equation:
+Finally, some further rearranging gives a convenient transcendental equation,
+keeping in mind that $$k_m$$ and the indices $$n_L$$, $$n_C$$ and $$n_R$$
+are generally complex numbers:
$$\begin{aligned}
\boxed{
@@ -223,9 +227,9 @@ $$\begin{aligned}
&= (1 - r_R) A_3 e^{i k_m (n_C - n_R) \ell/2}
\end{aligned}$$
-Note that we have not demanded continuity of the electric field.
-This is because the mirrors are infinitely thin "magic" planes;
-had we instead included the full microscopic mirror structure,
+Note that we have not demanded continuity of the electric field,
+because the mirrors are infinitely thin "magic" planes in this case.
+If we had instead included the full microscopic mirror structure,
then we would have demanded continuity as before.
diff --git a/source/know/concept/fermi-dirac-distribution/index.md b/source/know/concept/fermi-dirac-distribution/index.md
index 2a38eb3..7554e5a 100644
--- a/source/know/concept/fermi-dirac-distribution/index.md
+++ b/source/know/concept/fermi-dirac-distribution/index.md
@@ -13,18 +13,18 @@ layout: "concept"
which obey the [Pauli exclusion principle](/know/concept/pauli-exclusion-principle/),
distribute themselves across the available states in a system at equilibrium.
-Consider one single-particle state $$s$$,
+Consider one single-particle state $$\ket{i}$$,
which can contain $$0$$ or $$1$$ fermions.
-Because the occupation number $$N$$ is variable,
+Because the occupation number $$n_i$$ is variable,
we turn to the [grand canonical ensemble](/know/concept/grand-canonical-ensemble/),
whose grand partition function $$\mathcal{Z}$$ is as follows,
-where $$\varepsilon$$ is the energy of $$s$$
+where $$\varepsilon_i$$ is the energy of $$\ket{i}$$
and $$\mu$$ is the chemical potential:
$$\begin{aligned}
\mathcal{Z}
- = \sum_{N = 0}^1 \Big( e^{-\beta (\varepsilon - \mu)} \Big)^N
- = 1 + e^{-\beta (\varepsilon - \mu)}
+ = \sum_{m = 0}^1 \Big( e^{-\beta (\varepsilon_i - \mu)} \Big)^m
+ = 1 + e^{-\beta (\varepsilon_i - \mu)}
\end{aligned}$$
The corresponding [thermodynamic potential](/know/concept/thermodynamic-potential/)
@@ -33,43 +33,43 @@ is the Landau potential $$\Omega$$, given by:
$$\begin{aligned}
\Omega
= - k T \ln{\mathcal{Z}}
- = - k T \ln\!\Big( 1 + e^{-\beta (\varepsilon - \mu)} \Big)
+ = - k T \ln\!\Big( 1 + e^{-\beta (\varepsilon_i - \mu)} \Big)
\end{aligned}$$
-The average number of particles $$\expval{N}$$
-in $$s$$ is then found by taking a derivative of $$\Omega$$:
+The average number of particles $$\expval{n_i}$$
+in $$\ket{i}$$ is then found by taking a derivative of $$\Omega$$:
$$\begin{aligned}
- \expval{N}
+ \expval{n_i}
= - \pdv{\Omega}{\mu}
= k T \pdv{\ln{\mathcal{Z}}}{\mu}
- = \frac{e^{-\beta (\varepsilon - \mu)}}{1 + e^{-\beta (\varepsilon - \mu)}}
+ = \frac{e^{-\beta (\varepsilon_i - \mu)}}{1 + e^{-\beta (\varepsilon_i - \mu)}}
\end{aligned}$$
-By multiplying both the numerator and the denominator by $$e^{\beta (\varepsilon \!-\! \mu)}$$,
+By multiplying both the numerator and the denominator by $$e^{\beta (\varepsilon_i - \mu)}$$,
we arrive at the standard form of
the **Fermi-Dirac distribution** or **Fermi function** $$f_F$$:
$$\begin{aligned}
\boxed{
- \expval{N}
- = f_F(\varepsilon)
- = \frac{1}{e^{\beta (\varepsilon - \mu)} + 1}
+ \expval{n_i}
+ = f_F(\varepsilon_i)
+ = \frac{1}{e^{\beta (\varepsilon_i - \mu)} + 1}
}
\end{aligned}$$
-This gives the expected occupation number $$\expval{N}$$
-of state $$s$$ with energy $$\varepsilon$$,
+This gives the expected occupation number $$\expval{n_i}$$
+of state $$\ket{i}$$ with energy $$\varepsilon_i$$,
given a temperature $$T$$ and chemical potential $$\mu$$.
{% comment %}
-The corresponding variance $$\sigma^2 \equiv \expval{N^2} - \expval{N}^2$$ is found to be:
+The corresponding variance $$\sigma^2 \equiv \expval{n_i^2} - \expval{n_i}^2$$ is found to be:
$$\begin{aligned}
\boxed{
\sigma^2
- = k T \pdv{\expval{N}}{\mu}
- = \expval{N} \big(1 - \expval{N}\big)
+ = k T \pdv{\expval{n_i}}{\mu}
+ = \expval{n_i} \big(1 - \expval{n_i}\big)
}
\end{aligned}$$
{% endcomment %}
diff --git a/source/know/concept/fermi-gas/index.md b/source/know/concept/fermi-gas/index.md
new file mode 100644
index 0000000..6d316cc
--- /dev/null
+++ b/source/know/concept/fermi-gas/index.md
@@ -0,0 +1,219 @@
+---
+title: "Fermi gas"
+sort_title: "Fermi gas"
+date: 2026-09-02
+categories:
+- Physics
+- Quantum mechanics
+layout: "concept"
+---
+
+A **Fermi gas** is a system of many fermions
+that do not interact directly, only indirectly through
+the [Pauli exclusion principle](/know/concept/pauli-exclusion-principle/),
+and hence obey [Fermi-Dirac statistics](/know/concept/fermi-dirac-distribution/).
+
+There are several real-life systems for which this model is relevant,
+but most notably it serves as the foundation of the quantum-mechanical study
+of electrons (or electron holes) in materials.
+Obviously, electrons *do* interact strongly via the Coulomb force,
+but it is nevertheless a useful starting point to neglect that fact,
+and to then add the interactions later (see e.g. [jellium](/know/concept/jellium)).
+
+Consider a collection of infinitely many non-interacting fermions.
+For mathematical convenience, we restrict ourselves to a cube with side $$L$$,
+and impose periodic boundary conditions.
+Then, at the end of our calculation,
+we should in theory take the limit $$L \to \infty$$
+to recover the "true" system.
+
+In the absence of any potentials, all the fermions' wavefunctions
+are simply plane waves $$\ket{\psi_\vb{k}}$$ with wavevector $$\vb{k}$$.
+Due to the cube's finite size and its periodic boundary conditions,
+those waves have a discrete spectrum of allowed wavevectors $$\vb{k}$$,
+meaning that each particle's wavefunction $$\ket{\psi_\vb{k}}$$
+is as follows in $$\vb{r}$$-space (modulo a constant phase):
+
+$$\begin{aligned}
+ \psi_{\vb{k}}(\vb{r})
+ = \frac{1}{\sqrt{L^3}} \exp(i \vb{k} \cdot \vb{r})
+ \qquad \qquad
+ \vb{k} = \frac{2 \pi}{L} (n_x, n_y, n_z)
+\end{aligned}$$
+
+Where $$n_x, n_y, n_z \in \mathbb{Z}$$.
+This is a discrete (but infinite) set of independent orbitals,
+so it is natural to use the
+[second quantization](/know/concept/second-quantization/)'s
+operators $$\hat{c}^\dagger$$ and $$\hat{c}$$ in our analysis.
+
+Let the temperature $$T = 0$$,
+then the $$N$$ fermions inside our cube
+fill the $$N$$ lowest-energy orbitals.
+The resulting $$N$$-particle ground state
+is known as the **Fermi sea** or **Fermi sphere** $$\ket{\mathrm{FS}}$$,
+and can be written as follows, where $$S$$ is the spin degeneracy,
+i.e. for each $$\vb{k}$$ there are $$S$$ orbitals
+with the same energy but different spin $$s$$
+(for most relevant fermions $$S = 2$$):
+
+$$\begin{aligned}
+ \ket{\mathrm{FS}}
+ = \prod_{s} \prod_{j = 1}^{N/S} \hat{c}_{s,\vb{k}_j}^\dagger \ket{0}
+\end{aligned}$$
+
+The energy and wavenumber $$|\vb{k}|$$ of the highest filled orbital
+are called the **Fermi energy** $$\varepsilon_F$$ and **Fermi wavenumber** $$k_F$$,
+and obey the expected kinetic energy relation:
+
+$$\begin{aligned}
+ \boxed{
+ \varepsilon_F
+ = \frac{\hbar^2}{2 m} k_F^2
+ }
+\end{aligned}$$
+
+The Fermi sphere can be visualized in $$\vb{k}$$-space
+as a sphere with radius $$k_F$$.
+Because $$\vb{k}$$ is discrete, the sphere's surface is not smooth,
+but in the limit $$L \to \infty$$ that "roughness" disappears.
+
+Now, we would like a relation between the system's parameters,
+e.g. $$N$$ and $$L$$, and the resulting values of $$\varepsilon_F$$ or $$k_F$$.
+The total number $$N$$ of fermions in our cube is given by:
+
+$$\begin{aligned}
+ N
+ = \sum_{s} \sum_{\vb{k}} \matrixel{\mathrm{FS}}{\hat{c}_{s,\vb{k}}^\dagger \hat{c}_{s,\vb{k}}}{\mathrm{FS}}
+ = \sum_{s} \frac{L^3}{(2 \pi)^3} \int_{-\infty}^\infty \matrixel{\mathrm{FS}}{\hat{c}_{s,\vb{k}}^\dagger \hat{c}_{s,\vb{k}}}{\mathrm{FS}} \dd{\vb{k}}
+\end{aligned}$$
+
+Where the periodic boundary conditions have
+[enabled us](/know/concept/discrete-spectrum-summation/)
+to convert the sum over $$\vb{k}$$ to an integral.
+For $$T = 0$$, the matrix element
+$$\matrixel{\mathrm{FS}}{\hat{c}_{s,\vb{k}}^\dagger \hat{c}_{s,\vb{k}}}{\mathrm{FS}}$$
+is either $$0$$ or $$1$$,
+depending on whether $$\vb{k}$$ is outside or inside the Fermi sphere.
+We can write this using
+a [Heaviside step function](/know/concept/heaviside-step-function/):
+
+$$\begin{aligned}
+ N
+ = \sum_{s} \frac{L^3}{(2 \pi)^3} \int_{-\infty}^\infty \Theta(k_F - |\vb{k}|) \dd{\vb{k}}
+ = \frac{S L^3}{(2 \pi)^3} \int_{-\infty}^\infty \Theta(k_F - |\vb{k}|) \dd{\vb{k}}
+\end{aligned}$$
+
+Where we realized that spin does not matter,
+to replace the sum with a factor $$S$$.
+To evaluate this 3D integral, we transition to
+[spherical coordinates](/know/concept/spherical-coordinates/)
+$$(|\vb{k}|, \theta, \varphi)$$:
+
+$$\begin{aligned}
+ N
+ &= \frac{S L^3}{8 \pi^3} \int_0^{2 \pi} \int_0^\pi \int_0^\infty \Theta(k_F - |\vb{k}|) |\vb{k}|^2 \sin(\theta) \dd{|\vb{k}|} \dd{\theta} \dd{\varphi}
+ \\
+ &= \frac{S L^3}{8 \pi^3} 4 \pi \int_0^\infty \Theta(k_F - |\vb{k}|) |\vb{k}|^2 \sin(\theta) \dd{|\vb{k}|}
+ \\
+ &= \frac{S L^3}{2 \pi^2} \int_0^{k_F} |\vb{k}|^2 \dd{|\vb{k}|}
+ \\
+ &= \frac{S L^3}{6 \pi^2} k_F^3
+\end{aligned}$$
+
+Since the particle density $$n = N / L^3$$,
+we can rearrange this result to the following relation:
+
+$$\begin{aligned}
+ \boxed{
+ k_F^3
+ = \frac{6 \pi^2}{S} n
+ }
+ \qquad
+\end{aligned}$$
+
+Consequently, the Fermi energy $$\varepsilon_F$$
+and the corresponding orbital's velocity $$v_F = \hbar k_F / m$$
+can be expressed as a function of the density $$n$$:
+
+$$\begin{aligned}
+ \boxed{
+ \varepsilon_F
+ = \frac{\hbar^2}{2 m} \bigg( \frac{6 \pi^2}{S} \bigg)^{2/3} n^{2/3}
+ }
+ \qquad \qquad
+ \boxed{
+ v_F
+ = \frac{\hbar}{m} \bigg( \frac{6 \pi^2}{S} \bigg)^{1/3} n^{1/3}
+ }
+\end{aligned}$$
+
+This is an important result, especially for electrons in metals.
+We know the electron density $$n$$ for many conductors,
+and then these relations tell us that $$v_F \ll c$$,
+and that the "Fermi temperature" $$T_F = \varepsilon_F / k_B$$
+is very large (e.g. $$T_F \approx 8 \cdot 10^4 \: \mathrm{K}$$ for copper).
+This justifies our implicit assumptions that relativity
+and thermal fluctuations are negligible under normal circumstances.
+
+We now have an expression for $$\varepsilon_F$$ as a function of $$n$$,
+which we can control by adding or removing fermions from the system.
+But it is also useful to isolate this relation for $$n$$ instead:
+
+$$\begin{aligned}
+ n
+ &= \frac{S}{6 \pi^2} \bigg( \frac{2 m}{\hbar^2} \bigg)^{3/2} \varepsilon_F^{3/2}
+\end{aligned}$$
+
+The total population $$N = L^3 n$$ can therefore be expressed
+as a function of $$\varepsilon_F$$:
+
+$$\begin{aligned}
+ N(\varepsilon_F)
+ &= \frac{S L^3}{6 \pi^2} \bigg( \frac{2 m}{\hbar^2} \bigg)^{3/2} \varepsilon_F^{3/2}
+\end{aligned}$$
+
+And from this we obtain a formula for the
+[density of states](/know/concept/density-of-states/)
+$$g$$ of a 3D Fermi gas:
+
+$$\begin{aligned}
+ \boxed{
+ g(\varepsilon_F)
+ = \dv{N}{\varepsilon_F}
+ = \frac{S L^3}{4 \pi^2} \bigg( \frac{2 m}{\hbar^2} \bigg)^{3/2} \varepsilon_F^{1/2}
+ }
+\end{aligned}$$
+
+Now, $$\varepsilon_F$$ is the highest energy of a single fermion,
+but what about the total $$N$$-particle energy $$E$$?
+This is easy to calculate using the density of states:
+
+$$\begin{aligned}
+ E
+ &= \int_0^{\varepsilon_F} \varepsilon \: g(\varepsilon) \dd{\varepsilon}
+ \\
+ &= \frac{S L^3}{4 \pi^2} \bigg( \frac{2 m}{\hbar^2} \bigg)^{3/2}
+ \int_0^{\varepsilon_F} \varepsilon^{3/2} \dd{\varepsilon}
+ \\
+ &= \frac{3}{2} \frac{S L^3}{6 \pi^2} \bigg( \frac{2 m}{\hbar^2} \bigg)^{3/2} \: \frac{2}{5} \varepsilon_F^{5/2}
+\end{aligned}$$
+
+Here, we recognize $$N(\varepsilon_F)$$ from earlier,
+leading to the following expression for the total $$E$$:
+
+$$\begin{aligned}
+ \boxed{
+ E
+ = \frac{3}{5} N \varepsilon_F
+ }
+\end{aligned}$$
+
+This model is a strong foundation for many more advanced calculations.
+
+
+
+## References
+1. H. Bruus, K. Flensberg,
+ *Many-body quantum theory in condensed matter physics*,
+ 2016, Oxford.
diff --git a/source/know/concept/fundamental-relation-of-thermodynamics/index.md b/source/know/concept/fundamental-relation-of-thermodynamics/index.md
new file mode 100644
index 0000000..a51c231
--- /dev/null
+++ b/source/know/concept/fundamental-relation-of-thermodynamics/index.md
@@ -0,0 +1,326 @@
+---
+title: "Fundamental relation of thermodynamics"
+sort_title: "Fundamental relation of thermodynamics"
+date: 2024-07-21 # Originally 2021-07-07, major rewrite
+categories:
+- Physics
+- Thermodynamics
+layout: "concept"
+---
+
+In most areas of physics,
+we observe and analyze the behaviour
+of physical systems that have been "disturbed" some way,
+i.e. we try to understand what is *happening*.
+In thermodynamics, however,
+we start paying attention once the disturbance has ended,
+and the system has had some time to settle down:
+when nothing seems to be happening anymore.
+
+Then a common observation is that the system "forgets" what happened earlier,
+and settles into a so-called **equilibrium state**
+that appears to be independent of its history.
+No matter in what way you stir your tea, once you finish,
+eventually the liquid stops moving, cools down,
+and just... sits there, doing nothing.
+But how does it "choose" this equilibrium state?
+
+
+
+## Thermodynamic equilibrium
+
+This history-independence suggests that equilibrium
+is determined by only a few parameters of the system.
+Prime candidates are the **mole numbers** $$N_1, N_2, ..., N_n$$
+of each of the $$n$$ different types of particles in the system,
+and its **volume** $$V$$.
+Furthermore, the microscopic dynamics
+are driven by energy differences between components,
+and obey the universal principle of energy conservation,
+so it also sounds reasonable to define a total
+**internal energy** $$U$$.
+
+Thanks to many decades of empirical confirmations,
+we now know that the above arguments can be combined into a postulate:
+the equilibrium state of a closed system with fixed $$U$$, $$V$$ and $$N_i$$
+is completely determined by those parameters.
+The system then "finds" the equilibrium
+by varying its microscopic degrees of freedom
+such that the **entropy** $$S$$ is maximized
+subject to the given values of $$U$$, $$V$$ and $$N_i$$.
+This statement serves as a definition of $$S$$,
+and explains the **second law of thermodynamics**:
+the total entropy never decreases.
+
+We do not care about those microscopic degrees of freedom,
+but we do care about how $$U$$, $$V$$ and $$N_i$$ influence the equilibrium.
+For a given system, we want a formula $$S(U, V, N_1, ..., N_n)$$,
+which contains all thermodynamic information about the system
+and is therefore known as its **fundamental relation**.
+
+The next part of our definition of $$S$$
+is that it must be invertible with respect to $$U$$,
+meaning we can rearrange the fundamental relation
+to $$U(S, V, N_1, ... N_n)$$ without losing any information.
+Specifically, this means that $$S$$ must be continuous,
+differentiable, and monotonically increasing with $$U$$,
+such that $$S(U)$$ can be inverted to $$U(S)$$ and vice versa.
+
+The idea here is that maximizing $$S$$ at fixed $$U$$
+should be equivalent to minimizing $$U$$ for a given $$S$$
+(we prove this later).
+Often it is mathematically more convenient
+to choose one over the other,
+but by definition both approaches are equally valid.
+And because $$S$$ is rather abstract,
+it may be preferable to treat it as a parameter
+for a more intuitive quantity like $$U$$.
+
+Next, we demand that $$S$$ is additive over subsystems,
+so $$S = S_1 + S_2 + ...$$, with $$S_1$$ being the entropy of subsystem 1, etc.
+Consequently, $$S$$ is an **extensive** quantity of the system,
+just like $$U$$ (and $$V$$ and $$N_i$$),
+meaning they satisfy for any constant $$\lambda$$:
+
+$$\begin{aligned}
+ S(\lambda U, \lambda V, \lambda N_1, ..., \lambda N_n)
+ &= \lambda S(U, V, N_1, ..., N_n)
+ \\
+ U(\lambda S, \lambda V, \lambda N_1, ..., \lambda N_n)
+ &= \lambda U(S, V, N_1, ..., N_n)
+\end{aligned}$$
+
+For $$U$$, this makes intuitive sense:
+the total energy in two identical systems
+is double the energy of a single of those systems.
+Actually, reality is a bit hazier than this:
+dynamics are governed by energy *differences* only,
+so an offset $$U_0$$ can be added without a consequence.
+We should choose an offset and a way to split the system into subsystems
+such that the above relation holds for our convenience.
+Fortunately, this choice often makes itself.
+
+$$S$$ does not suffer from this ambiguity,
+since the **third law of thermodynamics** clearly defines
+where $$S = 0$$ should occur: at a temperature of absolute zero.
+In this article we will not explore the reason for this requirement,
+which is also known as the **Nernst postulate**.
+Furthermore, in most situations this law can simply be ignored.
+
+Since $$U$$, $$S$$, $$V$$ and $$N_i$$ are all extensive,
+the partial derivatives of the fundamental relation are **intensive** quantities,
+meaning they do not depend on the size of the system.
+Those derivatives are very important,
+since they are usually the equilibrium properties we want to find.
+
+
+
+## Energy representation
+
+When we have a fundamental relation of the form $$U(S, V, N_1, ..., N_n)$$,
+we say we are treating the system's thermodynamics
+in the **energy representation**.
+
+The following derivatives of $$U$$ are used as the thermodynamic *definitions*
+of the **temperature** $$T$$, the **pressure** $$P$$,
+and the **chemical potential** $$\mu_k$$ of the $$k$$th particle species:
+
+$$\begin{aligned}
+ \boxed{
+ \begin{aligned}
+ T
+ &\equiv \bigg( \pdv{U}{S} \bigg)_{V, N_i}
+ \\
+ P
+ &\equiv - \bigg( \pdv{U}{V} \bigg)_{S, N_i}
+ \\
+ \mu_k
+ &\equiv \bigg( \pdv{U}{N_k} \bigg)_{S, V, N_{i \neq k}}
+ \end{aligned}
+ }
+\end{aligned}$$
+
+The resulting expressions of the form $$T(S, V, N_1, ..., N_n)$$ etc.
+are known as the **equations of state** of the system.
+Unlike the fundamental relation, a single equation of state
+is not a complete thermodynamic description of the system.
+However, if *all* equations of state are known
+(for $$T$$, $$P$$, and all $$\mu_k$$),
+then the fundamental relation can be reconstructed.
+
+As explained above, physical dynamics are driven by energy differences only,
+so we expand an infinitesimal difference $$\dd{U}$$ as:
+
+$$\begin{aligned}
+ \dd{U}
+ = \bigg( \pdv{U}{S} \bigg)_{V, N_i} \!\dd{S}
+ \:\:+\:\: \bigg( \pdv{U}{V} \bigg)_{S, N_i} \!\dd{V}
+ \:\:+\:\: \sum_{k}^{} \bigg( \pdv{U}{N_k} \bigg)_{S, V, N_{i \neq k}} \!\dd{N_k}
+\end{aligned}$$
+
+Those partial derivatives look familiar.
+Substituting $$T$$, $$P$$ and $$\mu_k$$ gives a result
+that is also called the **fundamental relation of thermodynamics**
+(as opposed to the fundamental relation of the system only,
+just to make things confusing):
+
+$$\begin{aligned}
+ \boxed{
+ \dd{U}
+ = T \dd{S} - P \dd{V} + \sum_{k}^{} \mu_k \dd{N_k}
+ }
+\end{aligned}$$
+
+Where the first term represents heating/cooling (also written as $$\dd{Q}$$),
+and the second is physical work done on the system
+by compression/expansion (also written as $$\dd{W}$$).
+The third term is the energy change due to matter transfer and is often neglected.
+Hence this relation can be treated as a form
+of the **first law of thermodynamics** $$\Delta U = \Delta Q + \Delta W$$.
+
+Because $$T$$, $$P$$ and $$\mu_k$$ generally depend on $$S$$, $$V$$ and $$N_k$$,
+integrating the fundamental relation can be tricky.
+Fortunately, the fact that $$U$$ is extensive offers a shortcut.
+Recall that:
+
+$$\begin{aligned}
+ \lambda U(S, V, N_1, ..., N_n)
+ &= U(\lambda S, \lambda V, \lambda N_1, ..., \lambda N_n)
+\end{aligned}$$
+
+For any $$\lambda$$.
+Let us differentiate this equation with respect to $$\lambda$$, yielding:
+
+$$\begin{aligned}
+ U
+ &= \pdv{}{\lambda} U(\lambda S, \lambda V, \lambda N_1, ..., \lambda N_n)
+ \\
+ &= \pdv{U(\lambda S)}{(\lambda S)} \pdv{(\lambda S)}{\lambda}
+ + \pdv{U(\lambda V)}{(\lambda V)} \pdv{(\lambda V)}{\lambda}
+ + \sum_{k} \pdv{U(\lambda N_k)}{(\lambda N_k)} \pdv{(\lambda N_k)}{\lambda}
+ \\
+ &= \pdv{U(S)}{S} S
+ + \pdv{U(V)}{V} V
+ + \sum_{k} \pdv{U(N_k)}{N_k} N_k
+\end{aligned}$$
+
+Where we once again recognize the derivatives.
+The resulting equation is known as the **Euler form**
+of the fundamental relation of thermodynamics:
+
+$$\begin{aligned}
+ \boxed{
+ U
+ = T S - P V + \sum_{k} \mu_k N_k
+ }
+\end{aligned}$$
+
+Plus a constant $$U_0$$ of course,
+although $$U_0 = 0$$ is the most straightforward choice.
+
+
+
+## Entropy representation
+
+If the system's fundamental relation
+instead has the form $$S(U, V, N_1, ..., N_i)$$,
+we are treating it in the **entropy representation**.
+Isolating the above fundamental relation of thermodynamics
+for $$\dd{S}$$ yields its equivalent form in this representation:
+
+$$\begin{aligned}
+ \boxed{
+ \dd{S}
+ = \frac{1}{T} \dd{U} + \frac{P}{T} \dd{V} - \sum_{k}^{} \frac{\mu_k}{T} \dd{N_k}
+ }
+\end{aligned}$$
+
+From which we can then read off the standard partial derivatives of $$S(U, V, N_1, ..., N_n)$$:
+
+$$\begin{aligned}
+ \boxed{
+ \begin{aligned}
+ \frac{1}{T}
+ &= \bigg( \pdv{S}{U} \bigg)_{V, N_i}
+ \\
+ \frac{P}{T}
+ &= \bigg( \pdv{S}{V} \bigg)_{U, N_i}
+ \\
+ \frac{\mu_k}{T}
+ &= - \bigg( \pdv{S}{N_k} \bigg)_{U, V, N_{i \neq k}}
+ \end{aligned}
+ }
+\end{aligned}$$
+
+Note the signs: the parameters $$U$$, $$V$$ and $$N_i$$ are implicitly related
+by our requirement that $$S$$ is stationary at a maximum,
+so the [triple product rule](/know/concept/triple-product-rule/)
+must be used, which brings some perhaps surprising sign changes.
+Reading them off in this way is easier.
+
+And of course, since $$S$$ is defined to be an extensive quantity,
+it also has an Euler form:
+
+$$\begin{aligned}
+ \boxed{
+ S
+ = \frac{1}{T} U + \frac{P}{T} V - \sum_{k} \frac{\mu_k}{T} N_k
+ }
+\end{aligned}$$
+
+Finally, it is worth proving that minimizing $$U$$
+is indeed equivalent to maximizing $$S$$.
+For simplicity, we consider a system
+where only the volume $$V$$ can change
+in order to reach an equilibrium;
+the proof is analogous for all other parameters.
+Clearly, $$S$$ is stationary at its maximum:
+
+$$\begin{aligned}
+ 0
+ &= \bigg( \pdv{S}{V} \bigg)_{U, N_i}
+ = - \frac{ \bigg( \displaystyle\pdv{U}{V} \bigg)_{S, N_i} }{ \bigg( \displaystyle\pdv{U}{S} \bigg)_{V, N_i} }
+ = - \frac{1}{T} \bigg( \pdv{U}{V} \bigg)_{S, N_i}
+\end{aligned}$$
+
+Where we have used the triple product rule.
+This can only hold if $$(\ipdv{U}{S})_{S, N_i} = 0$$,
+meaning $$U$$ is also at an extremum.
+But $$S$$ is not just at any extremum: it is at a *maximum*, so:
+
+$$\begin{aligned}
+ 0
+ > \bigg( \pdvn{2}{S}{V} \bigg)_{U, N_i}
+ &= \bigg( \pdv{}{V} \Big( \frac{P}{T} \Big) \bigg)_{U, N_i}
+ \\
+ &= \bigg( \pdv{}{V} \Big( \frac{P}{T} \Big) \bigg)_{S, N_i}
+ + \bigg( \pdv{}{S} \Big( \frac{P}{T} \Big) \bigg)_{V, N_i} \bigg( \pdv{S}{V} \bigg)_{U, N_i}
+ \\
+ &= \bigg( \pdv{}{V} \Big( \frac{P}{T} \Big) \bigg)_{S, N_i}
+ + \frac{P}{T} \bigg( \pdv{}{S} \Big( \frac{P}{T} \Big) \bigg)_{V, N_i}
+ \\
+ &= \frac{1}{T} \bigg( \pdv{P}{V} \bigg)_{S, N_i}
+ - \frac{P}{T^2} \bigg( \pdv{T}{V} \bigg)_{S, N_i}
+ + \frac{P}{T} \bigg( \pdv{}{S} \Big( \frac{P}{T} \Big) \bigg)_{V, N_i}
+ \\
+ &= - \frac{1}{T} \bigg( \pdvn{2}{U}{V} \bigg)_{S, N_i}
+ + \frac{P}{T} \bigg[ \bigg( \pdv{}{S} \Big( \frac{P}{T} \Big) \bigg)_{V, N_i}
+ - \frac{1}{T} \bigg( \pdv{T}{V} \bigg)_{S, N_i} \bigg]
+\end{aligned}$$
+
+Because $$S$$ is at a maximum, we know that $$P/T = 0$$,
+and $$T$$ is always above absolute zero
+(since we defined $$S$$ to be monotonically increasing with $$U$$),
+which leaves $$(\ipdvn{2}{U}{V})_{S, N_i} > 0$$
+as the only way to satisfy this inequality.
+In other words, $$U$$ is at a minimum, as expected.
+
+
+
+## References
+1. H.B. Callen,
+ *Thermodynamics and an introduction to thermostatistics*, 2nd edition,
+ Wiley.
+2. H. Gould, J. Tobochnik,
+ *Statistical and thermal physics*, 2nd edition,
+ Princeton.
diff --git a/source/know/concept/fundamental-solution/index.md b/source/know/concept/fundamental-solution/index.md
index 947aada..4728c6f 100644
--- a/source/know/concept/fundamental-solution/index.md
+++ b/source/know/concept/fundamental-solution/index.md
@@ -11,7 +11,7 @@ layout: "concept"
Given a linear operator $$\hat{L}$$ acting on $$x \in [a, b]$$,
its **fundamental solution** $$G(x, x')$$ is defined as the response
of $$\hat{L}$$ to a [Dirac delta function](/know/concept/dirac-delta-function/)
-$$\delta(x - x')$$ for $$x \in ]a, b[$$:
+$$\delta(x - x')$$ located at $$x' \in \: ]a, b[$$:
$$\begin{aligned}
\boxed{
@@ -24,7 +24,7 @@ Where $$A$$ is a constant, usually $$1$$.
Fundamental solutions are often called **Green's functions**,
but are distinct from the (somewhat related)
[Green's functions](/know/concept/greens-functions/)
-in many-body quantum theory.
+in quantum mechanics.
Note that the definition of $$G(x, x')$$ generalizes that of
the [impulse response](/know/concept/impulse-response/).
@@ -44,20 +44,20 @@ $$\begin{aligned}
{% include proof/start.html id="proof-solution" -%}
-$$\hat{L}$$ only acts on $$x$$, so $$x' \in ]a, b[$$ is simply a parameter,
+$$\hat{L}$$ only acts on $$x$$, so $$x' \in \: ]a, b[$$ is simply a parameter,
meaning we are free to multiply the definition of $$G$$
by the constant $$f(x')$$ on both sides,
and exploit $$\hat{L}$$'s linearity:
$$\begin{aligned}
A f(x') \: \delta(x - x')
- = f(x') \hat{L}\{ G(x, x') \}
+ = f(x') \: \hat{L}\{ G(x, x') \}
= \hat{L}\{ f(x') \: G(x, x') \}
\end{aligned}$$
We then integrate both sides over $$x'$$ in the interval $$[a, b]$$,
allowing us to consume $$\delta(x \!-\! x')$$.
-Note that $$\int \dd{x'}$$ commutes with $$\hat{L}$$ acting on $$x$$:
+Note that integration commutes with $$\hat{L}$$'s action:
$$\begin{aligned}
A \int_a^b f(x') \: \delta(x - x') \dd{x'}
@@ -72,27 +72,37 @@ satisfies $$\hat{L}\{ u(x) \} = f(x)$$, recognizable here.
{% include proof/end.html id="proof-solution" %}
+In practice, $$G$$ usually only depends on the difference $$x - x'$$,
+in which case the integral shown above becomes a convolution:
+
+$$\begin{aligned}
+ u(x)
+ = \frac{1}{A} \int_a^b f(x') \: G(x - x') \dd{x'}
+ = \frac{1}{A} (f * G)(x)
+\end{aligned}$$
+
While the impulse response is typically used for initial value problems,
the fundamental solution $$G$$ is used for boundary value problems.
Suppose those boundary conditions are homogeneous,
-i.e. $$u(x)$$ or one of its derivatives is zero at the boundaries.
+i.e. $$u$$ or its derivative $$\dot{u}$$ is zero at the boundaries.
Then:
$$\begin{aligned}
0
&= u(a)
= \frac{1}{A} \int_a^b f(x') \: G(a, x') \dd{x'}
- \qquad \implies \quad
+ \quad \implies \quad
G(a, x') = 0
\\
0
- &= u_x(a)
- = \frac{1}{A} \int_a^b f(x') \: G_x(a, x') \dd{x'}
+ &= \dot{u}(a)
+ = \frac{1}{A} \int_a^b f(x') \: \dot{G}(a, x') \dd{x'}
\quad \implies \quad
- G_x(a, x') = 0
+ \dot{G}(a, x') = 0
\end{aligned}$$
-This holds for all $$x'$$, and analogously for the other boundary $$x = b$$.
+Where $$\dot{G}$$ is the derivative of $$G$$ with respect to its first argument.
+This holds for all $$x'$$, and also at the other boundary $$x = b$$.
In other words, the boundary conditions are built into $$G$$.
What if the boundary conditions are inhomogeneous?
@@ -104,7 +114,7 @@ has homogeneous boundaries again,
so we can use $$G$$ as usual to find $$u_i(x)$$, and then just add $$u_h(x)$$.
If $$\hat{L}$$ is self-adjoint
-(see e.g. [Sturm-Liouville theory](/know/concept/sturm-liouville-theory/)),
+(see [Sturm-Liouville theory](/know/concept/sturm-liouville-theory/)),
then the fundamental solution $$G(x, x')$$
has the following **reciprocity** boundary condition:
diff --git a/source/know/concept/fundamental-thermodynamic-relation/index.md b/source/know/concept/fundamental-thermodynamic-relation/index.md
deleted file mode 100644
index 0d945fa..0000000
--- a/source/know/concept/fundamental-thermodynamic-relation/index.md
+++ /dev/null
@@ -1,54 +0,0 @@
----
-title: "Fundamental thermodynamic relation"
-sort_title: "Fundamental thermodynamic relation"
-date: 2021-07-07
-categories:
-- Physics
-- Thermodynamics
-layout: "concept"
----
-
-The **fundamental thermodynamic relation** combines the first two
-[laws of thermodynamics](/know/concept/laws-of-thermodynamics/),
-and gives the change of the internal energy $$U$$,
-which is a [thermodynamic potential](/know/concept/thermodynamic-potential/),
-in terms of the change in
-entropy $$S$$, volume $$V$$, and the number of particles $$N$$.
-
-Starting from the first law of thermodynamics,
-we write an infinitesimal change in energy $$\dd{U}$$ as follows,
-where $$T$$ is the temperature and $$P$$ is the pressure:
-
-$$\begin{aligned}
- \dd{U} &= \dd{Q} + \dd{W} = T \dd{S} - P \dd{V}
-\end{aligned}$$
-
-The term $$T \dd{S}$$ comes from the second law of thermodynamics,
-and represents the transfer of thermal energy,
-while $$P \dd{V}$$ represents physical work.
-
-However, we are missing a term, namely matter transfer.
-If particles can enter/leave the system (i.e. the population $$N$$ is variable),
-then each such particle costs an amount $$\mu$$ of energy,
-where $$\mu$$ is known as the **chemical potential**:
-
-$$\begin{aligned}
- \dd{U} = T \dd{S} - P \dd{V} + \mu \dd{N}
-\end{aligned}$$
-
-To generalize even further, there may be multiple species of particle,
-which each have a chemical potential $$\mu_i$$.
-In that case, we sum over all species $$i$$:
-
-$$\begin{aligned}
- \boxed{
- \dd{U} = T \dd{S} - P \dd{V} + \sum_{i}^{} \mu_i \dd{N_i}
- }
-\end{aligned}$$
-
-
-
-## References
-1. H. Gould, J. Tobochnik,
- *Statistical and thermal physics*, 2nd edition,
- Princeton.
diff --git a/source/know/concept/heaviside-step-function/index.md b/source/know/concept/heaviside-step-function/index.md
index 9f5d4ec..6412914 100644
--- a/source/know/concept/heaviside-step-function/index.md
+++ b/source/know/concept/heaviside-step-function/index.md
@@ -45,15 +45,15 @@ $$\begin{aligned}
\end{aligned}$$
The [Fourier transform](/know/concept/fourier-transform/)
-of $$\Theta(t)$$ is as follows,
-where $$\pv{}$$ is the Cauchy principal value,
+of $$\Theta(t)$$ is as follows, where $$\mathcal{P}$$
+is the [Cauchy principal value](/know/concept/cauchy-principal-value/),
$$A$$ and $$s$$ are constants from the FT's definition,
and $$\mathrm{sgn}$$ is the signum function:
$$\begin{aligned}
\boxed{
\tilde{\Theta}(\omega)
- = \frac{A}{|s|} \Big( \pi \delta(\omega) + i \: \mathrm{sgn}(s) \pv{\frac{1}{\omega}} \Big)
+ = \frac{A}{|s|} \Big( \pi \delta(\omega) + i \:\mathrm{sgn}(s) \:\mathcal{P} \frac{1}{\omega} \Big)
}
\end{aligned}$$
@@ -77,18 +77,18 @@ $$\begin{aligned}
\end{aligned}$$
The first term is proportional to the Dirac delta function.
-The second integral is problematic, so we take the Cauchy principal value $$\pv{}$$
-and look up the integral:
+The second integral is problematic, so we take
+the Cauchy principal value $$\mathcal{P}$$ and look up the integral:
$$\begin{aligned}
\tilde{\Theta}(\omega)
- &= A \pi \delta(s \omega) + \frac{A}{2} \pv{\int_{-\infty}^\infty \mathrm{sgn}(t) \exp(i s \omega t) \dd{t}}
- = \frac{A}{|s|} \pi \delta(\omega) + i \frac{A}{s} \pv{\frac{1}{\omega}}
+ &= A \pi \delta(s \omega) + \frac{A}{2} \:\mathcal{P}\! \int_{-\infty}^\infty \mathrm{sgn}(t) \exp(i s \omega t) \dd{t}
+ = \frac{A}{|s|} \pi \delta(\omega) + i \frac{A}{s} \:\mathcal{P} \frac{1}{\omega}
\end{aligned}$$
{% include proof/end.html id="proof-fourier" %}
-The use of $$\pv{}$$ without an integral is an abuse of notation,
+The use of $$\mathcal{P}$$ without an integral is an abuse of notation,
and means that this result only makes sense when wrapped in an integral.
-Formally, $$\pv{\{1 / \omega\}}$$ is a [Schwartz distribution](/know/concept/schwartz-distribution/).
+Formally, $$\mathcal{P}\{1 / \omega\}$$ is a [Schwartz distribution](/know/concept/schwartz-distribution/).
diff --git a/source/know/concept/heisenberg-picture/index.md b/source/know/concept/heisenberg-picture/index.md
index 359ecfe..3ffe29a 100644
--- a/source/know/concept/heisenberg-picture/index.md
+++ b/source/know/concept/heisenberg-picture/index.md
@@ -8,99 +8,117 @@ categories:
layout: "concept"
---
-The **Heisenberg picture** is an alternative formulation of quantum
-mechanics, and is equivalent to the traditionally-taught Schrödinger equation.
+The **Heisenberg picture** is an alternative formulation of quantum mechanics,
+and is equivalent to the traditional Schrödinger equation.
-In the Schrödinger picture, the operators (observables) are fixed
-(as long as they do not depend on time), while the state
-$$\Ket{\psi_S(t)}$$ changes according to the Schrödinger equation,
-which can be written using the generator of translations $$\hat{U}(t)$$ like so,
-for a time-independent $$\hat{H}_S$$:
+In the Schrödinger picture,
+time-independent operators are constant by definition,
+and the state $$\Ket{\psi_S(t)}$$ varies as follows, where $$\hat{U}(t)$$
+is the [time evolution operator](/know/concept/time-evolution-operator/):
$$\begin{aligned}
- \Ket{\psi_S(t)} = \hat{U}(t) \Ket{\psi_S(0)}
- \qquad \quad
- \boxed{
- \hat{U}(t) \equiv \exp\!\bigg(\!-\! i \frac{\hat{H}_S t}{\hbar} \bigg)
- }
+ \Ket{\psi_S(t)}
+ = \hat{U}(t) \Ket{\psi_S(0)}
\end{aligned}$$
-In contrast, the Heisenberg picture reverses the roles:
-the states $$\Ket{\psi_H}$$ are invariant,
-and instead the operators vary with time.
-An advantage of this is that the basis states remain the same.
+In the Heisenberg picture, the roles are reversed:
+the states $$\Ket{\psi_H}$$ are constants,
+and instead the operators vary in time.
+In some situations this approach can be more convenient,
+and since we usually care about the evolution of observable quantities,
+studying the corresponding operators directly
+may make more sense than finding abstract quantum states.
+Another advantage is that basis states remain fixed,
+which can simplify calculations.
-Given a Schrödinger-picture state $$\Ket{\psi_S(t)}$$, and operator
-$$\hat{L}_S(t)$$ which may or may not depend on time, they can be
-converted to the Heisenberg picture by the following change of basis:
+Given a Schrödinger-picture state $$\Ket{\psi_S(t)}$$
+and an operator $$\hat{L}_S(t)$$ that may or may not depend on time,
+they can be converted to the Heisenberg picture by the following transformation:
$$\begin{aligned}
\boxed{
- \Ket{\psi_H} \equiv \Ket{\psi_S(0)}
- \qquad
- \hat{L}_H(t) \equiv \hat{U}^\dagger(t) \: \hat{L}_S(t) \: \hat{U}(t)
+ \Ket{\psi_H}
+ \equiv \Ket{\psi_S(0)}
+ }
+ \qquad\qquad
+ \boxed{
+ \hat{L}_H(t)
+ \equiv \hat{U}^\dagger(t) \: \hat{L}_S(t) \: \hat{U}(t)
}
\end{aligned}$$
-Since $$\hat{U}(t)$$ is unitary, the expectation value of a given operator is unchanged:
+Note that if $$\hat{H}_S$$ is time-independent,
+then it commutes with $$\hat{U}(t)$$,
+meaning $$\hat{H}_H = \hat{H}_S$$,
+so it can simply be labelled $$\hat{H}$$.
+This is not true for time-dependent Hamiltonians.
+
+Since $$\hat{U}(t)$$ is unitary,
+the expectation value of a given operator is unchanged:
$$\begin{aligned}
\expval{\hat{L}_H}
&= \matrixel{\psi_H}{\hat{L}_H(t)}{\psi_H}
- = \matrixel{\psi_S(0)}{\hat{U}^\dagger(t) \: \hat{L}_S(t) \: \hat{U}(t)}{\psi_S(0)}
+ \\
+ &= \matrixel{\psi_S(0)}{\hat{U}^\dagger(t) \: \hat{L}_S(t) \: \hat{U}(t)}{\psi_S(0)}
\\
&= \matrixel{\hat{U}(t) \psi_S(0)}{\hat{L}_S(t)}{\hat{U}(t) \psi_S(0)}
- = \matrixel{\psi_S(t)}{\hat{L}_S}{\psi_S(t)}
- = \expval{\hat{L}_S}
+ \\
+ &= \matrixel{\psi_S(t)}{\hat{L}_S}{\psi_S(t)}
+ \\
+ &= \expval{\hat{L}_S}
\end{aligned}$$
The Schrödinger and Heisenberg pictures therefore respectively
correspond to active and passive transformations by $$\hat{U}(t)$$
in [Hilbert space](/know/concept/hilbert-space/).
-The two formulations are thus entirely equivalent,
+The two formulations are entirely equivalent,
and can be derived from one another,
-as will be shown shortly.
+as we will show shortly.
In the Heisenberg picture, the states are constant,
so the time-dependent Schrödinger equation is not directly useful.
-Instead, we will use it derive a new equation for $$\hat{L}_H(t)$$.
-The key is that the generator $$\hat{U}(t)$$ is defined from the Schrödinger equation:
+Instead, we use it derive a new equation for $$\hat{L}_H(t)$$,
+with the key being that $$\hat{U}(t)$$ itself
+satisfies the Schrödinger equation by definition:
$$\begin{aligned}
- \dv{}{t}\hat{U}(t) = - \frac{i}{\hbar} \hat{H}_S(t) \: \hat{U}(t)
+ \dv{}{t} \hat{U}(t)
+ = - \frac{i}{\hbar} \hat{H}_S(t) \: \hat{U}(t)
\end{aligned}$$
Where $$\hat{H}_S(t)$$ may depend on time. We differentiate the definition of
-$$\hat{L}_H(t)$$ and insert the other side of the Schrödinger equation
-when necessary:
+$$\hat{L}_H(t)$$ and insert the other side of the Schrödinger equation when necessary:
$$\begin{aligned}
- \dv{}{\hat{L}H}{t}
+ \dv{\hat{L}_H}{t}
&= \dv{\hat{U}^\dagger}{t} \hat{L}_S \hat{U}
+ \hat{U}^\dagger \hat{L}_S \dv{\hat{U}}{t}
+ \hat{U}^\dagger \dv{\hat{L}_S}{t} \hat{U}
\\
&= \frac{i}{\hbar} \hat{U}^\dagger \hat{H}_S (\hat{U} \hat{U}^\dagger) \hat{L}_S \hat{U}
- \frac{i}{\hbar} \hat{U}^\dagger \hat{L}_S (\hat{U} \hat{U}^\dagger) \hat{H}_S \hat{U}
- + \Big( \dv{\hat{L}_S}{t} \Big)_H
+ + \bigg( \dv{\hat{L}_S}{t} \bigg)_H
\\
&= \frac{i}{\hbar} \hat{H}_H \hat{L}_H
- \frac{i}{\hbar} \hat{L}_H \hat{H}_H
- + \Big( \dv{\hat{L}_S}{t} \Big)_H
- = \frac{i}{\hbar} \comm{\hat{H}_H}{\hat{L}_H} + \Big( \dv{\hat{L}_S}{t} \Big)_H
+ + \bigg( \dv{\hat{L}_S}{t} \bigg)_H
\end{aligned}$$
-We thus get the equation of motion for operators in the Heisenberg picture:
+We thus get the following equation of motion for operators in the Heisenberg picture:
$$\begin{aligned}
\boxed{
- \dv{}{t}\hat{L}_H(t) = \frac{i}{\hbar} \comm{\hat{H}_H(t)}{\hat{L}_H(t)} + \Big( \dv{}{t}\hat{L}_S(t) \Big)_H
+ \dv{}{t}\hat{L}_H(t)
+ = \frac{i}{\hbar} \comm{\hat{H}_H(t)}{\hat{L}_H(t)} + \bigg( \dv{}{t}\hat{L}_S(t) \bigg)_H
}
\end{aligned}$$
-This equation is closer to classical mechanics than the Schrödinger picture:
-inserting the position $$\hat{X}$$ and momentum $$\hat{P} = - i \hbar \: \idv{}{\hat{X}}$$
-gives the following Newton-style equations:
+This result is arguably more intuitive than the Schrödinger picture,
+because it allows us to think about observables (i.e. operators) in a more classical way.
+For example, inserting the position $$\hat{X}$$
+and momentum $$\hat{P} = - i \hbar \: \idv{}{\hat{X}}$$
+gives the following Newton-style relations (details omitted):
$$\begin{aligned}
\dv{\hat{X}}{t}
@@ -112,5 +130,6 @@ $$\begin{aligned}
= - \dv{V(\hat{X})}{\hat{X}}
\end{aligned}$$
-For a proof, see [Ehrenfest's theorem](/know/concept/ehrenfests-theorem/),
-which is closely related to the Heisenberg picture.
+These equations would not be valid in the Schrödinger picture,
+unless we took their expectation value
+to get [Ehrenfest's theorem](/know/concept/ehrenfests-theorem/).
diff --git a/source/know/concept/hellmann-feynman-theorem/index.md b/source/know/concept/hellmann-feynman-theorem/index.md
index c6bf720..d02b285 100644
--- a/source/know/concept/hellmann-feynman-theorem/index.md
+++ b/source/know/concept/hellmann-feynman-theorem/index.md
@@ -72,7 +72,7 @@ $$\begin{aligned}
}
\end{aligned}$$
-While for $$m \neq n$$, we get the **Epstein generalization**
+While for $$m \neq n$$, we get the (unfortunately named) **Epstein generalization**
of the Hellmann-Feynman theorem, which is for example relevant for
the [Berry phase](/know/concept/berry-phase/):
diff --git a/source/know/concept/hilbert-space/index.md b/source/know/concept/hilbert-space/index.md
index 42b9cb1..2a60896 100644
--- a/source/know/concept/hilbert-space/index.md
+++ b/source/know/concept/hilbert-space/index.md
@@ -18,22 +18,32 @@ is an abstract **vector space** with a notion of length and angle.
An abstract **vector space** $$\mathbb{V}$$ is a generalization
of the traditional concept of vectors as "arrows".
It consists of a set of objects called **vectors**
-which support the following (familiar) operations:
+that support the following (familiar) operations:
-+ **Vector addition**: the sum of two vectors $$V$$ and $$W$$, denoted by $$V + W$$.
-+ **Scalar multiplication**: product of a vector $$V$$ with a scalar $$a$$, denoted by $$a V$$.
++ **Vector addition**:
+ the sum of two vectors $$V$$ and $$W$$, denoted by $$V + W$$.
++ **Scalar multiplication**:
+ product of a vector $$V$$ with a scalar $$a$$, denoted by $$a V$$.
-In addition, for a given $$\mathbb{V}$$ to qualify as a proper vector
-space, these operations must obey the following axioms:
+In addition, for a given $$\mathbb{V}$$ to qualify as a proper vector space,
+these operations must have the following (again familiar) properties:
-+ **Addition is associative**: $$U + (V + W) = (U + V) + W$$
-+ **Addition is commutative**: $$U + V = V + U$$
-+ **Addition has an identity**: there exists a $$\mathbf{0}$$ such that $$V + 0 = V$$
-+ **Addition has an inverse**: for every $$V$$ there exists $$-V$$ so that $$V + (-V) = 0$$
-+ **Multiplication is associative**: $$a (b V) = (a b) V$$
-+ **Multiplication has an identity**: There exists a $$1$$ such that $$1 V = V$$
-+ **Multiplication is distributive over scalars**: $$(a + b)V = aV + bV$$
-+ **Multiplication is distributive over vectors**: $$a (U + V) = a U + a V$$
++ **Addition is associative**:
+ $$U + (V + W) = (U + V) + W$$
++ **Addition is commutative**:
+ $$U + V = V + U$$
++ **Addition has an identity**:
+ there exists a $$\mathbf{0}$$ such that $$V + 0 = V$$
++ **Addition has an inverse**:
+ for every $$V$$ there exists $$-V$$ so that $$V + (-V) = 0$$
++ **Multiplication is associative**:
+ $$a (b V) = (a b) V$$
++ **Multiplication has an identity**:
+ There exists a $$1$$ such that $$1 V = V$$
++ **Multiplication is distributive over scalars**:
+ $$(a + b)V = aV + bV$$
++ **Multiplication is distributive over vectors**:
+ $$a (U + V) = a U + a V$$
A set of $$N$$ vectors $$V_1, V_2, ..., V_N$$ is **linearly independent**
if the only way to satisfy the following relation
@@ -46,25 +56,28 @@ $$\begin{aligned}
In other words, these vectors cannot be expressed in terms of each other.
Otherwise, they would be **linearly dependent**.
-A vector space $$\mathbb{V}$$ has **dimension** $$N$$
-if only up to $$N$$ of its vectors can be linearly indepedent.
+$$\mathbb{V}$$ has **dimension** $$N$$
+if only up to $$N$$ of its vectors can be linearly independent.
All other vectors in $$\mathbb{V}$$ can then be written
as a **linear combination** of these $$N$$ **basis vectors**.
-Let $$\vu{e}_1, ..., \vu{e}_N$$ be the basis vectors,
-then any vector $$V$$ in the same space can be **expanded**
-in the basis according to the unique weights $$v_n$$,
-known as the **components** of $$V$$ in that basis:
+Let $$\vu{e}_1, ..., \vu{e}_N$$ be a (generally not unique)
+valid set of basis vectors of $$\mathbb{V}$$,
+then any vector $$V$$ in that space can be **expanded**
+in that basis according to unique weights $$v_n$$,
+called the **components** of $$V$$ in that basis:
$$\begin{aligned}
V = \sum_{n = 1}^N v_n \vu{e}_n
\end{aligned}$$
-Using these, the vector space operations can then be implemented as follows:
+Using these components,
+the operations of vector addition and scalar multiplication
+can then be implemented as follows:
$$\begin{gathered}
V = \sum_{n = 1} v_n \vu{e}_n
- \quad
+ \qquad
W = \sum_{n = 1} w_n \vu{e}_n
\\
\quad \implies \quad
@@ -73,18 +86,24 @@ $$\begin{gathered}
a V = \sum_{n = 1}^N a v_n \vu{e}_n
\end{gathered}$$
+It is straightforward to see that this implementation satisfies the properties above.
+
## Inner product
-A given vector space $$\mathbb{V}$$ can be promoted to a **Hilbert space** or **inner product space**
+A given vector space $$\mathbb{V}$$ can be promoted
+to a **Hilbert space** or **inner product space**
if it supports an operation $$\Inprod{U}{V}$$ called the **inner product**,
which takes two vectors and returns a scalar,
and has the following properties:
-+ **Skew symmetry**: $$\Inprod{U}{V} = (\Inprod{V}{U})^*$$, where $${}^*$$ is the complex conjugate.
-+ **Positive semidefiniteness**: $$\Inprod{V}{V} \ge 0$$, and $$\Inprod{V}{V} = 0$$ if $$V = \mathbf{0}$$.
-+ **Linearity in second operand**: $$\Inprod{U}{(a V + b W)} = a \Inprod{U}{V} + b \Inprod{U}{W}$$.
++ **Skew symmetry**:
+ $$\Inprod{U}{V} = (\Inprod{V}{U})^*$$, where $${}^*$$ is the complex conjugate.
++ **Positive semidefiniteness**:
+ $$\Inprod{V}{V} \ge 0$$, and $$\Inprod{V}{V} = 0$$ if $$V = \mathbf{0}$$.
++ **Linearity in second operand**:
+ $$\Inprod{U}{(a V + b W)} = a \Inprod{U}{V} + b \Inprod{U}{W}$$.
The inner product describes the lengths and angles of vectors,
and in Euclidean space it is implemented by the dot product.
@@ -93,34 +112,39 @@ The **magnitude** or **norm** $$|V|$$ of a vector $$V$$ is given by
$$|V| = \sqrt{\Inprod{V}{V}}$$ and represents the real positive length of $$V$$.
A **unit vector** has a norm of 1.
-Two vectors $$U$$ and $$V$$ are **orthogonal** if their inner product
-$$\Inprod{U}{V} = 0$$. If in addition to being orthogonal, $$|U| = 1$$ and
-$$|V| = 1$$, then $$U$$ and $$V$$ are known as **orthonormal** vectors.
+Two vectors $$U$$ and $$V$$ are **orthogonal**
+if their inner product $$\Inprod{U}{V} = 0$$.
+If, in addition to being orthogonal, $$|U| = 1$$ and $$|V| = 1$$,
+then $$U$$ and $$V$$ are known as **orthonormal** vectors.
-Orthonormality is desirable for basis vectors, so if they are
-not already like that, it is common to manually turn them into a new
-orthonormal basis using e.g. the [Gram-Schmidt method](/know/concept/gram-schmidt-method).
+Orthonormality is desirable for basis vectors,
+so if they are not already like that,
+it is common to manually turn them into a new orthonormal basis,
+using e.g. the [Gram-Schmidt method](/know/concept/gram-schmidt-method).
-As for the implementation of the inner product, it is given by:
+The implementation of the inner product in terms of components and basis vectors
+is as follows, which can easily be shown to satisfy the properties above:
$$\begin{gathered}
V = \sum_{n = 1}^N v_n \vu{e}_n
- \quad
+ \qquad
W = \sum_{n = 1}^N w_n \vu{e}_n
\\
\quad \implies \quad
\Inprod{V}{W} = \sum_{n = 1}^N \sum_{m = 1}^N v_n^* w_m \Inprod{\vu{e}_n}{\vu{e}_j}
\end{gathered}$$
-If the basis vectors $$\vu{e}_1, ..., \vu{e}_N$$ are already
-orthonormal, this reduces to:
+If the basis vectors $$\vu{e}_1, ..., \vu{e}_N$$ are already orthonormal,
+this reduces to:
$$\begin{aligned}
\Inprod{V}{W} = \sum_{n = 1}^N v_n^* w_n
\end{aligned}$$
-As it turns out, the components $$v_n$$ are given by the inner product
-with $$\vu{e}_n$$, where $$\delta_{nm}$$ is the Kronecker delta:
+This suggests a way to calculate the components $$v_n$$:
+taking the inner product of $$V$$ with a basis vector $$\vu{e}_n$$
+"picks out" the corresponding component $$v_n$$.
+Let $$\delta_{nm}$$ be the Kronecker delta:
$$\begin{aligned}
\Inprod{\vu{e}_n}{V} = \sum_{m = 1}^N \delta_{nm} v_m = v_n
@@ -134,40 +158,46 @@ As the dimensionality $$N$$ tends to infinity, things may or may not
change significantly, depending on whether $$N$$ is **countably** or
**uncountably** infinite.
-In the former case, not much changes: the infinitely many **discrete**
-basis vectors $$\vu{e}_n$$ can all still be made orthonormal as usual,
-and as before:
+In the former case, not much changes:
+the infinitely many **discrete** basis vectors $$\vu{e}_n$$
+can all still be made orthonormal as usual, and as before:
$$\begin{aligned}
V = \sum_{n = 1}^\infty v_n \vu{e}_n
\end{aligned}$$
-A good example of such a countably-infinitely-dimensional basis are the
-solution eigenfunctions of a [Sturm-Liouville problem](/know/concept/sturm-liouville-theory/).
+A good example of such a countably-infinitely-dimensional basis
+are the solution eigenfunctions of
+a [Sturm-Liouville problem](/know/concept/sturm-liouville-theory/).
-However, if the dimensionality is uncountably infinite, the basis
-vectors are **continuous** and cannot be labeled by $$n$$. For example, all
-complex functions $$f(x)$$ defined for $$x \in [a, b]$$ which
-satisfy $$f(a) = f(b) = 0$$ form such a vector space.
-In this case $$f(x)$$ is expanded as follows, where $$x$$ is a basis vector:
+However, if the dimensionality is uncountably infinite,
+the basis vectors are **continuous** and cannot be labeled by $$n$$.
+For example, all complex functions $$f(x)$$ defined on the interval $$x \in [a, b]$$
+satisfying the boundary condition $$f(a) = f(b) = 0$$, form such a vector space.
+In this case, every value of $$f(x)$$ is the component of
+an abstract vector $$\Ket{f}$$ with respect to a basis vector $$\Ket{x}$$:
$$\begin{aligned}
- f(x) = \int_a^b \Inprod{x}{f} \dd{x}
+ f(x) = \Inprod{x}{f}
\end{aligned}$$
-Similarly, the inner product $$\Inprod{f}{g}$$ must also be redefined as
-follows:
+The inner product $$\Inprod{f}{g}$$ must be redefined as follows,
+effectively turning the sum over a discrete basis
+into an integral over a continuous basis:
$$\begin{aligned}
\Inprod{f}{g} = \int_a^b f^*(x) \: g(x) \dd{x}
\end{aligned}$$
-The concept of orthonormality must be also weakened. A finite function
-$$f(x)$$ can be normalized as usual, but the basis vectors $$x$$ themselves
-cannot, since each represents an infinitesimal section of the real line.
+The concept of orthonormality must be also weakened.
+A finite function $$f(x)$$ can be normalized as usual,
+but the basis vectors $$x$$ themselves cannot,
+since each represents an infinitesimal section of the real line.
+So how to proceed?
-The rationale in this case is that action of the identity operator $$\hat{I}$$ must
-be preserved, which is given here in [Dirac notation](/know/concept/dirac-notation/):
+The rationale in this case is that the action
+of the identity operator $$\hat{I}$$ must be preserved,
+which is given here in [Dirac notation](/know/concept/dirac-notation/):
$$\begin{aligned}
\hat{I} = \int_a^b \Ket{\xi} \Bra{\xi} \dd{\xi}
@@ -181,8 +211,9 @@ $$\begin{aligned}
= \int_a^b \Inprod{x}{\xi} f(\xi) \dd{\xi}
\end{aligned}$$
-Since we want the latter integral to reduce to $$f(x)$$, it is plain to see that
-$$\Inprod{x}{\xi}$$ can only be a [Dirac delta function](/know/concept/dirac-delta-function/),
+Since we want the latter integral to reduce to $$f(x)$$,
+it is plain to see that $$\Inprod{x}{\xi}$$ can only be
+a [Dirac delta function](/know/concept/dirac-delta-function/),
i.e $$\Inprod{x}{\xi} = \delta(x - \xi)$$:
$$\begin{aligned}
@@ -191,12 +222,13 @@ $$\begin{aligned}
= f(x)
\end{aligned}$$
-Consequently, $$\Inprod{x}{\xi} = 0$$ if $$x \neq \xi$$ as expected for an
-orthogonal set of vectors, but if $$x = \xi$$ the inner product
-$$\Inprod{x}{\xi}$$ is infinite, unlike earlier.
+Consequently, $$\Inprod{x}{\xi} = 0$$ if $$x \neq \xi$$
+as expected for an orthogonal set of vectors,
+but if $$x = \xi$$ then the inner product $$\Inprod{x}{\xi}$$ is infinite,
+unlike earlier.
-Technically, because the basis vectors $$x$$ cannot be normalized, they
-are not members of a Hilbert space, but rather of a superset called a
-**rigged Hilbert space**. Such vectors have no finite inner product with
-themselves, but do have one with all vectors from the actual Hilbert
-space.
+Technically, because the basis vectors $$x$$ cannot be normalized,
+they are not members of a Hilbert space,
+but rather of a superset called a **rigged Hilbert space**.
+Such vectors have no finite inner product with themselves,
+but do have one with all vectors from the actual Hilbert space.
diff --git a/source/know/concept/interaction-picture/index.md b/source/know/concept/interaction-picture/index.md
index de469fa..a3bb260 100644
--- a/source/know/concept/interaction-picture/index.md
+++ b/source/know/concept/interaction-picture/index.md
@@ -13,17 +13,19 @@ is an alternative formulation of quantum mechanics,
equivalent to both the Schrödinger picture
and the [Heisenberg picture](/know/concept/heisenberg-picture/).
-Recall that Schrödinger lets states $$\Ket{\psi_S(t)}$$ evolve in time,
-but keeps operators $$\hat{L}_S$$ fixed (except for explicit time dependence).
-Meanwhile, Heisenberg keeps states $$\Ket{\psi_H}$$ fixed,
-and puts all time dependence on the operators $$\hat{L}_H(t)$$.
+Recall that in the Schrödinger picture,
+the states $$\Ket{\psi_S(t)}$$ evolve in time,
+but time-independent operators $$\hat{L}_S$$ are fixed.
+Meanwhile in the Heisenberg picture,
+the states $$\Ket{\psi_H}$$ are constant,
+and all time dependence is on the operators $$\hat{L}_H(t)$$ instead.
-However, in the interaction picture,
+In the interaction picture,
both the states $$\Ket{\psi_I(t)}$$ and the operators $$\hat{L}_I(t)$$
evolve in $$t$$.
-This might seem unnecessarily complicated,
-but it turns out be convenient when considering
-a time-dependent "perturbation" $$\hat{H}_{1,S}$$
+This may seem unnecessarily complicated,
+but it turns out to be convenient when considering
+a system with a time-dependent "perturbation" $$\hat{H}_{1,S}$$
to a time-independent Hamiltonian $$\hat{H}_{0,S}$$:
$$\begin{aligned}
@@ -31,29 +33,43 @@ $$\begin{aligned}
= \hat{H}_{0,S} + \hat{H}_{1,S}(t)
\end{aligned}$$
-With $$\hat{H}_S(t)$$ the full Schrödinger Hamiltonian.
-We define the unitary conversion operator:
+Despite being called a perturbation,
+$$\hat{H}_{1, S}$$ need not be weak compared to $$\hat{H}_{0, S}$$.
+Basically, any way of splitting $$\hat{H}_S$$ is valid
+as long as $$\hat{H}_{0, S}$$ is time-independent,
+but only a few ways are useful.
+
+We now define the unitary conversion operator $$\hat{U}_0(t)$$ as shown below.
+Note its similarity to the
+[time-evolution operator](/know/concept/time-evolution-operator/) $$\hat{K}_S(t)$$:
$$\begin{aligned}
\boxed{
- \hat{U}(t)
- \equiv \exp\!\bigg( i \frac{\hat{H}_{0,S} t}{\hbar} \bigg)
+ \hat{U}_0(t)
+ \equiv \exp\!\bigg( \!-\! \frac{i}{\hbar} \hat{H}_{0,S} t \bigg)
}
\end{aligned}$$
-The interaction-picture states $$\Ket{\psi_I(t)}$$ and operators $$\hat{L}_I(t)$$
-are then defined to be:
+The interaction-picture states $$\Ket{\psi_I(t)}$$
+and operators $$\hat{L}_I(t)$$ are then defined as follows:
$$\begin{aligned}
\boxed{
\Ket{\psi_I(t)}
- \equiv \hat{U}(t) \Ket{\psi_S(t)}
- \qquad
+ \equiv \hat{U}_0^\dagger(t) \Ket{\psi_S(t)}
+ }
+ \qquad\qquad
+ \boxed{
\hat{L}_I(t)
- \equiv \hat{U}(t) \: \hat{L}_S(t) \: \hat{U}{}^\dagger(t)
+ \equiv \hat{U}_0^\dagger(t) \: \hat{L}_S(t) \: \hat{U}{}_0(t)
}
\end{aligned}$$
+Because $$\hat{H}_{0, S}$$ is time-independent,
+it commutes with $$\hat{U}_0$$,
+so conveniently $$\hat{H}_{0, I} = \hat{H}_{0, S}$$.
+
+
## Equations of motion
@@ -61,152 +77,128 @@ To find the equation of motion for $$\Ket{\psi_I(t)}$$,
we differentiate it and multiply by $$i \hbar$$:
$$\begin{aligned}
- i \hbar \dv{}{t}\Ket{\psi_I}
- &= i \hbar \Big( \dv{\hat{U}}{t} \Ket{\psi_S} + \hat{U} \dv{}{t}\Ket{\psi_S} \Big)
- \\
- &= i \hbar \Big( i \frac{\hat{H}_{0,S}}{\hbar} \Big) \hat{U} \Ket{\psi_S} + \hat{U} \Big( i \hbar \dv{}{t}\Ket{\psi_S} \Big)
+ i \hbar \dv{}{t} \Ket{\psi_I}
+ &= i \hbar \dv{\hat{U}_0^\dagger}{t} \Ket{\psi_S} + \hat{U}_0^\dagger \bigg( i \hbar \dv{}{t}\Ket{\psi_S} \bigg)
\end{aligned}$$
-We insert the Schrödinger equation into the second term,
-and use $$\comm{\hat{U}}{\hat{H}_{0,S}} = 0$$:
+We insert the definition of $$\hat{U}_0$$ in the first term
+and the Schrödinger equation into the second,
+and use the fact that $$\comm{\hat{H}_{0, S}}{\hat{U}_0} = 0$$
+thanks to the time-independence of $$\hat{H}_{0, S}$$:
$$\begin{aligned}
- i \hbar \dv{}{t}\Ket{\psi_I}
- &= - \hat{H}_{0,S} \hat{U} \Ket{\psi_S} + \hat{U} \hat{H}_S \Ket{\psi_S}
+ i \hbar \dv{}{t} \Ket{\psi_I}
+ &= - \hat{H}_{0,S} \hat{U}_0^\dagger \Ket{\psi_S} + \hat{U}_0^\dagger \hat{H}_S \Ket{\psi_S}
\\
- &= \hat{U} \big( \!-\! \hat{H}_{0,S} + \hat{H}_S \big) \Ket{\psi_S}
+ &= \hat{U}_0^\dagger \big( \!-\! \hat{H}_{0,S} + \hat{H}_S \big) \Ket{\psi_S}
\\
- &= \hat{U} \big( \hat{H}_{1,S} \big) \hat{U}{}^\dagger \hat{U} \Ket{\psi_S}
+ &= \hat{U}_0^\dagger \hat{H}_{1,S} \big( \hat{U}_0 \hat{U}_0^\dagger \big) \Ket{\psi_S}
\end{aligned}$$
Which leads to an analogue of the Schrödinger equation,
-with $$\hat{H}_{1,I} = \hat{U} \hat{H}_{1,S} \hat{U}{}^\dagger$$:
+with $$\hat{H}_{1,I} = \hat{U}_0^\dagger \hat{H}_{1,S} \hat{U}_0$$:
$$\begin{aligned}
\boxed{
- i \hbar \dv{}{t}\Ket{\psi_I(t)}
+ i \hbar \dv{}{t} \Ket{\psi_I(t)}
= \hat{H}_{1,I}(t) \Ket{\psi_I(t)}
}
\end{aligned}$$
Next, we do the same with an operator $$\hat{L}_I$$
-to find a description of its evolution in time:
+in order to describe its evolution in time:
$$\begin{aligned}
- \dv{}{t}\hat{L}_I
- &= \dv{\hat{U}}{t} \hat{L}_S \hat{U}{}^\dagger + \hat{U} \hat{L}_S \dv{\hat{U}{}^\dagger}{t} + \hat{U} \dv{\hat{L}_S}{t} \hat{U}{}^\dagger
+ \dv{\hat{L}_I}{t}
+ &= \dv{\hat{U}_0^\dagger}{t} \hat{L}_S \hat{U}_0 + \hat{U}_0^\dagger \hat{L}_S \dv{\hat{U}_0}{t}
+ + \hat{U}_0^\dagger \dv{\hat{L}_S}{t} \hat{U}_0
\\
- &= \frac{i}{\hbar} \hat{U} \hat{H}_{0,S} \big( \hat{U}{}^\dagger \hat{U} \big) \hat{L}_S \hat{U}{}^\dagger
- - \frac{i}{\hbar} \hat{U} \hat{L}_S \big( \hat{U}{}^\dagger \hat{U} \big) \hat{H}_{0,S} \hat{U}{}^\dagger
- + \Big( \dv{\hat{L}_S}{t} \Big)_I
+ &= \frac{i}{\hbar} \hat{U}_0^\dagger \hat{H}_{0,S} \big( \hat{U}_0 \hat{U}_0^\dagger \big) \hat{L}_S \hat{U}_0
+ - \frac{i}{\hbar} \hat{U}_0^\dagger \hat{L}_S \big( \hat{U}_0 \hat{U}_0^\dagger \big) \hat{H}_{0,S} \hat{U}_0
+ + \bigg( \dv{\hat{L}_S}{t} \bigg)_I
\\
&= \frac{i}{\hbar} \hat{H}_{0,I} \hat{L}_I
- \frac{i}{\hbar} \hat{L}_I \hat{H}_{0,I}
- + \Big( \dv{\hat{L}_S}{t} \Big)_I
- = \frac{i}{\hbar} \comm{\hat{H}_{0,I}}{\hat{L}_I} + \Big( \dv{\hat{L}_S}{t} \Big)_I
+ + \bigg( \dv{\hat{L}_S}{t} \bigg)_I
\end{aligned}$$
The result is analogous to the equation of motion in the Heisenberg picture:
$$\begin{aligned}
\boxed{
- \dv{}{t}\hat{L}_I(t)
- = \frac{i}{\hbar} \comm{\hat{H}_{0,I}(t)}{\hat{L}_I(t)} + \Big( \dv{}{t}\hat{L}_S(t) \Big)_I
+ \dv{}{t} \hat{L}_I(t)
+ = \frac{i}{\hbar} \comm{\hat{H}_{0,I}(t)}{\hat{L}_I(t)} + \bigg( \dv{}{t}\hat{L}_S(t) \bigg)_I
}
\end{aligned}$$
+In other words, in the interaction picture,
+the "simple" time-dependence (from $$\hat{H}_{0, S}$$) is given to the operators,
+and the "complicated" dependence (from $$\hat{H}_{1, S}$$) to the states.
+This means that the difficult part of a problem
+can be solved in isolation in a kind of Schrödinger picture.
-## Time evolution operator
-Recall that an alternative form of the Schrödinger equation is as follows,
-where a **time evolution operator** or
-**generator of translations in time** $$K_S(t, t_0)$$
-brings $$\Ket{\psi_S}$$ from time $$t_0$$ to $$t$$:
-$$\begin{aligned}
- \Ket{\psi_S(t)}
- = \hat{K}_S(t, t_0) \Ket{\psi_S(t_0)}
- \qquad \quad
- \hat{K}_S(t, t_0)
- \equiv \exp\!\Big( \!-\! i \frac{\hat{H}_S (t - t_0)}{\hbar} \Big)
-\end{aligned}$$
+## Time evolution operator
-We want to find an analogous operator in the interaction picture, satisfying:
+What about the time evolution operator $$\hat{K}_S(t)$$?
+Its interaction version $$\hat{K}_I(t)$$
+is unsurprisingly obtained by the standard transform
+$$\hat{K}_I = \hat{U}_0^\dagger \hat{K}_S \hat{U}_0$$:
$$\begin{aligned}
\Ket{\psi_I(t)}
- \equiv \hat{K}_I(t, t_0) \Ket{\psi_I(t_0)}
-\end{aligned}$$
-
-Inserting this definition into the equation of motion for $$\Ket{\psi_I}$$ yields
-an equation for $$\hat{K}_I$$, with the logical boundary condition $$\hat{K}_I(t_0, t_0) = 1$$:
-
-$$\begin{aligned}
- i \hbar \dv{}{t}\Big( \hat{K}_I(t, t_0) \Ket{\psi_I(t_0)} \Big)
- &= \hat{H}_{1,I}(t) \Big( \hat{K}_I(t, t_0) \Ket{\psi_I(t_0)} \Big)
+ &= \hat{U}_0^\dagger(t) \Ket{\psi_S(t)}
\\
- i \hbar \dv{}{t}\hat{K}_I(t, t_0)
- &= \hat{H}_{1,I}(t) \hat{K}_I(t, t_0)
-\end{aligned}$$
-
-We turn this into an integral equation
-by integrating both sides from $$t_0$$ to $$t$$:
-
-$$\begin{aligned}
- i \hbar \int_{t_0}^t \dv{}{t'}K_I(t', t_0) \dd{t'}
- = \int_{t_0}^t \hat{H}_{1,I}(t') \hat{K}_I(t', t_0) \dd{t'}
-\end{aligned}$$
-
-After evaluating the left integral,
-we see an expression for $$\hat{K}_I$$ as a function of $$\hat{K}_I$$ itself:
-
-$$\begin{aligned}
- K_I(t, t_0)
- = 1 + \frac{1}{i \hbar} \int_{t_0}^t \hat{H}_{1,I}(t') \hat{K}_I(t', t_0) \dd{t'}
+ &= \hat{U}_0^\dagger(t) \: \hat{K}_S(t) \Ket{\psi_S(0)}
+ \\
+ &= \hat{U}_0^\dagger(t) \: \hat{K}_S(t) \: \hat{U}_0(t) \: \hat{U}_0^\dagger(t) \Ket{\psi_S(0)}
+ \\
+ &\equiv \hat{K}_I(t) \Ket{\psi_I(0)}
\end{aligned}$$
-By recursively inserting $$\hat{K}_I$$ once, we get a longer expression,
-still with $$\hat{K}_I$$ on both sides:
+But we can do better. By inserting this definition of $$\hat{K}_I$$
+into the interaction picture's analogue of Schrödinger's equation,
+we get the following relation for $$\hat{K}_I$$:
$$\begin{aligned}
- K_I(t, t_0)
- = 1 + \frac{1}{i \hbar} \int_{t_0}^t \hat{H}_{1,I}(t') \dd{t'}
- + \frac{1}{(i \hbar)^2} \int_{t_0}^t \hat{H}_{1,I}(t') \int_{t_0}^{t'} \hat{H}_{1,I}(t'') \hat{K}_I(t'', t_0) \dd{t''} \dd{t'}
+ i \hbar \dv{}{t} \hat{K}_I(t)
+ &= \hat{H}_{1,I}(t) \: \hat{K}_I(t)
\end{aligned}$$
-And so on. Note the ordering of the integrals and integrands:
-upon closer inspection, we see that the $$n$$th term is
-a [time-ordered product](/know/concept/time-ordered-product/) $$\mathcal{T}$$
-of $$n$$ factors $$\hat{H}_{1,I}$$:
+In other words, $$\hat{K}_I$$ can be said to also obey
+the standard equation of motion for states, despite being an operator.
+We integrate both sides and use $$\hat{K}_I(0) = 1$$:
$$\begin{aligned}
- \hat{K}_I(t, t_0)
- &= 1 + \int_{t_0}^t \hat{H}_{1,I}(t_1) \dd{t_1}
- + \frac{1}{2} \int_{t_0}^{t} \int_{t_0}^{t_1} \mathcal{T} \Big\{ \hat{H}_{1,I}(t_1) \hat{H}_{1,I}(t_2) \Big\} \dd{t_1} \dd{t_2}
- + \: ...
- \\
- &= 1 + \sum_{n = 1}^\infty \frac{1}{n!} \frac{1}{(i \hbar)^n}
- \int_{t_0}^{t} \cdots \int_{t_0}^{t_n} \mathcal{T} \Big\{ \hat{H}_{1,I}(t_1) \cdots \hat{H}_{1,I}(t_n) \Big\} \dd{t_1} \cdots \dd{t_n}
- \\
- &= \sum_{n = 0}^\infty \frac{1}{n!} \frac{1}{(i \hbar)^n}
- \mathcal{T} \bigg\{ \bigg( \int_{t_0}^{t} \hat{H}_{1,I}(t') \dd{t'} \bigg)^n \bigg\}
+ K_I(t)
+ = 1 + \frac{1}{i \hbar} \int_0^t \hat{H}_{1,I}(\tau) \: \hat{K}_I(\tau) \dd{\tau}
\end{aligned}$$
-This construction is occasionally called the **Dyson series**.
-We recognize the well-known Taylor expansion of $$\exp(x)$$,
-leading us to a final expression for $$\hat{K}_I$$:
+This equation can be recursively inserted into itself forever.
+We recognize the resulting so called *Dyson series*
+from the derivation of $$\hat{K}_S(t)$$
+for time-dependent Hamiltonians in the Schrödinger picture
+([given here](/know/concept/time-evolution-operator/)),
+so we know that the result is given by:
$$\begin{aligned}
\boxed{
- \hat{K}_I(t, t_0)
- = \mathcal{T} \bigg\{ \exp\!\bigg( \frac{1}{i \hbar} \int_{t_0}^t \hat{H}_{1,I}(t') \dd{t'} \bigg) \bigg\}
+ \hat{K}_I(t)
+ = \mathcal{T} \bigg\{ \exp\!\bigg( \frac{1}{i \hbar} \int_0^t \hat{H}_{1,I}(\tau) \dd{\tau} \bigg) \bigg\}
}
\end{aligned}$$
+Where $$\mathcal{T}$$ is the
+[time-ordering meta-operator](/know/concept/time-ordered-product/),
+which is conventionally written in this way
+to say that it applies to the terms of a Taylor expansion of $$\exp(x)$$.
+This means that the evolution of a quantum state in the interaction picture
+is determined by the perturbation $$\hat{H}_{1, I}$$.
+
## References
1. H. Bruus, K. Flensberg,
*Many-body quantum theory in condensed matter physics*,
2016, Oxford.
-
diff --git a/source/know/concept/ito-integral/index.md b/source/know/concept/ito-integral/index.md
index 4a725e1..9b092d6 100644
--- a/source/know/concept/ito-integral/index.md
+++ b/source/know/concept/ito-integral/index.md
@@ -10,8 +10,7 @@ layout: "concept"
The **Itō integral** offers a way to integrate
a given [stochastic process](/know/concept/stochastic-process/) $$G_t$$
-with respect to a [Wiener process](/know/concept/wiener-process/) $$B_t$$,
-which is also a stochastic process.
+with respect to a [Wiener process](/know/concept/wiener-process/) $$B_t$$.
The Itō integral $$I_t$$ of $$G_t$$ is defined as follows:
$$\begin{aligned}
@@ -47,21 +46,21 @@ which can be applied recursively, leading to:
$$\begin{aligned}
X_{t+h}
\approx X_{t} + f(X_t) \: h
- \quad \implies \quad
+ \qquad \implies \qquad
X_t
\approx X_0 + \sum_{s = 0}^{s = t} f(X_s) \: h
\end{aligned}$$
-In the limit $$h \to 0$$, this leads to the following unsurprising integral for $$X_t$$:
+In the limit $$h \to 0$$, this unsurprisingly leads to the following integral for $$X_t$$:
$$\begin{aligned}
- \int_0^t f(X_s) \dd{s}
- = \lim_{h \to 0} \sum_{s = 0}^{s = t} f(X_s) \: h
+ \lim_{h \to 0} \sum_{s = 0}^{s = t} f(X_s) \: h
+ = \int_0^t f(X_s) \dd{s}
\end{aligned}$$
In contrast, consider the *stochastic differential equation* below,
where $$\xi_t$$ represents white noise,
-which is informally the $$t$$-derivative
+which is informally defined as the $$t$$-derivative
of the Wiener process $$\xi_t = \idv{B_t}{t}$$:
$$\begin{aligned}
@@ -89,9 +88,9 @@ $$\begin{aligned}
= X_0 + \int_0^t g(X_s) \dd{B_s}
\end{aligned}$$
-This integral is *defined* as below,
-analogously to the first, but with $$h$$ replaced by
-the increment $$B_{t+h} \!-\! B_t$$ of a Wiener process.
+The meaning of such an integral is *defined* below.
+It is analogous to the deterministic case,
+but $$h$$ is replaced by the increment $$B_{t+h} \!-\! B_t$$ of a Wiener process.
This is an Itō integral:
$$\begin{aligned}
@@ -100,7 +99,7 @@ $$\begin{aligned}
\end{aligned}$$
For more information about applying the Itō integral in this way,
-see the [Itō calculus](/know/concept/ito-process/).
+see [Itō calculus](/know/concept/ito-process/).
@@ -131,7 +130,7 @@ $$\begin{aligned}
A more interesting property is the **Itō isometry**,
which expresses the expectation of the square of an Itō integral of $$G_t$$
as a simpler "ordinary" integral of the expectation of $$G_t^2$$
-(which exists by the definition of Itō-integrability):
+(which exists due to the definition of Itō-integrability):
$$\begin{aligned}
\boxed{
@@ -172,24 +171,16 @@ $$\begin{aligned}
However, $$\mathcal{F}_t$$ says nothing about
the increment $$(B_{t + h} \!-\! B_t) \sim \mathcal{N}(0, h)$$,
-meaning that the conditional expectation is zero:
+meaning that the conditional expectation is zero for $$t \ge s + h$$:
$$\begin{aligned}
\mathbf{E} \Big[ G_t G_s (B_{t + h} \!-\! B_t) (B_{s + h} \!-\! B_s) \Big]
= 0
- \qquad \mathrm{for}\; t \ge s + h
\end{aligned}$$
-By swapping $$s$$ and $$t$$, the exact same result can be obtained for $$s \ge t \!+\! h$$:
-
-$$\begin{aligned}
- \mathbf{E} \Big[ G_t G_s (B_{t + h} \!-\! B_t) (B_{s + h} \!-\! B_s) \Big]
- = 0
- \qquad \mathrm{for}\; s \ge t + h
-\end{aligned}$$
-
-This leaves only one case which can be nonzero: $$[t, t\!+\!h] = [s, s\!+\!h]$$.
-Applying the law of total expectation again yields:
+By swapping $$s$$ and $$t$$, the exact same result can be obtained for $$s \ge t \!+\! h$$.
+This leaves only one possibly nonzero case: $$[t, t\!+\!h] = [s, s\!+\!h]$$.
+Applying the law of total expectation again:
$$\begin{aligned}
\mathbf{E} \bigg[ \sum_{t = a}^{t = b} G_t (B_{t + h} \!-\! B_t) \bigg]^2
@@ -198,15 +189,15 @@ $$\begin{aligned}
&= \sum_{t = a}^{t = b} \mathbf{E} \bigg[ \mathbf{E} \Big[ G_t^2 (B_{t + h} \!-\! B_t)^2 \Big| \mathcal{F}_t \Big] \bigg]
\end{aligned}$$
-We know $$G_t$$, and the expectation value of $$(B_{t+h} \!-\! B_t)^2$$,
-since the increment is normally distributed, is simply the variance $$h$$:
+We know $$G_t$$,
+and the expectation value of $$(B_{t+h} \!-\! B_t)^2$$ is simply the variance $$h$$:
$$\begin{aligned}
\mathbf{E} \bigg[ \sum_{t = a}^{t = b} G_t (B_{t + h} \!-\! B_t) \bigg]^2
&= \sum_{t = a}^{t = b} \mathbf{E} \big[ G_t^2 \big] h
- \longrightarrow
- \int_a^b \mathbf{E} \big[ G_t^2 \big] \dd{t}
\end{aligned}$$
+
+Taking the limit $$h \to 0$$ then yields the desired result.
{% include proof/end.html id="proof-isometry" %}
@@ -239,7 +230,7 @@ $$\begin{aligned}
\end{aligned}$$
We now have everything we need to calculate $$\mathbf{E} [ I_t | \mathcal{F_s} ]$$,
-giving the martingale property:
+leading to the martingale property:
$$\begin{aligned}
\mathbf{E} \big[ I_t | \mathcal{F}_s \big]
@@ -250,10 +241,10 @@ $$\begin{aligned}
For the existence of $$I_t$$,
we need $$\mathbf{E}[G_t^2]$$ to be integrable over the target interval,
-so from the Itō isometry we have $$\mathbf{E}[I]^2 < \infty$$,
-and therefore $$\mathbf{E}[I] < \infty$$,
-so $$I_t$$ has all the properties of a Martingale,
-since it is trivially $$\mathcal{F}_t$$-adapted.
+which implies via the Itō isometry that $$\mathbf{E}[I]^2$$ is finite.
+Therefore $$\mathbf{E}[I]$$ is also finite,
+so $$I_t$$ has all the properties of a Martingale
+(since it is trivially $$\mathcal{F}_t$$-adapted).
{% include proof/end.html id="proof-martingale" %}
diff --git a/source/know/concept/jellium/index.md b/source/know/concept/jellium/index.md
index 5c50f80..5cd8483 100644
--- a/source/know/concept/jellium/index.md
+++ b/source/know/concept/jellium/index.md
@@ -12,32 +12,24 @@ layout: "concept"
**Jellium**, also called the **uniform** or **homogeneous electron gas**,
is a theoretical material where all electrons are free,
and the ions' positive charge is smeared into a uniform background "jelly".
-This simple model lets us study electron interactions easily.
+This is a version of the [Fermi gas](/know/concept/fermi-gas/) model,
+which we extend by including electron-electron interactions using
+[time-independent perturbation theory](/know/concept/time-independent-perturbation-theory/).
-## Without interactions
-Let us start by neglecting electron-electron interactions.
-This is clearly a dubious assumption, but we will stick with it for now.
-For an infinitely large sample of jellium,
-the single-electron states are simply plane waves.
-We consider an arbitrary cube of volume $$V$$,
-and impose periodic boundary conditions on it,
-such that the single-particle orbitals are (suppressing spin):
+## 0th order
-$$\begin{aligned}
- \Inprod{\vb{r}}{\psi_{\vb{k}}}
- = \psi_{\vb{k}}(\vb{r})
- = \frac{1}{\sqrt{V}} \exp(i \vb{k} \cdot \vb{r})
- \qquad \quad
- \vb{k} = \frac{2 \pi}{V^{1/3}} (n_x, n_y, n_z)
-\end{aligned}$$
+Let us start with the 0th order of the perturbation expansion.
+Without interactions or potentials, this is simply a Fermi gas,
+so the single-electron wavefunctions are just plane waves.
+For mathematical convenience, we consider these waves
+in a cube of volume $$V$$ with periodic boundaries,
+leading to a discrete spectrum of allowed wavevectors $$\vb{k}$$,
+which becomes continuous for $$V \to \infty$$.
-Where $$n_x, n_y, n_z \in \mathbb{Z}$$.
-This is a discrete (but infinite) set of independent orbitals,
-so it is natural to use the
-[second quantization](/know/concept/second-quantization/)
-to write the non-interacting Hamiltonian $$\hat{H}_0$$,
+The unperturbed many-particle Hamiltonian $$\hat{H}_0$$ is given below in the
+[second quantization](/know/concept/second-quantization/),
where $$\hbar^2 |\vb{k}|^2 / (2 m)$$ is the kinetic energy
of the orbital with wavevector $$\vb{k}$$, and $$s$$ is the spin:
@@ -46,10 +38,9 @@ $$\begin{aligned}
= \sum_{s} \sum_{\vb{k}} \frac{\hbar^2 |\vb{k}|^2}{2 m} \hat{c}_{s,\vb{k}}^\dagger \hat{c}_{s,\vb{k}}
\end{aligned}$$
-Assuming that the temperature $$T = 0$$,
-the $$N$$-electron ground state of this Hamiltonian
-is known as the **Fermi sea** or **Fermi sphere** $$\Ket{\mathrm{FS}}$$,
-and is constructed by filling up the single-electron states
+Which, at absolute zero $$T = 0$$, has an $$N$$-electron ground state
+known as the *Fermi sphere* $$\Ket{\mathrm{FS}}$$
+that is constructed by filling up the single-electron states
starting from the lowest energy:
$$\begin{aligned}
@@ -57,63 +48,9 @@ $$\begin{aligned}
= \prod_{s} \prod_{j = 1}^{N/2} \hat{c}_{s,\vb{k}_j}^\dagger \Ket{0}
\end{aligned}$$
-Because $$T = 0$$, all the electrons stay in their assigned state.
-The energy and wavenumber $$|\vb{k}|$$ of the highest filled orbital
-are called the **Fermi energy** $$\epsilon_F$$ and **Fermi wavenumber** $$k_F$$,
-and obey the expected kinetic energy relation:
-
-$$\begin{aligned}
- \boxed{
- \epsilon_F
- = \frac{\hbar^2}{2 m} k_F^2
- }
-\end{aligned}$$
-
-The Fermi sea can be visualized in $$\vb{k}$$-space as a sphere with radius $$k_F$$.
-Because $$\vb{k}$$ is discrete, the sphere's surface is not smooth,
-but in the limit $$V \to \infty$$ it becomes perfect.
-
-Now, we would like a relation between the system's parameters,
-e.g. $$N$$ and $$V$$, and the resulting values of $$\epsilon_F$$ or $$k_F$$.
-The total population $$N$$ must be given by:
-
-$$\begin{aligned}
- N
- = \sum_{s} \sum_{\vb{k}} \matrixel{\mathrm{FS}}{\hat{c}_{s,\vb{k}}^\dagger \hat{c}_{s,\vb{k}}}{\mathrm{FS}}
- = \sum_{s} \frac{V}{(2 \pi)^3} \int_{-\infty}^\infty \matrixel{\mathrm{FS}}{\hat{c}_{s,\vb{k}}^\dagger \hat{c}_{s,\vb{k}}}{\mathrm{FS}} \dd{\vb{k}}
-\end{aligned}$$
-
-Where we have turned the sum over $$\vb{k}$$ into an integral with a constant factor,
-by using that each orbital exclusively occupies a volume $$(2 \pi)^3 / V$$ in $$\vb{k}$$-space.
-
-At zero temperature, this inner product can only be $$0$$ or $$1$$,
-depending on whether $$\vb{k}$$ is outside or inside the Fermi sphere.
-We can therefore rewrite using a
-[Heaviside step function](/know/concept/heaviside-step-function/):
-
-$$\begin{aligned}
- N
- = \sum_{s} \frac{V}{(2 \pi)^3} \int_{-\infty}^\infty \Theta(k_F - |\vb{k}|) \dd{\vb{k}}
- = 2 \frac{V}{(2 \pi)^3} \int_{-\infty}^\infty \Theta(k_F - |\vb{k}|) \dd{\vb{k}}
-\end{aligned}$$
-
-Where we realized that spin does not matter,
-and replaced the sum over $$s$$ by a factor $$2$$.
-In order to evaluate this 3D integral,
-we go to [spherical coordinates](/know/concept/spherical-coordinates/)
-$$(|\vb{k}|, \theta, \varphi)$$:
-
-$$\begin{aligned}
- N
- &= \frac{V}{4 \pi^3} \int_0^{2 \pi} \int_0^\pi \int_0^\infty \Theta(k_F - |\vb{k}|) |\vb{k}|^2 \sin(\theta) \dd{|\vb{k}|} \dd{\theta} \dd{\varphi}
- \\
- &= \frac{V}{4 \pi^3} 4 \pi \int_0^{k_F} |\vb{k}|^2 \dd{|\vb{k}|}
- = \frac{V}{\pi^2} \bigg[ \frac{|\vb{k}|^3}{3} \bigg]_0^{k_F}
- = \frac{V}{3 \pi^2} k_F^3
-\end{aligned}$$
-
-Using that the electron density $$n = N/V$$,
-we thus arrive at the following relation:
+From our analysis of the Fermi gas, we have an important result
+for the wavenumber $$k_F = |\vb{k}_{N/2}|$$ of the highest filled orbital,
+as a function of the particle density $$n = N / V$$:
$$\begin{aligned}
\boxed{
@@ -122,103 +59,137 @@ $$\begin{aligned}
}
\end{aligned}$$
-This result also justifies our assumption that $$T = 0$$:
-we can accurately calculate the density $$n$$ for many conducting materials,
-and this relation then gives $$k_F$$ and $$\epsilon_F$$.
-It turns out that $$\epsilon_F$$ is usually very large
-compared to the thermal energy $$k_B T$$ at reasonable temperatures,
-so we can conclude that thermal fluctuations are negligible.
-
-Now, $$\epsilon_F$$ is the highest single-electron energy,
-but about the total $$N$$-particle energy $$E^{(0)}$$?
+Now, let us calculate the total $$N$$-particle ground state
+energy $$E^{(0)}$$ of the unperturbed system:
$$\begin{aligned}
E^{(0)}
= \matrixel{\mathrm{FS}}{\hat{H}_0}{\mathrm{FS}}
- = \sum_{s} \sum_{\vb{k}} \frac{\hbar^2 |\vb{k}|^2}{2 m} \matrixel{\mathrm{FS}}{\hat{c}_{s,\vb{k}}^\dagger \hat{c}_{s,\vb{k}}}{\mathrm{FS}}
+ = 2 \sum_{\vb{k}} \frac{\hbar^2 |\vb{k}|^2}{2 m} \matrixel{\mathrm{FS}}{\hat{c}_{s,\vb{k}}^\dagger \hat{c}_{s,\vb{k}}}{\mathrm{FS}}
\end{aligned}$$
-Once again, we turn the sum over $$\vb{k}$$ into an integral,
-and recognize the spin's irrelevance:
+Where we have recognized the spin's irrelevance,
+by replacing the sum over $$s$$ with a factor $$2$$.
+Next, we turn the sum over the allowed $$\vb{k}$$-values into an integral,
+which is a [common trick](/know/concept/discrete-spectrum-summation/)
+enabled by our periodic boundary conditions, yielding:
$$\begin{aligned}
E^{(0)}
- &= \sum_{s} \frac{V}{(2 \pi)^3} \int_{-\infty}^\infty \frac{\hbar^2 |\vb{k}|^2}{2 m}
+ &= \frac{2 V}{(2 \pi)^3} \int_{-\infty}^\infty \frac{\hbar^2 |\vb{k}|^2}{2 m}
\matrixel{\mathrm{FS}}{\hat{c}_{\vb{k}}^\dagger \hat{c}_{\vb{k}}}{\mathrm{FS}} \dd{\vb{k}}
- \\
+\end{aligned}$$
+
+The matrix element
+$$\matrixel{\mathrm{FS}}{\hat{c}_{\vb{k}}^\dagger \hat{c}_{\vb{k}}}{\mathrm{FS}} \dd{\vb{k}}$$
+is either $$0$$ or $$1$$, depending on whether $$\vb{k}$$
+is outside the Fermi sphere, or, equivalently,
+whether $$|\vb{k}|$$ is above or below $$k_F$$.
+We can write this fact by introducing a
+[Heaviside step function](/know/concept/heaviside-step-function/) $$\Theta(k)$$:
+
+$$\begin{aligned}
+ E^{(0)}
&= \frac{\hbar^2 V}{8 \pi^3 m} \int_{-\infty}^\infty |\vb{k}|^2 \: \Theta(k_F - |\vb{k}|) \dd{\vb{k}}
\end{aligned}$$
-In spherical coordinates,
-we evaluate the integral and find that $$E^{(0)}$$ is proportional to $$k_F^5$$:
+We evaluate this in
+[spherical coordinates](/know/concept/spherical-coordinates/)
+and find that $$E^{(0)}$$ is proportional to $$k_F^5$$:
$$\begin{aligned}
E^{(0)}
&= \frac{\hbar^2 V}{8 \pi^3 m} \int_0^{2 \pi}
\int_0^\pi \int_0^\infty \Big( |\vb{k}|^2 \: \Theta(k_F - |\vb{k}|) \Big) |\vb{k}|^2 \sin(\theta) \dd{|\vb{k}|} \dd{\theta} \dd{\varphi}
\\
- &= \frac{\hbar^2 V}{8 \pi^3 m} 4 \pi \int_0^{k_F} |\vb{k}|^4 \dd{|\vb{k}|}
- = \frac{\hbar^2 V}{2 \pi^2 m} \bigg[ \frac{|\vb{k}|^5}{5} \bigg]_0^{k_F}
- = \frac{\hbar^2 V}{10 \pi^2 m} k_F^5
+ &= \frac{\hbar^2 V}{8 \pi^3 m} \: 4 \pi \int_0^{k_F} |\vb{k}|^4 \dd{|\vb{k}|}
+ \\
+ &= \frac{\hbar^2 V}{10 \pi^2 m} k_F^5
\end{aligned}$$
In general, it is more useful to consider
the average kinetic energy per electron $$E^{(0)} / N$$,
-which we find to be as follows, using that $$k_F^3 = 3 \pi^2 n$$:
+which we find to be as follows,
+using that $$k_F^3 = 3 \pi^2 N / V$$:
$$\begin{aligned}
\boxed{
\frac{E^{(0)}}{N}
= \frac{3 \hbar^2}{10 m} k_F^2
- = \frac{3}{5} \epsilon_F
}
- \:\sim\: n^{2/3}
+ \:\:\propto\: n^{2/3}
\end{aligned}$$
-Traditionally, this is expressed using a dimensionless parameter $$r_s$$,
+Traditionally, this is rewritten using the **Wigner-Seitz radius** $$r_s$$,
defined as the radius of a sphere containing a single electron,
-measured in Bohr radii $$a_0 \equiv 4 \pi \varepsilon_0 \hbar^2 / (e^2 m)$$:
+measured in Bohr radii $$a_0 \equiv 4 \pi \varepsilon_0 \hbar^2 / (e_0^2 m)$$:
$$\begin{aligned}
\frac{4 \pi}{3} (a_0 r_s)^3
- = \frac{1}{n}
- = \frac{3 \pi^2}{k_F^3}
- \quad \implies \quad
+ \equiv \frac{1}{n}
+ \qquad \implies \qquad
r_s
- = \Big( \frac{3}{4 \pi a_0^3 n} \Big)^{1/3}
- = \Big( \frac{9 \pi}{4} \Big)^{1/3} \frac{1}{a_0 k_F}
+ = \bigg( \frac{3}{4 \pi a_0^3 n} \bigg)^{1/3}
\end{aligned}$$
-Such that the ground state energy can be rewritten in Rydberg units of energy like so:
+Note that this is dimensionless due to our choice of $$a_0$$ as a unit.
+In the Fermi gas, we have:
+
+$$\begin{aligned}
+ r_s
+ = \bigg( \frac{9 \pi}{4} \bigg)^{1/3} \frac{1}{a_0 k_F}
+ \qquad \implies \qquad
+ k_F
+ = \bigg( \frac{9 \pi}{4} \bigg)^{1/3} \frac{1}{a_0 r_s}
+\end{aligned}$$
+
+By inserting this into the ground state energy
+and using the definition of $$a_0$$, we can write:
$$\begin{aligned}
\frac{E^{(0)}}{N}
- = \frac{3 \hbar^2}{10 m} \frac{4 \pi \varepsilon_0 e^2}{4 \pi \varepsilon_0 e^2} \frac{a_0^2 k_F^2}{a_0^2}
- = \frac{3 e^2}{40 \pi \varepsilon_0} \Big( \frac{9 \pi}{4} \Big)^{2/3} \frac{1}{a_0 r_s^2}
- \approx \frac{2.21}{r_s^2} \; \mathrm{Ry}
+ &= \frac{3 \hbar^2}{10 m} \bigg( \frac{9 \pi}{4} \bigg)^{2/3} \frac{1}{a_0^2 r_s^2}
+ \\
+ &= \frac{3}{5} \bigg( \frac{9 \pi}{4} \bigg)^{2/3} \bigg( \frac{e_0^2}{8 \pi \varepsilon_0 a_0} \bigg) \frac{1}{r_s^2}
\end{aligned}$$
+Where the last parenthesized expression is
+the Rydberg unit of energy $$\mathrm{Ry} \approx 13.6 \:\mathrm{eV}$$, so:
+
+$$\begin{aligned}
+ \boxed{
+ \frac{E^{(0)}}{N}
+ \approx \frac{2.21}{r_s^2} \; \mathrm{Ry}
+ }
+\end{aligned}$$
+
+This result is found in a lot of literature.
+The choice of Rydberg units is simply a tradition.
+
+
-## With interactions
+## 1st order
-To include Coulomb interactions, let us try
-[time-independent pertubation theory](/know/concept/time-independent-perturbation-theory/).
-Clearly, this will give better results when the interaction is relatively weak, if ever.
+In the next term of the perturbation expansion,
+we start to include Coulomb interactions.
+Clearly, this will give better results when the interaction is relatively weak,
+but is that ever the case?
The Coulomb potential is proportional to the inverse distance,
and the average electron spacing is roughly $$n^{-1/3}$$,
-so the interaction energy $$E_\mathrm{int}$$ should scale as $$n^{1/3}$$.
-We already know that the kinetic energy $$E_\mathrm{kin} = E^{(0)}$$ scales as $$n^{2/3}$$,
-meaning perturbation theory should be reasonable
-if $$1 \gg E_\mathrm{int} / E_\mathrm{kin} \sim n^{-1/3}$$,
-so in the limit of high density $$n \to \infty$$.
+so the interaction energy $$E_\mathrm{int}$$ scales as $$n^{1/3}$$.
+We also know that the kinetic energy $$E_\mathrm{kin} = E^{(0)}$$
+is proportional to $$n^{2/3}$$,
+meaning that it is reasonable to use perturbation theory
+as long as $$1 \gg E_\mathrm{int} / E_\mathrm{kin} \propto n^{-1/3}$$,
+i.e. in the limit of high density $$n \to \infty$$.
The two-body Coulomb interaction operator $$\hat{W}$$
is as follows in second-quantized form:
$$\begin{aligned}
\hat{W}
- = \frac{1}{2 V} \sum_{s_1 s_2} \sum_{\vb{k}_1 \vb{k}_2} \sum_{\vb{q} \neq 0} \frac{e^2}{\varepsilon_0 |\vb{q}|^2}
+ = \frac{1}{2 V} \sum_{s_1 s_2} \sum_{\vb{k}_1 \vb{k}_2} \sum_{\vb{q} \neq 0} \frac{e_0^2}{\varepsilon_0 |\vb{q}|^2}
\hat{c}_{s_1, \vb{k}_1 + \vb{q}}^\dagger \hat{c}_{s_2, \vb{k}_2 - \vb{q}}^\dagger \hat{c}_{s_2, \vb{k}_2} \hat{c}_{s_1, \vb{k}_1}
\end{aligned}$$
@@ -228,7 +199,7 @@ is then given by:
$$\begin{aligned}
E^{(1)}
= \matrixel{\mathrm{FS}}{\hat{W}}{\mathrm{FS}}
- = \frac{e^2}{2 \varepsilon_0 V} \sum_{s_1 s_2} \sum_{\vb{k}_1 \vb{k}_2} \sum_{\vb{q} \neq 0} \frac{1}{|\vb{q}|^2}
+ = \frac{e_0^2}{2 \varepsilon_0 V} \sum_{s_1 s_2} \sum_{\vb{k}_1 \vb{k}_2} \sum_{\vb{q} \neq 0} \frac{1}{|\vb{q}|^2}
\matrixel{\mathrm{FS}}{
\hat{c}_{s_1, \vb{k}_1 + \vb{q}}^\dagger \hat{c}_{s_2, \vb{k}_2 - \vb{q}}^\dagger \hat{c}_{s_2, \vb{k}_2} \hat{c}_{s_1, \vb{k}_1}
}{\mathrm{FS}}
@@ -246,17 +217,17 @@ Let $$s = s_1$$ and $$\vb{k} = \vb{k}_1$$:
$$\begin{aligned}
E^{(1)}
- &= \frac{e^2}{2 \varepsilon_0 V} \sum_{s} \sum_{\vb{k}} \sum_{\vb{q} \neq 0} \frac{1}{|\vb{q}|^2}
+ &= \frac{e_0^2}{2 \varepsilon_0 V} \sum_{s} \sum_{\vb{k}} \sum_{\vb{q} \neq 0} \frac{1}{|\vb{q}|^2}
\matrixel{\mathrm{FS}}{
\hat{c}_{s, \vb{k} + \vb{q}}^\dagger \hat{c}_{s, \vb{k}}^\dagger \hat{c}_{s, \vb{k} + \vb{q}} \hat{c}_{s, \vb{k}}
}{\mathrm{FS}}
\\
- &= \frac{- e^2}{2 \varepsilon_0 V} \sum_{s} \sum_{\vb{k}} \sum_{\vb{q} \neq 0} \frac{1}{|\vb{q}|^2}
+ &= \frac{- e_0^2}{2 \varepsilon_0 V} \sum_{s} \sum_{\vb{k}} \sum_{\vb{q} \neq 0} \frac{1}{|\vb{q}|^2}
\matrixel{\mathrm{FS}}{
\big( \hat{c}_{s, \vb{k} + \vb{q}}^\dagger \hat{c}_{s, \vb{k} + \vb{q}}\big) \big(\hat{c}_{s, \vb{k}}^\dagger \hat{c}_{s, \vb{k}}\big)
}{\mathrm{FS}}
\\
- &= \frac{- e^2}{2 \varepsilon_0 V} \sum_{s} \sum_{\vb{k}} \sum_{\vb{q} \neq 0} \frac{1}{|\vb{q}|^2}
+ &= \frac{- e_0^2}{2 \varepsilon_0 V} \sum_{s} \sum_{\vb{k}} \sum_{\vb{q} \neq 0} \frac{1}{|\vb{q}|^2}
\Theta(k_F - |\vb{k}|) \:\Theta(k_F - |\vb{k} \!+\! \vb{q}|)
\end{aligned}$$
@@ -269,11 +240,11 @@ This yields the integration limit, and therefore leads to:
$$\begin{aligned}
E^{(1)}
- &= \frac{- e^2}{(2 \pi)^3 \varepsilon_0} \sum_{\vb{k}}
+ &= \frac{- e_0^2}{(2 \pi)^3 \varepsilon_0} \sum_{\vb{k}}
\int_0^{2 \pi} \!\!\int_0^\pi \!\!\int_0^\infty \Theta(k_F \!-\! |\vb{k}|) \: \Theta(k_F \!-\! |\vb{k} \!+\! \vb{q}|) \frac{|\vb{q}|^2}{|\vb{q}|^2}
\sin(\theta_q) \dd{|\vb{q}|} \dd{\theta_q} \dd{\varphi_q}
\\
- &= \frac{- e^2}{2 \pi^2 \varepsilon_0} \sum_{\vb{k}}
+ &= \frac{- e_0^2}{2 \pi^2 \varepsilon_0} \sum_{\vb{k}}
\int_0^{2 k_F} \Theta(k_F \!-\! |\vb{k}|) \: \Theta(k_F \!-\! |\vb{k} \!+\! \vb{q}|) \dd{|\vb{q}|}
\end{aligned}$$
@@ -285,11 +256,11 @@ when we go to spherical coordinates $$(|\vb{k}|, \theta_k, \varphi_k)$$ for $$\v
$$\begin{aligned}
E^{(1)}
- &= \frac{- e^2 V}{16 \pi^5 \varepsilon_0} \int_0^{2 k_F} \!\!\!\!\int_0^{2 \pi} \!\!\!\int_0^\pi \!\!\!\int_0^\infty
+ &= \frac{- e_0^2 V}{16 \pi^5 \varepsilon_0} \int_0^{2 k_F} \!\!\!\!\int_0^{2 \pi} \!\!\!\int_0^\pi \!\!\!\int_0^\infty
\!\Theta(k_F \!-\! |\vb{k}|) \: \Theta(k_F \!-\! |\vb{k} \!+\! \vb{q}|)
\: |\vb{k}|^2 \sin(\theta_k) \dd{|\vb{k}|} \dd{\theta_k} \dd{\varphi_k} \dd{|\vb{q}|}
\\
- &= \frac{- e^2 V}{16 \pi^5 \varepsilon_0} \int_0^{2 k_F} \!\!\!\!\int_0^{2 \pi} \!\!\!\int_0^\pi \!\!\!\int_0^{k_F}
+ &= \frac{- e_0^2 V}{16 \pi^5 \varepsilon_0} \int_0^{2 k_F} \!\!\!\!\int_0^{2 \pi} \!\!\!\int_0^\pi \!\!\!\int_0^{k_F}
\!\Theta(k_F \!-\! |\vb{k} \!+\! \vb{q}|)
\: |\vb{k}|^2 \sin(\theta_k) \dd{|\vb{k}|} \dd{\theta_k} \dd{\varphi_k} \dd{|\vb{q}|}
\end{aligned}$$
@@ -335,13 +306,13 @@ substituting $$\xi \equiv \cos(\theta_k)$$:
$$\begin{aligned}
E^{(1)}
- &= \frac{- e^2 V}{16 \pi^5 \varepsilon_0} 2 \int_0^{2 k_F} \!\!\!\int_0^{2 \pi} \!\!\int_0^{\arccos{|\vb{q}| / (2 k_F)}}
+ &= \frac{- e_0^2 V}{16 \pi^5 \varepsilon_0} 2 \int_0^{2 k_F} \!\!\!\int_0^{2 \pi} \!\!\int_0^{\arccos{|\vb{q}| / (2 k_F)}}
\!\!\int_{|\vb{q}|/(2 \cos{\theta_k})}^{k_F} |\vb{k}|^2 \sin(\theta_k) \dd{|\vb{k}|} \dd{\theta_k} \dd{\varphi_k} \dd{|\vb{q}|}
\\
- &= \frac{e^2 V}{8 \pi^5 \varepsilon_0} 2 \pi \int_0^{2 k_F} \!\!\!\int_1^{|\vb{q}| / (2 k_F)}
+ &= \frac{e_0^2 V}{8 \pi^5 \varepsilon_0} 2 \pi \int_0^{2 k_F} \!\!\!\int_1^{|\vb{q}| / (2 k_F)}
\!\!\int_{|\vb{q}|/(2 \xi)}^{k_F} |\vb{k}|^2 \frac{\sin(\theta_k)}{\sin(\theta_k)} \dd{|\vb{k}|} \dd{\xi} \dd{|\vb{q}|}
\\
- &= \frac{- e^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F} \!\!\!\int_{|\vb{q}| / (2 k_F)}^1
+ &= \frac{- e_0^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F} \!\!\!\int_{|\vb{q}| / (2 k_F)}^1
\!\!\int_{|\vb{q}|/(2 \xi)}^{k_F} |\vb{k}|^2 \dd{|\vb{k}|} \dd{\xi} \dd{|\vb{q}|}
\end{aligned}$$
@@ -350,23 +321,23 @@ Evaluating these integrals:
$$\begin{aligned}
E^{(1)}
- &= \frac{- e^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F} \!\!\!\int_{|\vb{q}| / (2 k_F)}^1
+ &= \frac{- e_0^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F} \!\!\!\int_{|\vb{q}| / (2 k_F)}^1
\bigg[ \frac{|\vb{k}|^3}{3} \bigg]_{|\vb{q}|/(2 \xi)}^{k_F} \dd{\xi} \dd{|\vb{q}|}
\\
- &= \frac{- e^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F} \!\!\!\int_{|\vb{q}| / (2 k_F)}^1
+ &= \frac{- e_0^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F} \!\!\!\int_{|\vb{q}| / (2 k_F)}^1
\bigg( \frac{k_F^3}{3} - \frac{|\vb{q}|^3}{24 \xi^3} \bigg) \dd{\xi} \dd{|\vb{q}|}
\\
- &= \frac{- e^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F}
+ &= \frac{- e_0^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F}
\bigg[ \frac{k_F^3}{3} x + \frac{|\vb{q}|^3}{48 \xi^2} \bigg]_{|\vb{q}| / (2 k_F)}^1 \dd{|\vb{q}|}
\\
- &= \frac{- e^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F}
+ &= \frac{- e_0^2 V}{4 \pi^4 \varepsilon_0} \int_0^{2 k_F}
\bigg( \frac{k_F^3}{3} + \frac{|\vb{q}|^3}{48} - \frac{k_F^2 |\vb{q}|}{4} \bigg) \dd{|\vb{q}|}
\\
- &= \frac{- e^2 V}{4 \pi^4 \varepsilon_0} \bigg[ \frac{k_F^3 |\vb{q}|}{3} + \frac{|\vb{q}|^4}{192} - \frac{k_F^2 |\vb{q}|^2}{8} \bigg]_0^{2 k_F}
+ &= \frac{- e_0^2 V}{4 \pi^4 \varepsilon_0} \bigg[ \frac{k_F^3 |\vb{q}|}{3} + \frac{|\vb{q}|^4}{192} - \frac{k_F^2 |\vb{q}|^2}{8} \bigg]_0^{2 k_F}
\\
- &= \frac{- e^2 V}{16 \pi^4 \varepsilon_0} k_F^4
- = \frac{- e^2 N}{16 \pi^4 \varepsilon_0 n} k_F^4
- = -\frac{3 e^2 N}{16 \pi^2 \varepsilon_0} k_F
+ &= \frac{- e_0^2 V}{16 \pi^4 \varepsilon_0} k_F^4
+ = \frac{- e_0^2 N}{16 \pi^4 \varepsilon_0 n} k_F^4
+ = -\frac{3 e_0^2 N}{16 \pi^2 \varepsilon_0} k_F
\end{aligned}$$
Per particle, the first-order energy correction $$E^{(1)}$$
@@ -375,7 +346,7 @@ is therefore found to be as follows:
$$\begin{aligned}
\boxed{
\frac{E^{(1)}}{N}
- = -\frac{3 e^2}{16 \pi^2 \varepsilon_0} k_F
+ = -\frac{3 e_0^2}{16 \pi^2 \varepsilon_0} k_F
}
\end{aligned}$$
@@ -383,8 +354,8 @@ This can also be written using the parameter $$r_s$$ introduced above, leading t
$$\begin{aligned}
\frac{E^{(1)}}{N}
- = -\frac{3 e^2}{16 \pi^2 \varepsilon_0} \frac{a_0 k_F}{a_0}
- = -\frac{3 e^2}{16 \pi^2 \varepsilon_0} \Big( \frac{9 \pi}{4} \Big)^{1/3} \frac{1}{a_0 r_s}
+ = -\frac{3 e_0^2}{16 \pi^2 \varepsilon_0} \frac{a_0 k_F}{a_0}
+ = -\frac{3 e_0^2}{16 \pi^2 \varepsilon_0} \Big( \frac{9 \pi}{4} \Big)^{1/3} \frac{1}{a_0 r_s}
\end{aligned}$$
Consequently, for sufficiently high densities $$n$$,
diff --git a/source/know/concept/korteweg-de-vries-equation/index.md b/source/know/concept/korteweg-de-vries-equation/index.md
index 2857e23..13b1ee2 100644
--- a/source/know/concept/korteweg-de-vries-equation/index.md
+++ b/source/know/concept/korteweg-de-vries-equation/index.md
@@ -152,7 +152,7 @@ rather than transform the coordinate system,
the velocity is incorporated into his ansatz for $$f$$;
in other words, he assumed that the entire liquid is moving at $$q_0$$.
For a wave going in the positive $$x$$-direction,
-the linearized problem then predicts a profile $$\eta(x \!-\! (\sqrt{g h} \!+\! q_0))$$,
+the linearized problem then predicts a profile $$\eta(x \!-\! (\sqrt{g h} \!+\! q_0) t)$$,
so de Vries chose $$q_0 = -\sqrt{g h}$$ to make it stationary.
Analogously, $$q_0 = \sqrt{g h}$$ for a backward-moving wave.
With this in mind, the ansatz is:
@@ -162,11 +162,11 @@ $$\begin{aligned}
= q_0 - \frac{g}{q_0} \Big( \eta(x, t) + \alpha + \gamma(x, t) \Big)
\end{aligned}$$
-Where $$\alpha$$ is a constant parameter
-(which we will use to handle velocity discrepancies
-between the linear and nonlinear theories).
+Where $$\alpha$$ is a constant parameter,
+which we will use to handle velocity discrepancies
+between the linear and nonlinear theories.
The correction represented by $$\gamma$$ is much smaller,
-i.e. $$\eta \sim \alpha \gg \gamma$$.
+i.e. $$\eta \gg \alpha \gg \gamma$$.
We insert this ansatz into the above equations, yielding:
$$\begin{aligned}
@@ -265,14 +265,15 @@ $$\begin{aligned}
\equiv \frac{h^3}{3} - \frac{h T}{g \rho}
\end{aligned}$$
-What about $$\alpha$$?
+But what about $$\alpha$$?
Looking at the ansatz for $$f$$, we see that
-the body of water is already assumed to be moving at $$q_0$$,
-minus $$g \alpha / q_0$$, so by varying $$\alpha$$
-we are modifying the water's velocity.
-The term in the KdV equation simply corrects for our chosen value of $$\alpha$$.
-It has no deeper meaning than that: for any value of $$\alpha$$,
-the full range of KdV solutions can still be obtained.
+the body of water is assumed to be moving at $$q_0 - g \alpha / q_0$$,
+and $$q_0$$ is set to $$\pm \sqrt{g h}$$ by almost all authors,
+so $$\alpha$$ controls the velocity of our reference frame.
+Nonlinear waves do not travel at the same speed as linear waves,
+so we can choose $$\alpha$$ to make the wave stationary
+without breaking the $$q_0$$ "tradition".
+That term in the KdV equation simply corrects for our chosen value of $$\alpha$$.
@@ -383,14 +384,16 @@ These are the final scale parameter values,
leading to the desired dimensionless form:
$$\begin{aligned}
- 0
- &= \tilde{\eta}_{\tilde{t}} - 6 \tilde{\eta} \tilde{\eta}_{\tilde{x}} + \tilde{\eta}_{\tilde{x} \tilde{x} \tilde{x}}
+ \boxed{
+ 0
+ = \tilde{\eta}_{\tilde{t}} - 6 \tilde{\eta} \tilde{\eta}_{\tilde{x}} + \tilde{\eta}_{\tilde{x} \tilde{x} \tilde{x}}
+ }
\end{aligned}$$
Recall that $$\alpha$$ sets the background fluid velocity,
and $$v_c$$ controls the coordinate system's motion:
our choice of $$v_c$$ simply cancels out the effect of $$\alpha$$.
-This reveals the point of $$\alpha$$:
+This demonstrates the purpose of $$\alpha$$:
the KdV equation has solutions moving at various speeds,
so, for a given $$\eta$$, we can always choose $$\alpha$$ (and hence $$v_c$$)
such that the wave appears stationary.
diff --git a/source/know/concept/kramers-kronig-relations/index.md b/source/know/concept/kramers-kronig-relations/index.md
index 711023e..68e27dc 100644
--- a/source/know/concept/kramers-kronig-relations/index.md
+++ b/source/know/concept/kramers-kronig-relations/index.md
@@ -10,124 +10,145 @@ categories:
layout: "concept"
---
-Let $$\chi(t)$$ be a complex function describing
-the response of a system to an impulse $$f(t)$$ starting at $$t = 0$$.
-The **Kramers-Kronig relations** connect the real and imaginary parts of $$\chi(t)$$,
-such that one can be reconstructed from the other.
-Suppose we can only measure $$\chi_r(t)$$ or $$\chi_i(t)$$:
+Let $$\chi(t)$$ be the response function of a system
+to an external impulse $$f(t)$$, which starts at $$t = 0$$.
+Assuming initial equilibrium, the principle of causality
+states that there is no response before the impulse,
+so $$\chi(t) = 0$$ for $$t < 0$$.
+To enforce this, we demand that $$\chi(t)$$ satisfies a **causality test**,
+where $$\Theta(t)$$ is the [Heaviside step function](/know/concept/heaviside-step-function/):
$$\begin{aligned}
- \chi(t) = \chi_r(t) + i \chi_i(t)
+ \chi(t)
+ = \chi(t) \: \Theta(t)
\end{aligned}$$
-Assuming that the system was at rest until $$t = 0$$,
-the response $$\chi(t)$$ cannot depend on anything from $$t < 0$$,
-since the known impulse $$f(t)$$ had not started yet,
-This principle is called **causality**, and to enforce it,
-we use the [Heaviside step function](/know/concept/heaviside-step-function/)
-$$\Theta(t)$$ to create a **causality test** for $$\chi(t)$$:
-
-$$\begin{aligned}
- \chi(t) = \chi(t) \: \Theta(t)
-\end{aligned}$$
-
-If we [Fourier transform](/know/concept/fourier-transform/) this equation,
-then it will become a convolution in the frequency domain
+If we take the [Fourier transform](/know/concept/fourier-transform/) (FT)
+$$\chi(t) \!\to\! \tilde{\chi}(\omega)$$ of this equation,
+the right-hand side becomes a convolution in the frequency domain
thanks to the [convolution theorem](/know/concept/convolution-theorem/),
-where $$A$$, $$B$$ and $$s$$ are constants from the FT definition:
+where $$A$$, $$B$$ and $$s$$ are constants determined by
+how we choose to define our FT:
$$\begin{aligned}
\tilde{\chi}(\omega)
- = (\tilde{\chi} * \tilde{\Theta})(\omega)
- = B \int_{-\infty}^\infty \tilde{\chi}(\omega') \: \tilde{\Theta}(\omega - \omega') \dd{\omega'}
+ &= (\tilde{\chi} * \tilde{\Theta})(\omega)
+ \\
+ &= B \int_{-\infty}^\infty \tilde{\chi}(\omega') \: \tilde{\Theta}(\omega - \omega') \dd{\omega'}
\end{aligned}$$
-We look up the FT of the step function $$\tilde{\Theta}(\omega)$$,
+We look up the full expression for $$\tilde{\Theta}(\omega)$$,
which involves the signum function $$\mathrm{sgn}(t)$$,
the [Dirac delta function](/know/concept/dirac-delta-function/) $$\delta$$,
-and the Cauchy principal value $$\pv{}$$.
-We arrive at:
+and the [Cauchy principal value](/know/concept/cauchy-principal-value/) $$\pv{}$$.
+Inserting that, we arrive at:
$$\begin{aligned}
\tilde{\chi}(\omega)
&= \frac{A B}{|s|} \pv{\int_{-\infty}^\infty \tilde{\chi}(\omega')
- \Big( \pi \delta(\omega - \omega') + i \:\mathrm{sgn} \frac{1}{\omega - \omega'} \Big) \dd{\omega'}}
+ \bigg( \pi \delta(\omega - \omega') + i \frac{\mathrm{sgn}(s)}{\omega - \omega'} \bigg) \dd{\omega'}}
\\
- &= \Big( \frac{1}{2} \frac{2 \pi A B}{|s|} \Big) \tilde{\chi}(\omega)
- + i \Big( \frac{\mathrm{sgn}(s)}{2 \pi} \frac{2 \pi A B}{|s|} \Big)
+ &= \bigg( \frac{2}{2} \frac{\pi A B}{|s|} \bigg) \tilde{\chi}(\omega)
+ + i \: \mathrm{sgn}(s) \bigg( \frac{2 \pi}{2 \pi} \frac{A B}{|s|} \bigg)
\pv{\int_{-\infty}^\infty \frac{\tilde{\chi}(\omega')}{\omega - \omega'} \dd{\omega'}}
\end{aligned}$$
-From the definition of the Fourier transform we know that
-$$2 \pi A B / |s| = 1$$:
+From the definition of the FT we know that
+$$2 \pi A B / |s| = 1$$, so this reduces to:
$$\begin{aligned}
\tilde{\chi}(\omega)
&= \frac{1}{2} \tilde{\chi}(\omega)
- + \mathrm{sgn}(s) \frac{i}{2 \pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}(\omega')}{\omega - \omega'} \dd{\omega'}}
+ + i \: \mathrm{sgn}(s) \frac{1}{2 \pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}(\omega')}{\omega - \omega'} \dd{\omega'}}
\end{aligned}$$
-We isolate this equation for $$\tilde{\chi}(\omega)$$
-to get the final version of the causality test:
+We rearrange this equation a bit to get the final version of the causality test:
$$\begin{aligned}
\boxed{
\tilde{\chi}(\omega)
- = - \mathrm{sgn}(s) \frac{i}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}(\omega')}{\omega - \omega'} \dd{\omega'}}
+ = i \: \mathrm{sgn}(s) \frac{1}{\pi}
+ \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}(\omega')}{\omega - \omega'} \dd{\omega'}}
}
\end{aligned}$$
-By inserting $$\tilde{\chi}(\omega) = \tilde{\chi}_r(\omega) + i \tilde{\chi}_i(\omega)$$
-and splitting the equation into real and imaginary parts,
-we get the Kramers-Kronig relations:
+Next, we split $$\tilde{\chi}(\omega)$$
+into its real and imaginary parts,
+i.e. $$\tilde{\chi}(\omega) = \tilde{\chi}_r(\omega) + i \tilde{\chi}_i(\omega)$$:
+
+$$\begin{aligned}
+ \tilde{\chi}_r(\omega) + i \tilde{\chi}_i(\omega)
+ = i \: \mathrm{sgn}(s) \frac{1}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}_r(\omega')}{\omega - \omega'} \dd{\omega'}}
+ - \mathrm{sgn}(s) \frac{1}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}_i(\omega')}{\omega - \omega'} \dd{\omega'}}
+\end{aligned}$$
+
+This equation can likewise be split into real and imaginary parts,
+leading to the **Kramers-Kronig relations**,
+which enable us to reconstruct $$\tilde{\chi}_r(\omega)$$
+from $$\tilde{\chi}_i(\omega)$$ and vice versa:
$$\begin{aligned}
\boxed{
\begin{aligned}
\tilde{\chi}_r(\omega)
- &= \mathrm{sgn}(s) \frac{1}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}_i(\omega')}{\omega' - \omega} \dd{\omega'}}
+ &= - \mathrm{sgn}(s) \frac{1}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}_i(\omega')}{\omega - \omega'} \dd{\omega'}}
\\
\tilde{\chi}_i(\omega)
- &= - \mathrm{sgn}(s) \frac{1}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}_r(\omega')}{\omega' - \omega} \dd{\omega'}}
+ &= \mathrm{sgn}(s) \frac{1}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}_r(\omega')}{\omega - \omega'} \dd{\omega'}}
\end{aligned}
}
\end{aligned}$$
-If the time-domain response function $$\chi(t)$$ is real
-(so far we have assumed it to be complex),
-then we can take advantage of the fact that
-the FT of a real function satisfies
-$$\tilde{\chi}(-\omega) = \tilde{\chi}^*(\omega)$$, i.e. $$\tilde{\chi}_r(\omega)$$
-is even and $$\tilde{\chi}_i(\omega)$$ is odd. We multiply the fractions by
-$$(\omega' + \omega)$$ above and below:
+The sign of these expressions deserves special attention:
+it depends on an author's choice of FT definition via $$\mathrm{sgn}(s)$$,
+and, to make matters even more confusing,
+many also choose to use the opposite sign in the denominator,
+i.e. they write $$\omega' - \omega$$ instead of $$\omega - \omega'$$.
+
+In the special case where $$\chi(t)$$ is real,
+we can take advantage of the property that
+the FT of a real function always satisfies
+$$\tilde{\chi}(-\omega) = \tilde{\chi}^*(\omega)$$.
+Here, this means that $$\tilde{\chi}_r(\omega)$$ is even
+and $$\tilde{\chi}_i(\omega)$$ is odd.
+To use this fact, we simultaneously
+multiply and divide the integrands by $$\omega + \omega'$$:
$$\begin{aligned}
\tilde{\chi}_r(\omega)
- &= \mathrm{sgn}(s) \bigg( \frac{1}{\pi} \pv{\int_{-\infty}^\infty \frac{\omega' \tilde{\chi}_i(\omega')}{ {\omega'}^2 - \omega^2} \dd{\omega'}}
- + \frac{\omega}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}_i(\omega')}{ {\omega'}^2 - \omega^2} \dd{\omega'}} \bigg)
+ &= - \mathrm{sgn}(s) \frac{1}{\pi}
+ \bigg( \!\pv{\int_{-\infty}^\infty \frac{\omega \tilde{\chi}_i(\omega')}{\omega^2 - {\omega'}^2} \dd{\omega'}}
+ + \pv{\int_{-\infty}^\infty \frac{\omega' \tilde{\chi}_i(\omega')}{\omega^2 - {\omega'}^2} \dd{\omega'}} \bigg)
\\
\tilde{\chi}_i(\omega)
- &= - \mathrm{sgn}(s) \bigg( \frac{1}{\pi} \pv{\int_{-\infty}^\infty \frac{\omega' \tilde{\chi}_r(\omega')}{ {\omega'}^2 - \omega^2} \dd{\omega'}}
- + \frac{\omega}{\pi} \pv{\int_{-\infty}^\infty \frac{\tilde{\chi}_r(\omega')}{ {\omega'}^2 - \omega^2} \dd{\omega'}} \bigg)
+ &= \mathrm{sgn}(s) \frac{1}{\pi}
+ \bigg( \!\pv{\int_{-\infty}^\infty \frac{\omega \tilde{\chi}_r(\omega')}{\omega^2 - {\omega'}^2} \dd{\omega'}}
+ + \pv{\int_{-\infty}^\infty \frac{\omega' \tilde{\chi}_r(\omega')}{\omega^2 - {\omega'}^2} \dd{\omega'}} \bigg)
\end{aligned}$$
-For $$\tilde{\chi}_r(\omega)$$, the second integrand is odd, so we can drop it.
-Similarly, for $$\tilde{\chi}_i(\omega)$$, the first integrand is odd.
-We therefore find the following variant of the Kramers-Kronig relations:
+In $$\tilde{\chi}_r(\omega)$$'s equation, the first integrand is odd,
+so the integral's value is zero.
+Similarly, for $$\tilde{\chi}_i(\omega)$$, the second integrand is odd, so we drop it too.
+We thus arrive at the following common variant of the Kramers-Kronig relations,
+only valid for real $$\chi(t)$$:
$$\begin{aligned}
\boxed{
\begin{aligned}
\tilde{\chi}_r(\omega)
- &= \mathrm{sgn}(s) \frac{2}{\pi} \pv{\int_0^\infty \frac{\omega' \tilde{\chi}_i(\omega')}{ {\omega'}^2 - \omega^2} \dd{\omega'}}
+ &= - \mathrm{sgn}(s) \frac{2}{\pi}
+ \pv{\int_0^\infty \frac{\omega' \tilde{\chi}_i(\omega')}{\omega^2 - {\omega'}^2} \dd{\omega'}}
\\
\tilde{\chi}_i(\omega)
- &= - \mathrm{sgn}(s) \frac{2 \omega}{\pi} \pv{\int_0^\infty \frac{\tilde{\chi}_r(\omega')}{ {\omega'}^2 - \omega^2} \dd{\omega'}}
+ &= \mathrm{sgn}(s) \frac{2}{\pi}
+ \pv{\int_0^\infty \frac{\omega \tilde{\chi}_r(\omega')}{\omega^2 - {\omega'}^2} \dd{\omega'}}
\end{aligned}
}
\end{aligned}$$
-To reiterate: this version is only valid if $$\chi(t)$$ is real in the time domain.
+Note that we have modified the integration limits
+using the fact that the integrands are even,
+leading to an extra factor of $$2$$.
diff --git a/source/know/concept/kubo-formula/index.md b/source/know/concept/kubo-formula/index.md
index 4cb39ac..41fda3c 100644
--- a/source/know/concept/kubo-formula/index.md
+++ b/source/know/concept/kubo-formula/index.md
@@ -27,14 +27,15 @@ respectively refer to the Schrödinger
and [interaction pictures](/know/concept/interaction-picture/):
$$\begin{aligned}
- \expval{\hat{A}}(t)
+ \expval{\hat{A}(t)}
= \matrixel{\psi_S(t)}{\hat{A}_S}{\psi_S(t)}
&= \matrixel{\psi_I(t)}{\hat{A}_I(t)}{\psi_I(t)}
\\
&= \matrixel{\psi_I(t_0)\,}{\,\hat{K}_I^\dagger(t, t_0) \hat{A}_I(t) \hat{K}_I(t, t_0)\,}{\,\psi_I(t_0)}
\end{aligned}$$
-Where the time evolution operator $$\hat{K}_I(t, t_0)$$ is as follows,
+Where the [time evolution operator](/know/concept/time-evolution-operator/)
+$$\hat{K}_I(t, t_0)$$ is as follows,
which we Taylor-expand:
$$\begin{aligned}
@@ -71,18 +72,18 @@ where $$\Expval{}$$ is the expectation value for $$\Ket{\psi(t)}$$,
and $$\Expval{}_0$$ is the expectation value for $$\Ket{\psi_I(t_0)}$$:
$$\begin{aligned}
- \expval{\hat{A}}(t)
+ \expval{\hat{A}(t)}
= \expval{\hat{K}_I^\dagger \hat{A}_I \hat{K}_I}_0
= \expval{\hat{A}_I(t)}_0 - \frac{i}{\hbar} \int_{t_0}^t \Expval{\Comm{\hat{A}_I(t)}{\hat{H}_{1,I}(t')}}_0 \dd{t'}
\end{aligned}$$
-Now we define $$\delta\!\expval{\hat{A}}\!(t)$$
+Now we define $$\delta\!\expval{\hat{A}(t)}$$
as the change of $$\expval{\hat{A}}$$ due to the perturbation $$\hat{H}_1$$,
-and insert $$\expval{\hat{A}}(t)$$:
+and insert $$\expval{\hat{A}(t)}$$:
$$\begin{aligned}
- \delta\!\expval{\hat{A}}\!(t)
- \equiv \expval{\hat{A}}(t) - \expval{\hat{A}_I}_0
+ \delta\!\expval{\hat{A}(t)}
+ \equiv \expval{\hat{A}(t)} - \expval{\hat{A}_I(t)}_0
= - \frac{i}{\hbar} \int_{t_0}^t \Expval{\Comm{\hat{A}_I(t)}{\hat{H}_{1,I}(t')}}_0 \dd{t'}
\end{aligned}$$
@@ -94,7 +95,7 @@ describing the response of $$\expval{\hat{A}}$$ to first order in $$\hat{H}_1$$:
$$\begin{aligned}
\boxed{
- \delta\!\expval{\hat{A}}\!(t)
+ \delta\!\expval{\hat{A}(t)}
= \int_{t_0}^\infty C^R_{A H_1}(t, t') \dd{t'}
}
\end{aligned}$$
@@ -142,7 +143,7 @@ With this, the Kubo formula can be written as follows,
where we have set $$t_0 = - \infty$$:
$$\begin{aligned}
- \delta\!\expval{A}\!(t)
+ \delta\!\expval{\hat{A}(t)}
= \int_{-\infty}^\infty C^R_{A B}(t - t') f(t') \dd{t'}
= (C^R_{A B} * f)(t)
\end{aligned}$$
@@ -150,12 +151,12 @@ $$\begin{aligned}
This is a convolution,
so the [convolution theorem](/know/concept/convolution-theorem/)
states that the [Fourier transform](/know/concept/fourier-transform/)
-of $$\delta\!\expval{\hat{A}}\!(t)$$ is simply the product
+of $$\delta\!\expval{\hat{A}(t)}$$ is simply the product
of the transforms of $$C^R_{AB}$$ and $$f$$:
$$\begin{aligned}
\boxed{
- \delta\!\expval{\hat{A}}\!(\omega)
+ \delta\!\expval{\hat{A}(\omega)}
= \tilde{C}{}^R_{A B}(\omega) \: \tilde{f}(\omega)
}
\end{aligned}$$
diff --git a/source/know/concept/lagrange-multiplier/index.md b/source/know/concept/lagrange-multiplier/index.md
index 6b5e3fc..4c2e957 100644
--- a/source/know/concept/lagrange-multiplier/index.md
+++ b/source/know/concept/lagrange-multiplier/index.md
@@ -117,7 +117,7 @@ We often assign $$\lambda$$ an algebraic expression rather than a value,
usually without even bothering to calculate its final actual value.
In fact, in some cases, $$\lambda$$'s only function is to help us reason
about the interdependence of a system of equations
-(see [example 3](https://en.wikipedia.org/wiki/Lagrange_multiplier#Example_3:_Entropy) on Wikipedia);
+(see Wikipedia's [entropy example](https://en.wikipedia.org/wiki/Lagrange_multiplier#Examples));
then $$\lambda$$ is not even given an expression!
Hence it is sometimes also called an *undetermined multiplier*.
diff --git a/source/know/concept/langmuir-waves/index.md b/source/know/concept/langmuir-waves/index.md
index 2dbce8f..736ef71 100644
--- a/source/know/concept/langmuir-waves/index.md
+++ b/source/know/concept/langmuir-waves/index.md
@@ -54,13 +54,13 @@ are assumed to satisfy:
$$\begin{aligned}
\pdv{n_{e0}}{t} = 0
- \qquad
+ \qquad \quad
\pdv{\vb{u}_{e0}}{t} = 0
- \qquad
+ \qquad \quad
\nabla n_{e0} = 0
- \qquad
+ \qquad \quad
\vb{u}_{e0} = 0
- \qquad
+ \qquad \quad
\vb{E}_0 = 0
\end{aligned}$$
@@ -73,8 +73,7 @@ $$\begin{aligned}
\\
&= \pdv{n_{e1}}{t} + \nabla \cdot \Big( n_{e0} \vb{u}_{e1} + n_{e1} \vb{u}_{e1} \Big)
\\
- &\approx \pdv{n_{e1}}{t} + \nabla \cdot (n_{e0} \vb{u}_{e1})
- = \pdv{n_{e1}}{t} + n_{e0} \nabla \cdot \vb{u}_{e1}
+ &\approx \pdv{n_{e1}}{t} + n_{e0} \nabla \cdot \vb{u}_{e1}
\end{aligned}$$
Likewise, we insert it into Gauss' law,
@@ -83,7 +82,7 @@ and use the plasma's quasi-neutrality $$n_i = n_{e0}$$ to get:
$$\begin{aligned}
\varepsilon_0 \nabla \cdot \big( \vb{E}_0 \!+\! \vb{E}_1 \big)
= q_e (n_{e0} + n_{e1} - n_i)
- \quad \implies \quad
+ \qquad \implies \qquad
\varepsilon_0 \nabla \cdot \vb{E}_1
= q_e n_{e1}
\end{aligned}$$
@@ -106,12 +105,13 @@ Inserting this into the continuity equation and Gauss' law yields, respectively:
$$\begin{aligned}
- i \omega n_{e1} = - i n_{e0} \vb{k} \cdot \vb{u}_{e1}
- \qquad \quad
+ \qquad \qquad
-\! i \varepsilon_0 \vb{k} \cdot \vb{E}_1 = q_e n_{e1}
\end{aligned}$$
+These form a system of equations to be solved.
However, there are three unknowns $$n_{e1}$$, $$\vb{u}_{e1}$$ and $$\vb{E}_1$$,
-so one more equation is needed.
+so one more equation is needed before we can do so.
@@ -180,7 +180,8 @@ the oscillation is stationary.
## Warm Langmuir waves
Next, we generalize this result to nonzero $$T_e$$,
-in which case the pressure $$p_e$$ is involved:
+in which case the pressure $$p_e$$ is involved,
+so the electron momentum equation is given by:
$$\begin{aligned}
m_e n_{e0} \pdv{\vb{u}_{e1}}{t}
@@ -198,10 +199,11 @@ $$\begin{aligned}
\end{aligned}$$
With this, insertion of our plane-wave ansatz
-into the electron equation results in:
+into the momentum equation results in:
$$\begin{aligned}
- -i \omega m_e n_{e0} \vb{u}_{e1} = q_e n_{e0} \vb{E}_1 - i \gamma k_B T_e n_{e1} \vb{k}
+ -i \omega m_e n_{e0} \vb{u}_{e1}
+ = q_e n_{e0} \vb{E}_1 - i \gamma k_B T_e n_{e1} \vb{k}
\end{aligned}$$
Which once again closes the system of three equations.
@@ -209,7 +211,8 @@ Solving for $$\omega^2$$ then gives:
$$\begin{aligned}
\omega^2
- = \frac{\omega n_{e0}}{n_{e1}} \vb{k} \cdot \vb{u}_{e1}
+ &= \frac{\omega n_{e0}}{n_{e1}} \vb{k} \cdot \vb{u}_{e1}
+ \\
&= \frac{i \omega n_{e0}}{\omega n_{e0} m_e n_{e1}} \vb{k} \cdot \Big( q_e n_{e0} \vb{E}_1 - i \gamma k_B T_e n_{e1} \vb{k} \Big)
\\
&= \frac{n_{e0} q_e^2}{\varepsilon_0 m_e} - \frac{i \omega}{\omega m_e n_{e1}} i \gamma k_B T_e n_{e1} \big(\vb{k} \cdot \vb{k}\big)
@@ -235,13 +238,13 @@ $$\begin{aligned}
\end{aligned}$$
Unlike for $$T_e = 0$$, these "warm" waves do propagate,
-carrying information at group velocity $$v_g$$,
-which, in the limit of large $$k$$, is given by:
+because $$k$$ appears in the dispersion relation.
+They carry information at group velocity $$v_g = \ipdv{w}{k}$$,
+which in the limit of large $$k$$ becomes:
$$\begin{aligned}
- v_g
- = \pdv{\omega}{k}
- \to \sqrt{\frac{3 k_B T_e}{m_e}}
+ \lim_{k \to \infty} v_g
+ = \sqrt{\frac{3 k_B T_e}{m_e}}
\end{aligned}$$
This is the root-mean-square velocity of the
diff --git a/source/know/concept/larmor-precession/index.md b/source/know/concept/larmor-precession/index.md
index 774af7b..601dae7 100644
--- a/source/know/concept/larmor-precession/index.md
+++ b/source/know/concept/larmor-precession/index.md
@@ -36,8 +36,8 @@ and the exponentials are "twiddle factors":
$$\begin{aligned}
\Ket{\chi(t)}
- = a \exp(- i E_{\downarrow} t / \hbar) \: \Ket{\downarrow}
- \:+\: b \exp(- i E_{\uparrow} t / \hbar) \: \Ket{\uparrow}
+ = a e^{- i E_{\downarrow} t / \hbar} \Ket{\downarrow}
+ \:+\: b e^{- i E_{\uparrow} t / \hbar} \Ket{\uparrow}
\end{aligned}$$
For our purposes, we can safely assume that $$a$$ and $$b$$ are real,
@@ -45,8 +45,8 @@ and then say that there exists an angle $$\theta$$
satisfying $$a = \sin(\theta / 2)$$ and $$b = \cos(\theta / 2)$$, such that:
$$\begin{aligned}
- \Ket{\chi(t)} = \sin(\theta / 2) \exp(- i E_{\downarrow} t / \hbar) \: \Ket{\downarrow}
- \:+\: \cos(\theta / 2) \exp(- i E_{\uparrow} t / \hbar) \: \Ket{\uparrow}
+ \Ket{\chi(t)} = \sin(\theta / 2) \: e^{- i E_{\downarrow} t / \hbar} \Ket{\downarrow}
+ \:+\: \cos(\theta / 2) \: e^{- i E_{\uparrow} t / \hbar} \Ket{\uparrow}
\end{aligned}$$
Now, we find the expectation values of the spin operators
@@ -56,23 +56,23 @@ The first is:
$$\begin{aligned}
\matrixel{\chi}{\hat{S}_x}{\chi}
&= \frac{\hbar}{2}
- \begin{bmatrix} a \exp(i E_{\downarrow} t / \hbar) \\ b \exp(i E_{\uparrow} t / \hbar) \end{bmatrix}^{\mathrm{T}}
+ \begin{bmatrix} a e^{i E_{\downarrow} t / \hbar} \\ b e^{i E_{\uparrow} t / \hbar} \end{bmatrix}^{\mathrm{T}}
\cdot
\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}
\cdot
- \begin{bmatrix} a \exp(- i E_{\downarrow} t / \hbar) \\ b \exp(- i E_{\uparrow} t / \hbar) \end{bmatrix}
+ \begin{bmatrix} a e^{- i E_{\downarrow} t / \hbar} \\ b e^{- i E_{\uparrow} t / \hbar} \end{bmatrix}
\\
&= \frac{\hbar}{2}
- \begin{bmatrix} a \exp(i E_{\downarrow} t / \hbar) \\ b \exp(i E_{\uparrow} t / \hbar) \end{bmatrix}^{\mathrm{T}}
+ \begin{bmatrix} a e^{i E_{\downarrow} t / \hbar} \\ b e^{i E_{\uparrow} t / \hbar} \end{bmatrix}^{\mathrm{T}}
\cdot
- \begin{bmatrix} b \exp(- i E_{\uparrow} t / \hbar) \\ a \exp(- i E_{\downarrow} t / \hbar) \end{bmatrix}
+ \begin{bmatrix} b e^{- i E_{\uparrow} t / \hbar} \\ a e^{- i E_{\downarrow} t / \hbar} \end{bmatrix}
\\
- &= \frac{\hbar}{2} \Big( a b \exp(i (E_{\downarrow} \!-\! E_{\uparrow}) t / \hbar)
- + b a \exp(i (E_{\uparrow} \!-\! E_{\downarrow}) t / \hbar) \Big)
+ &= \frac{\hbar}{2} \Big( a b e^{i (E_{\downarrow} \!-\! E_{\uparrow}) t / \hbar}
+ + b a e^{i (E_{\uparrow} \!-\! E_{\downarrow}) t / \hbar} \Big)
\\
- &= \frac{\hbar}{2} \cos(\theta/2) \sin(\theta/2) \Big( \exp(i \gamma B t) + \exp(- i \gamma B t) \Big)
+ &= \frac{\hbar}{2} \cos(\theta/2) \sin(\theta/2) \Big( e^{i \gamma B t} + e^{- i \gamma B t} \Big)
\\
- &= \frac{\hbar}{2} \cos(\gamma B t) \Big( \cos(\theta/2) \sin(\theta/2) + \cos(\theta/2) \sin(\theta/2) \Big)
+ &= \frac{\hbar}{2} \cos(\gamma B t) \cdot 2 \cos(\theta/2) \sin(\theta/2)
\\
&= \frac{\hbar}{2} \sin(\theta) \cos(\gamma B t)
\end{aligned}$$
diff --git a/source/know/concept/laser-rate-equations/index.md b/source/know/concept/laser-rate-equations/index.md
index c81f02b..feec168 100644
--- a/source/know/concept/laser-rate-equations/index.md
+++ b/source/know/concept/laser-rate-equations/index.md
@@ -30,7 +30,7 @@ $$\begin{aligned}
Where $$n$$ is the background medium's refractive index,
$$\omega_0$$ the two-level system's gap resonance frequency,
-$$|g| \equiv |\matrixel{e}{\vu{x}}{g}|$$ the transition dipole moment,
+$$|g| \equiv |\!\matrixel{e}{\vu{x}}{g}\!|$$ the transition dipole moment,
$$\gamma_\perp$$ and $$\gamma_\parallel$$ empirical decay rates,
and $$D_0$$ the equilibrium inversion.
Note that $$\vb{E}^{-} = (\vb{E}^{+})^*$$.
@@ -110,7 +110,7 @@ $$\begin{aligned}
Where the Lorentzian gain curve $$\gamma(\omega)$$
(which also appears in the [SALT equation](/know/concept/salt-equation/))
-represents a laser's preferred spectrum for amplification,
+represents the laser's preferred spectrum for amplification,
and is defined like so:
$$\begin{aligned}
@@ -139,7 +139,7 @@ $$\begin{aligned}
Next, we insert our ansatz for $$\vb{E}^{+}$$ and $$\vb{P}^{+}$$
into the third MBE, and rewrite $$\vb{P}_0^{+}$$ as above.
-Using our identity for $$\gamma(\omega)$$,
+Using the aforementioned identity for $$\gamma(\omega)$$
and the fact that $$\vb{E}_0^{+} \cdot \vb{E}_0^{-} = |\vb{E}|^2$$, we find:
$$\begin{aligned}
@@ -218,8 +218,8 @@ $$\begin{aligned}
\end{aligned}$$
Where $$\gamma_e$$ is a redefinition of $$\gamma_\parallel$$
-depending on the electron decay processes,
-and the photon loss rate $$\gamma_p$$, the gain $$G$$,
+depending on the electron decay processes.
+The photon loss rate $$\gamma_p$$, the gain $$G$$,
and the carrier supply rate $$R_\mathrm{pump}$$
are defined like so:
diff --git a/source/know/concept/laws-of-thermodynamics/index.md b/source/know/concept/laws-of-thermodynamics/index.md
deleted file mode 100644
index 3605a0e..0000000
--- a/source/know/concept/laws-of-thermodynamics/index.md
+++ /dev/null
@@ -1,104 +0,0 @@
----
-title: "Laws of thermodynamics"
-sort_title: "Laws of thermodynamics"
-date: 2021-07-07
-categories:
-- Physics
-- Thermodynamics
-layout: "concept"
----
-
-The **laws of thermodynamics** are of great importance
-to physics, chemistry and engineering,
-since they restrict what a device or process can physically achieve.
-For example, the impossibility of *perpetual motion*
-is a consequence of these laws.
-
-
-## First law
-
-The **first law of thermodynamics** states that energy is conserved.
-When a system goes from one equilibrium to another,
-the change $$\Delta U$$ of its energy $$U$$ is equal to
-the work $$\Delta W$$ done by external forces,
-plus the energy transferred by heating ($$\Delta Q > 0$$) or cooling ($$\Delta Q < 0$$):
-
-$$\begin{aligned}
- \boxed{
- \Delta U = \Delta W + \Delta Q
- }
-\end{aligned}$$
-
-The internal energy $$U$$ is a state variable,
-so is independent of the path taken between equilibria.
-However, the work $$\Delta W$$ and heating $$\Delta Q$$ do depend on the path,
-so the first law means that
-the act of transferring energy is path-dependent,
-but the result has no "memory" of that path.
-
-
-## Second law
-
-The **second law of thermodynamics** states that
-the total entropy never decreases.
-An important consequence is that
-no machine can convert energy into work with 100% efficiency.
-
-It is possible for the local entropy $$S_{\mathrm{loc}}$$
-of a system to decrease, but doing so requires work,
-and therefore the entropy of the surroundings $$S_{\mathrm{sur}}$$
-must increase accordingly, such that:
-
-$$\begin{aligned}
- \boxed{
- \Delta S_{\mathrm{tot}} = \Delta S_{\mathrm{loc}} + \Delta S_{\mathrm{sur}} \ge 0
- }
-\end{aligned}$$
-
-Since the total entropy never decreases,
-the equilibrium state of a system must be a maximum
-of its entropy $$S$$, and therefore $$S$$ can be used as
-a [thermodynamic "potential"](/know/concept/thermodynamic-potential/).
-
-The only situation where $$\Delta S = 0$$ is a reversible process,
-since then it must be possible to return to
-the previous equilibrium state by doing the same work in the opposite direction.
-
-According to the first law,
-if a process is reversible, or if it is only heating/cooling,
-then (after one reversible cycle) the energy change
-is simply the heat transfer $$\dd{U} = \dd{Q}$$.
-An entropy change $$\dd{S}$$ is then expressed as follows
-(since $$\ipdv{S}{U} = 1 / T$$ by definition):
-
-$$\begin{aligned}
- \boxed{
- \dd{S}
- = \Big( \pdv{S}{U} \Big)_{V, N} \dd{U}
- = \frac{\dd{Q}}{T}
- }
-\end{aligned}$$
-
-Confusingly, this equation is sometimes also called the second law of thermodynamics.
-
-
-## Third law
-
-The **third law of thermodynamics** states that
-the entropy $$S$$ of a system goes to zero when the temperature reaches absolute zero:
-
-$$\begin{aligned}
- \boxed{
- \lim_{T \to 0} S = 0
- }
-\end{aligned}$$
-
-From this, the absolute quantity of $$S$$ is defined, otherwise we would
-only be able to speak of entropy differences $$\Delta S$$.
-
-
-
-## References
-1. H. Gould, J. Tobochnik,
- *Statistical and thermal physics*, 2nd edition,
- Princeton.
diff --git a/source/know/concept/legendre-transform/index.md b/source/know/concept/legendre-transform/index.md
index d09613f..0d168aa 100644
--- a/source/know/concept/legendre-transform/index.md
+++ b/source/know/concept/legendre-transform/index.md
@@ -11,9 +11,8 @@ layout: "concept"
The **Legendre transform** of a function $$f(x)$$ is a new function $$L(f')$$,
which depends only on the derivative $$f'(x)$$ of $$f(x)$$,
and from which the original $$f(x)$$ can be reconstructed.
-The point is that $$L(f')$$ contains the same information as $$f(x)$$,
-just in a different form,
-analogously to e.g. the [Fourier transform](/know/concept/fourier-transform/).
+The point is that $$L(f')$$ contains the same information as $$f(x)$$
+in a different form, like e.g. a [Fourier transform](/know/concept/fourier-transform/).
Let us choose an arbitrary point $$x_0 \in [a, b]$$ in the domain of $$f(x)$$.
Consider a line $$y(x)$$ tangent to $$f(x)$$ at $$x = x_0$$,
@@ -23,18 +22,17 @@ $$\begin{aligned}
y(x)
&= f'(x_0) (x - x_0) + f(x_0)
\\
- &= f'(x_0) \: x - C
+ &= f'(x_0) \: x - C(x_0)
\end{aligned}$$
-Where $$C \equiv f'(x_0) \: x_0 - f(x_0)$$.
+Where $$C(x) \equiv f'(x) \: x - f(x)$$.
We now define the *Legendre transform* $$L(f')$$,
-such that for all $$x_0 \in [a, b]$$ we have $$L(f'(x_0)) = C$$
-(some authors use $$-C$$ instead).
-Renaming $$x_0$$ to $$x$$:
+such that for all $$x_0 \in [a, b]$$ we have $$L(f'(x_0)) = C(x_0)$$
+(some authors use $$-C$$ instead):
$$\begin{aligned}
L(f'(x))
- &= f'(x) \: x - f(x)
+ &\equiv f'(x) \: x - f(x)
\end{aligned}$$
We want this function to depend only on the derivative $$f'$$,
diff --git a/source/know/concept/lindhard-function/index.md b/source/know/concept/lindhard-function/index.md
index fd620df..5f11d36 100644
--- a/source/know/concept/lindhard-function/index.md
+++ b/source/know/concept/lindhard-function/index.md
@@ -19,7 +19,7 @@ which describes the change in $$\Expval{\hat{n}}$$
due to a time-dependent perturbation $$\hat{H}_1$$:
$$\begin{aligned}
- \delta\!\Expval{ {\hat{n}}}\!(\vb{r}, t)
+ \delta\!\Expval{\hat{n}(\vb{r}, t)}
= -\frac{i}{\hbar} \int_{-\infty}^\infty \Theta(t - t') \Expval{\Comm{\hat{n}_I(\vb{r}, t)}{\hat{H}_{1,I}(t')}}_0 \dd{t'}
\end{aligned}$$
@@ -39,7 +39,7 @@ and $$U(\vb{r})$$ is an arbitrary potential function.
The Kubo formula becomes:
$$\begin{aligned}
- \delta\!\Expval{ {\hat{n}}}\!(\vb{r}, t)
+ \delta\!\Expval{\hat{n}(\vb{r}, t)}
= \iint_{-\infty}^\infty \chi(\vb{r}, \vb{r}'; t, t') \: U(\vb{r}') \: e^{i (\omega + i \eta) t'} \dd{t'} \dd{\vb{r}'}
\end{aligned}$$
@@ -95,8 +95,9 @@ $$\begin{aligned}
\: e^{i (\vb{q}_2 + \vb{q}) \cdot \vb{r}'} \dd{\vb{q}_2} \dd{\vb{r}'}
\end{aligned}$$
-For $$V \to \infty$$ we get a Dirac delta function,
-but in fact the conclusion holds for finite $$V$$ too:
+This gives a Dirac delta function for $$V \to \infty$$
+(a limit that we will take properly later,
+but beware that some authors set $$V = 1$$ until then):
$$\begin{aligned}
\chi(\vb{q}; t, t')
@@ -107,8 +108,9 @@ $$\begin{aligned}
\end{aligned}$$
Similarly, if the unperturbed Hamiltonian $$\hat{H}_0$$ is time-independent,
-$$\chi$$ only depends on the time difference $$t - t'$$.
-Note that $$\delta{\Expval{\hat{n}}}$$ already has the form of a Fourier transform,
+$$\chi$$ only depends on the time difference $$t\!-\!t'$$.
+Note that $$\delta{\Expval{\hat{n}}}$$ already has the form of a Fourier transform
+$$t\!-\!t' \to \omega\!+\!i \eta$$,
which gives us an opportunity to rewrite $$\chi$$
in the [Lehmann representation](/know/concept/lehmann-representation/):
@@ -119,12 +121,12 @@ $$\begin{aligned}
\Big( e^{-\beta E_\nu} - e^{- \beta E_{\nu'}} \Big)
\end{aligned}$$
-Where $$\Ket{\nu}$$ and $$\Ket{\nu'}$$ are many-electron eigenstates of $$\hat{H}_0$$,
+Where $$\Ket{\nu}$$ and $$\Ket{\nu'}$$ are many-particle eigenstates of $$\hat{H}_0$$,
and $$Z$$ is the [grand partition function](/know/concept/grand-canonical-ensemble/).
-According to the [convolution theorem](/know/concept/convolution-theorem/)
-$$\delta{\Expval{\hat{n}}}(\vb{q}, \omega) = \chi(\vb{q}, \omega) \: U(\vb{q})$$.
-In anticipation, we swap $$\nu$$ and $$\nu''$$ in the second term,
-so the general response function is written as:
+To get ready for the calculations ahead,
+we swap $$\nu$$ and $$\nu'$$ in the second term,
+so the response function is as shown below.
+All operators are in the Schrödinger picture from now on:
$$\begin{aligned}
\chi(\vb{q}, \omega)
@@ -135,7 +137,6 @@ $$\begin{aligned}
{\hbar (\omega + i \eta) + E_{\nu'} - E_\nu} \bigg) e^{-\beta E_\nu}
\end{aligned}$$
-All operators are in the Schrödinger picture from now on, hence we dropped the subscript $$S$$.
To proceed, we need to rewrite $$\hat{n}(\vb{q})$$ somehow.
If we neglect electron-electron interactions,
@@ -180,9 +181,8 @@ with per-value spacing $$2 \pi / V^{1/D}$$ along each axis.
Consequently, each orbital $$\psi_\vb{k}$$ uniquely occupies
a volume $$(2 \pi)^D / V$$ in $$\vb{k}$$-space, so we make the approximation
$$\sum_{\vb{k}} \approx V / (2 \pi)^D \int_{-\infty}^\infty \dd{\vb{k}}$$.
-This becomes exact for $$V \to \infty$$,
-in which case $$\vb{k}$$ also becomes continuous again,
-which is what we want for jellium.
+This is exact in the limit $$V \to \infty$$,
+in which case $$\vb{k}$$ also becomes a continuous variable again.
We apply this standard trick from condensed matter physics to $$\hat{n}$$,
and $$V$$ cancels out:
@@ -341,45 +341,49 @@ $$\begin{aligned}
}
\end{aligned}$$
-From this, we would like to get the
-[dielectric function](/know/concept/dielectric-function/) $$\varepsilon_r$$.
-Recall its definition, where $$U_\mathrm{tot}$$, $$U_\mathrm{ext}$$, and $$U_\mathrm{ind}$$
-are the total, external and induced potentials, respectively:
+This is its most general form, but for practical calculations
+we need to formally take the limit $$V \to \infty$$
+and then use $$\sum_{\vb{k}} = V / (2 \pi)^{D} \int_{-\infty}^{\infty} \dd{\vb{k}}$$.
+Furthermore, electrons are spin-1/2 particles,
+so each orbital contains two, meaning
+$$\sum_{\sigma}$$ simply gives a constant factor:
$$\begin{aligned}
- U_\mathrm{tot}
- = U_\mathrm{ext} + U_\mathrm{ind}
- = \frac{U_\mathrm{ext}}{\varepsilon_r}
+ \boxed{
+ \chi_0(\vb{q}, \omega)
+ = \frac{2}{(2 \pi)^{D}} \int_{-\infty}^{\infty}
+ \frac{n_F(\xi_{\vb{k}}) - n_F(\xi_{\vb{k} + \vb{q}})}
+ {\hbar (\omega + i \eta) + \xi_{\vb{k}} - \xi_{\vb{k} + \vb{q}}} \dd{\vb{k}}
+ }
\end{aligned}$$
-Note that these are all *energy* potentials:
-this choice is justified because all energy potentials
-are caused by electric fields in this case.
-The *electric* potential is recoverable as
-$$\Phi_\mathrm{tot} = q_e U_\mathrm{tot}$$,
+From this, we would like to get the
+[dielectric function](/know/concept/dielectric-function/) $$\varepsilon_r$$.
+When an external [electric field](/know/concept/electric-field/) is applied,
+the electrons respond and thereby modify the net field inside the material.
+We include this effect in our *energy* potential $$U$$,
+such that the net *electric* potential
+$$\Phi_\mathrm{tot} = U / q_e$$,
where $$q_e < 0$$ is the charge of an electron.
+This is not the same as including direct electron-electron interactions!
-From the Lindhard response function $$\chi_0$$,
-we get the induced particle density offset $$\delta{\Expval{\hat{n}}}$$
-caused by a potential $$U$$.
-The density $$\delta{\Expval{\hat{n}}}$$ should be self-consistent,
-implying $$U = U_\mathrm{tot}$$.
-In other words, we have a linear relation
-$$\delta{\Expval{\hat{n}}} = \chi_0 U_\mathrm{tot}$$,
-so the standard formula for $$\varepsilon_r$$ gives:
+We thus have a linear relation for the induced *particle* density
+$$\delta\!\Expval{\hat{n}(\vb{q}, \omega)} = \chi_0(\vb{q}, \omega) \: U(\vb{q})$$
+thanks to the [convolution theorem](/know/concept/convolution-theorem/).
+The corresponding induced *charge* density is given by
+$$\rho_\mathrm{ind} = q_e^2 \chi_0 \Phi_\mathrm{tot}$$,
+so the standard formula for $$\varepsilon_r$$ yields:
$$\begin{aligned}
\boxed{
\varepsilon_r(\vb{q}, \omega)
- = 1 - \frac{U_{ee}(\vb{q})}{V}
- \sum_{\sigma \vb{k}} \frac{n_F(\xi_{\vb{k}}) - n_F(\xi_{\vb{k} + \vb{q}})}{\hbar (\omega + i \eta) + \xi_{\vb{k}} - \xi_{\vb{k} + \vb{q}}}
+ = 1 - U_{ee}(\vb{q}) \frac{2}{(2 \pi)^{D}}
+ \int_{-\infty}^{\infty} \frac{n_F(\xi_{\vb{k}}) - n_F(\xi_{\vb{k} + \vb{q}})}{\hbar (\omega + i \eta) + \xi_{\vb{k}} - \xi_{\vb{k} + \vb{q}}} \dd{\vb{k}}
}
\end{aligned}$$
-Where $$U_{ee}(\vb{q}) = q_e^2 / (\varepsilon_0 |\vb{q}|^2)$$
-is Coulomb repulsion.
-This is the **Lindhard dielectric function** of a free
-non-interacting electron gas,
+Where $$U_{ee}(\vb{q}) = q_e^2 / (\varepsilon_0 |\vb{q}|^2)$$ is Coulomb repulsion.
+This is the **Lindhard dielectric function** of a free non-interacting electron gas,
at any temperature and for any dimensionality.
diff --git a/source/know/concept/lyddane-sachs-teller-relation/index.md b/source/know/concept/lyddane-sachs-teller-relation/index.md
new file mode 100644
index 0000000..9cec9dc
--- /dev/null
+++ b/source/know/concept/lyddane-sachs-teller-relation/index.md
@@ -0,0 +1,250 @@
+---
+title: "Lyddane-Sachs-Teller relation"
+sort_title: "Lyddane-Sachs-Teller relation"
+date: 2024-04-15
+categories:
+- Physics
+layout: "concept"
+---
+
+While the [Lorentz oscillator model](/know/concept/lorentz-oscillator-model/)
+originally studied the electric dipole formed by an electron and its nucleus,
+it can also be applied to the nuclei of polar crystals,
+i.e. crystals held together by polar bonds between ions.
+When an [electromagnetic wave](/know/concept/electromagnetic-wave-equation/)
+passes by, its [electric field](/know/concept/electric-field/)
+$$\vb{E}(t)$$ exerts a force on the ions, leading to an optical response.
+
+We are talking about light waves (photons)
+creating lattice vibrations (phonons),
+i.e. a photon-phonon conversion,
+where the total energy and momentum must be conserved.
+If the photon has frequency $$\omega$$ and wavenumber $$k$$,
+and the phonon $$\Omega$$ and $$K$$, then:
+
+$$\begin{aligned}
+ \hbar \omega
+ = \hbar \Omega
+ \qquad \qquad
+ \hbar k
+ = \hbar K
+\end{aligned}$$
+
+In other words, such a conversion can only take place
+at intersections of the dispersion relations $$\omega(k)$$ and $$\Omega(K)$$.
+The latter consists of two branches:
+low-frequency *acoustic* modes and higher-frequency *optical* modes.
+Meanwhile, the photon dispersion is simply $$\omega = c k / n$$,
+where $$n$$ is the medium's refractive index.
+
+For acoustic phonons, the dispersions only intersect at $$k = K = 0$$,
+which is simply a static solid in a static electric field.
+For optical phonons, the intersection is at a nonzero $$k$$.
+In addition, light is a transverse wave,
+so it can only interact with transverse phonons,
+meaning that we must only consider **transverse optical (TO) phonons**.
+
+A wave's group velocity is the slope of its dispersion,
+so $$\ipdv{\omega}{k}$$ and $$\ipdv{\Omega}{K}$$ in this case.
+Clearly, light is much faster than sound,
+so $$\omega(k)$$ is much steeper than $$\Omega(K)$$,
+meaning that the photon-phonon conversion
+will happen at relatively low $$k$$.
+In practice, the intersection is in the infrared (IR),
+hence TO phonons are sometimes called **IR active**.
+
+We consider a 1D chain of unit cells along the $$z$$-axis,
+each containing a positive and a negative ion
+oscillating transversely along the $$x$$-axis.
+For optical phonon modes, the ions always move in opposite directions.
+Let the ions have masses $$m_{-}$$ and $$m_{+}$$,
+then the Lorentz oscillator model tells us
+that the displacements $$\vb{x}_{+}(t)$$ and $$\vb{x}_{-}(t)$$ are governed by:
+
+$$\begin{aligned}
+ m_{+} \dvn{2}{\vb{x}_{+}}{t}
+ &= - \kappa (\vb{x}_{+} - \vb{x}_{-}) + q \vb{E}
+ \\
+ m_{-} \dvn{2}{\vb{x}_{-}}{t}
+ &= - \kappa (\vb{x}_{-} - \vb{x}_{+}) - q \vb{E}
+\end{aligned}$$
+
+Where $$\vb{E}(t) = \vb{E}_0 e^{- i \omega t}$$ represents the light,
+and $$\kappa$$ is the spring constant of the polar bonds' restoring force.
+Note that the latter depends on the displacement between the ions,
+instead of from their equilibrium position,
+so we need to write $$\vb{x}_{+} - \vb{x}_{-}$$ instead of $$\vb{x}_{+}$$.
+
+Respectively dividing the equations by $$m_{+}$$ and $$m_{-}$$
+and subtracting the latter from the former,
+we arrive at the following combined equation,
+where $$m$$ is the [reduced mass](/know/concept/reduced-mass/):
+
+$$\begin{aligned}
+ \dvn{2}{}{t} (\vb{x}_{+} - \vb{x}_{-})
+ = - \frac{\kappa}{m} (\vb{x}_{+} - \vb{x}_{-}) + \frac{q}{m} \vb{E}
+\end{aligned}$$
+
+Defining the relative displacement $$\vb{x} \equiv \vb{x}_{+} \!-\! \vb{x}_{-}$$,
+and recognizing that $$\kappa / m$$ is the TO phonons'
+natural resonance frequency $$\Omega_\mathrm{TO}^2$$:
+
+$$\begin{aligned}
+ \dvn{2}{\vb{x}}{t} + \Omega_\mathrm{TO}^2 \vb{x}
+ = \frac{q}{m} \vb{E}
+\end{aligned}$$
+
+Note that $$\Omega_\mathrm{TO}$$ is the phonon frequency for $$K = 0$$.
+This is because IR light waves are much larger than the crystal's unit cell,
+so we are ignoring all spatial variation in $$\vb{E}$$
+(i.e. the [electric dipole approximation](/know/concept/electric-dipole-approximation/)).
+This is equivalent to assuming that $$K \approx 0$$.
+
+For the sake of generality,
+we also introduce an empirical damping rate $$\gamma$$,
+like in the original Lorentz oscillator model:
+
+$$\begin{aligned}
+ \dvn{2}{\vb{x}}{t} + \gamma \dv{\vb{x}}{t} + \Omega_\mathrm{TO}^2 \vb{x}
+ = \frac{q}{m} \vb{E}
+\end{aligned}$$
+
+Inserting the ansatz $$\vb{x}(t) = \vb{x}_0 e^{- i \omega t}$$
+and isolating for the amplitude $$\vb{x}_0$$, we find:
+
+$$\begin{aligned}
+ \vb{x}_0
+ = \frac{q \vb{E}_0}{m (\Omega_\mathrm{TO}^2 - \omega^2 - i \gamma \omega)}
+\end{aligned}$$
+
+The induced polarization density $$\vb{P}$$ is then the sum
+of the electrons' and ions' contributions $$\vb{P}_e$$ and $$\vb{P}_i$$.
+The former is described by a background susceptibility $$\chi$$,
+and the latter by each unit cell's dipole moment $$\vb{p} = q \vb{x}$$
+multiplied by the number of cells per unit volume $$N$$:
+
+$$\begin{aligned}
+ \vb{P}
+ \approx \varepsilon_0 \chi \vb{E} + N q \vb{x}
+ = \bigg( \varepsilon_0 \chi + \frac{N q^2}{m (\Omega_\mathrm{TO}^2 - \omega^2 - i \gamma \omega)} \bigg) \vb{E}
+\end{aligned}$$
+
+Note that we are neglecting how each dipole shields its neighbors.
+This approximation can be improved afterwards by using
+the [Clausius-Mossotti relation](/know/concept/clausius-mossotti-relation/).
+
+With our expression for $$\vb{P}$$, we can find
+the [dielectric function](/know/concept/dielectric-function/) $$\varepsilon_r(\omega)$$
+using the definition of the electric displacement field
+$$\vb{D} = \varepsilon_0 \vb{E} + \vb{P} = \varepsilon_0 \varepsilon_r \vb{E}$$,
+yielding:
+
+$$\begin{aligned}
+ \boxed{
+ \varepsilon_r(\omega)
+ = 1 + \chi(\omega) + \frac{N q^2}{\varepsilon_0 m (\Omega_\mathrm{TO}^2 - \omega^2 - i \gamma \omega)}
+ }
+\end{aligned}$$
+
+In the limits of low and high frequencies $$\omega$$,
+we see that $$\varepsilon_r$$ is higher in the former:
+
+$$\begin{aligned}
+ \varepsilon_{\mathrm{low}}
+ &= \, \lim_{\omega \to 0} \, \varepsilon_r(\omega)
+ = 1 + \chi_\mathrm{low} + \frac{N q^2}{\varepsilon_0 m \Omega_\mathrm{TO}^2}
+ \\
+ \varepsilon_{\mathrm{high}}
+ &= \lim_{\omega \to \infty} \varepsilon_r(\omega)
+ = 1 + \chi_\mathrm{high}
+\end{aligned}$$
+
+We can use these quantities to rewrite the relative permittivity $$\varepsilon_r$$ as follows:
+
+$$\begin{aligned}
+ \varepsilon_r(\omega)
+ = \varepsilon_{\mathrm{high}} + (\varepsilon_{\mathrm{low}} - \varepsilon_{\mathrm{high}})
+ \frac{\Omega_\mathrm{TO}^2}{\Omega_\mathrm{TO}^2 - \omega^2 - i \gamma \omega}
+\end{aligned}$$
+
+For weak damping $$\gamma \approx 0$$, there exists a frequency,
+which we will call $$\Omega_\mathrm{LO}$$ in anticipation,
+where the dielectric function is zero:
+
+$$\begin{aligned}
+ 0
+ = \varepsilon_r(\Omega_\mathrm{LO})
+ = \varepsilon_{\mathrm{high}}
+ + (\varepsilon_{\mathrm{low}} - \varepsilon_{\mathrm{high}}) \frac{\Omega_\mathrm{TO}^2}{\Omega_\mathrm{TO}^2 - \Omega_\mathrm{LO}^2}
+\end{aligned}$$
+
+The physical significance of $$\varepsilon_r = 0$$ can be
+seen from [Gauss' law](/know/concept/maxwells-equations), under the assumption that there is
+no net charge density:
+
+$$\begin{aligned}
+ \nabla \cdot \vb{D}
+ = \varepsilon_0 \varepsilon_r \nabla \cdot \vb{E}
+ = 0
+\end{aligned}$$
+
+If $$\varepsilon_r \neq 0$$, then $$\nabla \cdot \vec{E} = 0$$,
+corresponding to a transverse light wave as usual.
+However, if $$\varepsilon_r = 0$$, then $$\nabla \cdot \vec{E} \neq 0$$,
+representing a longitudinal electric wave, like a plasmon in metal.
+Rearranging the equation for $$\Omega_\mathrm{LO}$$
+gives us the **Lyddane-Sachs-Teller (LST) relation**:
+
+$$\begin{aligned}
+ \boxed{
+ \frac{\Omega_\mathrm{LO}^2}{\Omega_\mathrm{TO}^2}
+ = \frac{\varepsilon_{\mathrm{low}}}{\varepsilon_{\mathrm{high}}}
+ }
+\end{aligned}$$
+
+$$\Omega_\mathrm{LO}$$ is the natural frequency
+of such **longitudinal optical (LO) phonons** for $$K = 0$$.
+Recall that only transverse phonons interact with light:
+the significance of this result is that we can measure
+$$\varepsilon_\mathrm{low}$$, $$\varepsilon_\mathrm{high}$$,
+and $$\Omega_\mathrm{TO}$$ with light,
+and use that to calculate a quantity for an effect
+that we cannot interact with directly.
+The caveat is that this is only valid for simple polar crystals.
+
+For $$\omega$$-values between $$\Omega_\mathrm{TO}$$ and $$\Omega_\mathrm{LO}$$,
+the permittivity $$\varepsilon_r$$ is negative,
+meaning the reflectivity $$R$$ equals $$1$$,
+i.e. the material becomes a perfect reflector:
+
+$$\begin{aligned}
+ R
+ = \bigg| \frac{i \sqrt{-\varepsilon_r} - 1}{i \sqrt{-\varepsilon_r} + 1} \bigg|^2
+ = \frac{\varepsilon_r^2 + 1^2}{\varepsilon_r^2 + 1^2}
+ = 1
+\end{aligned}$$
+
+This region of 100% reflectivity is called the **Reststrahlen band**.
+In practice, real materials have $$\gamma > 0$$, which reduces $$R$$ somewhat.
+
+Because the photons and TO phonons interact so strongly
+for $$\omega \approx \Omega_\mathrm{TO}$$,
+they can be treated as a single **phonon polariton** there,
+with a dispersion relation given by:
+
+$$\begin{aligned}
+ \omega_\mathrm{pp}(K)
+ = \frac{c}{\sqrt{\varepsilon_r(\omega_\mathrm{pp})}} K
+\end{aligned}$$
+
+Earlier, when treating the photon and phonon separately,
+we wanted the intersection between $$\omega(k)$$ and $$\Omega(K)$$.
+But now, for $$\omega_\mathrm{pp}(K)$$, there is none! This is a good example
+of the typical *anti-crossing* behavior of strongly coupled systems.
+
+
+
+## References
+1. M. Fox,
+ *Optical properties of solids*, 2nd edition,
+ Oxford.
diff --git a/source/know/concept/magnetohydrodynamics/index.md b/source/know/concept/magnetohydrodynamics/index.md
index bcc23f3..4431dfa 100644
--- a/source/know/concept/magnetohydrodynamics/index.md
+++ b/source/know/concept/magnetohydrodynamics/index.md
@@ -24,24 +24,23 @@ and electric current density $$\vb{J}$$ are:
$$\begin{aligned}
p
- = p_i + p_e
- \qquad \quad
+ &= p_i + p_e
+ \\
\vb{J}
- = q_i n_i \vb{u}_i + q_e n_e \vb{u}_e
+ &= q_i n_i \vb{u}_i + q_e n_e \vb{u}_e
\end{aligned}$$
Meanwhile, the macroscopic mass density $$\rho$$
-and center-of-mass flow velocity $$\vb{u}$$
-are as follows, although the ions dominate due to their large mass:
+and center-of-mass flow velocity $$\vb{u}$$ are as follows,
+although the ions dominate both due to their large mass,
+so $$\rho \approx m_i n_i$$ and $$\vb{u} \approx \vb{u}_i$$:
$$\begin{aligned}
\rho
- = m_i n_i + m_e n_e
- \approx m_i n_i
- \qquad \quad
+ &= m_i n_i + m_e n_e
+ \\
\vb{u}
- = \frac{1}{\rho} \Big( m_i n_i \vb{u}_i + m_e n_e \vb{u}_e \Big)
- \approx \vb{u}_i
+ &= \frac{1}{\rho} \Big( m_i n_i \vb{u}_i + m_e n_e \vb{u}_e \Big)
\end{aligned}$$
With these quantities in mind,
@@ -75,9 +74,9 @@ $$\begin{aligned}
\end{aligned}$$
We will assume that electrons' inertia
-is negligible compared to the [Lorentz force](/know/concept/lorentz-force/).
-Let $$\tau_\mathrm{char}$$ be the characteristic timescale of the plasma's dynamics,
-i.e. nothing noticable happens in times shorter than $$\tau_\mathrm{char}$$,
+is negligible compared to the Lorentz force.
+Let $$\tau_\mathrm{char}$$ be the characteristic timescale of the plasma's dynamics
+(i.e. nothing notable happens in times shorter than $$\tau_\mathrm{char}$$),
then this assumption can be written as:
$$\begin{aligned}
@@ -86,15 +85,14 @@ $$\begin{aligned}
\sim \frac{m_e n_e |\vb{u}_e| / \tau_\mathrm{char}}{q_e n_e |\vb{u}_e| |\vb{B}|}
= \frac{m_e}{q_e |\vb{B}| \tau_\mathrm{char}}
= \frac{1}{\omega_{ce} \tau_\mathrm{char}}
- \ll 1
\end{aligned}$$
-Where we have recognized the cyclotron frequency $$\omega_c$$ (see Lorentz force article).
+Where we have recognized the cyclotron frequency $$\omega_c$$
+(see [Lorentz force](/know/concept/lorentz-force/)).
In other words, our assumption is equivalent to
the electron gyration period $$2 \pi / \omega_{ce}$$
-being small compared to the macroscopic dynamics' timescale $$\tau_\mathrm{char}$$.
-By construction, we can thus ignore the left-hand side
-of the electron momentum equation, leaving:
+being small compared to the macroscopic timescale $$\tau_\mathrm{char}$$.
+We can thus ignore the left-hand side of the electron momentum equation, leaving:
$$\begin{aligned}
m_i n_i \frac{\mathrm{D} \vb{u}_i}{\mathrm{D} t}
@@ -138,8 +136,8 @@ $$\begin{aligned}
However, we found this by combining two equations into one,
so some information was implicitly lost;
-we need a second momentum equation.
-Therefore, we return to the electrons' momentum equation,
+we need a second one to keep our system of equations complete.
+Therefore we return to the electrons' momentum equation,
after a bit of rearranging:
$$\begin{aligned}
@@ -154,14 +152,14 @@ so:
$$\begin{aligned}
\vb{E} + \vb{u}_e \cross \vb{B} - \frac{\nabla p_e}{q_e n_e}
= \eta \vb{J}
- \qquad \quad
+ \qquad \qquad
\eta
\equiv \frac{f_{ei} m_e}{n_e q_e^2}
\end{aligned}$$
Where $$\eta$$ is the electrical resistivity of the plasma,
see [Spitzer resistivity](/know/concept/spitzer-resistivity/)
-for more information, and a rough estimate of this quantity for a plasma.
+for more information and a rough estimate of its value in a plasma.
Now, using that $$\vb{u} \approx \vb{u}_i$$,
we add $$(\vb{u} \!-\! \vb{u}_i) \cross \vb{B} \approx 0$$ to the equation,
@@ -183,34 +181,37 @@ $$\begin{aligned}
- \nabla \cross \frac{\nabla p_e}{q_e n_e}
\end{aligned}$$
-Where we have used Faraday's law.
+Where we have used [Faraday's law](/know/concept/maxwells-equations/).
This is the **induction equation**,
and is used to compute $$\vb{B}$$.
The pressure term can be rewritten using the ideal gas law $$p_e = k_B T_e n_e$$:
$$\begin{aligned}
\nabla \cross \frac{\nabla p_e}{q_e n_e}
- = \frac{k_B}{q_e} \nabla \cross \frac{\nabla (n_e T_e)}{n_e}
- = \frac{k_B}{q_e} \nabla \cross \Big( \nabla T_e + T_e \frac{\nabla n_e}{n_e} \Big)
+ &= \frac{k_B}{q_e} \nabla \cross \frac{\nabla (n_e T_e)}{n_e}
+ \\
+ &= \frac{k_B}{q_e} \nabla \cross \Big( \nabla T_e + T_e \frac{\nabla n_e}{n_e} \Big)
\end{aligned}$$
The curl of a gradient is always zero,
and we notice that $$\nabla n_e / n_e = \nabla\! \ln(n_e)$$.
-Then we use the vector identity $$\nabla \cross (f \nabla g) = \nabla f \cross \nabla g$$,
-leading to:
+Then we use the vector identity $$\nabla \cross (f \nabla g) = \nabla f \cross \nabla g$$ to get:
$$\begin{aligned}
\nabla \cross \frac{\nabla p_e}{q_e n_e}
- = \frac{k_B}{q_e} \nabla \cross \big( T_e \: \nabla\! \ln(n_e) \big)
- = \frac{k_B}{q_e} \big( \nabla T_e \cross \nabla\! \ln(n_e) \big)
- = \frac{k_B}{q_e n_e} \big( \nabla T_e \cross \nabla n_e \big)
+ &= \frac{k_B}{q_e} \nabla \cross \big( T_e \: \nabla\! \ln(n_e) \big)
+ \\
+ &= \frac{k_B}{q_e} \big( \nabla T_e \cross \nabla\! \ln(n_e) \big)
+ \\
+ &= \frac{k_B}{q_e n_e} \big( \nabla T_e \cross \nabla n_e \big)
\end{aligned}$$
It is reasonable to assume that $$\nabla T_e$$ and $$\nabla n_e$$
point in roughly the same direction,
in which case the pressure term can be neglected.
Consequently, $$p_e$$ has no effect on the dynamics of $$\vb{B}$$,
-so we argue that it can be dropped from the original (non-curled) equation too, leaving:
+so we argue that it can also be dropped
+from the original equation (before taking the curl):
$$\begin{aligned}
\boxed{
@@ -232,20 +233,18 @@ $$\begin{aligned}
From Faraday's law, we can obtain a scale estimate for $$\vb{E}$$.
Recall that $$\tau_\mathrm{char}$$ is the characteristic timescale of the plasma,
-and let $$\lambda_\mathrm{char} \gg \lambda_D$$ be its characteristic lengthscale:
+and let $$\lambda_\mathrm{char} \gg \lambda_D$$ be its characteristic length scale:
$$\begin{aligned}
\nabla \cross \vb{E}
= - \pdv{\vb{B}}{t}
- \quad \implies \quad
+ \qquad \implies \qquad
|\vb{E}|
\sim \frac{\lambda_\mathrm{char}}{\tau_\mathrm{char}} |\vb{B}|
\end{aligned}$$
-From this, we find when we can neglect
-the last term in Ampère's law:
-the characteristic velocity $$v_\mathrm{char}$$
-must be tiny compared to $$c$$,
+From this, we find that we can neglect the last term in Ampère's law
+as long as the characteristic velocity $$v_\mathrm{char}$$ is tiny compared to $$c$$,
i.e. the plasma must be non-relativistic:
$$\begin{aligned}
@@ -254,7 +253,6 @@ $$\begin{aligned}
\sim \frac{|\vb{E}| / \tau_\mathrm{char}}{|\vb{B}| c^2 / \lambda_\mathrm{char}}
\sim \frac{|\vb{B}| \lambda_\mathrm{char}^2 / \tau_\mathrm{char}^2}{|\vb{B}| c^2}
= \frac{v_\mathrm{char}^2}{c^2}
- \ll 1
\end{aligned}$$
We thus have the following reduced form of Ampère's law,
@@ -265,7 +263,7 @@ $$\begin{aligned}
\nabla \cross \vb{B}
= \mu_0 \vb{J}
}
- \qquad \quad
+ \qquad \qquad
\boxed{
\nabla \cross \vb{E}
= - \pdv{\vb{B}}{t}
@@ -287,10 +285,12 @@ the [material derivative](/know/concept/material-derivative/)
$$\mathrm{D} \rho / \mathrm{D} t$$ as follows:
$$\begin{aligned}
- \pdv{\rho}{t} + \nabla \cdot (\rho \vb{u})
- = \pdv{\rho}{t} + \rho \nabla \cdot \vb{u} + \vb{u} \cdot \nabla \rho
- = \rho \nabla \cdot \vb{u} + \frac{\mathrm{D} \rho}{\mathrm{D} t}
- = 0
+ 0
+ &= \pdv{\rho}{t} + \nabla \cdot (\rho \vb{u})
+ \\
+ &= \pdv{\rho}{t} + \rho \nabla \cdot \vb{u} + \vb{u} \cdot \nabla \rho
+ \\
+ &= \rho \nabla \cdot \vb{u} + \frac{\mathrm{D} \rho}{\mathrm{D} t}
\end{aligned}$$
Inserting this into the equation of state
@@ -311,6 +311,7 @@ but we have merged $$n_i$$ and $$n_e$$ into $$\rho$$,
and $$p_i$$ and $$p_i$$ into $$p$$.
+
## Ohm's law variants
It is worth discussing the generalized Ohm's law in more detail.
@@ -321,29 +322,27 @@ $$\begin{aligned}
= \eta \vb{J}
\end{aligned}$$
-However, most authors neglect some of its terms:
-this form is used for **Hall MHD**,
-where $$\vb{J} \cross \vb{B}$$ is called the *Hall term*.
-This term can be dropped in any of the following cases:
+However, most authors neglect some terms:
+the full form is used for **Hall MHD**,
+where $$\vb{J} \cross \vb{B}$$ is called the **Hall term**.
+It can be dropped in any of the following cases:
-$$\begin{gathered}
+$$\begin{aligned}
1
- \gg \frac{\big| \vb{J} \cross \vb{B} / q_e n_e \big|}{\big| \vb{u} \cross \vb{B} \big|}
+ &\gg \frac{\big| \vb{J} \cross \vb{B} / q_e n_e \big|}{\big| \vb{u} \cross \vb{B} \big|}
\sim \frac{\rho v_\mathrm{char} / \tau_\mathrm{char}}{v_\mathrm{char} |\vb{B}| q_i n_i}
\approx \frac{m_i n_i}{|\vb{B}| q_i n_i \tau_\mathrm{char}}
= \frac{1}{\omega_{ci} \tau_\mathrm{char}}
- \ll 1
\\
1
- \gg \frac{\big| \vb{J} \cross \vb{B} / q_e n_e \big|}{\big| \eta \vb{J} \big|}
+ &\gg \frac{\big| \vb{J} \cross \vb{B} / q_e n_e \big|}{\big| \eta \vb{J} \big|}
\sim \frac{|\vb{J}| |\vb{B}| q_e^2 n_e}{f_{ei} m_e |\vb{J}| q_e n_e}
= \frac{|\vb{B}| q_e}{f_{ei} m_e}
= \frac{\omega_{ce}}{f_{ei}}
- \ll 1
-\end{gathered}$$
+\end{aligned}$$
Where we have used the MHD momentum equation with $$\nabla p \approx 0$$
-to obtain the scale estimate $$\vb{J} \cross \vb{B} \sim \rho v_\mathrm{char} / \tau_\mathrm{char}$$.
+to obtain the scale estimate $$|\vb{J} \cross \vb{B}| \sim \rho v_\mathrm{char} / \tau_\mathrm{char}$$.
In other words, if the ion gyration period is short $$\tau_\mathrm{char} \gg \omega_{ci}$$,
and/or if the electron gyration period is long
compared to the electron-ion collision period $$\omega_{ce} \ll f_{ei}$$,
@@ -354,18 +353,17 @@ $$\begin{aligned}
= \eta \vb{J}
\end{aligned}$$
-Finally, we can neglect the resisitive term $$\eta \vb{J}$$
+Finally, we can neglect the resistive term $$\eta \vb{J}$$
if the Lorentz force is much larger.
We formalize this condition as follows,
-where we have used Ampère's law to find $$\vb{J} \sim \vb{B} / \mu_0 \lambda_\mathrm{char}$$:
+where we have used Ampère's law to find $$|\vb{J}| \sim |\vb{B}| / \mu_0 \lambda_\mathrm{char}$$:
$$\begin{aligned}
1
\ll \frac{\big| \vb{u} \cross \vb{B} \big|}{\big| \eta \vb{J} \big|}
- \sim \frac{v_\mathrm{char} |\vb{B}|}{\eta \vb{J}}
+ \sim \frac{v_\mathrm{char} |\vb{B}|}{\eta |\vb{J}|}
\sim \frac{v_\mathrm{char} |\vb{B}|}{\eta |\vb{B}| / \mu_0 \lambda_\mathrm{char}}
= \mathrm{R_m}
- \gg 1
\end{aligned}$$
Where we have defined the **magnetic Reynolds number** $$\mathrm{R_m}$$ as follows,
@@ -379,13 +377,15 @@ $$\begin{aligned}
\end{aligned}$$
If $$\mathrm{R_m} \ll 1$$, the plasma is "electrically viscous",
-such that resistivity needs to be accounted for,
+meaning resistivity needs to be accounted for,
whereas if $$\mathrm{R_m} \gg 1$$, the resistivity is negligible,
in which case we have **ideal MHD**:
$$\begin{aligned}
- \vb{E} + \vb{u} \cross \vb{B}
- = 0
+ \boxed{
+ \vb{E} + \vb{u} \cross \vb{B}
+ = 0
+ }
\end{aligned}$$
diff --git a/source/know/concept/martingale/index.md b/source/know/concept/martingale/index.md
index 53a346a..7daebea 100644
--- a/source/know/concept/martingale/index.md
+++ b/source/know/concept/martingale/index.md
@@ -20,7 +20,7 @@ then $$M_t$$ is a martingale if it satisfies all of the following:
1. $$M_t$$ is $$\mathcal{F}_t$$-adapted, meaning
the filtration $$\mathcal{F}_t$$ contains enough information
to reconstruct the current and all past values of $$M_t$$.
-2. For all times $$t \ge 0$$, the expectation value exists $$\mathbf{E}(M_t) < \infty$$.
+2. For all times $$t \ge 0$$, the expectation value $$\mathbf{E}(M_t)$$ is finite.
3. For all $$s, t$$ satisfying $$0 \le s \le t$$,
the [conditional expectation](/know/concept/conditional-expectation/)
$$\mathbf{E}(M_t | \mathcal{F}_s) = M_s$$,
diff --git a/source/know/concept/material-derivative/index.md b/source/know/concept/material-derivative/index.md
index 6bb83c5..4eb43e9 100644
--- a/source/know/concept/material-derivative/index.md
+++ b/source/know/concept/material-derivative/index.md
@@ -36,7 +36,7 @@ $$\begin{aligned}
In effect, we have simply made the coordinate $$\va{r}$$ dependent on time,
and have specifically chosen the time-dependence to track the parcel.
-The net evolution of $$f$$ is then its "true" (i.e. non-partial) derivative with respect to $$t$$,
+The evolution of $$f$$ is then its derivative with respect to $$t$$,
allowing us to apply the chain rule:
$$\begin{aligned}
@@ -58,11 +58,7 @@ $$\begin{aligned}
Note that $$\va{v} = \va{v}(\va{r}, t)$$,
that is, the velocity can change with time ($$t$$-dependence),
and depends on which parcel we track ($$\va{r}$$-dependence).
-
-Of course, the parcel is in our imagination:
-$$\va{r}$$ does not really depend on $$t$$;
-after all, we are dealing with a continuum.
-Nevertheless, the right-hand side of the equation is very useful,
+This result is very useful for fluid dynamics,
and is known as the **material derivative** or **comoving derivative**:
$$\begin{aligned}
@@ -76,7 +72,7 @@ The first term is called the **local rate of change**,
and the second is the **advective rate of change**.
In effect, the latter moves the frame of reference along with the material,
so that we can find the evolution of $$f$$
-without needing to worry about the continuum's motion.
+without needing to explicitly account for the continuum's motion.
That was for a scalar field $$f(\va{r}, t)$$,
but in fact the definition also works for vector fields $$\va{U}(\va{r}, t)$$:
diff --git a/source/know/concept/matsubara-greens-function/index.md b/source/know/concept/matsubara-greens-function/index.md
index 5e753db..6f60edf 100644
--- a/source/know/concept/matsubara-greens-function/index.md
+++ b/source/know/concept/matsubara-greens-function/index.md
@@ -64,7 +64,7 @@ $$\begin{aligned}
With $$-$$ for bosons, and $$+$$ for fermions,
due to the time-ordered product for $$\tau > \tau'$$.
-On this domain $$[-\hbar \beta, \hbar \beta]$$,
+On this domain $$]\!-\!\hbar \beta, \hbar \beta[$$,
the Matsubara Green's function $$C_{AB}$$
obeys a useful shift relation:
it is $$\hbar \beta$$-periodic for bosons,
@@ -133,7 +133,7 @@ $$\begin{aligned}
{% include proof/end.html id="proof-period" %}
-Due to this limited domain $$\tau \in [-\hbar \beta, \hbar \beta]$$,
+Due to this limited domain $$\tau \in \:]\!-\!\hbar \beta, \hbar \beta[$$,
the [Fourier transform](/know/concept/fourier-transform/)
of $$C_{AB}(\tau)$$ consists of discrete frequencies
$$k_n \equiv n \pi / (\hbar \beta)$$.
@@ -288,7 +288,7 @@ $$\begin{aligned}
\matrixel{n'}{\hat{B}}{n} e^{(E_n - E_{n'})(\tau - \tau') / \hbar}
\end{aligned}$$
-We take the Fourier transform by integrating over $$[0, \hbar \beta]$$:
+We take the Fourier transform by integrating over $$]0, \hbar \beta[$$:
$$\begin{aligned}
C_{AB}(i \omega_m)
@@ -324,7 +324,7 @@ $$\begin{aligned}
\end{aligned}$$
Since $$\tau \!-\! \tau' < 0$$ this time,
-we take the Fourier transform over $$[-\hbar \beta, 0]$$:
+we take the Fourier transform over $$]\!-\!\hbar \beta, 0[$$:
$$\begin{aligned}
C_{AB}(i \omega_m)
@@ -341,7 +341,7 @@ $$\begin{aligned}
\Big( e^{-\beta E_n} - e^{-i \hbar \omega_m \beta} e^{-\beta E_{n'}} \Big)
\\
&= \mp \frac{1}{Z} \sum_{n n'} \frac{\matrixel{n}{\hat{B}}{n'} \matrixel{n'}{\hat{A}}{n}}{i \hbar \omega_m - E_n + E_{n'}}
- \Big( e^{- \beta E_n} \pm e^{-\beta E_{n'}} \Big)
+ \Big( e^{- \beta E_n} \mp e^{-\beta E_{n'}} \Big)
\\
&= \frac{1}{Z} \sum_{n n'} \frac{\matrixel{n}{\hat{B}}{n'} \matrixel{n'}{\hat{A}}{n}}{i \hbar \omega_m - E_n + E_{n'}}
\Big( e^{- \beta E_{n'}} \mp e^{-\beta E_n} \Big)
diff --git a/source/know/concept/matsubara-sum/index.md b/source/know/concept/matsubara-summation/index.md
index 0e04455..de08024 100644
--- a/source/know/concept/matsubara-sum/index.md
+++ b/source/know/concept/matsubara-summation/index.md
@@ -1,6 +1,6 @@
---
-title: "Matsubara sum"
-sort_title: "Matsubara sum"
+title: "Matsubara summation"
+sort_title: "Matsubara summation"
date: 2021-11-13
categories:
- Physics
@@ -8,7 +8,7 @@ categories:
layout: "concept"
---
-A **Matsubara sum** is a summation of the following form,
+**Matsubara summation** is a technique for evaluating sums of the following form,
which notably appears as the inverse
[Fourier transform](/know/concept/fourier-transform/) of the
[Matsubara Green's function](/know/concept/matsubara-greens-function/):
@@ -23,7 +23,7 @@ $$\begin{aligned}
$$g(z)$$ is a *meromorphic* function on the complex frequency plane,
i.e. it is [holomorphic](/know/concept/holomorphic-function/)
except for a known set of simple poles,
-and $$\tau \in [-\hbar \beta, \hbar \beta]$$ is a real parameter.
+and $$\tau \in \:]\!-\!\hbar \beta, \hbar \beta[$$ is a real parameter.
The Matsubara frequencies $$i \omega_n$$ are defined as follows
for bosons (subscript $$B$$) or fermions (subscript $$F$$):
@@ -77,9 +77,9 @@ $$\begin{aligned}
h(z)
\equiv
\begin{cases}
- n_{B,F}(z) & \mathrm{if}\; \tau \ge 0
+ n_{B,F}(z) & \mathrm{if}\; 0 \le \tau < \hbar \beta
\\
- -n_{B,F}(-z) & \mathrm{if}\; \tau \le 0
+ -n_{B,F}(-z) & \mathrm{if}\; \!-\!\hbar \beta < \tau \le 0
\end{cases}
\end{aligned}$$
@@ -107,7 +107,7 @@ $$\begin{aligned}
&= \lim_{z \to i \omega_n}\!\bigg( \frac{z - i \omega_n}{e^{\hbar \beta z} + 1} \bigg)
= \lim_{\eta \to 0}\!\bigg( \frac{i \omega_n + \eta - i \omega_n}{e^{i \hbar \beta \omega_n} e^{\hbar \beta \eta} + 1} \bigg)
\\
- &= \lim_{\eta \to 0}\!\bigg( \frac{\eta}{e^{\hbar \beta \eta} + 1} \bigg)
+ &= \lim_{\eta \to 0}\!\bigg( \frac{\eta}{-e^{\hbar \beta \eta} + 1} \bigg)
= \lim_{\eta \to 0}\!\bigg( \frac{\eta}{- 1 - \hbar \beta \eta + 1} \bigg)
= - \frac{1}{\hbar \beta}
\end{aligned}$$
diff --git a/source/know/concept/maxwell-bloch-equations/index.md b/source/know/concept/maxwell-bloch-equations/index.md
index 1214703..28885af 100644
--- a/source/know/concept/maxwell-bloch-equations/index.md
+++ b/source/know/concept/maxwell-bloch-equations/index.md
@@ -17,8 +17,8 @@ where $$\varepsilon_g$$ and $$\varepsilon_e$$ are the time-independent eigenener
and the weights $$c_g$$ and $$c_g$$ are functions of $$t$$:
$$\begin{aligned}
- \ket{\Psi}
- &= c_g \ket{g} e^{-i \varepsilon_g t / \hbar} + c_e \ket{e} e^{-i \varepsilon_e t / \hbar}
+ \ket{\Psi(t)}
+ &= c_g(t) \ket{g} e^{-i \varepsilon_g t / \hbar} + c_e(t) \ket{e} e^{-i \varepsilon_e t / \hbar}
\end{aligned}$$
This system is being perturbed by an electromagnetic wave
@@ -32,8 +32,8 @@ $$\begin{aligned}
Where the forward-propagating component $$\vb{E}^{+}$$
is a modulated plane wave $$\vb{E}_0^{+} e^{-i \omega t}$$
with slowly-varying amplitude $$\vb{E}_0^{+}(t)$$,
-and similarly $$\vb{E}^{-}(t) \equiv \vb{E}_0^{-}(t) e^{i \omega t}$$;
-since $$\vb{E}$$ is real, $$\vb{E}_0^{+} \!=\! (\vb{E}_0^{-})^*$$.
+and similarly $$\vb{E}^{-}(t) \equiv \vb{E}_0^{-}(t) e^{i \omega t}$$.
+Since $$\vb{E}$$ is real, $$\vb{E}_0^{+} \!=\! (\vb{E}_0^{-})^*$$.
For $$\ket{\Psi}$$ as defined above,
the pure [density operator](/know/concept/density-operator/)
@@ -92,7 +92,7 @@ $$\begin{aligned}
\end{aligned}$$
However, the light wave affects the electron,
-so the actual electromagnetic dipole moment $$\vb{p}$$ is as follows,
+so the true electromagnetic dipole moment $$\vb{p}$$ is as follows,
using [Laporte's selection rule](/know/concept/selection-rules/)
to remove diagonal terms by assuming that
the electron's orbitals are spatially odd or even:
@@ -106,9 +106,9 @@ $$\begin{aligned}
\\
&= q \Big( \rho_{ge} \matrixel{e}{\vu{x}}{g} + \rho_{eg} \matrixel{g}{\vu{x}}{e} \Big)
\\
- &= \vb{p}_0^{-} \rho_{ge}(t) + \vb{p}_0^{+} \rho_{eg}(t)
+ &= \vb{p}_0^{-} \rho_{ge} + \vb{p}_0^{+} \rho_{eg}
\\
- &\equiv \vb{p}^{-}(t) + \vb{p}^{+}(t)
+ &\equiv \vb{p}^{-} + \vb{p}^{+}
\end{aligned}$$
Where we have split $$\vb{p}$$ analogously to $$\vb{E}$$
@@ -117,8 +117,9 @@ Its equation of motion can then be found from the optical Bloch equations:
$$\begin{aligned}
\dv{\vb{p}^{+}}{t}
- = \vb{p}_0^{+} \dv{\rho_{eg}}{t}
- = - \vb{p}_0^{+} \Big( \gamma_\perp + i \omega_0 \Big) \rho_{eg}
+ &= \vb{p}_0^{+} \dv{\rho_{eg}}{t}
+ \\
+ &= - \vb{p}_0^{+} \Big( \gamma_\perp + i \omega_0 \Big) \rho_{eg}
+ \frac{i}{\hbar} \vb{p}_0^{+} \Big( \vb{p}_0^{-} \cdot \vb{E}^{+} \Big) \Big( \rho_{gg} - \rho_{ee} \Big)
\end{aligned}$$
@@ -147,7 +148,8 @@ we find its equation of motion to be:
$$\begin{aligned}
\dv{d}{t}
&= \dv{\rho_{ee}}{t} - \dv{\rho_{gg}}{t}
- = 2 \gamma_g \rho_{gg} - 2 \gamma_e \rho_{ee}
+ \\
+ &= 2 \gamma_g \rho_{gg} - 2 \gamma_e \rho_{ee}
+ \frac{i 2}{\hbar} \Big( \vb{p}^{-} \cdot \vb{E}^{+} - \vb{p}^{+} \cdot \vb{E}^{-} \Big)
\end{aligned}$$
diff --git a/source/know/concept/maxwell-relations/index.md b/source/know/concept/maxwell-relations/index.md
index 892ced1..f51acea 100644
--- a/source/know/concept/maxwell-relations/index.md
+++ b/source/know/concept/maxwell-relations/index.md
@@ -9,7 +9,7 @@ layout: "concept"
---
The **Maxwell relations** are a useful set of relations in thermodynamics.
-They arise from the fact that the order of differentiation is irrelevant
+They arise from the fact that the ordering of differentiation is irrelevant
for well-behaved functions (sometimes known as the *Schwarz theorem*),
applied to the [thermodynamic potentials](/know/concept/thermodynamic-potential/).
@@ -54,7 +54,7 @@ $$\begin{aligned}
= \Big( \pdv{B}{x} \Big)_y^{-1}
\end{aligned}$$
-The following quantities are useful to rewrite some of the Maxwell relations:
+The following quantities can be useful to rewrite some of the Maxwell relations:
the iso-$$P$$ thermal expansion coefficient $$\alpha$$,
the iso-$$T$$ combressibility $$\kappa_T$$,
the iso-$$S$$ combressibility $$\kappa_S$$,
@@ -73,6 +73,10 @@ $$\begin{gathered}
C_P \equiv T \Big( \pdv{S}{T} \Big)_{P,N}
\end{gathered}$$
+But for simplicity and brevity,
+we will not do any such rewriting in this article.
+
+
## Internal energy
@@ -116,6 +120,7 @@ $$\begin{gathered}
\end{gathered}$$
+
## Enthalpy
The following Maxwell relations can be derived
@@ -158,6 +163,7 @@ $$\begin{gathered}
\end{gathered}$$
+
## Helmholtz free energy
The following Maxwell relations can be derived
@@ -200,6 +206,7 @@ $$\begin{gathered}
\end{gathered}$$
+
## Gibbs free energy
The following Maxwell relations can be derived
@@ -242,10 +249,11 @@ $$\begin{gathered}
\end{gathered}$$
+
## Landau potential
The following Maxwell relations can be derived
-from the Gibbs free energy $$\Omega(T, V, \mu)$$:
+from the Landau potential $$\Omega(T, V, \mu)$$:
$$\begin{gathered}
- \mpdv{\Omega}{V}{T} =
diff --git a/source/know/concept/multi-photon-absorption/index.md b/source/know/concept/multi-photon-absorption/index.md
index 80dbc9b..481c19d 100644
--- a/source/know/concept/multi-photon-absorption/index.md
+++ b/source/know/concept/multi-photon-absorption/index.md
@@ -30,7 +30,6 @@ Here, we have made the
to neglect the $$e^{i \omega t}$$ term,
because it turns out to be irrelevant in this discussion.
-
We call the ground state $$\Ket{0}$$,
but other than that, the other states need *not* be sorted by energy.
However, we demand that the following holds
@@ -187,7 +186,7 @@ i.e. for any odd-numbered final state $$\Ket{u}$$.
## Two-photon absorption
Next, we go to second-order perturbation theory.
-Based on the previous result, this time
+Thanks to the previous result $$c_e^{(1)}(t) = 0$$, this time
all odd-numbered states $$\Ket{u}$$ are unaffected:
$$\begin{aligned}
@@ -248,7 +247,7 @@ two identical photons $$\hbar \omega$$ are absorbed simultaneously
to bridge the energy gap $$\hbar \omega_{e0}$$.
Surprisingly, such a transition can only occur when $$\matrixel{e}{\vu{p}}{0} = 0$$,
i.e. for any even-numbered final state $$\Ket{e}$$.
-Notice that the rate is proportional to $$|\vb{E}|^4$$,
+The rate is proportional to $$|\vb{E}|^4$$,
so this effect is only noticeable at high light intensities.
@@ -339,7 +338,7 @@ due to the dependence on $$\vb{E}$$.
If $$N$$ is odd, only odd-numbered destinations $$\Ket{u}$$ are allowed
(assuming the electron starts in the ground state $$\Ket{0}$$),
and if $$N$$ is even, only even-numbered destinations $$\Ket{e}$$.
-Note that nothing has been said about the energies of these states
+Nothing has been said about the energies of these states
(other than $$\Ket{0}$$ being the minimum);
everything is determined by the matrix elements $$\matrixel{f}{\vu{p}}{i}$$.
diff --git a/source/know/concept/no-cloning-theorem/index.md b/source/know/concept/no-cloning-theorem/index.md
index 840a598..9c8b11d 100644
--- a/source/know/concept/no-cloning-theorem/index.md
+++ b/source/know/concept/no-cloning-theorem/index.md
@@ -30,14 +30,14 @@ $$\begin{aligned}
\ket{0} \ket{?}
\:\:\longrightarrow\:\:
\ket{0} \ket{0}
- \qquad \quad
+ \qquad \qquad
\ket{1} \ket{?}
\:\:\longrightarrow\:\:
\ket{1} \ket{1}
\end{aligned}$$
If we feed this machine a superposition $$\ket{\psi} = \alpha \ket{0} + \beta \ket{1}$$,
-we *want* the following behaviour:
+we *want* the following behavior:
$$\begin{aligned}
\Big( \alpha \ket{0} + \beta \ket{1} \Big) \ket{?}
@@ -47,7 +47,7 @@ $$\begin{aligned}
&= \Big( \alpha^2 \ket{0} \ket{0} + \alpha \beta \ket{0} \ket{1} + \alpha \beta \ket{1} \ket{0} + \beta^2 \ket{1} \ket{1} \Big)
\end{aligned}$$
-Note the appearance of the cross terms with a factor of $$\alpha \beta$$.
+Note the appearance of the cross-terms with a factor of $$\alpha \beta$$.
The problem is that the fundamental linearity of quantum mechanics
dictates different behaviour:
@@ -59,7 +59,7 @@ $$\begin{aligned}
\end{aligned}$$
This is clearly not the same as before: we have a contradiction,
-which implies that such a general cloning machine cannot ever exist.
+which implies that such a general cloning machine cannot exist.
diff --git a/source/know/concept/nonlinear-schrodinger-equation/index.md b/source/know/concept/nonlinear-schrodinger-equation/index.md
new file mode 100644
index 0000000..820b361
--- /dev/null
+++ b/source/know/concept/nonlinear-schrodinger-equation/index.md
@@ -0,0 +1,708 @@
+---
+title: "Nonlinear Schrödinger equation"
+sort_title: "Nonlinear Schrodinger equation" # sic
+date: 2024-09-15
+categories:
+- Physics
+- Mathematics
+- Fiber optics
+- Nonlinear optics
+layout: "concept"
+---
+
+The **nonlinear Schrödinger (NLS) equation**
+is a nonlinear 1+1D partial differential equation
+that appears in many areas of physics.
+It is often given in its dimensionless form,
+where it governs the envelope $$u(z, t)$$
+of an underlying carrier wave,
+with $$t$$ the transverse coordinate,
+and $$r = \pm 1$$ a parameter determining
+which of two regimes the equation is intended for:
+
+$$\begin{aligned}
+ \boxed{
+ i \pdv{u}{z} + \pdvn{2}{u}{t} + r |u|^2 u
+ = 0
+ }
+\end{aligned}$$
+
+Many variants exist, depending on the conventions used by authors.
+The NLS equation is used to describe pulses in fiber optics (as derived below),
+waves over deep water, local opening of DNA chains, and much more.
+Very roughly speaking, it is a valid description of
+"all" weakly nonlinear, slowly modulated waves in physics.
+
+It exhibits an incredible range of behaviors,
+from "simple" effects such as
+[dispersive broadening](/know/concept/dispersive-broadening/),
+[self-phase modulation](/know/concept/self-phase-modulation/)
+and [first-order solitons](/know/concept/optical-soliton/),
+to weirder and more complicated phenomena like
+[modulational instability](/know/concept/modulational-instability/),
+[optical wave breaking](/know/concept/optical-wave-breaking/)
+and periodic *higher-order solitons*.
+It is also often modified to include additional physics,
+further enriching its results with e.g.
+[self-steepening](/know/concept/self-steepening/)
+and *soliton self-frequency shifting*.
+
+We only consider fiber optics here;
+the NLS equation can be derived in many other ways.
+We start from the most general form of the
+[electromagnetic wave equation](/know/concept/electromagnetic-wave-equation/),
+after assuming the medium cannot be magnetized ($$\mu_r = 1$$):
+
+$$\begin{aligned}
+ \nabla \cross \big( \nabla \cross \vb{E} \big)
+ = - \mu_0 \varepsilon_0 \pdvn{2}{\vb{E}}{t} - \mu_0 \pdvn{2}{\vb{P}}{t}
+\end{aligned}$$
+
+Using the vector identity
+$$\nabla \cross (\nabla \cross \vb{E}) = \nabla (\nabla \cdot \vb{E}) - \nabla^2 \vb{E}$$
+and [Gauss's law](/know/concept/maxwells-equations/) $$\nabla \cdot \vb{E} = 0$$,
+and splitting the polarization $$\vb{P}$$
+into linear and nonlinear contributions
+$$\vb{P}_\mathrm{L}$$ and $$\vb{P}_\mathrm{NL}$$:
+
+$$\begin{aligned}
+ \nabla^2 \vb{E} - \mu_0 \varepsilon_0 \pdvn{2}{\vb{E}}{t}
+ &= \mu_0 \pdvn{2}{\vb{P}_\mathrm{L}}{t} + \mu_0 \pdvn{2}{\vb{P}_\mathrm{NL}}{t}
+\end{aligned}$$
+
+In general, $$\vb{P}_\mathrm{L}$$ is given by the convolution
+of $$\vb{E}$$ with a second-rank response tensor $$\chi^{(1)}$$:
+
+$$\begin{aligned}
+ \vb{P}_\mathrm{L}(\vb{r}, t)
+ = \varepsilon_0 \int_{-\infty}^\infty \chi^{(1)}(t - t') \cdot \vb{E}(\vb{r}, t') \dd{t'}
+\end{aligned}$$
+
+In $$\vb{P}_\mathrm{NL}$$ we only include third-order nonlinearities,
+since higher orders are usually negligible,
+and second-order nonlinear effects only exist in very specific crystals.
+So we "only" need to deal with a fourth-rank response tensor $$\chi^{(3)}$$:
+
+$$\begin{aligned}
+ \vb{P}_\mathrm{NL}(\vb{r}, t)
+ = \varepsilon_0 \iiint_{-\infty}^\infty \chi^{(3)}(t \!-\! t_1, t \!-\! t_2, t \!-\! t_3)
+ \:\vdots\: \vb{E}(\vb{r}, t_1) \vb{E}(\vb{r}, t_2) \vb{E}(\vb{r}, t_3) \dd{t_1} \dd{t_2} \dd{t_3}
+\end{aligned}$$
+
+In practice, two phenomena contribute to $$\chi^{(3)}$$:
+the *Kerr effect* due to electrons' response to $$\vb{E}$$,
+and *Raman scattering* due to nuclei's response,
+which is slower because of their mass.
+But if the light pulses are sufficiently long (>1ps in silica),
+both effects can be treated as fast, so:
+
+$$\begin{aligned}
+ \chi^{(3)}(t \!-\! t_1, t \!-\! t_2, t \!-\! t_3)
+ &= \chi^{(3)} \delta(t - t_1) \delta(t - t_2) \delta(t - t_3)
+\end{aligned}$$
+
+Where $$\delta$$ is the [Dirac delta function](/know/concept/dirac-delta-function/).
+To keep things simple,
+we consider linearly $$x$$-polarized light $$\vb{E} = \vu{x} |\vb{E}|$$,
+such that the tensor can be replaced with its scalar element $$\chi^{(3)}_{xxxx}$$.
+Then:
+
+$$\begin{aligned}
+ \vb{P}_\mathrm{NL}
+ = \varepsilon_0 \chi^{(3)}_{xxxx} \big( \vb{E} \cdot \vb{E} \big) \vb{E}
+\end{aligned}$$
+
+For the same reasons, the linear polarization is reduced to:
+
+$$\begin{aligned}
+ \vb{P}_\mathrm{L}
+ &= \varepsilon_0 \chi^{(1)}_{xx} \vb{E}
+\end{aligned}$$
+
+Next, we decompose $$\vb{E}$$ as follows,
+consisting of a carrier wave $$e^{-i \omega_0 t}$$
+at a constant frequency $$\omega_0$$,
+modulated by an envelope $$E$$
+that is assumed to be slowly-varying compared to the carrier,
+plus the complex conjugate $$E^* e^{i \omega_0 t}$$:
+
+$$\begin{aligned}
+ \vb{E}(\vb{r}, t)
+ &= \vu{x} \frac{1}{2} \Big( E(\vb{r}, t) e^{- i \omega_0 t} + E^*(\vb{r}, t) e^{i \omega_0 t} \Big)
+\end{aligned}$$
+
+Note that no generality has been lost in this step.
+Inserting it into the polarizations:
+
+$$\begin{aligned}
+ \mathrm{P}_\mathrm{L}
+ &= \vu{x} \frac{1}{2} \varepsilon_0 \chi^{(1)}_{xx} \Big( E(\vb{r}, t) e^{- i \omega_0 t} + E^*(\vb{r}, t) e^{i \omega_0 t} \Big)
+ \\
+ \vb{P}_\mathrm{NL}
+ &= \vu{x} \frac{1}{8} \varepsilon_0 \chi^{(3)}_{xxxx} \Big( E e^{- i \omega_0 t} + E^* e^{i \omega_0 t} \Big)^{3}
+ \\
+ &= \vu{x} \frac{1}{8} \varepsilon_0 \chi^{(3)}_{xxxx}
+ \Big( E^3 e^{- i 3 \omega_0 t} + 3 E^2 E^* e^{- i \omega_0 t} + 3 E (E^*)^2 e^{i \omega_0 t} + (E^*)^3 e^{i 3 \omega_0 t} \Big)
+\end{aligned}$$
+
+The terms with $$3 \omega_0$$ represent *third-harmonic generation*,
+and only matter if the carrier is phase-matched
+to the tripled wave, which is generally not the case,
+so they can be ignored.
+Now, if we decompose the polarizations in the same was as $$\vb{E}$$:
+
+$$\begin{aligned}
+ \vb{P}_\mathrm{L}(\vb{r}, t)
+ &= \vu{x} \frac{1}{2} \Big( P_\mathrm{L}(\vb{r}, t) e^{- i \omega_0 t} + P_\mathrm{L}^*(\vb{r}, t) e^{i \omega_0 t} \Big)
+ \\
+ \vb{P}_\mathrm{NL}(\vb{r}, t)
+ &= \vu{x} \frac{1}{2} \Big( P_\mathrm{NL}(\vb{r}, t) e^{- i \omega_0 t} + P_\mathrm{NL}^*(\vb{r}, t) e^{i \omega_0 t} \Big)
+\end{aligned}$$
+
+Then it is straightforward to see that their envelope functions are given by:
+
+$$\begin{aligned}
+ P_\mathrm{L}
+ &= \varepsilon_0 \chi^{(1)}_{xx} E
+ \\
+ P_\mathrm{NL}
+ &= \frac{3}{4} \varepsilon_0 \chi^{(3)}_{xxxx} |E|^2 E
+\end{aligned}$$
+
+The forward carrier $$e^{- i \omega_0 t}$$
+and the backward carrier $$e^{i \omega_0 t}$$
+can be regarded as separate channels,
+which only interact via $$P_\mathrm{NL}$$.
+From now on, we only consider the forward-propagating wave,
+so all terms containing $$e^{i \omega_0 t}$$ are dropped;
+by taking the complex conjugate of the resulting equations,
+the backward-propagating counterparts can always be recovered,
+so no information is really lost.
+Therefore, the main wave equation becomes:
+
+$$\begin{aligned}
+ 0
+ &= \bigg(
+ \nabla^2 E - \mu_0 \varepsilon_0 \pdvn{2}{E}{t} - \mu_0 \pdvn{2}{P_\mathrm{L}}{t} - \mu_0 \pdvn{2}{P_\mathrm{NL}}{t}
+ \bigg) e^{-i \omega_0 t}
+ \\
+ &\approx \bigg(
+ \nabla^2 E - \Big( 1 + \chi^{(1)}_{xx} + \frac{3}{4} \chi^{(3)}_{xxxx} |E|^2 \Big) \mu_0 \varepsilon_0 \pdvn{2}{E}{t}
+ \bigg) e^{-i \omega_0 t}
+\end{aligned}$$
+
+Where we have used our assumption that $$E$$ is slowly-varying
+to treat $$|E|^2$$ as a constant,
+in order to move it outside the $$t$$-derivative.
+We thus arrive at:
+
+$$\begin{aligned}
+ 0
+ &= \bigg( \nabla^2 E - \frac{\varepsilon_r}{c^2} \pdvn{2}{E}{t} \bigg) e^{-i \omega_0 t}
+\end{aligned}$$
+
+Where $$c = 1 / \sqrt{\mu_0 \varepsilon_0}$$ is the phase velocity of light in a vacuum,
+and the relative permittivity $$\varepsilon_r$$ is defined as shown below.
+Note that this is a mild abuse of notation,
+since the symbol $$\varepsilon_r$$ is usually reserved for linear materials:
+
+$$\begin{aligned}
+ \varepsilon_r
+ \equiv 1 + \chi^{(1)}_{xx} + \frac{3}{4} \chi^{(3)}_{xxxx} |E|^2
+\end{aligned}$$
+
+Next, we take the [Fourier transform](/know/concept/fourier-transform/)
+$$t \to \omega$$ of the wave equation,
+again treating $$|E|^2$$ (inside $$\varepsilon_r$$) as a constant.
+The constant $$s = \pm 1$$ is included here
+to deal with the fact that different authors use different sign conventions:
+
+$$\begin{aligned}
+ 0
+ &= \hat{\mathcal{F}}\bigg\{ \bigg( \nabla^2 E - \frac{\varepsilon_r}{c^2} \pdvn{2}{E}{t} \bigg) e^{-i \omega_0 t} \bigg\}
+ \\
+ &= \int_{-\infty}^\infty
+ \bigg( \nabla^2 E - \frac{\varepsilon_r}{c^2} \pdvn{2}{E}{t} \bigg)
+ e^{i s (\omega - \omega_0) t} \dd{t}
+ \\
+ &= \nabla^2 E + s^2 (\omega - \omega_0)^2 \frac{\varepsilon_r}{c^2} E
+\end{aligned}$$
+
+We use $$s^2 = 1$$ and define $$\Omega \equiv \omega - \omega_0$$
+as the frequency shift relative to the carrier wave:
+
+$$\begin{aligned}
+ 0
+ &= \nabla^2 E + \frac{\Omega^2 \varepsilon_r}{c^2} E
+\end{aligned}$$
+
+This is a so-called *Helmholtz equation* in 3D,
+which we will solve using separation of variables,
+by assuming that its solution can be written as:
+
+$$\begin{aligned}
+ E(\vb{r}, \Omega)
+ &= F(x, y) \: A(z, \Omega) \: e^{i \beta_0 z}
+\end{aligned}$$
+
+Where $$\beta_0$$ is the wavenumber of the carrier,
+which will be determined later.
+Inserting this ansatz into the Helmholtz equation yields:
+
+$$\begin{aligned}
+ 0
+ &= \Big( \pdvn{2}{F}{x} + \pdvn{2}{F}{y} \Big) A e^{i \beta_0 z}
+ + \pdvn{2}{}{z} \Big( A e^{i \beta_0 z} \Big) F
+ + \frac{\Omega^2 \varepsilon_r}{c^2} F A e^{i \beta_0 z}
+ \\
+ &= \bigg( \Big( \pdvn{2}{F}{x} + \pdvn{2}{F}{y} \Big) A
+ + \Big( \pdvn{2}{A}{z} + 2 i \beta_0 \pdv{A}{z} - \beta_0^2 A \Big) F
+ + \frac{\Omega^2 \varepsilon_r}{c^2} F A \bigg) e^{i \beta_0 z}
+\end{aligned}$$
+
+We divide by $$F A \: e^{i \beta_0 z}$$
+and rearrange the terms in a specific way:
+
+$$\begin{aligned}
+ \Big( \pdvn{2}{F}{x} + \pdvn{2}{F}{y} \Big) \frac{1}{F} + \frac{\Omega^2 \varepsilon_r}{c^2}
+ &= - 2 i \beta_0 \pdv{A}{z} \frac{1}{A} + \beta_0^2
+\end{aligned}$$
+
+Now all the $$x$$- and $$y$$-dependence is on the left,
+and the $$z$$-dependence is on the right.
+We have placed the $$\varepsilon_r$$-term on the left too
+because it depends relatively strongly on $$(x, y)$$
+to describe the fiber's internal structure,
+and weakly on $$z$$ due to nonlinear effects.
+Meanwhile, $$\beta_0$$ is on the right because that will lead to
+a nicer equation for $$A$$ later.
+
+Note that both sides are functions of $$\Omega$$.
+Based on the aforementioned dependences,
+in order for this equation to have a solution for all $$(x, y, z)$$,
+there must exist a quantity $$\beta(\Omega)$$ that is constant in space,
+such that we obtain two separated equations for $$F$$ and $$A$$:
+
+$$\begin{aligned}
+ \beta(\omega)
+ &= \bigg( \pdvn{2}{F}{x} + \pdvn{2}{F}{y} \bigg) \frac{1}{F} + \frac{\omega^2 \varepsilon_r}{c^2}
+ \\
+ \beta(\Omega)
+ &= - 2 i \beta_0 \pdv{A}{z} \frac{1}{A} + \beta_0^2
+\end{aligned}$$
+
+Note that we replaced $$\Omega$$ with $$\omega$$ in $$F$$'s equation
+(and redefined $$\beta$$ and $$\varepsilon_r$$ accordingly).
+This is not an innocent detail:
+the idea is that $$\omega \sqrt{\varepsilon_r} / c$$
+would be the light's wavenumber if it had not been trapped in a waveguide,
+and that $$\beta$$ is the *confined* wavenumber,
+also known as the **propagation constant**.
+If we had kept $$\Omega$$,
+the meaning of $$\beta$$ would not be so straightforward.
+
+The difference between $$\beta(\omega)$$ and $$\beta_0$$
+is simply that $$\beta_0 \equiv \beta(\omega_0)$$.
+Our ansatz for separating the variables contained $$\beta_0$$,
+such that the full carrier wave $$e^{i \beta_0 z - i \omega_0 t}$$ was represented
+(with $$e^{- i \omega_0 t}$$ now hidden inside the Fourier transform).
+But later, to properly describe how light behaves inside the fiber,
+the full dispersion relation $$\beta(\omega)$$ will be needed.
+
+Multiplying by $$F$$ and $$A$$,
+we get the following set of equations,
+implicitly coupled via $$\beta$$:
+
+$$\begin{aligned}
+ \boxed{
+ \begin{aligned}
+ 0
+ &= \pdvn{2}{F}{x} + \pdvn{2}{F}{y} + \bigg( \frac{\omega^2 \varepsilon_r}{c^2} - \beta^2 \bigg) F
+ \\
+ 0
+ &= 2 i \beta_0 \pdv{A}{z} + \big( \beta^2 - \beta_0^2 \big) A
+ \end{aligned}
+ }
+\end{aligned}$$
+
+The equation for $$F$$ must be solved first.
+To do so, we treat the nonlinearity as a perturbation
+to be neglected initially.
+In other words, we first solve the following eigenvalue problem for $$\beta^2$$,
+where $$n(x, y)$$ is the linear refractive index,
+with $$n^2 = 1 + \Real\{\chi^{(1)}_{xx}\} \approx \varepsilon_r$$:
+
+$$\begin{aligned}
+ \pdvn{2}{F}{x} + \pdvn{2}{F}{y} + \bigg( \frac{\omega^2 n^2}{c^2} - \beta^2 \bigg) F
+ = 0
+\end{aligned}$$
+
+This gives us the allowed values of $$\beta$$;
+see [step-index fiber](/know/concept/step-index-fiber/) for an example solution.
+Now we add the small index change $$\Delta{n}(x, y)$$ due to nonlinear effects:
+
+$$\begin{aligned}
+ \varepsilon_r
+ = (n + \Delta{n})^2
+ \approx n^2 + 2 n \: \Delta{n}
+\end{aligned}$$
+
+Then it can be shown using first-order
+[perturbation theory](/know/concept/time-independent-perturbation-theory/)
+that the eigenfunction $$F$$ is not really affected,
+and the eigenvalue $$\beta^2$$ is shifted by $$\Delta(\beta^2)$$, given by:
+
+$$\begin{aligned}
+ \Delta(\beta^2)
+ = \frac{2 \omega^2}{c^2} \frac{\displaystyle \iint_{-\infty}^\infty n \: \Delta{n} \: |F|^2 \dd{x} \dd{y}}
+ {\displaystyle \iint_{-\infty}^\infty |F|^2 \dd{x} \dd{y}}
+\end{aligned}$$
+
+But we are more interested in the *wavenumber* shift $$\Delta{\beta}$$
+than the *eigenvalue* shift $$\Delta(\beta^2)$$.
+They are related to one another as follows:
+
+$$\begin{aligned}
+ \beta^2 + \Delta(\beta^2)
+ = (\beta + \Delta{\beta})^2
+ \approx \beta^2 + 2 \beta \Delta{\beta}
+\end{aligned}$$
+
+Furthermore, we assume that the fiber only consists of materials
+with similar refractive indices, or in other words,
+that it confines the light using only a small index difference,
+in which case we can treat $$n$$ as a constant and move it outside the integral.
+Then $$\Delta{\beta}$$ becomes:
+
+$$\begin{aligned}
+ \Delta{\beta}
+ = \frac{\omega^2 n}{\beta c^2} \frac{\displaystyle \iint_{-\infty}^\infty \Delta{n} \: |F|^2 \dd{x} \dd{y}}
+ {\displaystyle \iint_{-\infty}^\infty |F|^2 \dd{x} \dd{y}}
+\end{aligned}$$
+
+Recall that $$\beta$$ is the wavenumber of the confined mode:
+by solving the unperturbed $$F$$-equation,
+it can be shown that $$\beta$$'s value is somewhere
+between the bulk wavenumbers of the fiber materials.
+Since we just approximated $$n$$ as a constant,
+this means that $$\omega n / c \approx \beta$$, leading us to
+the general "final" form of $$\Delta{\beta}$$,
+with all the arguments shown for clarity:
+
+$$\begin{aligned}
+ \boxed{
+ \Delta{\beta}(\omega)
+ = \frac{\omega}{c \mathcal{A}_\mathrm{mode}}
+ \iint_{-\infty}^\infty \Delta{n}(x, y, \omega) \: |F(x, y)|^2 \dd{x} \dd{y}
+ }
+\end{aligned}$$
+
+Where we have defined the *mode area* $$\mathcal{A}_\mathrm{mode}$$ as shown below.
+In order for $$\mathcal{A}_\mathrm{mode}$$ to be in units of area,
+$$F$$ must be dimensionless,
+and consequently $$A$$ has (SI) units of an electric field.
+
+$$\begin{aligned}
+ \mathcal{A}_\mathrm{mode}
+ \equiv \iint_{-\infty}^\infty |F|^2 \dd{x} \dd{y}
+\end{aligned}$$
+
+Now we finally turn our attention to the equation for $$A$$.
+Before perturbation, it was:
+
+$$\begin{aligned}
+ 0
+ &= 2 i \beta_0 \pdv{A}{z} + \big( \beta^2 - \beta_0^2 \big) A
+\end{aligned}$$
+
+Where $$\beta \approx \beta_0$$, so we can replace
+$$\beta^2 - \beta_0^2$$ with $$2 \beta_0 (\beta - \beta_0)$$.
+Also including $$\Delta{\beta}$$, we get:
+
+$$\begin{aligned}
+ 0
+ &= i \pdv{A}{z} + \big( \beta + \Delta{\beta} - \beta_0 \big) A
+\end{aligned}$$
+
+Usually, we do not know a full expression for $$\beta(\omega)$$,
+so it makes sense to expand it around the carrier frequency $$\omega_0$$ as follows,
+where $$\beta_n = \idvn{n}{\beta}{\omega} |_{\omega = \omega_0}$$:
+
+$$\begin{aligned}
+ \beta(\omega)
+ &= \beta_0
+ + (\omega - \omega_0) \beta_1
+ + (\omega - \omega_0)^2 \frac{\beta_2}{2}
+ + (\omega - \omega_0)^3 \frac{\beta_3}{6}
+ + \: ...
+\end{aligned}$$
+
+Spectrally, the broader the light pulse, the more terms must be included.
+Recall that earlier, in order to treat $$\chi^{(3)}$$ as instantaneous,
+we already assumed a temporally broad
+(spectrally narrow) pulse.
+Hence, for simplicity, we can cut off this Taylor series at $$\beta_2$$,
+which is good enough in many cases.
+Inserting the expansion into $$A$$'s equation:
+
+$$\begin{aligned}
+ 0
+ &= i \pdv{A}{z} + i \frac{\beta_1}{s} (-i s \Omega) A - \frac{\beta_2}{2 s^2} (- i s \Omega)^2 A + \Delta{\beta}_0 A
+\end{aligned}$$
+
+Which we have rewritten in preparation for taking the inverse Fourier transform,
+by introducing $$s$$ and by replacing $$\Delta{\beta}(\omega)$$
+with $$\Delta{\beta_0} \equiv \Delta{\beta}(\omega_0)$$
+in order to remove all explicit dependence on $$\omega$$,
+i.e. we only keep the first term of $$\Delta{\beta}$$'s Taylor expansion.
+After transforming and using $$s^2 = 1$$,
+we get the following equation for $$A(z, t)$$:
+
+$$\begin{aligned}
+ 0
+ &= i \pdv{A}{z} + i s \beta_1 \pdv{A}{t} - \frac{\beta_2}{2} \pdvn{2}{A}{t} + \Delta{\beta}_0 A
+\end{aligned}$$
+
+The next step is to insert our expression for $$\Delta{\beta}_0$$,
+for which we must first choose a specific form for $$\Delta{n}$$
+according to which effects we want to include.
+Earlier, we approximated $$\varepsilon_r \approx n^2$$,
+so if we instead say that $$\varepsilon_r = (n \!+\! \Delta{n})^2$$,
+then $$\Delta{n}$$ should include absorption and nonlinearity.
+The most commonly used form for $$\Delta{n}$$ is therefore:
+
+$$\begin{aligned}
+ \Delta{n}(x, y, \omega)
+ = n_2(\omega) \: I(x, y, \omega) + i \frac{c \alpha(\omega)}{2 \omega}
+\end{aligned}$$
+
+Where $$I$$ is the intensity (i.e. power per unit area) of the light,
+$$n_2$$ is the material's *Kerr coefficient* in units of inverse intensity,
+and $$\alpha$$ is the attenuation coefficient
+consisting of linear and nonlinear contributions
+(see [multi-photon absorption](/know/concept/multi-photon-absorption/)).
+Specifically, they are given by:
+
+$$\begin{aligned}
+ n_2
+ = \frac{3 \Real\{\chi^{(3)}_{xxxx}\}}{4 \varepsilon_0 c n^2}
+ \qquad
+ \alpha
+ = \frac{\omega \Imag\{\chi^{(1)}_{xx}\}}{c n}
+ + \frac{3 \omega \Imag\{\chi^{(3)}_{xxxx}\}}{2 \varepsilon_0 c^2 n^2} I
+ \qquad
+ I
+ = \frac{\varepsilon_0 c n}{2} |F|^2 |A|^2
+\end{aligned}$$
+
+For simplicity we set $$\Imag\{\chi^{(3)}_{xxxx}\} = 0$$,
+which is a good approximation for silica fibers.
+Inserting this form of $$\Delta{n}$$ into $$\Delta{\beta_0}$$
+and neglecting the $$(x, y)$$-dependence of $$\Delta{n}$$ yields:
+
+$$\begin{aligned}
+ \Delta{\beta}_0
+ &= i \frac{\alpha}{2} \frac{\mathcal{A}_\mathrm{mode}}{\mathcal{A}_\mathrm{mode}}
+ + \frac{\omega_0 \varepsilon_0 c n n_2}{2 c \mathcal{A}_\mathrm{mode}} |A|^2 \iint_{-\infty}^\infty |F|^4 \dd{x} \dd{y}
+ \\
+ &= i \frac{\alpha}{2}
+ + \gamma_0 \frac{\varepsilon_0 c n}{2} \mathcal{A}_\mathrm{mode} |A|^2
+\end{aligned}$$
+
+Where we have defined the parameter $$\gamma_0 \equiv \gamma(\omega_0)$$ like so,
+involving the **effective mode area** $$\mathcal{A}_\mathrm{eff}$$,
+which contains all information about $$F$$ needed for solving $$A$$'s equation:
+
+$$\begin{aligned}
+ \boxed{
+ \gamma(\omega)
+ \equiv \frac{\omega n_2(\omega)}{c \mathcal{A}_\mathrm{eff}(\omega)}
+ }
+ \qquad \qquad
+ \boxed{
+ \mathcal{A}_\mathrm{eff}(\omega)
+ \equiv \frac{\displaystyle \bigg( \iint_{-\infty}^\infty |F|^2 \dd{x} \dd{y} \bigg)^2}
+ {\displaystyle \iint_{-\infty}^\infty |F|^4 \dd{x} \dd{y}}
+ }
+\end{aligned}$$
+
+Note the $$\omega$$-dependence of $$A_\mathrm{eff}$$:
+so far we have conveniently ignored that $$F$$ also depends on $$\omega$$,
+because it is a parameter in its eigenvalue equation.
+This is valid for spectrally narrow pulses, so we will stick with it.
+Just beware that some people make the ad-hoc generalization
+$$\gamma_0 \to \gamma(\omega)$$, which is not correct in general
+(this is an advanced topic, see Lægsgaard).
+
+Substituting $$\Delta{\beta_0}$$ into the main problem
+yields a prototype of the NLS equation:
+
+$$\begin{aligned}
+ 0
+ &= i \pdv{A}{z} + i s \beta_1 \pdv{A}{t} - \frac{\beta_2}{2} \pdvn{2}{A}{t} + i \frac{\alpha}{2} A
+ + \gamma_0 \frac{\varepsilon_0 c n}{2} \mathcal{A}_\mathrm{mode} |A|^2 A
+\end{aligned}$$
+
+The factor $$\varepsilon_0 c n / 2$$ looks familiar from the intensity $$I$$.
+This, combined with $$\mathcal{A}_\mathrm{mode}$$
+and the fact that $$A$$ is an electric field,
+suggests that we can redefine $$A \to A'$$
+such that $$|A'|^2$$ is the optical power in watts.
+Hence we make the following transformation:
+
+$$\begin{aligned}
+ \frac{\varepsilon_0 c n}{2} \mathcal{A}_\mathrm{mode} |A|^2
+ \:\:\to\:\:
+ |A|^2
+\end{aligned}$$
+
+We can divide away the transformation factors
+from all other terms in the equation, since they are linear,
+leading to the full *nonlinear Schrödinger equation*:
+
+$$\begin{aligned}
+ \boxed{
+ 0
+ = i \pdv{A}{z} + i s \beta_1 \pdv{A}{t} - \frac{\beta_2}{2} \pdvn{2}{A}{t} + i \frac{\alpha}{2} A + \gamma_0 |A|^2 A
+ }
+\end{aligned}$$
+
+This can be reduced by switching to a coordinate system
+where the time axis slides along the propagation axis at a speed $$s v$$,
+so we define $$Z \equiv z$$ and $$T \equiv t - s z / v$$ such that:
+
+$$\begin{aligned}
+ \pdv{A}{z}
+ &= \pdv{A}{Z} \pdv{Z}{z} + \pdv{A}{T} \pdv{T}{z}
+ = \pdv{A}{Z} - \frac{s}{v} \pdv{A}{T}
+ \\
+ \pdv{A}{t}
+ &= \pdv{A}{Z} \pdv{Z}{t} + \pdv{A}{T} \pdv{T}{t}
+ = \pdv{A}{T}
+\end{aligned}$$
+
+We insert this and set $$v = v_g$$,
+where $$v_g = 1 / \beta_1$$ is the light's group velocity:
+
+$$\begin{aligned}
+ \boxed{
+ 0
+ = i \pdv{A}{Z} - \frac{\beta_2}{2} \pdvn{2}{A}{T} + i \frac{\alpha}{2} A + \gamma_0 |A|^2 A
+ }
+\end{aligned}$$
+
+The NLS equation's name is due to its similarity
+to the Schrödinger equation of quantum physics,
+if you set $$\alpha = 0$$ and treat $$\gamma_0 |A|^2$$ as a potential.
+In fiber optics, the equation is usually rearranged
+to highlight that $$Z$$ (or $$z$$) is the propagation direction:
+
+$$\begin{aligned}
+ \pdv{A}{Z}
+ = - i \frac{\beta_2}{2} \pdvn{2}{A}{T} - \frac{\alpha}{2} A + i \gamma_0 |A|^2 A
+\end{aligned}$$
+
+Next, we want to reduce the equation to its dimensionless form.
+To do so, we make the following coordinate transformation,
+where $$\tilde{A}$$, $$\tilde{Z}$$ and $$\tilde{T}$$ are unitless,
+and $$A_c$$, $$Z_c$$ and $$T_c$$ are dimensioned scale parameters
+to be determined later:
+
+$$\begin{aligned}
+ \tilde{A}(\tilde{Z}, \tilde{T})
+ = \frac{A(Z, T)}{A_c}
+ \qquad\qquad
+ \tilde{Z}
+ = \frac{Z}{Z_c}
+ \qquad\qquad
+ \tilde{T}
+ = \frac{T}{T_c}
+\end{aligned}$$
+
+We insert this into the NLS equation,
+after setting $$\alpha = 0$$ according to convention:
+
+$$\begin{aligned}
+ 0
+ = i \frac{A_c}{Z_c} \pdv{\tilde{A}}{\tilde{Z}}
+ - \frac{\beta_2}{2} \frac{A_c}{T_c^2} \pdvn{2}{\tilde{A}}{\tilde{T}}
+ + \gamma_0 A_c^3 \big|\tilde{A}\big|^2 \tilde{A}
+\end{aligned}$$
+
+Multiplying by $$Z_c / A_c$$ to make all terms dimensionless leads us to:
+
+$$\begin{aligned}
+ 0
+ = i \pdv{\tilde{A}}{\tilde{Z}}
+ - \frac{\beta_2 Z_c}{2 T_c^2} \pdvn{2}{\tilde{A}}{\tilde{T}}
+ + \gamma_0 A_c^2 Z_c \big|\tilde{A}\big|^2 \tilde{A}
+\end{aligned}$$
+
+The goal is to remove those constant factors.
+In other words, we demand:
+
+$$\begin{aligned}
+ \frac{\beta_2 Z_c}{2 T_c^2}
+ = -1
+ \qquad\qquad
+ \gamma_0 A_c^2 Z_c
+ = r
+\end{aligned}$$
+
+Where $$r \equiv \pm 1$$, whose sign choice will be explained shortly.
+Note that we have two equations for three unknowns
+($$A_c$$, $$Z_c$$ and $$T_c$$),
+so one of the parameters needs to fixed manually.
+For example, we could choose our "input power"
+$$A_c \equiv \sqrt{1\:\mathrm{W}}$$, and then:
+
+$$\begin{aligned}
+ Z_c
+ = - \frac{2 T_c^2}{\beta_2}
+ \qquad
+ T_c^2
+ = -\frac{r \beta_2}{2 \gamma_0 A_c^2}
+ \qquad\implies\qquad
+ Z_c
+ = \frac{r}{\gamma_0 A_c^2}
+ \qquad
+ T_c
+ = \sqrt{ -\frac{r \beta_2}{2 \gamma_0 A_c^2} }
+\end{aligned}$$
+
+Because $$T_c$$ must be real,
+we should choose $$r \equiv - \sgn(\gamma_0 \beta_2)$$.
+We thus arrive at:
+
+$$\begin{aligned}
+ \boxed{
+ 0
+ = i \pdv{\tilde{A}}{\tilde{Z}}
+ + \pdvn{2}{\tilde{A}}{\tilde{T}}
+ + r \big|\tilde{A}\big|^2 \tilde{A}
+ }
+\end{aligned}$$
+
+In fiber optics, $$\gamma_0 > 0$$ for all materials,
+meaning $$r$$ represents the dispersion regime,
+so $$r = 1$$ is called *anomalous dispersion*
+and $$r = -1$$ *normal dispersion*.
+In some other fields, where $$\beta_2 < 0$$ always,
+$$r = 1$$ is called a *focusing nonlinearity*
+and $$r = -1$$ a *defocusing nonlinearity*.
+The famous bright solitons only exist for $$r = 1$$,
+so many authors only show that case.
+
+
+
+## References
+
+1. G.P. Agrawal,
+ *Nonlinear fiber optics*, 6th edition,
+ Elsevier.
+2. O. Bang,
+ *Nonlinear mathematical physics: lecture notes*,
+ 2020, unpublished.
+3. J. Lægsgaard,
+ [Mode profile dispersion in the generalized nonlinear Schrödinger equation](https://doi.org/10.1364/OE.15.016110),
+ 2007, Optica.
diff --git a/source/know/concept/optical-soliton/bright-full.png b/source/know/concept/optical-soliton/bright-full.png
new file mode 100644
index 0000000..dc02c73
--- /dev/null
+++ b/source/know/concept/optical-soliton/bright-full.png
Binary files differ
diff --git a/source/know/concept/optical-soliton/bright-half.avif b/source/know/concept/optical-soliton/bright-half.avif
new file mode 100644
index 0000000..ca95808
--- /dev/null
+++ b/source/know/concept/optical-soliton/bright-half.avif
Binary files differ
diff --git a/source/know/concept/optical-soliton/bright-half.jpg b/source/know/concept/optical-soliton/bright-half.jpg
new file mode 100644
index 0000000..f9375dc
--- /dev/null
+++ b/source/know/concept/optical-soliton/bright-half.jpg
Binary files differ
diff --git a/source/know/concept/optical-soliton/bright-half.png b/source/know/concept/optical-soliton/bright-half.png
new file mode 100644
index 0000000..e5042af
--- /dev/null
+++ b/source/know/concept/optical-soliton/bright-half.png
Binary files differ
diff --git a/source/know/concept/optical-soliton/bright-half.webp b/source/know/concept/optical-soliton/bright-half.webp
new file mode 100644
index 0000000..5e450a4
--- /dev/null
+++ b/source/know/concept/optical-soliton/bright-half.webp
Binary files differ
diff --git a/source/know/concept/optical-soliton/dark-full.png b/source/know/concept/optical-soliton/dark-full.png
new file mode 100644
index 0000000..4001bb5
--- /dev/null
+++ b/source/know/concept/optical-soliton/dark-full.png
Binary files differ
diff --git a/source/know/concept/optical-soliton/dark-half.avif b/source/know/concept/optical-soliton/dark-half.avif
new file mode 100644
index 0000000..c25d92f
--- /dev/null
+++ b/source/know/concept/optical-soliton/dark-half.avif
Binary files differ
diff --git a/source/know/concept/optical-soliton/dark-half.jpg b/source/know/concept/optical-soliton/dark-half.jpg
new file mode 100644
index 0000000..b52efa9
--- /dev/null
+++ b/source/know/concept/optical-soliton/dark-half.jpg
Binary files differ
diff --git a/source/know/concept/optical-soliton/dark-half.png b/source/know/concept/optical-soliton/dark-half.png
new file mode 100644
index 0000000..327166d
--- /dev/null
+++ b/source/know/concept/optical-soliton/dark-half.png
Binary files differ
diff --git a/source/know/concept/optical-soliton/dark-half.webp b/source/know/concept/optical-soliton/dark-half.webp
new file mode 100644
index 0000000..eaf12b5
--- /dev/null
+++ b/source/know/concept/optical-soliton/dark-half.webp
Binary files differ
diff --git a/source/know/concept/optical-soliton/index.md b/source/know/concept/optical-soliton/index.md
new file mode 100644
index 0000000..843642f
--- /dev/null
+++ b/source/know/concept/optical-soliton/index.md
@@ -0,0 +1,576 @@
+---
+title: "Optical soliton"
+sort_title: "Optical soliton"
+date: 2024-09-20
+categories:
+- Physics
+- Mathematics
+- Fiber optics
+- Nonlinear optics
+layout: "concept"
+---
+
+In general, a **soliton** is a wave packet
+that maintains its shape as it travels over great distances.
+They are only explainable by nonlinear physics,
+but many (often unrelated) nonlinear equations give rise to solitons:
+the [Boussinesq equations](/know/concept/boussinesq-wave-theory/),
+the [Korteweg-de Vries equation](/know/concept/korteweg-de-vries-equation/),
+the [nonlinear Schrödinger (NLS) equation](/know/concept/nonlinear-schrodinger-equation/),
+and more.
+Here we consider waveguide optics,
+which is governed by the NLS equation,
+given in dimensionless form by:
+
+$$\begin{aligned}
+ i u_z + u_{tt} + r |u|^2 u
+ = 0
+\end{aligned}$$
+
+Where $$r = \pm 1$$ determines the dispersion regime,
+and subscripts denote differentiation.
+We start by making the most general ansatz
+for the pulse envelope $$u(z, t)$$, namely:
+
+$$\begin{aligned}
+ u(z, t)
+ = \phi(z, t) \: e^{i \theta(z, t)}
+\end{aligned}$$
+
+With $$\phi$$ and $$\theta$$ both real.
+Note that no generality has been lost yet:
+we have simply split a single complex function
+into two real ones.
+The derivatives of $$u$$ thus become:
+
+$$\begin{aligned}
+ u_z
+ &= (\phi_z + i \phi \theta_z) \: e^{i \theta}
+ \\
+ u_t
+ &= (\phi_t + i \phi \theta_t) \: e^{i \theta}
+ \\
+ u_{tt}
+ &= (\phi_{tt} + 2 i \phi_t \theta_t + i \phi \theta_{tt} - \phi \theta_t^2) \: e^{i \theta}
+\end{aligned}$$
+
+Inserting $$u_z$$ and $$u_{tt}$$ into the NLS equation leads us to:
+
+$$\begin{aligned}
+ 0
+ &= i \phi_z - \phi \theta_z + \phi_{tt} + 2 i \phi_t \theta_t + i \phi \theta_{tt} - \phi \theta_t^2 + r \phi^3
+ \\
+ &= \phi_{tt} - \phi \theta_t^2 - \phi \theta_z + r \phi^3 + i (\phi \theta_{tt} + 2 \phi_t \theta_t + \phi_z)
+\end{aligned}$$
+
+Since $$\phi$$ and $$\theta$$ are both real,
+we can split this equation into its real and imaginary parts:
+
+$$\begin{aligned}
+ \boxed{
+ \begin{aligned}
+ 0
+ &= \phi_{tt} - \phi \theta_t^2 - \phi \theta_z + r \phi^3
+ \\
+ 0
+ &= \phi \theta_{tt} + 2 \phi_t \theta_t + \phi_z
+ \end{aligned}
+ }
+\end{aligned}$$
+
+Still no generality has been lost so far:
+these coupled equation are totally equivalent to the NLS equation.
+But now it is time make a more specific ansatz,
+namely that $$\phi$$ and $$\theta$$ both have a fixed shape
+but move at a group velocity $$v$$
+and phase velocity $$w$$, respectively:
+
+$$\begin{aligned}
+ \phi(z, t)
+ &= \phi(t - v z)
+ \\
+ \theta(z, t)
+ &= \theta(t - w z)
+\end{aligned}$$
+
+Meaning $$\phi_z = -v \phi_t$$ and $$\theta_z = -w \theta_t$$.
+Now the coupled equations are given by:
+
+$$\begin{aligned}
+ 0
+ &= \phi_{tt} - \phi \theta_t^2 + w \phi \theta_t + r \phi^3
+ \\
+ 0
+ &= \phi \theta_{tt} + 2 \phi_t \theta_t - v \phi_t
+\end{aligned}$$
+
+We multiply the imaginary part's equation by $$\phi$$ and take its indefinite integral,
+which can then be evaluated by recognizing the product rule of differentiation:
+
+$$\begin{aligned}
+ 0
+ &= \int \Big( \phi^2 \theta_{tt} + 2 \phi \phi_t \theta_t - v \phi \phi_t \Big) \dd{t}
+ \\
+ &= \phi^2 \theta_t - \frac{v}{2} \phi^2
+\end{aligned}$$
+
+Where the integration constant has been set to zero.
+This implies $$\theta_t = v/2$$, which we insert into the real part's equation, giving:
+
+$$\begin{aligned}
+ 0
+ &= \phi_{tt} + \frac{v}{4} (2 w - v) \phi + r \phi^3
+\end{aligned}$$
+
+Defining $$B \equiv v (v - 2 w) / 4$$,
+multiplying by $$2 \phi_t$$, and integrating in the same way:
+
+$$\begin{aligned}
+ 0
+ &= \int \Big( 2 \phi_t \phi_{tt} - 2 B \phi \phi_t + 2 r \phi^3 \phi_t \Big) \dd{t}
+ \\
+ &= \phi_t^2 - B \phi^2 + \frac{r}{2} \phi^4 - C
+\end{aligned}$$
+
+Where $$C$$ is an integration constant.
+Rearranging this yields a powerful equation,
+which can be interpreted as a "pseudoparticle"
+with kinetic energy $$\phi_t^2$$ moving in a potential $$-P(\phi)$$:
+
+$$\begin{aligned}
+ \boxed{
+ \phi_t^2
+ = P(\phi)
+ \equiv -\frac{r}{2} \phi^4 + B \phi^2 + C
+ }
+\end{aligned}$$
+
+We further restrict the set of acceptable solutions
+by demanding that $$\phi(t)$$ is localized,
+meaning $$\phi \to \phi_\infty$$ when $$t \to \pm \infty$$,
+for a finite constant $$\phi_\infty$$.
+This implies $$\phi_t \to 0$$ and $$\phi_{tt} \to 0$$:
+the former clearly requires $$P(\phi_\infty) = 0$$.
+Regarding the latter, we differentiate
+the pseudoparticle equation with respect to $$t$$,
+which tells us for $$t \to \pm \infty$$:
+
+$$\begin{aligned}
+ 0
+ = \phi_{tt}
+ &= \frac{1}{2} P'(\phi_\infty)
+ = (B - r \phi_\infty^2) \phi_\infty
+\end{aligned}$$
+
+Here we have two options:
+the "bright" case $$\phi_\infty = 0$$,
+and the "dark" case $$\phi_\infty^2 = r B$$.
+Before we investigate those further,
+let us finish finding $$\theta$$:
+we know that $$\theta_t = v/2$$, so:
+
+$$\begin{aligned}
+ \theta(t - w z)
+ = \int \theta_t \dd{(t - w v)}
+ = \frac{v}{2} (t - w v)
+\end{aligned}$$
+
+Where we can ignore the integration constant
+because the NLS equation has *Gauge symmetry*,
+i.e. it is invariant under a transformation
+of the form $$u \to u e^{i a}$$ with constant $$a$$.
+Finally, we rewrite this result to eliminate $$w$$ in favor of $$B$$:
+
+$$\begin{aligned}
+ \theta(z, t)
+ = \frac{v}{2} t - \bigg( \frac{v^2}{4} - B \bigg) z
+\end{aligned}$$
+
+
+
+## Bright solitons
+
+First we consider the "bright" option $$\phi_\infty = 0$$,
+where our requirement that $$P(\theta_\infty) = 0$$
+clearly means that we must set $$C = 0$$.
+We are therefore left with:
+
+$$\begin{aligned}
+ \phi_t^2
+ = P(\phi)
+ = -\frac{r}{2} \phi^4 + B \phi^2
+\end{aligned}$$
+
+We must consider $$r = 1$$ and $$r = -1$$, and the sign of $$B$$;
+the possible forms of $$P(\phi)$$ are shown in the sketch below.
+Because $$\phi_t$$ is real by definition,
+valid solutions can only exist in the shaded regions where $$P(\phi) \ge 0$$:
+
+{% include image.html file="bright-full.png" width="75%"
+ alt="Sketch of candidate potentials for bright solitons" %}
+
+However, in order to have *stable* solutions
+where $$\phi$$ does not grow uncontrolably,
+we must restrict ourselves to shaded regions with a finite area.
+Otherwise, if they are infinite (as for $$r = -1$$),
+then a positive feedback loop arises:
+$$\phi_t^2$$ grows, so $$|\phi|$$ increases,
+then according to the sketch $$\phi_t^2$$ grows even more, etc.
+While mathematically correct, that would be physically unacceptable,
+so the only valid case here is $$r = 1$$ with $$B > 0$$.
+
+Armed with this knowledge,
+we are now ready to integrate the pseudoparticle integration.
+First, we rewrite it as follows, defining $$x \equiv t - vz$$:
+
+$$\begin{aligned}
+ \phi_t
+ = \pdv{\phi}{x}
+ = \pm \sqrt{P(\phi)}
+ = \pm \phi \sqrt{B - \phi^2 / 2}
+\end{aligned}$$
+
+This can be rearranged such that the differential elements
+$$\dd{x}$$ and $$\dd{\phi}$$ are on opposite sides,
+which can then each be wrapped in an integral, like so:
+
+$$\begin{aligned}
+ \dd{x}
+ = \pm \frac{\sqrt{2}}{\phi \sqrt{2 B - \phi^2}} \dd{\phi}
+ \qquad\implies\qquad
+ \int_{x_0}^{x} \dd{\xi}
+ = \pm \sqrt{2} \int_{\phi_0}^{\phi} \frac{1}{\psi \sqrt{2 B - \psi^2}} \dd{\psi}
+\end{aligned}$$
+
+Note that these are *indefinite* integrals,
+which have been written as *definite* integrals
+by placing the constants $$x_0$$ and $$\phi_0$$
+and target variables $$x$$ and $$\phi$$ in the limits.
+
+In order to integrate by substitution,
+we define the new variable $$f \equiv \psi / \sqrt{2 B}$$
+and update the limits accordingly
+to $$F \equiv \phi / \sqrt{2 B}$$
+and $$F_0 \equiv \phi_0 / \sqrt{2 B}$$:
+
+$$\begin{aligned}
+ x - x_0
+ &= \pm \sqrt{2} \int_{F_0}^{F} \frac{\sqrt{2 B}}{f \sqrt{2 B} \sqrt{2 B - 2 B f^2}} \dd{f}
+ \\
+ &= \pm \frac{1}{\sqrt{B}} \int_{F_0}^{F} \frac{1}{f \sqrt{1 - f^2}} \dd{f}
+\end{aligned}$$
+
+We look up this integrand, and discover that it is in fact the derivative
+of the inverse $$\sech^{-1}$$ of the hyperbolic secant function, so we arrive at:
+
+$$\begin{aligned}
+ x - x_0
+ &= \pm \frac{1}{\sqrt{B}} \int_{F_0}^{F} \dv{}{f} \Big( \sech^{-1}(f) \Big) \dd{f}
+ \\
+ &= \pm \frac{1}{\sqrt{B}} \sech^{-1}(F) \mp \frac{1}{\sqrt{B}} \sech^{-1}(F_0)
+\end{aligned}$$
+
+Rearranging and combining the integration constants
+$$x_0$$ and $$F_0$$ into a single $$t_0$$, we get:
+
+$$\begin{aligned}
+ \sech^{-1}(F)
+ = \pm \sqrt{B} (x - t_0)
+ \qquad\qquad
+ t_0
+ \equiv x_0 \mp \frac{1}{\sqrt{B}} \sech^{-1}(F_0)
+\end{aligned}$$
+
+Then, wrapping everything in $$\sech$$
+(which is an even function, so we can discard the $$\pm$$)
+and using $$F \equiv \phi / \sqrt{2 B}$$,
+we finally arrive at the desired solution for $$\phi$$:
+
+$$\begin{aligned}
+ \phi(x)
+ = \sqrt{2 B} \sech\!\Big( \sqrt{B} (x - t_0) \Big)
+\end{aligned}$$
+
+Combining this result with our earlier solution for $$\theta$$,
+we find that the full so-called **bright soliton** $$u$$
+is as follows, controlled by two real parameters
+$$B > 0$$ and $$v$$:
+
+$$\begin{aligned}
+ \boxed{
+ u(z, t)
+ = \sqrt{2 B} \sech\!\bigg( \sqrt{B} (t - v z - t_0) \bigg)
+ \exp\!\bigg( i \frac{v}{2} t - i \Big( \frac{v^2}{4} - B \Big) z \bigg)
+ }
+\end{aligned}$$
+
+It is always possible to transform the NLS equation
+into a new moving coordinate system such that $$v = 0$$,
+yielding a stationary soliton given by:
+
+$$\begin{aligned}
+ \boxed{
+ u(z, t)
+ = \sqrt{2 B} \sech\!\Big( \sqrt{B} (t - t_0) \Big) \exp(i B z)
+ }
+\end{aligned}$$
+
+You may be wondering how we can set $$v = 0$$ without affecting $$B$$;
+a more correct way of saying it would be that
+we take the limits $$v \to 0$$ and $$w \to -\infty$$.
+
+That was for the dimensionless form of the NLS equation;
+let us specialize this to its usual form in fiber optics.
+We thus make a transformation $$u \to U/U_c$$,
+$$t \to T/T_c$$ and $$z \to Z/Z_c$$:
+
+$$\begin{aligned}
+ \frac{U(Z, T)}{U_c}
+ &= \sqrt{2 B} \sech\!\bigg( \sqrt{B} \: \frac{T - T_0}{T_c} \bigg)
+ \exp\!\bigg( i B \frac{Z}{Z_c} \bigg)
+\end{aligned}$$
+
+Where $$U_c$$, $$T_c$$ and $$Z_c$$ are scale constants
+determined during non-dimensionalization
+to obey the relations below.
+We only have two relations, so we can choose one value freely,
+say, $$U_c$$:
+
+$$\begin{aligned}
+ Z_c
+ = \frac{1}{\gamma_0 U_c^2}
+ \qquad\qquad
+ T_c
+ = \sqrt{\frac{- \beta_2}{2 \gamma_0 U_c^2}}
+\end{aligned}$$
+
+Note that $$r = 1$$ implies $$\beta_2 < 0$$ assuming $$\gamma_0 > 0$$.
+In other words, bright solitons only exist
+in the anomalous dispersion regime of an optical fiber.
+Inserting these relations into the expression
+and defining the peak power $$P_0 \equiv 2 B U_c^2$$ yields:
+
+$$\begin{aligned}
+ U(Z, T)
+ &= \sqrt{P_0}
+ \sech\!\Bigg( \sqrt{\frac{\gamma_0 P_0}{- \beta_2}} (T - T_0) \Bigg)
+ \exp\!\bigg( i \frac{\gamma_0 P_0}{2} Z \bigg)
+\end{aligned}$$
+
+In practice, most authors write this as follows,
+where $$T_\mathrm{w}$$ determines the width of the pulse:
+
+$$\begin{aligned}
+ \boxed{
+ U(Z, T)
+ = \sqrt{P_0} \sech\!\bigg( \frac{T - T_0}{T_\mathrm{w}} \bigg) \exp\!\bigg( i \frac{\gamma_0 P_0}{2} Z \bigg)
+ }
+\end{aligned}$$
+
+Clearly, for this to be a valid solution of the NLS equation,
+$$T_\mathrm{w}$$ must be subject to a constraint
+involving the so-called **soliton number** $$N_\mathrm{sol}$$:
+
+$$\begin{aligned}
+ \boxed{
+ N_\mathrm{sol}^2
+ \equiv \frac{L_D}{L_N}
+ = \frac{\gamma_0 P_0 T_\mathrm{w}^2}{|\beta_2|}
+ = 1
+ }
+\end{aligned}$$
+
+Where $$L_D \equiv T_0 / |\beta_2|$$ is the linear length scale
+of [dispersive broadening](/know/concept/dispersive-broadening/),
+and $$L_N \equiv 1 / (\gamma_0 P_0)$$ is the nonlinear length scale
+of [self-phase modulation](/know/concept/self-phase-modulation/).
+A *first-order* soliton has $$N_\mathrm{sol} = 1$$
+and simply maintains its shape,
+whereas higher-order solitons have complicated periodic dynamics.
+
+
+
+## Dark solitons
+
+The other option to satisfy $$P'(\phi_\infty) = 0$$
+is $$\phi_\infty^2 = r B$$, which implies $$r B > 0$$
+such that $$\phi_\infty$$ is real.
+With this in mind, we again sketch all remaining candidates for $$P(\phi)$$:
+
+{% include image.html file="dark-full.png" width="75%"
+ alt="Sketch of candidate potentials for dark solitons" %}
+
+At a glance, there are plenty of solutions here, even stable ones!
+However, as explained earlier, our localization requirement
+means that we need $$P(\phi_\infty) = 0$$ and $$P'(\phi_\infty) = 0$$.
+The latter is only satisfied by the solid curve above,
+so we must limit ourselves to $$r = -1$$ and $$B < 0$$,
+with $$C = C_0$$ for some positive $$C_0$$.
+The next step is to find $$C_0$$.
+
+We notice that the target curve has two double roots
+at $$\pm \phi_\infty$$, so we can rewrite:
+
+$$\begin{aligned}
+ P(\phi)
+ &= \frac{1}{2} \Big( \phi^4 + 2 B \phi^2 + 2 C \Big)
+ \\
+ &= \frac{1}{2} \Big( \phi^4 + 2 B \phi^2 + B^2 - B^2 + 2 C \Big)
+ \\
+ &= \frac{1}{2} \big( \phi^2 + B \big)^2 - \frac{1}{2} \big( B^2 - 2 C \big)
+\end{aligned}$$
+
+Here we see that $$P(\phi_\infty)$$ can only have a double root
+when $$C = C_0 = B^2 / 2$$, in which case the root is clearly $$\phi_\infty = \pm \sqrt{-B}$$.
+We are therefore left with:
+
+$$\begin{aligned}
+ \phi_t^2
+ = P(\phi)
+ = \frac{1}{2} \big( \phi^2 + B \big)^2
+\end{aligned}$$
+
+Now we are ready to integrate this equation.
+Taking the square root with $$x \equiv t - v z$$:
+
+$$\begin{aligned}
+ \phi_t
+ = \pdv{\phi}{x}
+ = \pm \sqrt{P(\phi)}
+ = \pm \frac{1}{\sqrt{2}} (\phi^2 + B)
+\end{aligned}$$
+
+We put the differential elements $$\dd{\phi}$$ and $$\dd{x}$$
+on opposite sides and take the integrals:
+
+$$\begin{aligned}
+ \dd{x}
+ = \pm \frac{\sqrt{2}}{\phi^2 + B} \dd{\phi}
+ \qquad\implies\qquad
+ \int_{x_0}^{x} \dd{\xi}
+ = \pm \sqrt{2} \int_{\phi_0}^{\phi} \frac{1}{\psi^2 + B} \dd{\psi}
+\end{aligned}$$
+
+Then we define $$f \equiv \psi / \sqrt{-B}$$,
+and update the limits to
+$$F = \phi / \sqrt{-B}$$ and $$F_0 = \phi_0 / \sqrt{-B}$$,
+in order to integrate by substitution:
+
+$$\begin{aligned}
+ x - x_0
+ &= \pm \sqrt{2} \int_{F_0}^{F} \frac{\sqrt{-B}}{- B f^2 + B} \dd{f}
+ \\
+ &= \pm \sqrt{-\frac{2}{B}} \int_{F_0}^{F} \frac{1}{1 - f^2} \dd{f}
+\end{aligned}$$
+
+The integrand can be looked up:
+it turns out be the derivative of $$\tanh^{-1}$$,
+the inverse hyperbolic tangent function,
+so we arrive at:
+
+$$\begin{aligned}
+ x - x_0
+ &= \pm \sqrt{-\frac{2}{B}} \int_{F_0}^{F} \dv{}{f} \Big( \tanh^{-1}(f) \Big) \dd{f}
+ \\
+ &= \pm \sqrt{-\frac{2}{B}} \tanh^{-1}(F) \mp \sqrt{-\frac{2}{B}} \tanh^{-1}(F_0)
+\end{aligned}$$
+
+Rearranging, and combining the integration constants
+$$x_0$$ and $$F_0$$ into a single $$t_0$$, yields:
+
+$$\begin{aligned}
+ \tanh^{-1}(F)
+ &= \pm \sqrt{-\frac{B}{2}} (x - t_0)
+ \qquad\qquad
+ t_0
+ \equiv x_0 \mp \sqrt{-\frac{2}{B}} \tanh^{-1}(F_0)
+\end{aligned}$$
+
+Next, we take the $$\tanh$$ of both sides.
+It is an odd function, so the $$\pm$$ can be moved outside,
+where it can be ignored entirely thanks to the NLS equation's Gauge symmetry.
+Using $$F = \phi / \sqrt{-B}$$:
+
+$$\begin{aligned}
+ \phi(x)
+ &= \sqrt{-B} \tanh\!\Bigg( \sqrt{-\frac{B}{2}} (x - t_0) \Bigg)
+\end{aligned}$$
+
+Combining this with our expression for $$\theta$$,
+we arrive at the full **dark soliton** solution for $$u$$:
+
+$$\begin{aligned}
+ \boxed{
+ u(z, t)
+ = \sqrt{-B} \tanh\!\Bigg( \sqrt{-\frac{B}{2}} (t - v z - t_0) \Bigg)
+ \exp\!\bigg( i \frac{v}{2} t - i \Big( \frac{v^2}{4} - B \Big) z \bigg)
+ }
+\end{aligned}$$
+
+There are two free parameters here: $$B < 0$$ and $$v$$.
+Once again, we can always transform to a moving coordinate system such that $$v = 0$$,
+resulting in a stationary soliton:
+
+$$\begin{aligned}
+ \boxed{
+ u(z, t)
+ = \sqrt{-B} \tanh\!\Bigg( \sqrt{-\frac{B}{2}} (t - t_0) \Bigg)
+ \exp(i B z)
+ }
+\end{aligned}$$
+
+Like we did for the bright solitons,
+let us specialize this result to fiber optics.
+Making a similar transformation $$u \to U/U_c$$,
+$$t \to T/T_c$$ and $$z \to Z/Z_c$$ yields:
+
+$$\begin{aligned}
+ \frac{U(Z, T)}{U_c}
+ = \sqrt{-B} \tanh\!\Bigg( \sqrt{-\frac{B}{2}} \frac{T - T_0}{T_c} \Bigg)
+ \exp\!\bigg( i B \frac{Z}{Z_c} \bigg)
+\end{aligned}$$
+
+Where we again choose $$U_c$$ manually,
+and then find $$T_c$$ and $$Z_c$$ using these relations
+(note the opposite signs because $$r = -1$$ in this case):
+
+$$\begin{aligned}
+ Z_c
+ = \frac{-1}{\gamma_0 U_c^2}
+ \qquad\qquad
+ T_c
+ = \sqrt{\frac{\beta_2}{2 \gamma_0 U_c^2}}
+\end{aligned}$$
+
+Recall that $$r = -1$$ implies $$\beta_2 > 0$$ assuming $$\gamma_0 > 0$$,
+meaning dark solitons can only exist in the normal dispersion regime.
+Inserting this into the expression
+and defining the background power $$P_0 \equiv -B U_c^2$$
+such that $$|U|^2 \to P_0$$ for $$t \to \pm \infty$$,
+we arrive at:
+
+$$\begin{aligned}
+ U(Z, T)
+ = \sqrt{P_0} \tanh\!\Bigg( \sqrt{\frac{\gamma_0 P_0}{\beta_2}} (T - T_0) \Bigg) \exp(i \gamma_0 P_0 Z)
+\end{aligned}$$
+
+Which, as for bright solitons, can be rewritten
+with a pulse width $$T_\mathrm{w}$$ satisfying $$N_\mathrm{sol} = 1$$:
+
+$$\begin{aligned}
+ \boxed{
+ U(Z, T)
+ = \sqrt{P_0} \tanh\!\bigg( \frac{T - T_0}{T_\mathrm{w}} \bigg) \exp(i \gamma_0 P_0 Z)
+ }
+\end{aligned}$$
+
+
+
+## References
+
+1. A. Scott,
+ *Nonlinear science: emergence and dynamics of coherent structures*,
+ 2nd edition, Oxford.
+2. O. Bang,
+ *Nonlinear mathematical physics: lecture notes*,
+ 2020, unpublished.
diff --git a/source/know/concept/optical-wave-breaking/frequency-full.png b/source/know/concept/optical-wave-breaking/frequency-full.png
deleted file mode 100644
index 93e0506..0000000
--- a/source/know/concept/optical-wave-breaking/frequency-full.png
+++ /dev/null
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/frequency-half.avif b/source/know/concept/optical-wave-breaking/frequency-half.avif
deleted file mode 100644
index c4dfc19..0000000
--- a/source/know/concept/optical-wave-breaking/frequency-half.avif
+++ /dev/null
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/frequency-half.jpg b/source/know/concept/optical-wave-breaking/frequency-half.jpg
deleted file mode 100644
index ff24e69..0000000
--- a/source/know/concept/optical-wave-breaking/frequency-half.jpg
+++ /dev/null
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/frequency-half.png b/source/know/concept/optical-wave-breaking/frequency-half.png
deleted file mode 100644
index e39c8ea..0000000
--- a/source/know/concept/optical-wave-breaking/frequency-half.png
+++ /dev/null
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/frequency-half.webp b/source/know/concept/optical-wave-breaking/frequency-half.webp
deleted file mode 100644
index f3d04b1..0000000
--- a/source/know/concept/optical-wave-breaking/frequency-half.webp
+++ /dev/null
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-domegadt-full.png b/source/know/concept/optical-wave-breaking/gauss-domegadt-full.png
new file mode 100644
index 0000000..3b08cbf
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-domegadt-full.png
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-domegadt-half.avif b/source/know/concept/optical-wave-breaking/gauss-domegadt-half.avif
new file mode 100644
index 0000000..6241a2b
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-domegadt-half.avif
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-domegadt-half.jpg b/source/know/concept/optical-wave-breaking/gauss-domegadt-half.jpg
new file mode 100644
index 0000000..764e183
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-domegadt-half.jpg
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-domegadt-half.png b/source/know/concept/optical-wave-breaking/gauss-domegadt-half.png
new file mode 100644
index 0000000..d74c860
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-domegadt-half.png
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-domegadt-half.webp b/source/know/concept/optical-wave-breaking/gauss-domegadt-half.webp
new file mode 100644
index 0000000..dc6c2ec
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-domegadt-half.webp
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-omega-full.png b/source/know/concept/optical-wave-breaking/gauss-omega-full.png
new file mode 100644
index 0000000..385206a
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-omega-full.png
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-omega-half.avif b/source/know/concept/optical-wave-breaking/gauss-omega-half.avif
new file mode 100644
index 0000000..b2f882b
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-omega-half.avif
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-omega-half.jpg b/source/know/concept/optical-wave-breaking/gauss-omega-half.jpg
new file mode 100644
index 0000000..faa77c6
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-omega-half.jpg
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-omega-half.png b/source/know/concept/optical-wave-breaking/gauss-omega-half.png
new file mode 100644
index 0000000..5e50523
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-omega-half.png
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/gauss-omega-half.webp b/source/know/concept/optical-wave-breaking/gauss-omega-half.webp
new file mode 100644
index 0000000..e17c47b
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/gauss-omega-half.webp
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/index.md b/source/know/concept/optical-wave-breaking/index.md
index 1b6b558..2d81b8f 100644
--- a/source/know/concept/optical-wave-breaking/index.md
+++ b/source/know/concept/optical-wave-breaking/index.md
@@ -1,7 +1,7 @@
---
title: "Optical wave breaking"
sort_title: "Optical wave breaking"
-date: 2021-02-27
+date: 2024-10-06 # Originally 2021-02-27, major rewrite
categories:
- Physics
- Optics
@@ -10,223 +10,470 @@ categories:
layout: "concept"
---
-In fiber optics, **optical wave breaking** (OWB) is a nonlinear effect
-caused by interaction between
-[group velocity dispersion](/know/concept/dispersive-broadening/) (GVD) and
-[self-phase modulation](/know/concept/self-phase-modulation/) (SPM).
+In fiber optics, **optical wave breaking (OWB)** is an effect
+that can occur in light pulse envelopes $$A(z, t)$$ governed by
+the [nonlinear Schrödinger equation](/know/concept/nonlinear-schrodinger-equation/):
+
+$$\begin{aligned}
+ 0
+ &= i \pdv{A}{z} - \frac{\beta_2}{2} \pdvn{2}{A}{t} + \gamma_0 |A|^2 A
+\end{aligned}$$
+
+OWB is caused by an interaction between
+the [group velocity dispersion (GVD)](/know/concept/dispersive-broadening/)
+caused by the $$\beta_2$$-term,
+and the [self-phase modulation (SPM)](/know/concept/self-phase-modulation/)
+caused by the $$\gamma_0$$ term.
It only happens in the normal dispersion regime ($$\beta_2 > 0$$)
-for pulses meeting a certain criterium, as we will see.
+for pulses meeting certain criteria, as we shall see.
-SPM creates low frequencies at the front of the pulse, and high ones at the back,
-and if $$\beta_2 > 0$$, GVD lets low frequencies travel faster than high ones.
+In short, SPM creates low frequencies at the front of the pulse
+and high ones at the back, and for $$\beta_2 > 0$$,
+GVD makes low frequencies travel faster than high ones.
When those effects interact, the pulse gets temporally stretched
in a surprisingly sophisticated way.
-To illustrate this, the instantaneous frequency $$\omega_i(z, t) = -\ipdv{\phi}{t}$$
-has been plotted below for a theoretical Gaussian input pulse experiencing OWB,
-with settings $$T_0 = 100\:\mathrm{fs}$$, $$P_0 = 5\:\mathrm{kW}$$,
-$$\beta_2 = 2\:\mathrm{ps}^2/\mathrm{m}$$ and $$\gamma = 0.1/\mathrm{W}/\mathrm{m}$$.
+To illustrate the resulting dynamics,
+the simulated power $$|A|^2$$ of a Gaussian pulse with settings
+$$T_0 = 100\:\mathrm{fs}$$, $$P_0 = 5\:\mathrm{kW}$$,
+$$\beta_2 = 2\:\mathrm{ps}^2/\mathrm{m}$$ and $$\gamma = 0.1/\mathrm{W}/\mathrm{m}$$
+is plotted below as a function of $$z$$,
+with the time domain on the left
+and the frequency domain on the right:
-In the left panel, we see the typical S-shape caused by SPM,
-and the arrows indicate the direction that GVD is pushing the curve in.
-This leads to steepening at the edges, i.e. the S gradually turns into a Z.
-Shortly before the slope would become infinite,
-small waves start "falling off" the edge of the pulse,
-hence the name *wave breaking*:
-
-{% include image.html file="frequency-full.png" width="100%"
- alt="Instantaneous frequency profile evolution" %}
+$$\begin{aligned}
+ A(0, t)
+ &= \sqrt{P_0} \exp\!\bigg( \!-\!\frac{t^2}{2 T_0^2} \bigg)
+\end{aligned}$$
-Several interesting things happen around this moment.
-To demonstrate this, spectrograms of the same simulation
-have been plotted below, together with pulse profiles
-in both the $$t$$-domain and $$\omega$$-domain on an arbitrary linear scale
-(click the image to get a better look).
+{% include image.html file="simulation-full.png" width="100%"
+ alt="Plot of optical wave breaking simulation results" %}
-Initially, the spectrum broadens due to SPM in the usual way,
-but shortly after OWB, this process is stopped by the appearance
-of so-called **sidelobes** in the $$\omega$$-domain on either side of the pulse.
-In the meantime, in the time domain,
-the pulse steepens at the edges, but flattens at the peak.
-After OWB, a train of small waves falls off the edges,
-which eventually melt together, leading to a trapezoid shape in the $$t$$-domain.
-Dispersive broadening then continues normally:
+OWB occurs at a distance called $$L_\mathrm{WB}$$,
+and until that point things look relatively normal,
+with SPM causing spectral broadening
+and GVD causing subtle internal deformation in the time domain.
+After $$L_\mathrm{WB}$$, the pulse suddenly explodes due to GVD,
+and complicated so-called **sidelobes** appear in the frequency domain,
+which seem to block any further SPM.
+To investigate, we plot a series of spectrograms of the same simulation:
{% include image.html file="spectrograms-full.png" width="100%"
- alt="Spectrograms of pulse shape evolution" %}
+ alt="Spectrograms of simulated pulse shape evolution" %}
-We call the distance at which the wave breaks $$L_\mathrm{WB}$$,
-and want to predict it analytically.
-We do this using the instantaneous frequency $$\omega_i$$,
-by estimating when the SPM fluctuations overtake their own base,
-as was illustrated earlier.
+At first, we see the appearance of SPM's typical "S" shape,
+which quickly starts turning into a "Z" due to GVD.
+When the transition to "Z" is complete,
+there are many overlapping frequencies at the edges of the pulse.
+This causes a complicated interaction
+that generates the sidelobes,
+and causes a train of small waves to "fall off"
+the near-vertical pulse edges in the time domain,
+hence the name *wave breaking*.
+Eventually, those small waves melt together,
+leaving behind a curious trapezoid shape
+that gets stretched by GVD as usual.
-To get $$\omega_i$$ of a Gaussian pulse experiencing both GVD and SPM,
-it is a reasonable approximation, for small $$z$$, to simply add up
-the instantaneous frequencies for these separate effects:
+We would like to theoretically predict
+the distance $$L_\mathrm{WB}$$ at which the wave breaks.
+First we show the general principle,
+and then we apply it to a couple of example pulses.
+
+
+
+## General method
+
+We make the following ansatz for the complex envelope $$A(z, t)$$,
+without loss of generality:
$$\begin{aligned}
- \omega_i(z,t)
- &\approx \omega_\mathrm{GVD}(z,t) + \omega_\mathrm{SPM}(z,t)
- = \frac{tz}{T_0^2} \bigg( \frac{\beta_2 / T_0^2}{1 + \beta_2^2 z^2 / T_0^4}
- + 2\gamma P_0 \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big) \bigg)
+ A(z, t)
+ = \psi(z, t) \exp\!\big(i \phi(z, t)\big)
\end{aligned}$$
-Assuming that $$z$$ is small enough such that $$z^2 \approx 0$$, this
-expression can be reduced to:
+Inserting this into the NLS equation and dividing out $$e^{i \phi}$$ yields:
$$\begin{aligned}
- \omega_i(z,t)
- \approx \frac{\beta_2 tz}{T_0^4} \bigg( 1 + 2\frac{\gamma P_0 T_0^2}{\beta_2} \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big) \bigg)
- = \frac{\beta_2 t z}{T_0^4} \bigg( 1 + 2 N_\mathrm{sol}^2 \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big) \bigg)
+ 0
+ &= i \psi_z - \psi \phi_z - \frac{\beta_2}{2} (\psi_{tt} + 2 i \psi_t \phi_t + i \psi \phi_{tt} - \psi \phi_t^2) + \gamma_0 \psi^3
\end{aligned}$$
-Where we have assumed $$\beta_2 > 0$$,
-and $$N_\mathrm{sol}$$ is the **soliton number**,
-which is defined as:
+Since $$\psi$$ and $$\phi$$ are real by definition,
+we can split this into its real and imaginary parts:
$$\begin{aligned}
- N_\mathrm{sol}^2
- \equiv \frac{L_D}{L_N}
- = \frac{\gamma P_0 T_0^2}{|\beta_2|}
+ 0
+ &= \psi_z - \frac{\beta_2}{2} (2 \psi_t \phi_t + \psi \phi_{tt})
+ \\
+ 0
+ &= - \psi \phi_z - \frac{\beta_2}{2} (\psi_{tt} - \psi \phi_t^2) + \gamma_0 \psi^3
\end{aligned}$$
-This quantity is very important in anomalous dispersion,
-but even in normal dispersion, it is still a useful measure of the relative strengths of GVD and SPM.
-As was illustrated earlier, $$\omega_i$$ overtakes itself at the edges,
-so OWB occurs when $$\omega_i$$ oscillates there,
-which starts when its $$t$$-derivative,
-the **instantaneous chirpyness** $$\xi_i$$,
-has *two* real roots for $$t^2$$:
+For our purposes, the second equation is enough.
+We divide it by $$\psi$$ to get an expression for $$\phi_z$$:
$$\begin{aligned}
- 0
- = \xi_i(z,t)
- = \pdv{\omega_i}{t}
- &= \frac{\beta_2 z}{T_0^4} \bigg( 1 + 2 N_\mathrm{sol}^2 \Big( 1 - \frac{2 t^2}{T_0^2} \Big) \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big) \bigg)
- \equiv \frac{\beta_2 z}{T_0^4} \: f\Big(\frac{t^2}{T_0^2}\Big)
+ \phi_z
+ &= - \frac{\beta_2}{2} \frac{\psi_{tt}}{\psi} + \frac{\beta_2}{2} \Omega_i^2 + \gamma_0 \psi^2
+\end{aligned}$$
+
+Where $$\Omega_i \equiv -\phi_t$$ is the **instantaneous frequency**,
+also called the **frequency-chirp variation**,
+which describes the dominant frequency component at a given point $$(z, t)$$;
+basically the center of the spectrograms shown earlier.
+For small $$z$$, this gives us a linear approximation of $$\phi$$:
+
+$$\begin{aligned}
+ \phi(z, t)
+ &\approx \bigg( \!-\! \frac{\beta_2}{2} \frac{\psi_{tt}}{\psi}
+ + \frac{\beta_2}{2} \Omega_i^2 + \gamma_0 \psi^2 \bigg)\bigg|_{z = 0} z
+ + \phi(0, t)
\end{aligned}$$
-Where the function $$f(x)$$ has been defined for convenience. As it turns
-out, this equation can be solved analytically using the *Lambert $$W$$ function*,
-leading to the following exact minimum value $$N_\mathrm{min}^2$$ for $$N_\mathrm{sol}^2$$,
-such that OWB can only occur when $$N_\mathrm{sol}^2 > N_\mathrm{min}^2$$:
+And therefore $$\Omega_i$$ is as follows,
+assuming no initial chirp variation $$\Omega_i(0, t) = 0$$:
$$\begin{aligned}
\boxed{
- N_\mathrm{min}^2
- = \frac{1}{4} \exp\!\Big(\frac{3}{2}\Big)
- \approx 1.12
+ \Omega_i(z, t)
+ = -\pdv{\phi}{t}
+ \approx \bigg( \frac{\beta_2}{2} \frac{\psi_{ttt}}{\psi}
+ - \frac{\beta_2}{2} \frac{\psi_{tt} \psi_t}{\psi^2}
+ - 2 \gamma_0 \psi \psi_t \bigg) \bigg|_{z = 0} z
}
\end{aligned}$$
-If this condition $$N_\mathrm{sol}^2 > N_\mathrm{min}^2$$ is not satisfied,
-$$\xi_i$$ cannot have two roots for $$t^2$$, meaning $$\omega_i$$ cannot overtake itself.
-GVD is unable to keep up with SPM, so OWB will not occur.
+Once we have $$\Omega_i$$ for a known input pulse,
+we can check whether OWB is even possible under the given circumstances:
+$$\Omega_i$$ must be non-monotonic,
+i.e. $$\ipdv{\Omega_i}{t} = 0$$ must have a solution.
+In other words, there must be a sufficiently prominent "bump" in $$\Omega_i$$
+that gets pulled away by GVD faster than its surroundings,
+until those more-off-center frequencies overtake
+less-off-center ones and lead to the overlap
+that generates the sidelobes and other OWB phenomena.
-Next, consider two points at $$t_1$$ and $$t_2$$ in the pulse,
-separated by a small initial interval $$(t_2 - t_1)$$.
-The frequency difference between these points due to $$\omega_i$$
-will cause them to displace relative to each other
-after a short distance $$z$$ by some amount $$\Delta t$$,
-estimated by:
+Let us assume that OWB will occur.
+Consider two parts of the pulse, located $$t_1$$ and $$t_2$$ for $$z = 0$$,
+so separated by a small initial interval $$\Delta{t} \equiv t_2 - t_1$$.
+Due to $$\Omega_i$$ there is a frequency difference between these points,
+causing $$\Delta{t}$$ to change by an amount $$\tau$$
+after the pulse has propagated a short distance $$z$$,
+estimated as follows:
-$$\begin{aligned}
- \Delta t
+$$\begin{alignedat}{2}
+ \tau
&\approx z \Delta\beta_1
- \qquad
- &&\Delta\beta_1
- \equiv \beta_1(\omega_i(z,t_2)) - \beta_1(\omega_i(z,t_1))
+ \approx z \pdv{\beta_1}{\Omega} \Delta{\Omega_i}
+ = z \beta_2 \Delta\Omega_i
+ \approx z \beta_2 \pdv{\Omega_i}{t} \Delta{t}
+\end{alignedat}$$
+
+Where $$\Delta\Omega_i \equiv \Omega_i(z,t_2) - \Omega_i(z,t_1)$$,
+and $$\Delta{\beta_1}$$ is the difference in inverse group velocity $$\beta_1(\Omega)$$
+between $$t_2$$ and $$t_1$$, specifically
+$$\Delta\beta_1 \equiv \beta_1(\Omega_i(z,t_2)) - \beta_1(\Omega_i(z,t_1))$$.
+OWB takes place when $$t_1$$ and $$t_2$$ catch up to each other,
+which is when $$\tau = -\Delta{t}$$.
+In that case, we have:
+
+$$\begin{aligned}
+ z
+ = - \frac{1}{\beta_2 \displaystyle\pdv{\Omega_i}{t}}
+\end{aligned}$$
+
+Assuming $$\beta_2 > 0$$,
+this implies that the wave starts breaking first
+at the $$t$$-values where $$\Omega_i$$ has its most negative slope
+(note that for a symmetric input pulse,
+$$\ipdv{\Omega_i}{t}$$ is also symmetric,
+so OWB will occur simultaneous on both sides).
+We can therefore write an equation for $$L_\mathrm{WB}$$ like so,
+valid for any input pulse shape
+for which we know $$\Omega_i(z, t)$$:
+
+$$\begin{aligned}
+ \boxed{
+ L_\mathrm{WB}
+ = - \frac{1}{\beta_2 \: \mathrm{min}_t\bigg\{ \displaystyle\pdv{\Omega_i}{t} \Big|_{z = L_\mathrm{WB}} \bigg\}}
+ }
+\end{aligned}$$
+
+Let us apply this method to a few specific examples:
+a Gaussian input pulse, and a soliton-shaped one
+(keeping in mind that true [bright solitons](/know/concept/optical-soliton/)
+do not exist for $$\beta_2 > 0$$).
+
+
+
+## Gaussian pulse
+
+For a Guassian input, the amplitude $$\psi$$ is as follows
+in our ansatz $$A = \psi e^{i \phi}$$:
+
+$$\begin{aligned}
+ \psi(0, t)
+ &= \sqrt{P_0} \exp\!\bigg( \!-\!\frac{t^2}{2 T_0^2} \bigg)
+\end{aligned}$$
+
+For reference, its relevant $$t$$-derivatives are given by:
+
+$$\begin{aligned}
+ \psi_t(0, t)
+ &= - \frac{\sqrt{P_0}}{T_0^2} t \exp\!\bigg( \!-\!\frac{t^2}{2 T_0^2} \bigg)
\\
- &\approx z \beta_2 \Delta\omega_i
- \qquad
- &&\Delta\omega_i
- \equiv \omega_i(z,t_2) - \omega_i(z,t_1)
+ \psi_{tt}(0, t)
+ &= \frac{\sqrt{P_0}}{T_0^2} \bigg( \frac{t^2}{T_0^2} - 1 \bigg) \exp\!\bigg( \!-\!\frac{t^2}{2 T_0^2} \bigg)
\\
- &\approx z \beta_2 \Delta\xi_i \,(t_2 - t_1)
- \qquad \quad
- &&\Delta\xi_i
- \equiv \xi_i(z,t_2) - \xi_i(z,t_1)
+ \psi_{ttt}(0, t)
+ &= \frac{\sqrt{P_0}}{T_0^4} \bigg( 3 - \frac{t^2}{T_0^2} \bigg) t \exp\!\bigg( \!-\!\frac{t^2}{2 T_0^2} \bigg)
\end{aligned}$$
-Where $$\beta_1(\omega)$$ is the inverse of the group velocity.
-For a certain choice of $$t_1$$ and $$t_2$$,
-OWB occurs when they catch up to each other,
-which is when $$-\Delta t = (t_2 - t_1)$$.
-The distance $$L_\mathrm{WB}$$ at which this happens first
-must satisfy the following condition for some value of $$t$$:
+Substituting these into our general linear approximation
+of $$\Omega_i$$ leads us to:
$$\begin{aligned}
- L_\mathrm{WB} \: \beta_2 \: \xi_i(L_\mathrm{WB}, t)
- = -1
- \qquad \implies \qquad
- L_\mathrm{WB}^2
- = - \frac{T_0^4}{\beta_2^2 \: f(t^2/T_0^2)}
+ \Omega_i(z, t)
+ &= z \frac{\beta_2 t}{T_0^4} \bigg( 1 + 2 \frac{\gamma_0 P_0 T_0^2}{\beta_2} \exp\!\Big( \!-\!\frac{t^2}{T_0^2} \Big) \bigg)
\end{aligned}$$
-The time $$t$$ of OWB must be where $$\omega_i(t)$$ has its steepest slope,
-which is at the minimum value of $$\xi_i(t)$$, and by extension $$f(x)$$.
-This turns out to be $$f(3/2)$$:
+Since we are in the normal dispersion regime, $$\beta_2 > 0$$,
+so we can recognize the **soliton number** $$N_\mathrm{sol}$$ here,
+which is a useful measure of the relative strengths of GVD and SPM:
+
+$$\begin{aligned}
+ N_\mathrm{sol}^2
+ \equiv \frac{\gamma_0 P_0 T_0^2}{|\beta_2|}
+ = \frac{L_D}{L_N}
+\end{aligned}$$
+
+We thus have the following expression for $$\Omega_i$$,
+sketched below for several values of $$N_\mathrm{sol}$$:
+
+$$\begin{aligned}
+ \Omega_i(z, t)
+ &= z \frac{\beta_2 t}{T_0^4} \bigg( 1 + 2 N_\mathrm{sol}^2 \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big) \bigg)
+\end{aligned}$$
+
+{% include image.html file="gauss-omega-full.png" width="75%"
+ alt="Sketch of instantaneous frequency of Gaussian pulse" %}
+
+At a certain value of $$N_\mathrm{sol}$$, which we call $$N_\mathrm{min}$$,
+we see that $$\Omega_i$$ transitions from having no extrema,
+to having a local minimum and maximum with respect to $$t^2$$.
+Those "bumps" get pulled outward by GVD as indicated by the arrows,
+steepening the outer edges until the slope becomes infinite,
+at which point OWB occurs.
+However, for $$N_\mathrm{sol} < N_\mathrm{min}$$,
+the bumps are not prominent enough:
+the peaks cannot catch up to the outer edges,
+so OWB can never happen.
+
+We would like to find $$N_\mathrm{min}$$.
+To do so, we demand that $$\Omega_i$$ has local extrema
+where the derivative $$\ipdv{\Omega_i}{t}$$ vanishes, as illustrated below.
+Abbreviating $$f(x) \equiv (1 - 2x) e^{-x}$$:
+
+$$\begin{aligned}
+ 0
+ = \pdv{\Omega_i}{t}
+ &= z \frac{\beta_2}{T_0^4} \bigg( 1 + 2 N_\mathrm{sol}^2 \Big( 1 - \frac{2 t^2}{T_0^2} \Big)
+ \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big) \bigg)
+ \\
+ &= z \frac{\beta_2}{T_0^4} \bigg( 1 + 2 N_\mathrm{sol}^2 \: f\Big(\frac{t^2}{T_0^2}\Big) \bigg)
+\end{aligned}$$
+
+{% include image.html file="gauss-domegadt-full.png" width="75%"
+ alt="Sketch of derivative of instantaneous frequency of Gaussian pulse" %}
+
+Here we see that as $$N_\mathrm{sol}$$ increases,
+it pulls down the minimum of $$f(x)$$ until it hits the horizontal axis
+when $$N_\mathrm{sol} = N_\mathrm{min}$$.
+We should therefore find the location $$x_\mathrm{min}$$ of this minimum:
+
+$$\begin{aligned}
+ 0
+ = f'(x)
+ = (2 x - 3) e^{-x}
+ \qquad\implies\qquad
+ x_\mathrm{min}
+ = \frac{3}{2}
+\end{aligned}$$
+
+So the corresponding minimum value of $$f(x)$$ is given by:
$$\begin{aligned}
f_\mathrm{min}
- = f(3/2)
- = 1 - 4 N_\mathrm{sol}^2 \exp(-3/2)
- = 1 - N_\mathrm{sol}^2 / N_\mathrm{min}^2
+ = f(x_\mathrm{min})
+ = -2 e^{-3/2}
+\end{aligned}$$
+
+Inserting this into our demand that $$\ipdv{\Omega_i}{t} = 0$$
+yields a simple expression for $$N_\mathrm{min}$$:
+
+$$\begin{aligned}
+ 0
+ = 1 + 2 N_\mathrm{min}^2 \: f_\mathrm{min}
+ \qquad\implies\qquad
+ \boxed{
+ N_\mathrm{min}^2
+ = \frac{e^{3/2}}{4}
+ \approx 1.12
+ }
\end{aligned}$$
-Clearly, $$f_\mathrm{min} \ge 0$$ when $$N_\mathrm{sol}^2 \le N_\mathrm{min}^2$$,
-which, when inserted above, leads to an imaginary $$L_\mathrm{WB}$$,
-confirming that OWB cannot occur in that case.
-Otherwise, if $$N_\mathrm{sol}^2 > N_\mathrm{min}^2$$, then:
+If $$N_\mathrm{sol}^2 < N_\mathrm{min}^2$$,
+then our demand cannot be satisfied:
+$$\Omega_i$$ cannot overtake itself,
+GVD is unable to keep up with SPM, and OWB cannot occur.
+From now on, we assume $$N_\mathrm{sol}^2 > N_\mathrm{min}^2$$.
+
+We now have everything we need to calculate the OWB distance $$L_\mathrm{WB}$$
+using its general recipe.
+Inserting $$\ipdv{\Omega_i}{t}$$,
+whose minimum we already know, we get:
+
+$$\begin{aligned}
+ L_\mathrm{WB}^2
+ = - \frac{T_0^4}{\beta_2^2 (1 + 2 N_\mathrm{sol}^2 f_\mathrm{min})}
+ = \frac{T_0^4}{\beta_2^2 (N_\mathrm{sol}^2 / N_\mathrm{min}^2 - 1)}
+\end{aligned}$$
+
+Leading to the following prediction for $$L_\mathrm{WB}$$,
+which appears to agree well with the OWB
+observed in the simulation shown earlier.
+Note that if $$N_\mathrm{sol} < N_\mathrm{min}$$
+then $$L_\mathrm{WB}$$ is imaginary,
+confirming that OWB is not possible in that situation:
$$\begin{aligned}
\boxed{
L_\mathrm{WB}
- = \frac{T_0^2}{\beta_2 \, \sqrt{- f_\mathrm{min}}}
- = \frac{L_D}{\sqrt{N_\mathrm{sol}^2 / N_\mathrm{min}^2 - 1}}
+ = \frac{T_0^2}{\beta_2 \sqrt{N_\mathrm{sol}^2 / N_\mathrm{min}^2 - 1}}
}
\end{aligned}$$
-This prediction for $$L_\mathrm{WB}$$ appears to agree well
-with the OWB observed in the simulation:
-{% include image.html file="simulation-full.png" width="100%"
- alt="Optical wave breaking simulation results" %}
-Because all spectral broadening up to $$L_\mathrm{WB}$$ is caused by SPM,
-whose $$\omega$$-domain behaviour is known,
-it is in fact possible to draw some analytical conclusions
-about the achieved bandwidth when OWB sets in.
-Filling $$L_\mathrm{WB}$$ in into $$\omega_\mathrm{SPM}$$ gives:
+## Soliton-shaped pulse
+
+Although solitons do not exist in the normal dispersion regime,
+we can still create pulses with the same shape, given by:
+
+$$\begin{aligned}
+ \psi(0, t)
+ &= \sqrt{P_0} \sech\!\Big( \frac{t}{T_0} \Big)
+\end{aligned}$$
+
+For reference, we also calculate its relevant $$t$$-derivatives:
+
+$$\begin{aligned}
+ \psi_t(0, t)
+ &= - \frac{\sqrt{P_0}}{T_0} \tanh\!\Big( \frac{t}{T_0} \Big) \sech\!\Big( \frac{t}{T_0} \Big)
+ \\
+ \psi_{tt}(0, t)
+ &= \frac{\sqrt{P_0}}{T_0^2} \bigg( \tanh^2\!\Big( \frac{t}{T_0} \Big) - \sech^2\!\Big( \frac{t}{T_0} \Big) \bigg)
+ \sech\!\Big( \frac{t}{T_0} \Big)
+ \\
+ \psi_{ttt}(0, t)
+ &= \frac{\sqrt{P_0}}{T_0^3} \bigg( 5 \sech^2\!\Big( \frac{t}{T_0} \Big) - \tanh^2\!\Big( \frac{t}{T_0} \Big) \bigg)
+ \tanh\!\Big( \frac{t}{T_0} \Big) \sech\!\Big( \frac{t}{T_0} \Big)
+\end{aligned}$$
+
+Substituting these into our general linear approximation of $$\Omega_i$$,
+and once again recognizing the soliton number $$N_\mathrm{sol}$$,
+leads us to the following function, sketched below:
+
+$$\begin{aligned}
+ \Omega_i(z, t)
+ &= z \frac{2 \beta_2}{T_0^3} \big( 1 + N_\mathrm{sol}^2 \big)
+ \sech^2\!\Big( \frac{t}{T_0} \Big) \tanh\!\Big( \frac{t}{T_0} \Big)
+\end{aligned}$$
+
+{% include image.html file="sech-omega-full.png" width="75%"
+ alt="Sketch of instantaneous frequency of soliton-shaped pulse" %}
+
+Curiously, this $$\Omega_i$$ is non-monotonic for all $$N_\mathrm{sol}$$,
+so OWB occurs even in the linear limit $$N_\mathrm{sol} \to 0$$.
+This suggests that OWB is not an inherently nonlinear effect,
+instead happening as long as there are bumps in $$\Omega_i$$,
+regardless of their origin (SPM or simply the pulse shape).
+
+We do not care where those local extrema are, only that they exist,
+so we move on immediately to finding where $$\Omega_i$$
+has its most negative slope,
+which is at some (but not all) solutions of:
+
+$$\begin{aligned}
+ 0
+ &= \pdvn{2}{\Omega_i}{t}
+ \\
+ &= z \frac{8 \beta_2}{T_0^5} \big( 1 + N_\mathrm{sol}^2 \big)
+ \bigg( \tanh^2\!\Big( \frac{t}{T_0} \Big) - 2 \sech^2\!\Big( \frac{t}{T_0} \Big) \bigg)
+ \sech^2\!\Big( \frac{t}{T_0} \Big) \tanh\!\Big( \frac{t}{T_0} \Big)
+\end{aligned}$$
+
+One solution is clearly $$t = 0$$ because $$\tanh(0) = 0$$,
+but from the plot we can see that $$\Omega_i$$'s slope is positive there,
+so we must continue our search.
+The next candidate is:
+
+$$\begin{aligned}
+ 0
+ &= \tanh^2(x) - 2 \sech^2(x)
+ \\
+ &= 3 \tanh^2(x) - 2
+\end{aligned}$$
+
+Where we have used the standard identity $$\sech^2(x) + \tanh^2(x) = 1$$.
+Isolating for $$x$$ and writing out $$\tanh^{-1}(x)$$ as a logarithm yields:
$$\begin{aligned}
- \omega_{\mathrm{SPM}}(L_\mathrm{WB},t)
- = \frac{2 \gamma P_0 t}{\beta_2 \sqrt{4 N_\mathrm{sol}^2 \exp(-3/2) - 1}} \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big)
+ x
+ &= \tanh^{-1}\!\bigg( \!\pm\!\sqrt{\frac{2}{3}}\bigg)
+ \\
+ &= \frac{1}{2} \ln\!\bigg( \frac{1 \pm \sqrt{2/3}}{1 \mp \sqrt{2/3}} \bigg)
+ \\
+ &= \frac{1}{2} \ln\!\bigg( \frac{\sqrt{3} \pm \sqrt{2}}{\sqrt{3} \mp \sqrt{2}} \bigg)
+ \\
+ &= \frac{1}{2} \ln\!\bigg( \frac{(\sqrt{3} \pm \sqrt{2})^2}{(\sqrt{3} \mp \sqrt{2}) (\sqrt{3} \pm \sqrt{2})} \bigg)
+ \\
+ &= \frac{1}{2} \ln(5 \pm 2 \sqrt{6})
\end{aligned}$$
-Assuming that $$N_\mathrm{sol}^2$$ is large in the denominator, this can
-be approximately reduced to:
+Note that $$\ln(5 \!+\! 2 \sqrt{6}) = - \ln(5 \!-\! 2 \sqrt{6}) \equiv 2 x_0$$.
+The values of $$\sech$$ and $$\tanh$$ are given by:
$$\begin{aligned}
- \omega_\mathrm{SPM}(L_\mathrm{WB}, t)
- \approx \frac{2 \gamma P_0 t}{\beta_2 N_\mathrm{sol}} \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big)
- = 2 \sqrt{\frac{\gamma P_0}{\beta_2}} \frac{t}{T_0} \exp\!\Big(\!-\!\frac{t^2}{T_0^2}\Big)
+ \sech(\pm x_0)
+ = \frac{1}{\sqrt{3}}
+ \qquad\qquad
+ \tanh(\pm x_0)
+ = \pm \sqrt{\frac{2}{3}}
\end{aligned}$$
-The expression $$x \exp(-x^2)$$ has its global extrema
-$$\pm 1 / \sqrt{2 e}$$ at $$x^2 = 1/2$$. The maximum SPM frequency shift
-achieved at $$L_\mathrm{WB}$$ is therefore given by:
+The minimum value of the slope $$\ipdv{\Omega_i}{t}$$ is therefore as follows:
$$\begin{aligned}
- \omega_\mathrm{max}
- = \sqrt{\frac{2 \gamma P_0}{e \beta_2}}
+ \mathrm{min}_t\bigg\{ \displaystyle\pdv{\Omega_i}{t} \bigg\}
+ &= z \frac{2 \beta_2}{T_0^4} (1 + N_\mathrm{sol}^2)
+ \bigg( \sech^2\!\Big( \frac{t}{T_0} \Big) - 2 \tanh^2\!\Big( \frac{t}{T_0} \Big) \bigg) \sech^2\!\Big( \frac{t}{T_0} \Big)
+ \bigg|_{t = x_0 T_0}
+ \\
+ &= - z \frac{2 \beta_2}{3 T_0^4} \big( 1 + N_\mathrm{sol}^2 \big)
\end{aligned}$$
-Interestingly, this expression does not contain $$T_0$$ at all,
-so the achieved spectrum when SPM is halted by OWB
-is independent of the pulse width,
-for sufficiently large $$N_\mathrm{sol}$$.
+Inserting this into $$L_\mathrm{WB}$$'s general equation,
+we find that OWB occurs at a distance with a similar
+$$T_0^2 / \beta_2$$-dependence as for the Gaussian pulse,
+confirming that OWB is mostly linear:
+
+$$\begin{aligned}
+ \boxed{
+ L_\mathrm{WB}
+ = \frac{\sqrt{3} T_0^2}{\beta_2 \sqrt{2 + 2 N_\mathrm{sol}^2}}
+ }
+\end{aligned}$$
@@ -237,4 +484,3 @@ for sufficiently large $$N_\mathrm{sol}$$.
2. A.M. Heidt, A. Hartung, H. Bartelt,
[Generation of ultrashort and coherent supercontinuum light pulses in all-normal dispersion fibers](https://doi.org/10.1007/978-1-4939-3326-6_6),
2016, Springer Media.
-
diff --git a/source/know/concept/optical-wave-breaking/sech-omega-full.png b/source/know/concept/optical-wave-breaking/sech-omega-full.png
new file mode 100644
index 0000000..0d02e52
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/sech-omega-full.png
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/sech-omega-half.avif b/source/know/concept/optical-wave-breaking/sech-omega-half.avif
new file mode 100644
index 0000000..fc89079
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/sech-omega-half.avif
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/sech-omega-half.jpg b/source/know/concept/optical-wave-breaking/sech-omega-half.jpg
new file mode 100644
index 0000000..85bd2ce
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/sech-omega-half.jpg
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/sech-omega-half.png b/source/know/concept/optical-wave-breaking/sech-omega-half.png
new file mode 100644
index 0000000..8d619eb
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/sech-omega-half.png
Binary files differ
diff --git a/source/know/concept/optical-wave-breaking/sech-omega-half.webp b/source/know/concept/optical-wave-breaking/sech-omega-half.webp
new file mode 100644
index 0000000..7fba41b
--- /dev/null
+++ b/source/know/concept/optical-wave-breaking/sech-omega-half.webp
Binary files differ
diff --git a/source/know/concept/path-integral-formulation/index.md b/source/know/concept/path-integral-formulation/index.md
index a8dcc76..657ff17 100644
--- a/source/know/concept/path-integral-formulation/index.md
+++ b/source/know/concept/path-integral-formulation/index.md
@@ -8,170 +8,225 @@ categories:
layout: "concept"
---
-In quantum mechanics, the **path integral formulation**
-is an alternative description of quantum mechanics,
-which is equivalent to the "traditional" Schrödinger equation.
+The **path integral formulation** is an alternative description
+of quantum mechanics, equivalent to the traditional Schrödinger equation.
Whereas the latter is based on [Hamiltonian mechanics](/know/concept/hamiltonian-mechanics/),
the former comes from [Lagrangian mechanics](/know/concept/lagrangian-mechanics/).
It expresses the [propagator](/know/concept/propagator/) $$K$$
-using the following sum over all possible paths $$x(t)$$,
-which all go from the initial position $$x_0$$ at time $$t_0$$
-to the destination $$x_N$$ at time $$t_N$$:
+as the following "sum" over all possible paths $$x(t)$$
+that take the particle from the starting point $$(x_0, t_0)$$
+to the destination $$(x_N, t_N)$$:
$$\begin{aligned}
- \boxed{
- K(x_N, t_N; x_0, t_0)
- = A \sum_{\mathrm{all}\:x(t)} \exp(i S[x] / \hbar)
- }
+ K(x_N, t_N; x_0, t_0)
+ = A \sum_{\mathrm{all}\:x(t)} \exp(i S[x] / \hbar)
\end{aligned}$$
-Where $$A$$ normalizes.
-$$S[x]$$ is the classical action of the path $$x$$, whose minimization yields
-the Euler-Lagrange equation from Lagrangian mechanics.
-Note that each path is given an equal weight,
-even unrealistic paths that make big detours.
+Where $$A$$ is a normalization constant,
+and $$S[x]$$ is the classical action of the path $$x(t)$$,
+defined as shown below from the system's Lagrangian $$L$$,
+and whose minimization would lead to the
+[Euler-Lagrange equation](/know/concept/euler-lagrange-equation/)
+of classical Lagrangian mechanics.
+Let $$\dot{x}(t) = \idv{x}{t}$$:
-This apparent problem solves itself,
-thanks to the fact that paths close to the classical optimum $$x_c(t)$$
+$$\begin{aligned}
+ S[x]
+ \equiv \int_{t_0}^{t_N} L(x, \dot{x}, \tau) \dd{\tau}
+\end{aligned}$$
+
+Note that $$K$$'s sum gives each path an equal weight,
+even unrealistic paths taking bigs detours.
+This apparent problem solves itself as follows:
+paths close to the classical optimum $$x_c(t)$$
have an action close to $$S_c = S[x_c]$$,
-while the paths far away have very different actions.
-Since $$S[x]$$ is inside a complex exponential,
-this means that paths close to $$x_c$$ add contructively,
-and the others add destructively and cancel out.
+since $$S$$ is stationary there.
+Meanwhile, for paths far away from $$x_c$$,
+$$S$$ gives very different values,
+which change by a lot if a small change is made to $$x$$.
+Because $$S[x]$$ is inside a complex exponential,
+paths close to $$x_c$$ therefore add more or less constructively,
+while the others add destructively and cancel out.
+
+Consequently, the "quantum path" is still close to $$x_c(t)$$.
+An interesting way to think about this is by treating $$\hbar$$ as a parameter:
+as its value decreases, small action changes result in bigger phase differences,
+which makes the quantum wavefunction stay closer to $$x_c$$
+for the aforementioned reasons.
+In the limit $$\hbar \to 0$$, quantum mechanics simply turns into classical mechanics.
+
+In reality, $$K$$'s sum is evaluated as an integral over all paths $$x(t)$$,
+hence this is called the *path integral formulation*.
+The proof that the propagator $$K$$'s Schrödinger-picture definition
+can be rewritten as such an integral is given below.
+
-An interesting way too look at it is by varying $$\hbar$$:
-as its value decreases, minor action differences yield big phase differences,
-which make the quantum wave function stay closer to $$x_c$$.
-In the limit $$\hbar \to 0$$, quantum mechanics thus turns into classical mechanics.
## Time-slicing derivation
-The most popular way to derive the path integral formulation proceeds as follows:
-starting from the definition of the propagator $$K$$,
-we divide the time interval $$t_N - t_0$$ into $$N$$ "slices"
-of equal width $$\Delta t = (t_N - t_0) / N$$,
-where $$N$$ is large:
+For a time-independent Hamiltonian $$\hat{H}$$,
+we start from the definition of the propagator $$K$$,
+and divide the time interval $$t_N \!-\! t_0$$ into $$N$$ "slices"
+of equal width $$\Delta{t} \equiv (t_N \!-\! t_0) / N$$:
$$\begin{aligned}
K(x_N, t_N; x_0, t_0)
&= \matrixel{x_N}{e^{- i \hat{H} (t_N - t_0) / \hbar}}{x_0}
- = \matrixel{x_N}{e^{- i \hat{H} \Delta t / \hbar} \cdots e^{- i \hat{H} \Delta t / \hbar}}{x_0}
+ \\
+ &= \matrixel{x_N}{e^{- i \hat{H} \Delta{t} / \hbar} \cdots e^{- i \hat{H} \Delta{t} / \hbar}}{x_0}
\end{aligned}$$
-Between the exponentials we insert $$N\!-\!1$$ identity operators
-$$\hat{I} = \int \Ket{x} \Bra{x} \dd{x}$$,
-and define $$x_j = x(t_j)$$ for an arbitrary path $$x(t)$$:
+Between the exponentials we insert identity operators
+$$\int_{-\infty}^\infty \Ket{x} \Bra{x} \dd{x}$$,
+and define $$x_j \equiv x(t_j)$$ for an arbitrary path $$x(t)$$,
+where $$t_j$$ is the endpoint of the $$j$$th slice.
+This is equivalent to splitting $$K$$
+into a product of all slices' individual propagators:
$$\begin{aligned}
K
- &= \int\cdots\int \matrixel{x_N}{e^{- i \hat{H} \Delta t / \hbar}}{x_{N-1}} \cdots \matrixel{x_1}{e^{- i \hat{H} \Delta t / \hbar}}{x_0}
+ &= K(x_N, t_N; x_{N-1}, t_{N-1})
+ \cdots K(x_2, t_2; x_1, t_1) \: K(x_1, t_1; x_0, t_0)
+ \\
+ &= \int \!\cdots \! \int
+ \matrixel{x_N}{e^{- i \hat{H} \Delta{t} / \hbar}}{x_{N-1}}
+ \cdots \matrixel{x_1}{e^{- i \hat{H} \Delta{t} / \hbar}}{x_0}
\dd{x_1} \cdots \dd{x_{N - 1}}
\end{aligned}$$
-For sufficiently small time steps $$\Delta t$$ (i.e. large $$N$$
-we make the following approximation
-(which would be exact, were it not for the fact that
-$$\hat{T}$$ and $$\hat{V}$$ are operators):
+For sufficiently small time steps $$\Delta{t}$$ (i.e. large $$N$$),
+we can split the Hamiltonian
+into its kinetic and potential terms $$\hat{H} = \hat{T} + \hat{V}$$.
+Note that this is an approximation,
+since $$\hat{T}$$ and $$\hat{V}$$ are operators that do not commute,
+but it becomes exact in the limit $$\Delta{t} \to 0$$:
$$\begin{aligned}
- e^{- i \hat{H} \Delta t / \hbar}
- = e^{- i (\hat{T} + \hat{V}) \Delta t / \hbar}
- \approx e^{- i \hat{T} \Delta t / \hbar} e^{- i \hat{V} \Delta t / \hbar}
+ e^{- i \hat{H} \Delta{t} / \hbar}
+ \approx e^{- i \hat{T} \Delta{t} / \hbar} \: e^{- i \hat{V} \Delta{t} / \hbar}
\end{aligned}$$
-Since $$\hat{V} = V(x_j)$$,
-we can take it out of the inner product as a constant factor:
+We substitute $$\hat{V} = V(x_j)$$, and apply it directly to $$\ket{x_j}$$,
+such that we can take it out of the inner product as a constant factor:
$$\begin{aligned}
- \matrixel{x_{j+1}}{e^{- i \hat{T} \Delta t / \hbar} e^{- i \hat{V} \Delta t / \hbar}}{x_j}
- = e^{- i V(x_j) \Delta t / \hbar} \matrixel{x_{j+1}}{e^{- i \hat{T} \Delta t / \hbar}}{x_j}
+ \matrixel{x_{j+1}}{e^{- i \hat{H} \Delta{t} / \hbar}}{x_j}
+ &= \matrixel{x_{j+1}}{e^{- i \hat{T} \Delta{t} / \hbar} \: e^{- i \hat{V} \Delta{t} / \hbar}}{x_j}
+ \\
+ &= e^{- i V(x_j) \Delta{t} / \hbar} \matrixel{x_{j+1}}{e^{- i \hat{T} \Delta{t} / \hbar}}{x_j}
\end{aligned}$$
-Here we insert the identity operator
-expanded in the momentum basis $$\hat{I} = \int \Ket{p} \Bra{p} \dd{p}$$,
-and commute it with the kinetic energy $$\hat{T} = \hat{p}^2 / (2m)$$ to get:
+In order to evaluate the remaining inner product,
+we insert the identity operator again,
+this time expanded in the momentum basis $$\int_{-\infty}^\infty \Ket{p} \Bra{p} \dd{p}$$,
+and use $$\hat{T} = \hat{p}^2 / (2m)$$ to get:
$$\begin{aligned}
\matrixel{x_{j+1}}{e^{- i \hat{T} \Delta t / \hbar}}{x_j}
- = \int_{-\infty}^\infty \Inprod{x_{j+1}}{p} \exp\!\Big(\!-\! i \frac{p^2 \Delta t}{2 m \hbar}\Big) \Inprod{p}{x_j} \dd{p}
+ &= \int_{-\infty}^\infty \matrixel{x_{j+1}}{e^{- i \hat{T} \Delta{t} / \hbar}}{p} \inprod{p}{x_j} \dd{p}
+ \\
+ &= \int_{-\infty}^\infty \exp\!\bigg(\!-\! i \frac{p^2 \Delta{t}}{2 m \hbar} \bigg) \inprod{x_{j+1}}{p} \inprod{p}{x_j} \dd{p}
\end{aligned}$$
In the momentum basis $$\Ket{p}$$,
-the position basis vectors
-are represented by plane waves:
+the position basis vectors $$\Ket{x}$$
+are given by plane waves:
$$\begin{aligned}
- \Inprod{p}{x_j}
- = \frac{1}{\sqrt{2 \pi \hbar}} \exp\!\Big( \!-\! i \frac{x_j p}{\hbar} \Big)
- \qquad
- \Inprod{x_{j+1}}{p}
- = \frac{1}{\sqrt{2 \pi \hbar}} \exp\!\Big( i \frac{x_{j+1} p}{\hbar} \Big)
+ \inprod{p}{x}
+ = \frac{e^{- i x p / \hbar}}{\sqrt{2 \pi \hbar}}
\end{aligned}$$
-With this, we return to the inner product and further evaluate the integral:
+Inserting this and looking up the resulting integral,
+we arrive at:
$$\begin{aligned}
\matrixel{x_{j+1}}{e^{- i \hat{T} \Delta t / \hbar}}{x_j}
&= \frac{1}{2 \pi \hbar} \int_{-\infty}^\infty
- \exp\!\Big(\!-\! i \frac{p^2 \Delta t}{2 m \hbar}\Big) \exp\!\Big(i \frac{(x_{j+1} - x_j) p}{\hbar}\Big) \:dp
+ \exp\!\bigg( \!-\! i \frac{\Delta{t}}{2 m \hbar} p^2 + i \frac{(x_{j+1} \!-\! x_j)}{\hbar} p \bigg) \dd{p}
\\
- &= \frac{1}{2 \pi \hbar} \sqrt{\frac{2 \pi m \hbar}{i \Delta t}} \exp\!\Big( i \frac{m (x_{j+1} - x_j)^2}{2 \hbar \Delta t} \Big)
+ &= \frac{1}{2 \pi \hbar} \sqrt{\frac{2 \pi m \hbar}{i \Delta{t}}}
+ \exp\!\bigg( i \frac{m (x_{j+1} \!-\! x_j)^2}{2 \hbar \Delta{t}} \bigg)
\end{aligned}$$
-Inserting this back into the definition of the propagator $$K(x_N, t_N; x_0, t_0)$$ yields:
+Including the factor due to $$\hat{V}$$,
+we find that the propagator of a single time slice is:
$$\begin{aligned}
- K
- = \Big( \frac{- i m}{2 \pi \hbar \Delta t} \Big)^{\!N / 2}
- \int\cdots\int
- \exp\!\bigg(\! \sum_{j = 0}^{N - 1} i \Big( \frac{m (x_{j+1} \!-\! x_j)^2}{2 \hbar \Delta t} - \frac{V(x_j) \Delta t}{\hbar} \Big) \!\bigg)
- \dd{x_1} \cdots \dd{x_{N-1}}
+ \matrixel{x_{j+1}}{e^{- i \hat{H} \Delta t / \hbar}}{x_j}
+ = \sqrt{\frac{- i m}{2 \pi \hbar \Delta{t}}}
+ \exp\!\bigg( \frac{i}{\hbar} \frac{m}{2} \frac{(x_{j+1} \!-\! x_j)^2}{\Delta{t}} - \frac{i}{\hbar} V(x_j) \: \Delta{t} \bigg)
\end{aligned}$$
-For large $$N$$ and small $$\Delta t$$, the sum in the exponent becomes an integral:
+This is a "local" result;
+inserting it into the "global" propagator $$K(x_N, t_N; x_0, t_0)$$ yields:
$$\begin{aligned}
- \frac{i}{\hbar} \sum_{j = 0}^{N - 1} \Big( \frac{m (x_{j+1} \!-\! x_j)^2}{2 \Delta t^2} - V(x_j) \Big) \Delta t
- \quad \to \quad
- \frac{i}{\hbar} \int_{t_0}^{t_N} \Big( \frac{1}{2} m \dot{x}^2 - V(x) \Big) \dd{\tau}
+ K
+ &= \bigg( \frac{- i m}{2 \pi \hbar \Delta{t}} \bigg)^{\!N / 2}
+ \!\int\!\cdots\!\int \prod_{j = 0}^{N - 1}
+ \exp\!\bigg( \frac{i}{\hbar} \frac{m}{2} \frac{(x_{j+1} \!-\! x_j)^2}{\Delta{t}} - \frac{i}{\hbar} V(x_j) \: \Delta{t} \bigg)
+ \dd{x_1} \cdots \dd{x_{N-1}}
+ \\
+ &= \Big( \frac{- i m}{2 \pi \hbar \Delta{t}} \Big)^{\!N / 2}
+ \!\int\!\cdots\!\int
+ \exp\!\bigg( \frac{i \Delta{t}}{\hbar} \sum_{j = 0}^{N-1}
+ \Big( \frac{m}{2} \frac{(x_{j+1} \!-\! x_j)^2}{\Delta{t}^2} - V(x_j) \Big) \bigg)
+ \dd{x_1} \cdots \dd{x_{N-1}}
\end{aligned}$$
-Upon closer inspection, this integral turns out to be the classical action $$S[x]$$,
-with the integrand being the Lagrangian $$L$$:
-
-$$\begin{aligned}
- S[x(t)]
- = \int_{t_0}^{t_N} L(x, \dot{x}, \tau) \dd{\tau}
- = \int_{t_0}^{t_N} \Big( \frac{1}{2} m \dot{x}^2 - V(x) \Big) \dd{\tau}
-\end{aligned}$$
+It is worth noting that there are $$N\!-\!1$$ integrals,
+but $$N$$ factors $$(-i m / 2 \pi \hbar \Delta{t})^{1/2}$$
+i.e. one for each slice.
+According to convention, $$N\!-\!1$$ of those factors
+are said to belong to the integrals,
+and then the remaining one belongs to the process as a whole.
-The definition of the propagator $$K$$ is then further reduced to the following:
+In the limit $$\Delta{t} \to 0$$ (or $$N \to \infty$$),
+the sum in the exponent becomes an integral:
$$\begin{aligned}
- K
- = \Big( \frac{- i m}{2 \pi \hbar \Delta t} \Big)^{\!N / 2}
- \int\cdots\int \exp(i S[x] / \hbar) \dd{x_1} \cdots \dd{x_{N-1}}
+ \lim_{\Delta{t} \to 0}
+ \sum_{j = 0}^{N - 1} \bigg( \frac{m}{2} \frac{(x_{j+1} \!-\! x_j)^2}{\Delta{t}^2} - V(x_j) \bigg) \Delta{t}
+ \:\:&=\:\:
+ \int_{t_0}^{t_N} \!\bigg( \frac{1}{2} m \dot{x}^2 - V(x) \bigg) \dd{\tau}
+ \\
+ \:\:&=\:\:
+ \int_{t_0}^{t_N} L(x, \dot{x}, \tau) \dd{\tau}
+ \\
+ \:\:&=\:\:
+ S[x]
\end{aligned}$$
-Finally, for the purpose of normalization,
-we define the integral over all paths $$x(t)$$ as follows,
-where we write $$D[x]$$ instead of $$\dd{x}$$:
+Where we have recognized the Lagrangian $$L = T - V$$
+and hence the action $$S[x]$$ of the path $$x(t)$$.
+We thus arrive at the following formula for the global propagator $$K$$,
+known as **Feynman's path integral**
+or sometimes the **configuration space path integral**:
$$\begin{aligned}
- \int D[x]
- \equiv \lim_{N \to \infty} \Big( \frac{- i m}{2 \pi \hbar \Delta t} \Big)^{\!N / 2} \int\cdots\int \dd{x_1} \cdots \dd{x_{N-1}}
+ \boxed{
+ K
+ = \int e^{i S[x] / \hbar} \:\mathcal{D}{x}
+ }
\end{aligned}$$
-We thus arrive at **Feynman's path integral**,
-which sums over all possible paths $$x(t)$$:
+Where we have introduced the following notation
+to indicate an integral over all paths,
+because writing the factor and all those integrals can become tedious:
$$\begin{aligned}
- K
- = \int \exp(i S[x] / \hbar) \:D[x]
- = A \sum_{\mathrm{all}\:x(t)} \exp(i S[x] / \hbar)
+ \boxed{
+ \int \mathcal{D}{x}
+ \equiv \lim_{N \to \infty} \Big( \frac{- i m}{2 \pi \hbar \Delta t} \Big)^{\!N / 2} \int\cdots\int \dd{x_1} \cdots \dd{x_{N-1}}
+ }
\end{aligned}$$
+It is worth stressing that this is simply an abbreviation;
+in practice, calculating $$K$$ in this way
+still requires the individual slices to be taken into account.
+
## References
diff --git a/source/know/concept/pauli-exclusion-principle/index.md b/source/know/concept/pauli-exclusion-principle/index.md
index 9821718..15130d9 100644
--- a/source/know/concept/pauli-exclusion-principle/index.md
+++ b/source/know/concept/pauli-exclusion-principle/index.md
@@ -8,57 +8,69 @@ categories:
layout: "concept"
---
-In quantum mechanics, the **Pauli exclusion principle** is a theorem with
-profound consequences for how the world works.
+In quantum mechanics, the **Pauli exclusion principle** is a theorem
+with profound consequences for how the world works.
Suppose we have a composite state
-$$\ket{x_1}\ket{x_2} = \ket{x_1} \otimes \ket{x_2}$$, where the two
-identical particles $$x_1$$ and $$x_2$$ each can occupy the same two allowed
-states $$a$$ and $$b$$. We then define the permutation operator $$\hat{P}$$ as
-follows:
+$$\ket{x_1}\ket{x_2} = \ket{x_1} \otimes \ket{x_2}$$,
+where the two identical particles $$x_1$$ and $$x_2$$
+each can occupy the same two allowed states $$a$$ and $$b$$.
+We then define the permutation operator $$\hat{P}$$ as follows:
$$\begin{aligned}
- \hat{P} \Ket{a}\Ket{b} = \Ket{b}\Ket{a}
+ \hat{P} \Ket{a}\Ket{b}
+ = \Ket{b}\Ket{a}
\end{aligned}$$
-That is, it swaps the states of the particles. Obviously, swapping the
-states twice simply gives the original configuration again, so:
+That is, it swaps the states of the particles.
+Obviously, swapping the states twice simply gives the original configuration again, so:
$$\begin{aligned}
- \hat{P}^2 \Ket{a}\Ket{b} = \Ket{a}\Ket{b}
+ \hat{P}^2 \Ket{a}\Ket{b}
+ = \Ket{a}\Ket{b}
\end{aligned}$$
-Therefore, $$\Ket{a}\Ket{b}$$ is an eigenvector of $$\hat{P}^2$$ with
-eigenvalue $$1$$. Since $$[\hat{P}, \hat{P}^2] = 0$$, $$\Ket{a}\Ket{b}$$
-must also be an eigenket of $$\hat{P}$$ with eigenvalue $$\lambda$$,
-satisfying $$\lambda^2 = 1$$, so we know that $$\lambda = 1$$ or $$\lambda = -1$$:
+Therefore, $$\Ket{a}\Ket{b}$$ is an eigenvector of $$\hat{P}^2$$ with eigenvalue $$1$$.
+Since $$[\hat{P}, \hat{P}^2] = 0$$,
+$$\Ket{a}\Ket{b}$$ must also be an eigenket of $$\hat{P}$$
+with eigenvalue $$\lambda$$, satisfying $$\lambda^2 = 1$$,
+so we know that $$\lambda = 1$$ or $$\lambda = -1$$:
$$\begin{aligned}
- \hat{P} \Ket{a}\Ket{b} = \lambda \Ket{a}\Ket{b}
+ \hat{P} \Ket{a}\Ket{b}
+ = \lambda \Ket{a}\Ket{b}
\end{aligned}$$
-As it turns out, in nature, each class of particle has a single
-associated permutation eigenvalue $$\lambda$$, or in other words: whether
-$$\lambda$$ is $$-1$$ or $$1$$ depends on the type of particle that $$x_1$$
-and $$x_2$$ are. Particles with $$\lambda = -1$$ are called
-**fermions**, and those with $$\lambda = 1$$ are known as **bosons**. We
-define $$\hat{P}_f$$ with $$\lambda = -1$$ and $$\hat{P}_b$$ with
-$$\lambda = 1$$, such that:
+As it turns out, in nature, each type of particle has a single
+associated permutation eigenvalue $$\lambda$$, or in other words:
+whether $$\lambda$$ is $$-1$$ or $$1$$ depends on
+the type of particle that $$x_1$$ and $$x_2$$ are.
+Particles with $$\lambda = -1$$ are called **fermions**,
+and those with $$\lambda = 1$$ are known as **bosons**.
+We define $$\hat{P}_f$$ with $$\lambda = -1$$ and $$\hat{P}_b$$ with $$\lambda = 1$$,
+such that:
$$\begin{aligned}
- \hat{P}_f \Ket{a}\Ket{b} = \Ket{b}\Ket{a} = - \Ket{a}\Ket{b}
- \qquad
- \hat{P}_b \Ket{a}\Ket{b} = \Ket{b}\Ket{a} = \Ket{a}\Ket{b}
+ \hat{P}_f \Ket{a}\Ket{b}
+ &= \Ket{b}\Ket{a}
+ = - \Ket{a}\Ket{b}
+ \\
+ \hat{P}_b \Ket{a}\Ket{b}
+ &= \Ket{b}\Ket{a}
+ = \Ket{a}\Ket{b}
\end{aligned}$$
-Another fundamental fact of nature is that identical particles cannot be
-distinguished by any observation. Therefore it is impossible to tell
-apart $$\Ket{a}\Ket{b}$$ and the permuted state $$\Ket{b}\Ket{a}$$,
-regardless of the eigenvalue $$\lambda$$. There is no physical difference!
+Another fundamental fact is that identical particles
+cannot be distinguished by any observation.
+Therefore, it is impossible to tell apart $$\Ket{a}\Ket{b}$$
+and the permuted state $$\Ket{b}\Ket{a}$$,
+regardless of the eigenvalue $$\lambda$$.
+There is no physical difference!
-But this does not mean that $$\hat{P}$$ is useless: despite not having any
-observable effect, the resulting difference between fermions and bosons
-is absolutely fundamental. Consider the following superposition state,
+But this does not mean that $$\hat{P}$$ is useless:
+despite not having any observable effect,
+the resulting difference between fermions and bosons is absolutely profound.
+Consider the following superposition state,
where $$\alpha$$ and $$\beta$$ are unknown:
$$\begin{aligned}
@@ -66,9 +78,10 @@ $$\begin{aligned}
= \alpha \Ket{a}\Ket{b} + \beta \Ket{b}\Ket{a}
\end{aligned}$$
-When we apply $$\hat{P}$$, we can "choose" between two "intepretations" of
-its action, both shown below. Obviously, since the left-hand sides are
-equal, the right-hand sides must be equal too:
+When we apply $$\hat{P}$$, we can "choose" between
+two "intepretations" of its action, both shown below.
+Obviously, since the left-hand sides are equal,
+the right-hand sides must be equal too:
$$\begin{aligned}
\hat{P} \Ket{\Psi(a, b)}
@@ -78,25 +91,28 @@ $$\begin{aligned}
&= \alpha \Ket{b}\Ket{a} + \beta \Ket{a}\Ket{b}
\end{aligned}$$
-This gives us the equations $$\lambda \alpha = \beta$$ and
-$$\lambda \beta = \alpha$$. In fact, just from this we could have deduced
-that $$\lambda$$ can be either $$-1$$ or $$1$$. In any case, for bosons
-($$\lambda = 1$$), we thus find that $$\alpha = \beta$$:
+This gives us the equations $$\lambda \alpha = \beta$$ and $$\lambda \beta = \alpha$$.
+In fact, just from this we could have deduced
+that $$\lambda$$ can be either $$-1$$ or $$1$$.
+In any case, for bosons ($$\lambda = 1$$), we thus find that $$\alpha = \beta$$:
$$\begin{aligned}
- \Ket{\Psi(a, b)}_b = C \big( \Ket{a}\Ket{b} + \Ket{b}\Ket{a} \big)
+ \Ket{\Psi(a, b)}_b
+ = C \big( \Ket{a}\Ket{b} + \Ket{b}\Ket{a} \big)
\end{aligned}$$
-Where $$C$$ is a normalization constant. As expected, this state is
-**symmetric**: switching $$a$$ and $$b$$ gives the same result. Meanwhile, for
-fermions ($$\lambda = -1$$), we find that $$\alpha = -\beta$$:
+Where $$C$$ is a normalization constant.
+As expected, this state is **symmetric**:
+switching $$a$$ and $$b$$ gives the same result.
+Meanwhile, for fermions ($$\lambda = -1$$), we find that $$\alpha = -\beta$$:
$$\begin{aligned}
- \Ket{\Psi(a, b)}_f = C \big( \Ket{a}\Ket{b} - \Ket{b}\Ket{a} \big)
+ \Ket{\Psi(a, b)}_f
+ = C \big( \Ket{a}\Ket{b} - \Ket{b}\Ket{a} \big)
\end{aligned}$$
-This state is called **antisymmetric** under exchange: switching $$a$$ and $$b$$
-causes a sign change, as we would expect for fermions.
+This state is called **antisymmetric** under exchange:
+switching $$a$$ and $$b$$ causes a sign change, as we would expect for fermions.
Now, what if the particles $$x_1$$ and $$x_2$$ are in the same state $$a$$?
For bosons, we just need to update the normalization constant $$C$$:
@@ -106,7 +122,7 @@ $$\begin{aligned}
= C \Ket{a}\Ket{a}
\end{aligned}$$
-However, for fermions, the state is unnormalizable and thus unphysical:
+However, for fermions, the state is unnormalizable and therefore unphysical:
$$\begin{aligned}
\Ket{\Psi(a, a)}_f
@@ -114,7 +130,8 @@ $$\begin{aligned}
= 0
\end{aligned}$$
-And this is the Pauli exclusion principle: **fermions may never
-occupy the same quantum state**. One of the many notable consequences of
-this is that the shells of atoms only fit a limited number of
-electrons (which are fermions), since each must have a different quantum number.
+And this is the Pauli exclusion principle:
+**fermions may never occupy the same quantum state**.
+One of the many notable consequences of this is
+that the shells of atoms only fit a limited number of electrons (which are fermions),
+since each must have a different quantum number.
diff --git a/source/know/concept/propagator/index.md b/source/know/concept/propagator/index.md
index 54e9eb6..50228e2 100644
--- a/source/know/concept/propagator/index.md
+++ b/source/know/concept/propagator/index.md
@@ -8,63 +8,82 @@ categories:
layout: "concept"
---
-In quantum mechanics, the **propagator** $$K(x_f, t_f; x_i, t_i)$$
-gives the probability amplitude that a particle
-starting at $$x_i$$ at $$t_i$$ ends up at position $$x_f$$ at $$t_f$$.
-It is defined as follows:
+In quantum mechanics, the **propagator** $$K(x, t; x_0, t_0)$$
+gives the probability amplitude that a (spinless) particle
+starting at $$(x_0, t_0)$$ ends up at $$(x, t)$$.
+It is defined as:
$$\begin{aligned}
\boxed{
- K(x_f, t_f; x_i, t_i)
- \equiv \matrixel{x_f}{\hat{U}(t_f, t_i)}{x_i}
+ K(x, t; x_0, t_0)
+ \equiv \matrixel{x}{\hat{U}(t, t_0)}{x_0}
}
\end{aligned}$$
-Where $$\hat{U} \equiv \exp(- i t \hat{H} / \hbar)$$ is the time-evolution operator.
-The probability that a particle travels
-from $$(x_i, t_i)$$ to $$(x_f, t_f)$$ is then given by:
+With $$\hat{U}$$ the [time evolution operator](/know/concept/time-evolution-operator/),
+given by $$\hat{U}(t, t_0) = e^{- i (t - t_0) \hat{H} / \hbar}$$
+for a time-independent $$\hat{H}$$.
+Practically, $$K$$ is often calculated using
+[path integrals](/know/concept/path-integral-formulation/).
-$$\begin{aligned}
- P
- &= \big| K(x_f, t_f; x_i, t_i) \big|^2
-\end{aligned}$$
-
-Given a general (i.e. non-collapsed) initial state $$\psi_i(x) \equiv \psi(x, t_i)$$,
-we must integrate over $$x_i$$:
+The principle here is straightforward:
+evolve the initial state with $$\hat{U}$$,
+and project the resulting superposition $$\ket{\psi}$$ onto the queried final state.
+The probability density $$P$$ that the particle has travelled
+from $$(x_0, t_0)$$ to $$(x, t)$$ is then:
$$\begin{aligned}
P
- &= \bigg| \int_{-\infty}^\infty K(x_f, t_f; x_i, t_i) \: \psi_i(x_i) \dd{x_i} \bigg|^2
+ \propto \big| K(x, t; x_0, t_0) \big|^2
\end{aligned}$$
-And if the final state $$\psi_f(x) \equiv \psi(x, t_f)$$
-is not a basis vector either, then we integrate twice:
+The propagator is also useful if the particle
+starts in a general superposition $$\ket{\psi(t_0)}$$,
+in which case the final wavefunction $$\psi(x, t)$$ is as follows:
$$\begin{aligned}
- P
- &= \bigg| \iint_{-\infty}^\infty \psi_f^*(x_f) \: K(x_f, t_f; x_i, t_i) \: \psi_i(x_i) \dd{x_i} \dd{x_f} \bigg|^2
+ \psi(x, t)
+ &= \inprod{x}{\psi(t)}
+ \\
+ &= \matrixel{x}{\hat{U}(t, t_0)}{\psi(t_0)}
+ \\
+ &= \int_{-\infty}^\infty \bra{x} \hat{U}(t, t_0) \Big( \exprod{x_0}{x_0} \Big) \ket{\psi(t_0)} \dd{x_0}
\end{aligned}$$
-Given a $$\psi_i(x)$$, the propagator can also be used
-to find the full final wave function:
+Where we introduced an identity operator
+and recognized $$\psi(x_0, t_0) = \inprod{x_0}{\psi(t_0)}$$, so:
$$\begin{aligned}
\boxed{
- \psi(x_f, t_f)
- = \int_{-\infty}^\infty \psi_i(x_i) K(x_f, t_f; x_i, t_i) \:dx_i
+ \psi(x, t)
+ = \int_{-\infty}^\infty K(x, t; x_0, t_0) \: \psi(x_0, t_0) \dd{x_0}
}
\end{aligned}$$
-Sometimes the name "propagator" is also used to refer to
+The probability density of finding
+the particle at $$(x, t)$$ is then
+$$P \propto \big| \psi(x, t) \big|^2 $$ as usual.
+
+Sometimes the name *propagator* is also used to refer to
the [fundamental solution](/know/concept/fundamental-solution/) $$G$$
of the time-dependent Schrödinger equation,
which is related to $$K$$ by:
$$\begin{aligned}
- \boxed{
- G(x_f, t_f; x_i, t_i)
- = - \frac{i}{\hbar} \: \Theta(t_f - t_i) \: K(x_f, t_f; x_i, t_i)
- }
+ G(x, t; x_0, t_0)
+ = - \frac{i}{\hbar} \: \Theta(t - t_0) \: K(x, t; x_0, t_0)
\end{aligned}$$
Where $$\Theta(t)$$ is the [Heaviside step function](/know/concept/heaviside-step-function/).
+This $$G$$ is a particular example
+of a [Green's function](/know/concept/greens-functions/),
+but not all Green's functions are fundamental solutions
+to the Schrödinger equation.
+To add to the confusion, older literature tends to
+call *all* fundamental solutions *Green's functions*,
+even in classical contexts,
+ so the term has a distinct (but related) meaning
+inside and outside quantum mechanics.
+The result is a mess where the terms *propagator*,
+*fundamental solution* and *Green's function*
+are used more or less interchangeably.
diff --git a/source/know/concept/quantum-teleportation/index.md b/source/know/concept/quantum-teleportation/index.md
index 095c2c6..f57f981 100644
--- a/source/know/concept/quantum-teleportation/index.md
+++ b/source/know/concept/quantum-teleportation/index.md
@@ -22,7 +22,7 @@ $$\begin{aligned}
She can only directly communicate with Bob over a classical channel.
This is not enough: even if Alice did know $$\alpha$$ and $$\beta$$ exactly
-(which would need her having infinitely many copies to measure),
+(for which she would need infinitely many copies to measure),
sending an arbitrary real number requires an infinite amount of classical data.
However, between them, she and Bob also have an entangled [Bell state](/know/concept/bell-state/),
@@ -32,7 +32,7 @@ with $$A'$$ being Alice' qubit, $$A$$ her side of the Bell state, and $$B$$ Bob'
$$\begin{aligned}
\Ket{q}_{A'} \otimes \ket{\Phi^+}_{AB}
- &= \frac{1}{\sqrt{2}} \Big( \alpha \Ket{0} + \beta \Ket{1} \Big)_{A'} \Big( \Ket{00} + \Ket{11} \Big)_{AB}
+ &= \frac{1}{\sqrt{2}} \Big( \alpha \Ket{0} + \beta \Ket{1} \Big)_{A'} \otimes \Big( \Ket{00} + \Ket{11} \Big)_{AB}
\\
&= \frac{1}{\sqrt{2}} \Big( \alpha \Ket{000} + \beta \Ket{100}
+ \alpha \Ket{011} + \beta \Ket{111} \Big)_{A'AB}
@@ -78,8 +78,10 @@ $$\begin{aligned}
+ \ket{\Psi^{-}}_{A'A} \Big( \alpha \Ket{1} - \beta \Ket{0} \Big)_{B} \bigg)
\end{aligned}$$
-Thus, purely due to entanglement,
-Bob's qubit $$B$$ is in a superposition of the following states:
+Therefore, thanks to entanglement,
+Bob's qubit $$B$$ is in a superposition of the following states,
+where $$\hat{\sigma}_x$$ and $$\hat{\sigma}_z$$ are Pauli matrices
+(see [quantum gate](/know/concept/quantum-gate/)):
$$\begin{aligned}
\Ket{q}
@@ -95,8 +97,8 @@ $$\begin{aligned}
= \alpha \Ket{1} - \beta \Ket{0}
\end{aligned}$$
-Consequently, Alice and Bob are sharing (or, to be precise, seeing different sides of)
-the following entangled three-qubit state:
+Consequently, Alice and Bob are seeing different sides of
+this entangled three-qubit state:
$$\begin{aligned}
\Ket{q}_{A'} \ket{\Phi^+}_{AB}
@@ -123,7 +125,7 @@ who then either does nothing (for $$\Ket{q}$$),
applies $$\hat{\sigma}_z$$ (for $$\hat{\sigma}_z \Ket{q}$$),
applies $$\hat{\sigma}_x$$ (for $$\hat{\sigma}_x \Ket{q}$$),
or applies $$\hat{\sigma}_z \hat{\sigma}_x$$ (for $$\hat{\sigma}_x \hat{\sigma}_z \Ket{q}$$).
-Then, due to the fact that $$\hat{\sigma}_x^2 = \hat{\sigma}_z^2 = \hat{I}$$,
+Then, thanks to the fact that $$\hat{\sigma}_x^2 = \hat{\sigma}_z^2 = \hat{I}$$,
he recovers $$\Ket{q}$$ in his local qubit $$B$$.
This is not violating the [no-cloning theorem](/know/concept/no-cloning-theorem)
@@ -140,6 +142,7 @@ Before receiving that, Bob only sees his side of the maximally entangled
Bell state $$\ket{\Phi^{+}}_{AB}$$, which contains nothing of $$\Ket{q}$$.
+
## References
1. J.B. Brask,
*Quantum information: lecture notes*,
diff --git a/source/know/concept/random-phase-approximation/index.md b/source/know/concept/random-phase-approximation/index.md
index 03fd302..ab2681f 100644
--- a/source/know/concept/random-phase-approximation/index.md
+++ b/source/know/concept/random-phase-approximation/index.md
@@ -127,7 +127,7 @@ $$\begin{aligned}
\frac{1}{i \hbar \omega_n^B + i \hbar \omega_m^F - \varepsilon_{\vb{k}+\vb{q}}} \: \frac{1}{i \hbar \omega_m^F - \varepsilon_{\vb{q}}} \dd{\vb{q}}
\end{aligned}$$
-Here we recognize a [Matsubara sum](/know/concept/matsubara-sum/),
+Here we recognize a [Matsubara sum](/know/concept/matsubara-summation/),
and rewrite accordingly.
Note that the residues of $$n_F$$ are $$1 / (\hbar \beta)$$
when it is a function of frequency,
diff --git a/source/know/concept/repetition-code/index.md b/source/know/concept/repetition-code/index.md
index fa039a3..ba83c1a 100644
--- a/source/know/concept/repetition-code/index.md
+++ b/source/know/concept/repetition-code/index.md
@@ -94,7 +94,7 @@ We could measure the state, but that would make it collapse,
which is probably not what we want.
The trick is to use operators called **stabilizers**,
-in this case for example $$ZZI = Z_1 \otimes Z_2 \otimes I_3$$,
+in this case $$ZZI = Z_1 \otimes Z_2 \otimes I_3$$,
where $$I$$ is identity and $$Z$$ is the Pauli-$$Z$$ gate.
The 3-qubit basis states are its eigenvectors:
@@ -127,7 +127,7 @@ $$\begin{alignedat}{2}
We could measure $$ZZI$$ for $$\ket{\overline{\psi}}$$,
and if the eigenvalue is $$-1$$,
we know that a bit flip has occurred,
-whereas if the eigenvalue is $$+1$$,
+but if the eigenvalue is $$+1$$,
there is *maybe* no error ($$\Ket{001}$$ and $$\Ket{110}$$ are false negatives).
These false negatives are fixed by including another stabilizer $$IZZ$$,
@@ -170,7 +170,7 @@ thanks to the eigenvalues:
| $$I$$ | $$+1$$ | $$+1$$ |
| $$X_1$$ | $$-1$$ | $$+1$$ |
| $$X_2$$ | $$-1$$ | $$-1$$ |
-| $$X_1$$ | $$+1$$ | $$-1$$ |
+| $$X_3$$ | $$+1$$ | $$-1$$ |
Where e.g. $$X_3$$ denotes that the 3rd qubit was flipped.
The measurement outcomes on the last three rows are called **error syndromes**,
@@ -309,6 +309,9 @@ $$\begin{aligned}
III \: XXX \: XXX
\end{aligned}$$
+In this way, we are protected against all single-qubit errors,
+but at a significant physical cost.
+
## References
diff --git a/source/know/concept/ritz-method/index.md b/source/know/concept/ritz-method/index.md
index 902b7cf..ef694da 100644
--- a/source/know/concept/ritz-method/index.md
+++ b/source/know/concept/ritz-method/index.md
@@ -25,25 +25,26 @@ consider the following functional to be optimized:
$$\begin{aligned}
R[u]
- = \frac{1}{S} \int_a^b p(x) \big|u_x(x)\big|^2 - q(x) \big|u(x)\big|^2 \dd{x}
+ \equiv \frac{1}{S} \int_a^b p(x) \big|u_x(x)\big|^2 - q(x) \big|u(x)\big|^2 \dd{x}
\end{aligned}$$
Where $$u(x) \in \mathbb{C}$$ is the unknown function,
and $$p(x), q(x) \in \mathbb{R}$$ are given.
-In addition, $$S$$ is the norm of $$u$$, which we demand be constant
+In addition, $$S$$ is the norm of $$u$$, which we take to be constant
with respect to a weight function $$w(x) \in \mathbb{R}$$:
$$\begin{aligned}
S
- = \int_a^b w(x) \big|u(x)\big|^2 \dd{x}
+ \equiv \int_a^b w(x) \big|u(x)\big|^2 \dd{x}
\end{aligned}$$
-To handle this normalization requirement,
-we introduce a [Lagrange multiplier](/know/concept/lagrange-multiplier/) $$\lambda$$,
-and define the Lagrangian $$\Lambda$$ for the full constrained optimization problem as:
+This normalization requirement acts as a constraint
+to the optimization problem for $$R[u]$$,
+so we introduce a [Lagrange multiplier](/know/concept/lagrange-multiplier/) $$\lambda$$,
+and define the Lagrangian $$\mathcal{L}$$ for the full problem as:
$$\begin{aligned}
- \Lambda
+ \mathcal{L}
\equiv \frac{1}{S} \bigg( \big( p |u_x|^2 - q |u|^2 \big) - \lambda \big( w |u|^2 \big) \bigg)
\end{aligned}$$
@@ -51,7 +52,7 @@ The resulting Euler-Lagrange equation is then calculated in the standard way, yi
$$\begin{aligned}
0
- &= \pdv{\Lambda}{u^*} - \dv{}{x}\Big( \pdv{\Lambda}{u_x^*} \Big)
+ &= \pdv{\mathcal{L}}{u^*} - \dv{}{x}\Big( \pdv{\mathcal{L}}{u_x^*} \Big)
\\
&= - \frac{1}{S} \bigg( q u + \lambda w u + \dv{}{x}\big( p u_x \big) \bigg)
\end{aligned}$$
@@ -69,15 +70,14 @@ SLPs have useful properties, but before we can take advantage of those,
we need to handle an important detail: the boundary conditions (BCs) on $$u$$.
The above equation is only a valid SLP for certain BCs,
as seen in the derivation of Sturm-Liouville theory.
-
-Let us return to the definition of $$R[u]$$,
+Let us return to the definition of $$R$$,
and integrate it by parts:
$$\begin{aligned}
R[u]
&= \frac{1}{S} \int_a^b p u_x u_x^* - q u u^* \dd{x}
\\
- &= \frac{1}{S} \Big[ p u_x u^* \Big]_a^b - \frac{1}{S} \int_a^b \dv{}{x}\Big(p u_x\Big) u^* + q u u^* \dd{x}
+ &= \frac{1}{S} \Big[ p u_x u^* \Big]_a^b - \frac{1}{N} \int_a^b \dv{}{x}\Big(p u_x\Big) u^* + q u u^* \dd{x}
\end{aligned}$$
The boundary term vanishes for a subset of the BCs that make a valid SLP,
@@ -88,10 +88,11 @@ such that we can use Sturm-Liouville theory later:
$$\begin{aligned}
R[u]
&= - \frac{1}{S} \int_a^b \bigg( \dv{}{x}\Big(p u_x\Big) + q u \bigg) u^* \dd{x}
- \equiv - \frac{1}{S} \int_a^b u^* \hat{H} u \dd{x}
+ \\
+ &\equiv - \frac{1}{S} \int_a^b u^* \hat{L} u \dd{x}
\end{aligned}$$
-Where $$\hat{H}$$ is the self-adjoint Sturm-Liouville operator.
+Where $$\hat{L}$$ is the self-adjoint Sturm-Liouville operator.
Because the constrained Euler-Lagrange equation is now an SLP,
we know that it has an infinite number of real discrete eigenvalues $$\lambda_n$$ with a lower bound,
corresponding to mutually orthogonal eigenfunctions $$u_n(x)$$.
@@ -102,16 +103,16 @@ and now insert one of the eigenfunctions $$u_n$$ into $$R$$:
$$\begin{aligned}
R[u_n]
- &= - \frac{1}{S_n} \int_a^b u_n^* \hat{H} u_n \dd{x}
- = \frac{1}{S_n} \int_a^b u_n^* \lambda_n w u_n \dd{x}
+ &= - \frac{1}{S_n} \int_a^b u_n^* \hat{L} u_n \dd{x}
+ \\
+ &= \frac{1}{S_n} \int_a^b \lambda_n w |u_n|^2 \dd{x}
\\
- &= \frac{1}{S_n} \lambda_n \int_a^b w |u_n|^2 \dd{x}
- = \frac{S_n}{S_n} \lambda_n
+ &= \frac{S_n}{S_n} \lambda_n
\end{aligned}$$
Where $$S_n$$ is the normalization of $$u_n$$.
-In other words, when given $$u_n$$,
-the functional $$R$$ yields the corresponding eigenvalue $$\lambda_n$$:
+In other words, when given $$u_n$$ as input,
+the functional $$R$$ returns the corresponding eigenvalue $$\lambda_n$$:
$$\begin{aligned}
\boxed{
@@ -121,6 +122,11 @@ $$\begin{aligned}
\end{aligned}$$
This powerful result was not at all clear from $$R$$'s initial definition.
+Note that some authors use the opposite sign for $$\lambda$$ in their SLP definition,
+in which case this result can still be obtained
+simply by also defining $$R$$ with the opposite sign.
+This sign choice is consistent with quantum mechanics,
+with the Hamiltonian $$\hat{H} = - \hat{L}$$.
@@ -137,81 +143,79 @@ $$\begin{aligned}
Here, we are using the fact that the eigenfunctions of an SLP form a complete set,
so our (known) guess $$u$$ can be expanded in the true (unknown) eigenfunctions $$u_n$$.
-We are assuming that $$u$$ is already quite close to its target $$u_0$$,
-such that the (unknown) expansion coefficients $$c_n$$ are small;
-specifically $$|c_n|^2 \ll 1$$.
-Let us start from what we know:
+Next, by definition:
$$\begin{aligned}
\boxed{
R[u]
- = - \frac{\displaystyle\int u^* \hat{H} u \dd{x}}{\displaystyle\int u^* w u \dd{x}}
+ = - \frac{\displaystyle\int u^* \hat{L} u \dd{x}}{\displaystyle\int u^* w u \dd{x}}
}
\end{aligned}$$
-This quantity is known as the **Rayleigh quotient**.
+This quantity is known as the **Rayleigh quotient**,
+and again beware of the sign in its definition; see the remark above.
Inserting our ansatz $$u$$,
-and using that the true $$u_n$$ have corresponding eigenvalues $$\lambda_n$$:
+and using that the true $$u_n$$ have corresponding eigenvalues $$\lambda_n$$,
+we have:
$$\begin{aligned}
R[u]
- &= - \frac{\displaystyle\int \Big( u_0^* + \sum_n c_n^* u_n^* \Big) \: \hat{H} \Big\{ u_0 + \sum_n c_n u_n \Big\} \dd{x}}
+ &= - \frac{\displaystyle\int \Big( u_0^* + \sum_n c_n^* u_n^* \Big) \: \hat{L} \Big\{ u_0 + \sum_n c_n u_n \Big\} \dd{x}}
{\displaystyle\int w \Big( u_0 + \sum_n c_n u_n \Big) \Big( u_0^* + \sum_n c_n^* u_n^* \Big) \dd{x}}
\\
- &= - \frac{\displaystyle\int \Big( u_0^* + \sum_n c_n^* u_n^* \Big) \Big( \!-\! \lambda_0 w u_0 - \sum_n c_n \lambda_n w u_n \Big) \dd{x}}
+ &= - \frac{\displaystyle\int \Big( u_0^* + \sum_n c_n^* u_n^* \Big)
+ \Big( \!-\! \lambda_0 w u_0 - \sum_n c_n \lambda_n w u_n \Big) \dd{x}}
{\displaystyle\int w \Big( u_0^* + \sum_n c_n^* u_n^* \Big) \Big( u_0 + \sum_n c_n u_n \Big) \dd{x}}
\end{aligned}$$
For convenience, we switch to [Dirac notation](/know/concept/dirac-notation/)
-before evaluating further.
+before evaluating further:
$$\begin{aligned}
- R
- &= \frac{\displaystyle \Big( \Bra{u_0} + \sum_n c_n^* \Bra{u_n} \Big) \cdot \Big( \lambda_0 \Ket{w u_0} + \sum_n c_n \lambda_n \Ket{w u_n} \Big)}
- {\displaystyle \Big( \Bra{u_0} + \sum_n c_n^* \Bra{u_n} \Big) \cdot \Big( \Ket{w u_0} + \sum_n c_n \Ket{w u_n} \Big)}
+ R[u]
+ &= \frac{\displaystyle \Big( \Bra{u_0} + \sum_n c_n^* \Bra{u_n} \Big)
+ \Big( \lambda_0 \Ket{w u_0} + \sum_n c_n \lambda_n \Ket{w u_n} \Big)}
+ {\displaystyle \Big( \Bra{u_0} + \sum_n c_n^* \Bra{u_n} \Big) \Big( \Ket{w u_0} + \sum_n c_n \Ket{w u_n} \Big)}
\\
- &= \frac{\displaystyle \lambda_0 \Inprod{u_0}{w u_0} + \lambda_0 \sum_{n = 1}^\infty c_n^* \Inprod{u_n}{w u_0}
- + \sum_{n = 1}^\infty c_n \lambda_n \Inprod{u_0}{w u_n} + \sum_{m n} c_n c_m^* \lambda_n \Inprod{u_m}{w u_n}}
- {\displaystyle \Inprod{u_0}{w u_0} + \sum_{n = 1}^\infty c_n^* \Inprod{u_n}{w u_0}
- + \sum_{n = 1}^\infty c_n \Inprod{u_0}{w u_n} + \sum_{m n} c_n c_m^* \Inprod{u_m}{w u_n}}
+ &= \frac{\displaystyle \lambda_0 \inprod{u_0}{w u_0} + \lambda_0 \sum_{n} c_n^* \inprod{u_n}{w u_0}
+ + \sum_{n} c_n \lambda_n \inprod{u_0}{w u_n} + \sum_{m n} c_n c_m^* \lambda_n \inprod{u_m}{w u_n}}
+ {\displaystyle \inprod{u_0}{w u_0} + \sum_{n} c_n^* \inprod{u_n}{w u_0}
+ + \sum_{n} c_n \inprod{u_0}{w u_n} + \sum_{m n} c_n c_m^* \inprod{u_m}{w u_n}}
\end{aligned}$$
-Using orthogonality $$\Inprod{u_m}{w u_n} = S_n \delta_{mn}$$,
+Using orthogonality $$\inprod{u_m}{w u_n} = S_n \delta_{mn}$$,
and the fact that $$n \neq 0$$ by definition, we find:
$$\begin{aligned}
- R
+ R[u]
&= \frac{\displaystyle \lambda_0 S_0 + \lambda_0 \sum_n c_n^* S_n \delta_{n0}
+ \sum_n c_n \lambda_n S_n \delta_{n0} + \sum_{m n} c_n c_m^* \lambda_n S_n \delta_{mn}}
{\displaystyle S_0 + \sum_n c_n^* S_n \delta_{n0} + \sum_n c_n S_n \delta_{n0} + \sum_{m n} c_n c_m^* S_n \delta_{mn}}
\\
- &= \frac{\displaystyle \lambda_0 S_0 + 0 + 0 + \sum_{n} c_n c_n^* \lambda_n S_n}
- {\displaystyle S_0 + 0 + 0 + \sum_{n} c_n c_n^* S_n}
- = \frac{\displaystyle \lambda_0 S_0 + \sum_{n} |c_n|^2 \lambda_n S_n}
+ &= \frac{\displaystyle \lambda_0 S_0 + \sum_{n} |c_n|^2 \lambda_n S_n}
{\displaystyle S_0 + \sum_{n} |c_n|^2 S_n}
\end{aligned}$$
It is always possible to choose our normalizations such that $$S_n = S$$ for all $$u_n$$, leaving:
$$\begin{aligned}
- R
- &= \frac{\displaystyle \lambda_0 S + \sum_{n} |c_n|^2 \lambda_n S}
- {\displaystyle S + \sum_{n} |c_n|^2 S}
- = \frac{\displaystyle \lambda_0 + \sum_{n} |c_n|^2 \lambda_n}
+ R[u]
+ &= \frac{\displaystyle \lambda_0 + \sum_{n} |c_n|^2 \lambda_n}
{\displaystyle 1 + \sum_{n} |c_n|^2}
\end{aligned}$$
And finally, after rearranging the numerator, we arrive at the following relation:
$$\begin{aligned}
- R
+ R[u]
&= \frac{\displaystyle \lambda_0 + \sum_{n} |c_n|^2 \lambda_0 + \sum_{n} |c_n|^2 (\lambda_n - \lambda_0)}
{\displaystyle 1 + \sum_{n} |c_n|^2}
- = \lambda_0 + \frac{\displaystyle \sum_{n} |c_n|^2 (\lambda_n - \lambda_0)}
+ \\
+ &= \lambda_0 + \frac{\displaystyle \sum_{n} |c_n|^2 (\lambda_n - \lambda_0)}
{\displaystyle 1 + \sum_{n} |c_n|^2}
\end{aligned}$$
-Thus, if we improve our guess $$u$$,
+Thus, if we improve our guess $$u$$ (i.e. reduce $$|c_n|$$),
then $$R[u]$$ approaches the true eigenvalue $$\lambda_0$$.
For numerically finding $$u_0$$ and $$\lambda_0$$, this gives us a clear goal: minimize $$R$$, because:
@@ -228,19 +232,21 @@ In the context of quantum mechanics, this is not surprising,
since any superposition of multiple states
is guaranteed to have a higher energy than the ground state.
-Note that the convergence to $$\lambda_0$$ goes as $$|c_n|^2$$,
+As our guess $$u$$ is improved, $$\lambda_0$$ converges as $$|c_n|^2$$,
while $$u$$ converges to $$u_0$$ as $$|c_n|$$ by definition,
-so even a fairly bad guess $$u$$ will give a decent estimate for $$\lambda_0$$.
+so even a fairly bad ansatz $$u$$ gives a decent estimate for $$\lambda_0$$.
## The method
In the following, we stick to Dirac notation,
-since the results hold for both continuous functions $$u(x)$$ and discrete vectors $$\vb{u}$$,
-as long as the operator $$\hat{H}$$ is self-adjoint.
+since the results hold for both continuous functions $$u(x)$$
+and discrete vectors $$\vb{u}$$,
+as long as the operator $$\hat{L}$$ is self-adjoint.
Suppose we express our guess $$\Ket{u}$$ as a linear combination
-of *known* basis vectors $$\Ket{f_n}$$ with weights $$a_n \in \mathbb{C}$$:
+of *known* basis vectors $$\Ket{f_n}$$ with weights $$a_n \in \mathbb{C}$$,
+where $$\Ket{f_n}$$ are not necessarily eigenvectors of $$\hat{L}$$:
$$\begin{aligned}
\Ket{u}
@@ -250,11 +256,11 @@ $$\begin{aligned}
\end{aligned}$$
For numerical tractability, we truncate the sum at $$N$$ terms,
-and for generality, we allow $$\Ket{f_n}$$ to be non-orthogonal,
+and for generality we allow $$\Ket{f_n}$$ to be non-orthogonal,
as described by an *overlap matrix* with elements $$S_{mn}$$:
$$\begin{aligned}
- \Inprod{f_m}{w f_n} = S_{m n}
+ \inprod{f_m}{w f_n} = S_{m n}
\end{aligned}$$
From the discussion above,
@@ -262,11 +268,10 @@ we know that the ground-state eigenvalue $$\lambda_0$$ is estimated by:
$$\begin{aligned}
\lambda_0
- \approx \lambda
- = R[u]
- = \frac{\inprod{u}{\hat{H} u}}{\Inprod{u}{w u}}
- = \frac{\displaystyle \sum_{m n} a_m^* a_n \inprod{f_m}{\hat{H} f_n}}{\displaystyle \sum_{m n} a_m^* a_n \Inprod{f_m}{w f_n}}
- \equiv \frac{\displaystyle \sum_{m n} a_m^* a_n H_{m n}}{\displaystyle \sum_{m n} a_m^* a_n S_{mn}}
+ \approx R[u]
+ = - \frac{\inprod{u}{\hat{L} u}}{\inprod{u}{w u}}
+ = - \frac{\displaystyle \sum_{m n} a_m^* a_n \inprod{f_m}{\hat{L} f_n}}{\displaystyle \sum_{m n} a_m^* a_n \inprod{f_m}{w f_n}}
+ \equiv - \frac{\displaystyle \sum_{m n} a_m^* a_n L_{m n}}{\displaystyle \sum_{m n} a_m^* a_n S_{mn}}
\end{aligned}$$
And we also know that our goal is to minimize $$R[u]$$,
@@ -274,25 +279,27 @@ so we vary $$a_k^*$$ to find its extremum:
$$\begin{aligned}
0
- = \pdv{R}{a_k^*}
- &= \frac{\displaystyle \Big( \sum_{n} a_n H_{k n} \Big) \Big( \sum_{m n} a_n a_m^* S_{mn} \Big)
- - \Big( \sum_{n} a_n S_{k n} \Big) \Big( \sum_{m n} a_n a_m^* H_{mn} \Big)}
+ = - \pdv{R}{a_k^*}
+ &= \frac{\displaystyle \Big( \sum_{n} a_n L_{k n} \Big) \Big( \sum_{m n} a_n a_m^* S_{mn} \Big)
+ - \Big( \sum_{n} a_n S_{k n} \Big) \Big( \sum_{m n} a_n a_m^* L_{mn} \Big)}
{\Big( \displaystyle \sum_{m n} a_n a_m^* S_{mn} \Big)^2}
\\
- &= \frac{\displaystyle \Big( \sum_{n} a_n H_{k n} \Big) - R[u] \Big( \sum_{n} a_n S_{k n}\Big)}{\Inprod{u}{w u}}
- = \frac{\displaystyle \sum_{n} a_n \big(H_{k n} - \lambda S_{k n}\big)}{\Inprod{u}{w u}}
+ &= \frac{\displaystyle \Big( \sum_{n} a_n L_{k n} \Big) - R[u] \Big( \sum_{n} a_n S_{k n}\Big)}
+ {\displaystyle \sum_{m n} a_n a_m^* S_{mn}}
+ \\
+ &= \sum_{n} a_n \frac{\big(L_{k n} - \lambda S_{k n}\big)}{\inprod{u}{w u}}
\end{aligned}$$
Clearly, this is only satisfied if the following holds for all $$k = 0, 1, ..., N\!-\!1$$:
$$\begin{aligned}
0
- = \sum_{n = 0}^{N - 1} a_n \big(H_{k n} - \lambda S_{k n}\big)
+ = \sum_{n = 0}^{N - 1} a_n \big(L_{k n} - \lambda S_{k n}\big)
\end{aligned}$$
For illustrative purposes,
we can write this as a matrix equation
-with $$M_{k n} \equiv H_{k n} - \lambda S_{k n}$$:
+with $$M_{k n} \equiv L_{k n} - \lambda S_{k n}$$:
$$\begin{aligned}
\begin{bmatrix}
@@ -311,53 +318,47 @@ $$\begin{aligned}
\end{bmatrix}
\end{aligned}$$
-Note that this looks like an eigenvalue problem for $$\lambda$$.
-Indeed, demanding that $$\overline{M}$$ cannot simply be inverted
-(i.e. the solution is non-trivial)
-yields a characteristic polynomial for $$\lambda$$:
+This looks like an eigenvalue problem for $$\lambda$$,
+so we demand that its determinant vanishes:
$$\begin{aligned}
0
- = \det\!\Big[ \overline{M} \Big]
- = \det\!\Big[ \overline{H} - \lambda \overline{S} \Big]
+ = \det\!\Big[ \bar{M} \Big]
+ = \det\!\Big[ \bar{L} - \lambda \bar{S} \Big]
\end{aligned}$$
This gives a set of $$\lambda$$,
-which are the exact eigenvalues of $$\overline{H}$$,
-and the estimated eigenvalues of $$\hat{H}$$
-(recall that $$\overline{H}$$ is $$\hat{H}$$ expressed in a truncated basis).
+which are exact eigenvalues of $$\bar{L}$$,
+and estimated eigenvalues of $$\hat{L}$$
+(recall that $$\bar{L}$$ is $$\hat{L}$$ expressed in a truncated basis).
The eigenvector $$\big[ a_0, a_1, ..., a_{N-1} \big]$$ of the lowest $$\lambda$$
-gives the optimal weights to approximate $$\Ket{u_0}$$ in the basis $$\{\Ket{f_n}\}$$.
-Likewise, the higher $$\lambda$$'s eigenvectors approximate
-excited (i.e. non-ground) eigenstates of $$\hat{H}$$,
-although in practice the results are less accurate the higher we go.
-
-The overall accuracy is determined by how good our truncated basis is,
-i.e. how large a subspace it spans
-of the [Hilbert space](/know/concept/hilbert-space/) in which the true $$\Ket{u_0}$$ resides.
-Clearly, adding more basis vectors will improve the results,
-at the cost of computation.
-For example, if $$\hat{H}$$ represents a helium atom,
-a good choice for $$\{\Ket{f_n}\}$$ would be hydrogen orbitals,
-since those are qualitatively similar.
+gives the optimal weights $$a_n$$ to approximate $$\Ket{u_0}$$ in the basis $$\{\Ket{f_n}\}$$.
+Likewise, the higher $$\lambda$$s' eigenvectors approximate
+excited (i.e. non-ground) eigenstates of $$\hat{L}$$,
+although in practice the results become less accurate the higher we go.
+If we only care about the ground state,
+then we already know $$\lambda$$ from $$R[u]$$,
+so we just need to solve the matrix equation for $$a_n$$.
-You may find this result unsurprising;
-it makes some intuitive sense that approximating $$\hat{H}$$
-in a limited basis would yield a matrix $$\overline{H}$$ giving rough eigenvalues.
+You may find this result unsurprising:
+it makes some intuitive sense that approximating $$\hat{L}$$
+in a limited basis would yield a matrix $$\bar{L}$$ giving rough eigenvalues.
The point of this discussion is to rigorously show
the validity of this approach.
-If we only care about the ground state,
-then we already know $$\lambda$$ from $$R[u]$$,
-so all we need to do is solve the above matrix equation for $$a_n$$.
-Keep in mind that $$\overline{M}$$ is singular,
-and $$a_n$$ are only defined up to a constant factor.
-
Nowadays, there exist many other methods to calculate eigenvalues
-of complicated operators $$\hat{H}$$,
+of complicated operators $$\hat{L}$$,
but an attractive feature of the Ritz method is that it is single-step,
whereas its competitors tend to be iterative.
-That said, the Ritz method cannot recover from a poorly chosen basis.
+That said, this method cannot recover from a poorly chosen basis $$\{\Ket{f_n}\}$$.
+
+Indeed, the overall accuracy is determined by how good our truncated basis is,
+i.e. how large a subspace it spans
+of the [Hilbert space](/know/concept/hilbert-space/) in which the true $$\Ket{u_0}$$ resides.
+Clearly, adding more basis vectors improves the results,
+but at a computational cost;
+it is usually more efficient to carefully choose *which* $$\ket{f_n}$$ to use,
+rather than just *how many*.
diff --git a/source/know/concept/rotating-wave-approximation/index.md b/source/know/concept/rotating-wave-approximation/index.md
index edb13e9..54e0675 100644
--- a/source/know/concept/rotating-wave-approximation/index.md
+++ b/source/know/concept/rotating-wave-approximation/index.md
@@ -16,7 +16,7 @@ in the [electric dipole approximation](/know/concept/electric-dipole-approximati
$$\begin{aligned}
\hat{H}_1(t)
- = \hat{V} \cos(\omega t)
+ \equiv \hat{V} \cos(\omega t)
= \frac{\hat{V}}{2} \Big( e^{i \omega t} + e^{-i \omega t} \Big)
\end{aligned}$$
@@ -26,17 +26,17 @@ of the system that is getting perturbed by $$\hat{H}_1$$.
As an example, consider a two-level system
consisting of states $$\ket{g}$$ and $$\ket{e}$$,
-with a resonance frequency $$\omega_0 = (E_e \!-\! E_g) / \hbar$$.
+with a resonance frequency $$\omega_0 \equiv (E_e \!-\! E_g) / \hbar$$.
From the [amplitude rate equations](/know/concept/amplitude-rate-equations/),
we know that the general superposition state
$$\ket{\Psi} = c_g \ket{g} + c_e \ket{e}$$ evolves as:
$$\begin{aligned}
i \hbar \dv{c_g}{t}
- &= \matrixel{g}{\hat{H}_1(t)}{g} \: c_g(t) + \matrixel{g}{\hat{H}_1(t)}{e} \: c_e(t) \: e^{- i \omega_0 t}
+ &= \matrixel{g}{\hat{H}_1(t)}{g} c_g(t) + \matrixel{g}{\hat{H}_1(t)}{e} c_e(t) \: e^{- i \omega_0 t}
\\
i \hbar \dv{c_e}{t}
- &= \matrixel{e}{\hat{H}_1(t)}{g} \: c_g(t) \: e^{i \omega_0 t} + \matrixel{e}{\hat{H}_1(t)}{e} \: c_e(t)
+ &= \matrixel{e}{\hat{H}_1(t)}{g} c_g(t) \: e^{i \omega_0 t} + \matrixel{e}{\hat{H}_1(t)}{e} c_e(t)
\end{aligned}$$
Typically, $$\hat{V}$$ has odd spatial parity, in which case
@@ -66,15 +66,10 @@ $$\begin{aligned}
At last, here we make the **rotating wave approximation**:
since $$\omega$$ is assumed to be close to $$\omega_0$$,
-we argue that $$\omega \!+\! \omega_0$$ is so much larger than $$\omega \!-\! \omega_0$$
-that those oscillations turn out negligible
-if the system is observed over a reasonable time interval.
-
-Specifically, since both exponentials have the same weight,
-the fast ($$\omega \!+\! \omega_0$$) oscillations
-have a tiny amplitude compared to the slow ($$\omega \!-\! \omega_0$$) ones.
-Furthermore, since they average out to zero over most realistic time intervals,
-the fast terms can be dropped, leaving:
+we argue that $$\omega \!+\! \omega_0$$ is much larger than $$\omega \!-\! \omega_0$$,
+so that those oscillations average out to zero
+when the system is observed over a realistic time interval.
+Hence we drop those terms:
$$\begin{aligned}
\boxed{
@@ -103,13 +98,12 @@ $$\begin{aligned}
This approximation's name is a bit confusing:
the idea is that going from the Schrödinger to
the [interaction picture](/know/concept/interaction-picture/)
-has the effect of removing the exponentials of $$\omega_0$$ from the above equations,
-i.e. multiplying them by $$e^{i \omega_0 t}$$ and $$e^{- i \omega_0 t}$$
+involves removing the exponentials of $$\omega_0$$ from the above equations,
+i.e. they are multiplied by $$e^{i \omega_0 t}$$ and $$e^{- i \omega_0 t}$$
respectively, which can be regarded as a rotation.
-
-Relative to this rotation, when we split the wave $$\cos(\omega t)$$
-into two exponentials, one co-rotates, and the other counter-rotates.
-We keep only the co-rotating waves, hence the name.
+When we split the wave $$\cos(\omega t)$$ into two exponentials,
+one co-rotates relative to this rotation, and the other counter-rotates.
+We keep only the co-rotating terms, hence the name.
The rotating wave approximation is usually used in the context
of the two-level quantum system for light-matter interactions,
diff --git a/source/know/concept/runge-kutta-method/index.md b/source/know/concept/runge-kutta-method/index.md
index 4c3dacf..f0e54ba 100644
--- a/source/know/concept/runge-kutta-method/index.md
+++ b/source/know/concept/runge-kutta-method/index.md
@@ -88,12 +88,13 @@ since this is not a practical way to describe RKMs,
but it is helpful to understand how they work.
+
## Example derivation
For example, let us truncate at $$n = 3$$,
such that $$N_1 = 3$$, $$N_2 = 3$$ and $$N_3 = 1$$.
The following derivation is very general,
-except it requires all $$\alpha_j \neq 0$$.
+only requiring all $$\alpha_j \neq 0$$.
Renaming $$\omega_{mj}$$, we start from:
$$\begin{aligned}
@@ -177,6 +178,7 @@ there is an enormous freedom of choice here,
all leading to valid RKMs, although not necessarily good ones.
+
## General form
A more practical description goes as follows:
diff --git a/source/know/concept/rutherford-scattering/index.md b/source/know/concept/rutherford-scattering/index.md
index edf391c..7a2a1f2 100644
--- a/source/know/concept/rutherford-scattering/index.md
+++ b/source/know/concept/rutherford-scattering/index.md
@@ -27,13 +27,13 @@ Intuitively, we expect $$\theta$$ to be larger for smaller $$b$$.
By combining Coulomb's law with Newton's laws,
these particles' equations of motion are found to be as follows,
-where $$r = |\vb{r}_1 - \vb{r}_2|$$ is the distance between 1 and 2:
+where $$r \equiv |\vb{r}_1 \!-\! \vb{r}_2|$$ is the distance between 1 and 2:
$$\begin{aligned}
m_1 \dv{\vb{v}_1}{t}
= \vb{F}_1
= \frac{q_1 q_2}{4 \pi \varepsilon_0} \frac{\vb{r}_1 - \vb{r}_2}{r^3}
- \qquad \quad
+ \qquad \qquad
m_2 \dv{\vb{v}_2}{t}
= \vb{F}_2
= - \vb{F}_1
@@ -56,8 +56,9 @@ $$(r, \varphi, z)$$:
$$\begin{aligned}
\vb{r}
- = r \cos{\varphi} \:\vu{e}_x + r \sin{\varphi} \:\vu{e}_y + z \:\vu{e}_z
- = r \:\vu{e}_r + z \:\vu{e}_z
+ &= r \cos{\varphi} \:\vu{e}_x + r \sin{\varphi} \:\vu{e}_y + z \:\vu{e}_z
+ \\
+ &= r \:\vu{e}_r + z \:\vu{e}_z
\end{aligned}$$
These new coordinates are sketched below,
@@ -76,6 +77,7 @@ we can find $$\vb{v}$$ by differentiating with respect to time:
$$\begin{aligned}
\vb{v}
+ = \vb{r}'
&= \big( r' \cos{\varphi} - r \varphi' \sin{\varphi} \big) \:\vu{e}_x
+ \big( r' \sin{\varphi} + r \varphi' \cos{\varphi} \big) \:\vu{e}_y + z' \:\vu{e}_z
\\
@@ -107,32 +109,34 @@ $$\begin{aligned}
= \mu r^2 \varphi' \:\vu{e}_z
\end{aligned}$$
-Now, from the figure above,
-we can argue geometrically that at infinity $$t = \pm \infty$$,
-the ratio $$b/r$$ is related to the angle $$\chi$$ between $$\vb{v}$$ and $$\vb{r}$$ like so:
+Now, in the figure above, imagine a right-angled triangle
+with hypotenuse $$\vb{r}$$ and short side $$b$$.
+When $$t \to +\infty$$, trigonometry tells us the following,
+where $$\chi$$ is the final angle between $$\vb{v}$$ and $$\vb{r}$$:
$$\begin{aligned}
- \frac{b}{r(\pm \infty)}
- = \sin{\chi(\pm \infty)}
- \qquad \quad
- \chi(t)
- \equiv \measuredangle(\vb{r}, \vb{v})
+ \lim_{t \to +\infty} \frac{b}{r(t)}
+ = \sin{\chi}
+ \qquad \qquad
+ \chi
+ \equiv
+ \lim_{t \to +\infty} \measuredangle(\vb{r}(t), \vb{v}(t))
\end{aligned}$$
-With this, we can rewrite
-the magnitude of the angular momentum $$\vb{L}$$ as follows,
-where the total velocity $$|\vb{v}|$$ is a constant,
-thanks to conservation of energy:
+With this, we can rewrite the magnitude of the angular momentum $$\vb{L}$$ as follows,
+where the relative speed $$|\vb{v}|$$ is a constant thanks to energy conservation:
$$\begin{aligned}
- \big| \vb{L}(\pm \infty) \big|
- = \mu \big| \vb{r} \cross \vb{v} \big|
+ \lim_{t \to +\infty}
+ \big| \vb{L}(t) \big|
= \mu r |\vb{v}| \sin{\chi}
= \mu b |\vb{v}|
\end{aligned}$$
-However, conveniently,
-angular momentum is also conserved, i.e. $$\vb{L}$$ is constant in time:
+This is useful, because angular momentum is conserved,
+i.e. $$\vb{L}$$ is constant in time.
+We prove this by using the product rule of differentiation,
+and replacing $$\mu \vb{v}'$$ with the reduced equation of motion:
$$\begin{aligned}
\vb{L}'(t)
@@ -142,8 +146,8 @@ $$\begin{aligned}
= 0
\end{aligned}$$
-Where we have replaced $$\mu \vb{v}'$$ with the equation of motion.
-Thanks to this, we can equate the two preceding expressions for $$\vb{L}$$,
+Thanks to this, we can equate the two preceding expressions
+for the magnitude $$|\vb{L}|$$,
leading to the relation below.
Note the appearance of a new minus,
because the sketch shows that $$\varphi' < 0$$,
@@ -178,8 +182,8 @@ $$\begin{aligned}
= \frac{q_1 q_2}{4 \pi \varepsilon_0 b |\vb{v}|} \dd{(\cos{\varphi})}
\end{aligned}$$
-Integrating this from the initial state $$i$$ at $$t = -\infty$$
-to the final state $$f$$ at $$t = \infty$$ yields:
+Integrating this from the initial state $$i$$ at $$t \to -\infty$$
+to the final state $$f$$ at $$t \to +\infty$$ yields:
$$\begin{aligned}
\Delta v_y
@@ -187,18 +191,18 @@ $$\begin{aligned}
= \frac{q_1 q_2}{4 \pi \varepsilon_0 b |\vb{v}| \mu} \big( \cos{\varphi_f} - \cos{\varphi_i} \big)
\end{aligned}$$
-From symmetry, we see that $$\varphi_i = \pi \!-\! \varphi_f$$,
-and that $$\Delta v_y = v_{y,f} \!-\! v_{y,i} = 2 v_{y,f}$$, such that:
+From symmetry, we see that $$\Delta v_y = v_{y,f} \!-\! v_{y,i} = 2 v_{y,f}$$,
+and that $$\varphi_i = \pi \!-\! \varphi_f$$, such that:
$$\begin{aligned}
- 2 v_{y,f}
+ \Delta v_y
+ = 2 v_{y,f}
= \frac{q_1 q_2}{4 \pi \varepsilon_0 b |\vb{v}| \mu} \big( \cos{\varphi_f} - \cos(\pi \!-\! \varphi_f) \big)
= \frac{q_1 q_2}{4 \pi \varepsilon_0 b |\vb{v}| \mu} \big( 2 \cos{\varphi_f} \big)
\end{aligned}$$
-Furthermore, geometrically, at $$t = \infty$$
-we notice that $$v_{y,f} = |\vb{v}| \sin{\varphi_f}$$,
-leading to:
+Furthermore, geometrically for $$t \to +\infty$$
+we notice that $$v_{y,f} = |\vb{v}| \sin{\varphi_f}$$, leading to:
$$\begin{aligned}
2 |\vb{v}| \sin{\varphi_f}
@@ -206,7 +210,7 @@ $$\begin{aligned}
\end{aligned}$$
Rearranging this yields the following equation
-for the final polar angle $$\varphi_f \equiv \varphi(\infty)$$:
+for the final polar angle $$\varphi_f$$:
$$\begin{aligned}
\tan{\varphi_f}
@@ -214,14 +218,14 @@ $$\begin{aligned}
= \frac{q_1 q_2}{4 \pi \varepsilon_0 b |\vb{v}|^2 \mu}
\end{aligned}$$
-However, we want $$\theta$$, not $$\varphi_f$$.
+However, we want the deflection angle $$\theta$$, not $$\varphi_f$$.
One last use of symmetry and geometry
tells us that $$\theta = 2 \varphi_f$$,
and we thus arrive at the celebrated **Rutherford scattering formula**:
$$\begin{aligned}
\boxed{
- \tan\!\Big( \frac{\theta}{2} \Big)
+ \tan\!\bigg( \frac{\theta}{2} \bigg)
= \frac{q_1 q_2}{4 \pi \varepsilon_0 b |\vb{v}|^2 \mu}
}
\end{aligned}$$
diff --git a/source/know/concept/salt-equation/index.md b/source/know/concept/salt-equation/index.md
index d7f8ef3..e6ed5e5 100644
--- a/source/know/concept/salt-equation/index.md
+++ b/source/know/concept/salt-equation/index.md
@@ -80,7 +80,7 @@ $$\begin{aligned}
+ \frac{i}{\hbar} \big(\vb{p}_0^{+} \vb{p}_0^{-}\big) \cdot \Psi_n \: D
\end{aligned}$$
-With being $$\vb{p}_0^{+} \vb{p}_0^{-}$$ a dyadic product.
+With $$\vb{p}_0^{+} \vb{p}_0^{-}$$ denoting a dyadic product.
Isolating the latter equation for $$\vb{p}_n$$ gives us:
$$\begin{aligned}
@@ -275,10 +275,10 @@ so there are multiple active modes competing for charge carriers.
Below threshold (i.e. before any mode is lasing), the problem is linear in $$\Psi_n$$,
but above threshold it is nonlinear via $$h(\vb{x})$$.
-Then the amplitude of $$\Psi_n$$ gets adjusted
+Then the amplitude of $$\Psi_n$$ adjusts itself
such that its respective $$k_n$$ never leaves the real axis.
Once a mode is lasing, hole burning makes it harder for any other modes to activate,
-since they modes must compete for the carrier supply $$D_0$$.
+since they must compete for the carrier supply $$D_0$$.
diff --git a/source/know/concept/second-quantization/index.md b/source/know/concept/second-quantization/index.md
index e446557..605ffd1 100644
--- a/source/know/concept/second-quantization/index.md
+++ b/source/know/concept/second-quantization/index.md
@@ -15,29 +15,26 @@ whether it is fermions or bosons that are being considered
(see [Pauli exclusion principle](/know/concept/pauli-exclusion-principle/)).
Regardless of whether the system is fermionic or bosonic,
-the idea is to change basis to a set of certain many-particle wave functions,
-known as the **Fock states**, which are specific members of a **Fock space**,
-a special kind of [Hilbert space](/know/concept/hilbert-space/),
+the idea is to change basis to a set of many-particle wavefunctions
+known as the **Fock states**, which are specific members of a **Fock space**
+(a special kind of [Hilbert space](/know/concept/hilbert-space/))
with a well-defined number of particles.
For a set of $$N$$ single-particle energy eigenstates
-$$\psi_n(x)$$ and $$N$$ identical particles $$x_n$$, the Fock states are
-all the wave functions which contain $$n$$ particles, for $$n$$ going from $$0$$ to $$N$$.
-
-So for $$n = 0$$, there is one basis vector with $$0$$ particles,
-for $$n = 1$$, there are $$N$$ basis vectors with $$1$$ particle each,
-for $$n = 2$$, there are $$N (N \!-\! 1)$$ basis vectors with $$2$$ particles,
-etc.
+$$\psi_k(x)$$ and $$N$$ identical particles $$x_k$$,
+the Fock states are all the wavefunctions which contain $$n$$ particles,
+for $$n$$ going from $$0$$ to $$N$$.
In this basis, we define the **particle creation operators**
and **particle annihilation operators**,
which respectively add/remove a particle to/from a given state.
-In other words, these operators relate the Fock basis vectors
+In other words, these operators relate the Fock basis states
to one another, and are very useful.
-The point is to express the system's state in such a way that the
-fermionic/bosonic constraints are automatically satisfied, and the
-formulae look the same regardless of the number of particles.
+The idea is to express states in such a way
+that the fermionic/bosonic constraints are automatically satisfied,
+and that the formulas look the same regardless of the number of particles.
+
## Fermions
@@ -56,6 +53,8 @@ $$\begin{aligned}
\\
n &= 2:
\qquad \Ket{1, 1, 0, ...} \quad \Ket{1, 0, 1, ...} \quad \Ket{0, 1, 1, ...} \quad \cdots
+ \\
+ &\:\:\vdots \qquad \qquad \qquad \vdots
\end{aligned}
}
\end{aligned}$$
@@ -79,16 +78,17 @@ $$\begin{aligned}
The creation operator $$\hat{c}_\alpha^\dagger$$ and annihilation
operator $$\hat{c}_\alpha$$ are defined to live up to their name:
-they create or destroy a particle in the state $$\psi_\alpha$$:
+they create or destroy a particle in the state $$\psi_\alpha$$.
+Formally, this means:
$$\begin{aligned}
\boxed{
\begin{aligned}
- \hat{c}_\alpha^\dagger \Ket{... (N_\alpha\!=\!0) ...}
- &= J_\alpha \Ket{... (N_\alpha\!=\!1) ...}
+ \hat{c}_\alpha^\dagger \Ket{...0_\alpha...}
+ &= J_\alpha \Ket{...1_\alpha...}
\\
- \hat{c}_\alpha \Ket{... (N_\alpha\!=\!1) ...}
- &= J_\alpha \Ket{... (N_\alpha\!=\!0) ...}
+ \hat{c}_\alpha \Ket{...1_\alpha...}
+ &= J_\alpha \Ket{...0_\alpha...}
\end{aligned}
}
\end{aligned}$$
@@ -98,7 +98,8 @@ and is necessary here to enforce the fermionic antisymmetry,
when creating or destroying a particle in the $$\alpha$$th state:
$$\begin{aligned}
- J_\alpha = (-1)^{\sum_{j < \alpha} N_j}
+ J_\alpha
+ = (-1)^{\sum_{j < \alpha} N_j}
\end{aligned}$$
So, for example, when creating a particle in state 4
@@ -110,7 +111,8 @@ $$\begin{aligned}
\end{aligned}$$
The point of the Jordan-Wigner string
-is that the order matters when applying the creation and annihilation operators:
+is that the order matters when applying the creation and annihilation operators,
+so, for example:
$$\begin{aligned}
\hat{c}_1^\dagger \hat{c}_2 \Ket{0, 1}
@@ -124,14 +126,21 @@ $$\begin{aligned}
In other words, $$\hat{c}_1^\dagger \hat{c}_2 = - \hat{c}_2 \hat{c}_1^\dagger$$,
meaning that the anticommutator $$\{\hat{c}_2, \hat{c}_1^\dagger\} = 0$$.
-You can verify for youself that
+You can verify for yourself that
the general anticommutators of these operators are given by:
$$\begin{aligned}
\boxed{
- \{\hat{c}_\alpha, \hat{c}_\beta\} = \{\hat{c}_\alpha^\dagger, \hat{c}_\beta^\dagger\} = 0
- \qquad \quad
- \{\hat{c}_\alpha, \hat{c}_\beta^\dagger\} = \delta_{\alpha\beta}
+ \begin{aligned}
+ \{\hat{c}_\alpha, \hat{c}_\beta\}
+ &= 0
+ \\
+ \{\hat{c}_\alpha^\dagger, \hat{c}_\beta^\dagger\}
+ &= 0
+ \\
+ \{\hat{c}_\alpha, \hat{c}_\beta^\dagger\}
+ &= \delta_{\alpha\beta}
+ \end{aligned}
}
\end{aligned}$$
@@ -141,24 +150,29 @@ Note that these are *scalar* zeros:
$$\begin{aligned}
\boxed{
- \hat{c}_\alpha^\dagger \Ket{... (N_\alpha\!=\!1) ...} = 0
- \qquad \quad
- \hat{c}_\alpha \Ket{... (N_\alpha\!=\!0) ...} = 0
+ \begin{aligned}
+ \hat{c}_\alpha^\dagger \Ket{...1_\alpha...}
+ &= 0
+ \\
+ \hat{c}_\alpha \Ket{...0_\alpha...}
+ &= 0
+ \end{aligned}
}
\end{aligned}$$
Finally, as has already been suggested by the notation, they are each other's adjoint:
$$\begin{aligned}
- \matrixel{... (N_\alpha\!=\!1) ...}{\hat{c}_\alpha^\dagger}{... (N_\alpha\!=\!0) ...}
- = \matrixel{...(N_\alpha\!=\!0) ...}{\hat{c}_\alpha}{... (N_\alpha\!=\!1) ...}
+ \matrixel{...1_\alpha...}{\hat{c}_\alpha^\dagger}{...0_\alpha...}
+ = \matrixel{...0_\alpha...}{\hat{c}_\alpha}{...1_\alpha...}^{*}
\end{aligned}$$
Let us now use these operators to define the **number operator** $$\hat{N}_\alpha$$ as follows:
$$\begin{aligned}
\boxed{
- \hat{N}_\alpha = \hat{c}_\alpha^\dagger \hat{c}_\alpha
+ \hat{N}_\alpha
+ = \hat{c}_\alpha^\dagger \hat{c}_\alpha
}
\end{aligned}$$
@@ -171,6 +185,7 @@ $$\begin{aligned}
\end{aligned}$$
+
## Bosons
Bosons do not need to obey the Pauli exclusion principle, so multiple can occupy a single state.
@@ -188,8 +203,10 @@ $$\begin{aligned}
n &= 2:
\qquad \Ket{1, 1, 0, ...} \quad \Ket{1, 0, 1, ...} \quad \Ket{0, 1, 1, ...} \quad \cdots
\\
- &\qquad\:\:\:
+ &\qquad\:\,\,
\qquad \Ket{2, 0, 0, ...} \quad \Ket{0, 2, 0, ...} \quad \Ket{0, 0, 2, ...} \quad \cdots
+ \\
+ &\:\:\vdots \qquad \qquad \qquad \vdots
\end{aligned}
}
\end{aligned}$$
@@ -212,23 +229,31 @@ $$\begin{gathered}
\end{aligned}
}\end{gathered}$$
-Applying the annihilation operator $$\hat{c}_\alpha$$ when there are zero
-particles in $$\alpha$$ will quench the state:
+Applying the annihilation operator $$\hat{c}_\alpha$$
+when there are zero particles in $$\alpha$$ quenches the state:
$$\begin{aligned}
\boxed{
- \hat{c}_\alpha \Ket{... (N_\alpha\!=\!0) ...} = 0
+ \hat{c}_\alpha \Ket{...0_\alpha...}
+ = 0
}
\end{aligned}$$
There is no Jordan-Wigner string, and therefore no sign change when commuting.
-Consequently, these operators therefore satisfy the following:
+Consequently, these operators satisfy the following commutators:
$$\begin{aligned}
\boxed{
- [\hat{c}_\alpha, \hat{c}_\beta] = [\hat{c}_\alpha^\dagger, \hat{c}_\beta^\dagger] = 0
- \qquad
- [\hat{c}_\alpha, \hat{c}_\beta^\dagger] = \delta_{\alpha\beta}
+ \begin{aligned}
+ [\hat{c}_\alpha, \hat{c}_\beta]
+ &= 0
+ \\
+ [\hat{c}_\alpha^\dagger, \hat{c}_\beta^\dagger]
+ &= 0
+ \\
+ [\hat{c}_\alpha, \hat{c}_\beta^\dagger]
+ &= \delta_{\alpha\beta}
+ \end{aligned}
}
\end{aligned}$$
@@ -237,90 +262,93 @@ ensure that $$\hat{N}_\alpha$$ keeps the same nice form:
$$\begin{aligned}
\boxed{
- \hat{N}_\alpha = \hat{c}_\alpha^\dagger \hat{c}_\alpha
+ \hat{N}_\alpha
+ = \hat{c}_\alpha^\dagger \hat{c}_\alpha
}
\end{aligned}$$
+
## Operators
-Traditionally, an operator $$\hat{V}$$ simultaneously acting on $$N$$ indentical particles
-is the sum of the individual single-particle operators $$\hat{V}_1$$ acting on the $$n$$th particle:
+In the second quantization,
+changing between different bases of single-particle states
+is done in the usual way, where $$\alpha$$ and $$b$$ need not be in the same basis.
+Note that $$\Ket{0}$$ is the zero-particle Fock state,
+and $$\Ket{\alpha}$$ etc. are one-particle Fock states:
$$\begin{aligned}
- \hat{V}
- = \sum_{n = 1}^N \hat{V}_1
+ \hat{c}_b^\dagger \Ket{0}
+ = \Ket{b}
+ = \sum_{\alpha} \Ket{\alpha} \inprod{\alpha}{b}
+ = \sum_{\alpha} \inprod{\alpha}{b} \hat{c}_\alpha^\dagger \Ket{0}
\end{aligned}$$
-This can be rewritten using the second quantization operators as follows:
+With this, we define the **field operators**,
+which create or destroy a particle at a position $$\vb{r}$$:
$$\begin{aligned}
\boxed{
- \hat{V}
- = \sum_{\alpha, \beta} \matrixel{\alpha}{\hat{V}_1}{\beta} \hat{c}_\alpha^\dagger \hat{c}_\beta
+ \hat{\Psi}^\dagger(\vb{r})
+ = \sum_{\alpha} \inprod{\alpha}{\vb{r}} \hat{c}_\alpha^\dagger
+ \qquad \qquad
+ \hat{\Psi}(\vb{r})
+ = \sum_{\alpha} \inprod{\vb{r}}{\alpha} \hat{c}_\alpha
}
\end{aligned}$$
-Where the matrix element $$\matrixel{\alpha}{\hat{V}_1}{\beta}$$ is to be
-evaluated in the normal way:
-
-$$\begin{aligned}
- \matrixel{\alpha}{\hat{V}_1}{\beta}
- = \int \psi_\alpha^*(\vec{r}) \: \hat{V}_1(\vec{r}) \: \psi_\beta(\vec{r}) \dd{\vec{r}}
-\end{aligned}$$
-
-Similarly, given some two-particle operator $$\hat{V}$$ in first-quantized form:
+By the same basis-changing principle,
+any single-particle (non-interacting) operator $$\hat{V}$$ can be translated
+to its second-quantized $$N$$-particle version as follows:
$$\begin{aligned}
\hat{V}
- = \sum_{n \neq m} v(\vec{r}_n, \vec{r}_m)
+ &= \sum_{\alpha, \beta} \ket{\alpha} \matrixel{\alpha}{\hat{V}}{\beta} \bra{\beta}
+ = \sum_{\alpha, \beta} \ket{\hat{c}_\alpha^\dagger 0} \matrixel{\alpha}{\hat{V}}{\beta} \bra{\hat{c}_\beta^\dagger 0}
\end{aligned}$$
-We can rewrite this in second-quantized form as follows.
-Note the ordering of the subscripts:
+We take out the creation operators,
+which allows us to generalize to multi-particle states:
$$\begin{aligned}
\boxed{
\hat{V}
- = \sum_{\alpha, \beta, \gamma, \delta}
- v_{\alpha \beta \gamma \delta} \hat{c}_\alpha^\dagger \hat{c}_\beta^\dagger \hat{c}_\delta \hat{c}_\gamma
+ = \sum_{\alpha, \beta} \matrixel{\alpha}{\hat{V}}{\beta} \hat{c}_\alpha^\dagger \hat{c}_\beta
}
\end{aligned}$$
-Where the constant $$v_{\alpha \beta \gamma \delta}$$ is defined from the
-single-particle wave functions:
+Where the matrix element $$\matrixel{\alpha}{\hat{V}}{\beta}$$
+is to be evaluated in the normal way:
$$\begin{aligned}
- v_{\alpha \beta \gamma \delta}
- = \iint \psi_\alpha^*(\vec{r}_1) \: \psi_\beta^*(\vec{r}_2)
- \: v(\vec{r}_1, \vec{r}_2) \: \psi_\gamma(\vec{r}_1)
- \: \psi_\delta(\vec{r}_2) \dd{\vec{r}_1} \dd{\vec{r}_2}
+ \matrixel{\alpha}{\hat{V}}{\beta}
+ = \int \psi_\alpha^*(\vb{r}) \: \hat{V}(\vb{r}) \: \psi_\beta(\vb{r}) \dd{\vb{r}}
\end{aligned}$$
-Finally, in the second quantization, changing basis is done in the usual way:
+In the same way, a two-particle interaction operator $$\hat{W}$$
+can be rewritten in the form below.
+Note the ordering of the operators' subscripts:
$$\begin{aligned}
- \hat{c}_b^\dagger \Ket{0}
- = \Ket{b}
- = \sum_{\alpha} \Ket{\alpha} \Inprod{\alpha}{b}
- = \sum_{\alpha} \Inprod{\alpha}{b} \hat{c}_\alpha^\dagger \Ket{0}
+ \boxed{
+ \hat{W}
+ = \sum_{\alpha, \beta, \gamma, \delta}
+ W_{\alpha \beta \gamma \delta} \: \hat{c}_\alpha^\dagger \hat{c}_\beta^\dagger \hat{c}_\delta \hat{c}_\gamma
+ }
\end{aligned}$$
-Where $$\alpha$$ and $$b$$ need not be in the same basis.
-With this, we can define the **field operators**,
-which create or destroy a particle at a given position $$\vec{r}$$:
+Where the constant $$W_{\alpha \beta \gamma \delta}$$
+is defined from the single-particle wavefunctions like so:
$$\begin{aligned}
- \boxed{
- \hat{\Psi}^\dagger(\vec{r})
- = \sum_{\alpha} \Inprod{\alpha}{\vec{r}} \hat{c}_\alpha^\dagger
- \qquad \quad
- \hat{\Psi}(\vec{r})
- = \sum_{\alpha} \Inprod{\vec{r}}{\alpha} \hat{c}_\alpha
- }
+ W_{\alpha \beta \gamma \delta}
+ \equiv \iint \psi_\alpha^*(\vb{r}_1) \: \psi_\beta^*(\vb{r}_2)
+ \: W(\vb{r}_1, \vb{r}_2) \: \psi_\gamma(\vb{r}_1)
+ \: \psi_\delta(\vb{r}_2) \dd{\vb{r}_1} \dd{\vb{r}_2}
\end{aligned}$$
+
## References
1. L.E. Ballentine,
*Quantum mechanics: a modern development*, 2nd edition,
diff --git a/source/know/concept/self-steepening/index.md b/source/know/concept/self-steepening/index.md
index f96c020..015aa40 100644
--- a/source/know/concept/self-steepening/index.md
+++ b/source/know/concept/self-steepening/index.md
@@ -1,7 +1,7 @@
---
title: "Self-steepening"
sort_title: "Self-steepening"
-date: 2021-02-26
+date: 2024-09-29 # Originally 2021-02-26, major rewrite
categories:
- Physics
- Optics
@@ -10,121 +10,229 @@ categories:
layout: "concept"
---
-For a laser pulse travelling through an optical fiber,
-its intensity is highest at its peak, so the Kerr effect will be strongest there.
-This means that the peak travels slightly slower
-than the rest of the pulse, leading to **self-steepening** of its trailing edge.
-Mathematically, this is described by adding a new term to the
-nonlinear Schrödinger equation:
+A laser pulse travelling in an optical fiber
+causes a nonlinear change of the material's refractive index,
+and the resulting dynamics are described by
+the [nonlinear Schrödinger (NLS) equation](/know/concept/nonlinear-schrodinger-equation/),
+given in its most basic form by:
$$\begin{aligned}
0
- = i\pdv{A}{z} - \frac{\beta_2}{2} \pdvn{2}{A}{t} + \gamma \Big(1 + \frac{i}{\omega_0} \pdv{}{t} \Big) |A|^2 A
+ = i\pdv{A}{z} - \frac{\beta_2}{2} \pdvn{2}{A}{t} + \gamma_0 |A|^2 A
\end{aligned}$$
-Where $$\omega_0$$ is the angular frequency of the pump.
-We will use the following ansatz,
-consisting of an arbitrary power profile $$P$$ with a phase $$\phi$$:
+Where $$A(z, t)$$ is the modulation profile of the carrier wave,
+$$\beta_2$$ is the group velocity dispersion
+at the carrier frequency $$\omega_0$$,
+and $$\gamma_0 \equiv \gamma(\omega_0)$$ is a nonlinear parameter
+involving the material's Kerr coefficient $$n_2$$
+and the transverse mode's effective area $$A_\mathrm{eff}$$:
+
+$$\begin{aligned}
+ \gamma(\omega)
+ \equiv \frac{\omega n_2(\omega)}{c A_\mathrm{eff}(\omega)}
+\end{aligned}$$
+
+As a consequence of treating $$\gamma_0$$ as frequency-independent,
+only the nonlinear *phase* velocity change is represented,
+but not the *group* velocity change.
+Unfortunately, this form of the NLS equation
+does not allow us to include the full $$\gamma(\omega)$$
+(this is an advanced topic, see Lægsgaard),
+but a decent approximation is to simply Taylor-expand $$\gamma(\omega)$$ around $$\omega_0$$:
+
+$$\begin{aligned}
+ \gamma(\omega)
+ = \gamma_0 + \gamma_1 \Omega + \frac{\gamma_2}{2} \Omega^2 + \frac{\gamma_3}{6} \Omega^2 + ...
+\end{aligned}$$
+
+Where $$\Omega \equiv \omega - \omega_0$$
+and $$\gamma_n \equiv \ipdvn{n}{\gamma}{\omega}|_{\omega=\omega_0}$$.
+For pulses with a sufficiently narrow spectrum,
+we only need the first two terms.
+We insert this into the [Fourier transform (FT)](/know/concept/fourier-transform/)
+$$\hat{\mathcal{F}}$$ of the equation,
+where $$s = \pm 1$$ is the sign of the FT exponent,
+which might vary from author to author
+($$s = +1$$ corresponds to a forward-propagating carrier wave and vice versa):
+
+$$\begin{aligned}
+ 0
+ = i\pdv{A}{z} - \frac{\beta_2}{2} (-i s \Omega)^2 A + (\gamma_0 + \gamma_1 \Omega) \hat{\mathcal{F}}\big\{ |A|^2 A \big\}
+\end{aligned}$$
+
+If we now take the inverse FT,
+the factor $$\Omega$$ becomes an operator $$i s \ipdv{}{t}$$:
+
+$$\begin{aligned}
+ 0
+ = i\pdv{A}{z} - \frac{\beta_2}{2} \pdvn{2}{A}{t} + \Big( \gamma_0 + i s \gamma_1 \pdv{}{t} \Big) |A|^2 A
+\end{aligned}$$
+
+In theory, this is the desired new NLS equation,
+but in fact most authors make a small additional approximation.
+Let us write out the derivative of $$\gamma(\omega)$$:
+
+$$\begin{aligned}
+ \dv{\gamma}{\omega}
+ = \frac{n_2}{c A_\mathrm{eff}}
+ + \frac{\omega}{c A_\mathrm{eff}} \dv{n_2}{\omega}
+ - \frac{\omega n_2}{c A_\mathrm{eff}^2} \dv{A_\mathrm{eff}}{\omega}
+\end{aligned}$$
+
+In practice, the $$\omega$$-dependence of $$n_2$$ and $$A_\mathrm{eff}$$
+is relatively weak, so the first term is dominant
+and hence sufficient for our purposes.
+We therefore have $$\gamma_1 \approx \gamma_0 / \omega_0$$, leading to:
+
+$$\begin{aligned}
+ \boxed{
+ 0
+ = i\pdv{A}{z} - \frac{\beta_2}{2} \pdvn{2}{A}{t} + \gamma_0 \Big( 1 + i \frac{s}{\omega_0} \pdv{}{t} \Big) |A|^2 A
+ }
+\end{aligned}$$
+
+Beware that this NLS equation does not conserve the total energy
+$$E \equiv \int_{-\infty}^\infty |A|^2 \dd{t}$$ anymore,
+which is often used to quantify simulation errors.
+Fortunately, another value can then be used instead:
+it can be shown that the "photon number" $$N$$
+is still conserved, defined like so,
+where $$\omega$$ is the absolute frequency
+(as opposed to the relative frequency $$\Omega$$):
+
+$$\begin{aligned}
+ \boxed{
+ N(z)
+ \equiv \int_0^\infty \frac{|A(z, \omega)|^2}{\omega} \dd{\omega}
+ }
+\end{aligned}$$
+
+A pulse's intensity is highest at its peak,
+so the nonlinear index shift is strongest there,
+meaning that the peak travels slightly slower than the rest of the pulse,
+leading to **self-steepening** of its trailing edge;
+an effect exhibited by our modified NLS equation.
+Note that $$s$$ controls which edge is regarded as the trailing one.
+
+Let us make the ansatz below,
+consisting of an arbitrary power profile $$P$$ with phase $$\phi$$:
$$\begin{aligned}
A(z,t)
= \sqrt{P(z,t)} \, \exp\!\big(i \phi(z,t)\big)
\end{aligned}$$
-For a long pulse travelling over a short distance, it is reasonable to
-neglect dispersion ($$\beta_2 = 0$$).
-Inserting the ansatz then gives the following, where $$\varepsilon = \gamma / \omega_0$$:
+We assume that $$A$$ has a sufficiently narrow spectrum
+that we can neglect dispersion $$\beta_2 = 0$$ over a short distance.
+Inserting the ansatz into the NLS equation
+with $$\varepsilon \equiv \gamma_0 / \omega_0$$ gives:
$$\begin{aligned}
0
- &= i \frac{1}{2} \frac{P_z}{\sqrt{P}} - \sqrt{P} \phi_z + \gamma P \sqrt{P} + i \varepsilon \frac{3}{2} P_t \sqrt{P} - \varepsilon P \sqrt{P} \phi_t
+ &= i \frac{1}{2} \frac{P_z}{\sqrt{P}} - \sqrt{P} \phi_z + \gamma_0 P \sqrt{P}
+ + i s \varepsilon \frac{3}{2} P_t \sqrt{P} - s \varepsilon P \sqrt{P} \phi_t
\end{aligned}$$
-This results in two equations, respectively corresponding to the real
-and imaginary parts:
+Since $$P$$ is real, this results in two equations,
+for the real and imaginary parts:
$$\begin{aligned}
0
- &= - \phi_z - \varepsilon P \phi_t + \gamma P
+ &= - \phi_z + \gamma_0 P - s \varepsilon P \phi_t
\\
0
- &= P_z + \varepsilon 3 P_t P
+ &= P_z + 3 s \varepsilon P_t P
\end{aligned}$$
The phase $$\phi$$ is not so interesting, so we focus on the latter equation for $$P$$.
-As it turns out, it has a general solution of the form below (you can verify this yourself),
-which shows that more intense parts of the pulse
-will lag behind compared to the rest:
+You can easily show (by insertion) that it has a general solution of the form below,
+which says that more intense parts of the pulse
+lag behind the rest, as expected:
$$\begin{aligned}
P(z,t)
- = f(t - 3 \varepsilon z P)
+ = f(t - 3 s \varepsilon z P)
\end{aligned}$$
-Where $$f$$ is the initial power profile: $$f(t) = P(0,t)$$.
+Where $$f(t) \equiv P(0,t)$$ is the initial power profile.
The derivatives $$P_t$$ and $$P_z$$ are given by:
$$\begin{aligned}
P_t
- &= (1 - 3 \varepsilon z P_t) \: f'
- \qquad \quad \implies \quad
- P_t
- = \frac{f'}{1 + 3 \varepsilon z f'}
+ &= (1 - 3 s \varepsilon z P_t) \: f'
+ \qquad\quad\!\! = \frac{f'}{1 + 3 s \varepsilon z f'}
\\
P_z
- &= (-3 \varepsilon P - 3 \varepsilon z P_z) \: f'
- \quad \implies \quad
- P_z
- = \frac{- 3 \varepsilon P f'}{1 + 3 \varepsilon z f'}
+ &= (-3 s \varepsilon P - 3 s \varepsilon z P_z) \: f'
+ = \frac{- 3 s \varepsilon P f'}{1 + 3 s \varepsilon z f'}
\end{aligned}$$
-These derivatives both go to infinity when their denominator is zero,
-which, since $$\varepsilon$$ is positive, will happen earliest where $$f'$$
-has its most negative value, called $$f_\mathrm{min}'$$,
-which is located on the trailing edge of the pulse.
+Both expressions blow up when their denominator goes to zero,
+which, since $$\varepsilon > 0$$, happens earliest at an extremum of $$f'$$;
+either its minimum ($$s = +1$$) or maximum ($$s = -1$$).
+Let us call this value $$f_\mathrm{extr}'$$,
+located on the trailing edge of the pulse.
At the propagation distance $$z$$ where this occurs, $$L_\mathrm{shock}$$,
-the pulse will "tip over", creating a discontinuous shock:
+the pulse "tips over", creating a discontinuous shock:
$$\begin{aligned}
0
- = 1 + 3 \varepsilon z f_\mathrm{min}'
+ = 1 + 3 s \varepsilon z f_\mathrm{extr}'
\qquad \implies \qquad
- \boxed{
+ z
+ = \boxed{
L_\mathrm{shock}
- \equiv -\frac{1}{3 \varepsilon f_\mathrm{min}'}
+ \equiv -\frac{\omega_0}{3 s \gamma_0 f_\mathrm{extr}'}
}
\end{aligned}$$
-In practice, however, this will never actually happen, because by the time
-$$L_\mathrm{shock}$$ is reached, the pulse spectrum will have become so
-broad that dispersion can no longer be neglected.
+In practice, however, this never actually happens,
+because as the pulse approaches $$L_\mathrm{shock}$$,
+its spectrum becomes so broad that dispersion cannot be neglected:
+[dispersive broadening](/know/concept/dispersive-broadening/)
+pulls the pulse apart before a shock can occur.
+The early steepening is observable though.
A simulation of self-steepening without dispersion is illustrated below
-for the following Gaussian initial power distribution,
+for the following Gaussian power distribution,
with $$T_0 = 25\:\mathrm{fs}$$, $$P_0 = 3\:\mathrm{kW}$$,
-$$\beta_2 = 0$$ and $$\gamma = 0.1/\mathrm{W}/\mathrm{m}$$:
+$$\beta_2 = 0$$, $$\gamma_0 = 0.1/\mathrm{W}/\mathrm{m}$$,
+and a vacuum carrier wavelength $$\lambda_0 \approx 73\:\mathrm{nm}$$
+(the latter determined by the simulation's resolution settings):
$$\begin{aligned}
f(t)
- = P(0,t) = P_0 \exp\!\Big(\! -\!\frac{t^2}{T_0^2} \Big)
+ = P(0,t) = P_0 \exp\!\bigg(\!-\!\frac{t^2}{T_0^2} \bigg)
\end{aligned}$$
+The first and second derivatives of this Gaussian $$f$$ are as follows:
-Its steepest points are found to be at $$2 t^2 = T_0^2$$, so
-$$f_\mathrm{min}'$$ and $$L_\mathrm{shock}$$ are given by:
+$$\begin{aligned}
+ f'(t)
+ &= - \frac{2 P_0}{T_0^2} t \exp\!\bigg(\!-\!\frac{t^2}{T_0^2} \bigg)
+ \\
+ f''(t)
+ &= \frac{2 P_0}{T_0^2} \bigg( \frac{2 t^2}{T_0^2} - 1 \bigg) \exp\!\bigg(\!-\!\frac{t^2}{T_0^2} \bigg)
+\end{aligned}$$
+
+The steepest points of $$f'$$ are the roots of $$f''$$,
+clearly located at $$2 t^2 = T_0^2$$,
+meaning that $$f_\mathrm{extr}'$$ and $$L_\mathrm{shock}$$
+are in this case given by:
$$\begin{aligned}
- f_\mathrm{min}'
- = - \frac{\sqrt{2} P_0}{T_0} \exp\!\Big(\!-\!\frac{1}{2}\Big)
- \quad \implies \quad
+ f_\mathrm{extr}'
+ = \mp \sqrt{2} e^{-1/2} \frac{P_0}{T_0}
+ \qquad \implies \qquad
L_\mathrm{shock}
- = \frac{T_0}{3 \sqrt{2} \varepsilon P_0} \exp\!\Big(\frac{1}{2}\Big)
+ = \frac{e^{1/2}}{3 \sqrt{2}} \frac{\omega_0 T_0}{\gamma_0 P_0}
\end{aligned}$$
This example Gaussian pulse therefore has a theoretical
$$L_\mathrm{shock} = 0.847\,\mathrm{m}$$,
-which turns out to be accurate,
-although the simulation breaks down due to insufficient resolution:
+which seems to be accurate based on these plots,
+although the simulation breaks down just before that point due to insufficient resolution:
{% include image.html file="simulation-full.png" width="100%"
alt="Self-steepening simulation results" %}
@@ -133,24 +241,17 @@ Unfortunately, self-steepening cannot be simulated perfectly: as the
pulse approaches $$L_\mathrm{shock}$$, its spectrum broadens to infinite
frequencies to represent the singularity in its slope.
The simulation thus collapses into chaos when the edge of the frequency window is reached.
-Nevertheless, the general trends are nicely visible:
+Nevertheless, the trend is nicely visible:
the trailing slope becomes extremely steep, and the spectrum
-broadens so much that dispersion cannot be neglected anymore.
-
-{% comment %}
-When self-steepening is added to the nonlinear Schrödinger equation,
-it no longer conserves the total pulse energy $$\int |A|^2 \dd{t}$$.
-Fortunately, the photon number $$N_\mathrm{ph}$$ is still
-conserved, which for the physical envelope $$A(z,t)$$ is defined as:
-
-$$\begin{aligned}
- \boxed{
- N_\mathrm{ph}(z) = \int_0^\infty \frac{|\tilde{A}(z,\omega)|^2}{\omega} \dd{\omega}
- }
-\end{aligned}$$
-{% endcomment %}
+broadens so much that dispersion can no longer be neglected.
## References
-1. B.R. Suydam, [Self-steepening of optical pulses](https://doi.org/10.1007/0-387-25097-2_6), 2006, Springer.
+
+1. B.R. Suydam,
+ [Self-steepening of optical pulses](https://doi.org/10.1007/0-387-25097-2_6),
+ 2006, Springer.
+2. J. Lægsgaard,
+ [Mode profile dispersion in the generalized nonlinear Schrödinger equation](https://doi.org/10.1364/OE.15.016110),
+ 2007, Optica.
diff --git a/source/know/concept/shors-algorithm/index.md b/source/know/concept/shors-algorithm/index.md
index 678d5d2..bab88a3 100644
--- a/source/know/concept/shors-algorithm/index.md
+++ b/source/know/concept/shors-algorithm/index.md
@@ -29,10 +29,6 @@ This is a so-called *hidden subgroup problem* for a *finite Abelian group*.
With minimal modifications,
Shor's algorithm can solve practically every such problem.
-
-
-## Integer factorization
-
Originally, Shor's algorithm was designed to factorize an integer $$N$$.
For reasons explained later,
this means our goal is to find the period $$s$$ of
@@ -40,7 +36,7 @@ the modular exponentiation function $$f$$:
$$\begin{aligned}
f(x)
- = a^x \bmod N
+ \equiv a^x \bmod N
\end{aligned}$$
For a given $$a$$ and $$N$$.
@@ -72,7 +68,8 @@ $$\begin{aligned}
= \frac{1}{\sqrt{Q}} \sum_{x = 0}^{Q - 1} \Ket{x} \Ket{0}^{\otimes q}
\end{aligned}$$
-Where $$Q = 2^q$$, and $$\Ket{x}$$ is the computational basis state $$\Ket{x_1} \cdots \Ket{x_q}$$.
+Where $$Q \equiv 2^q$$,
+and $$\Ket{x}$$ is the computational basis state $$\Ket{x_1} \cdots \Ket{x_q}$$.
Moving on to $$U_f$$:
$$\begin{aligned}
@@ -81,32 +78,41 @@ $$\begin{aligned}
\frac{1}{\sqrt{Q}} \sum_{x = 0}^{Q - 1} \Ket{x} \Ket{f(x)}
\end{aligned}$$
-Then we measure $$f(x)$$, causing it collapse as follows
-for an unknown arbitrary value of $$x_0$$:
+Then we measure $$f(x)$$, causing it collapse
+for an unknown arbitrary value of $$x_0$$.
+Let $$L$$ be number of periods that fit in the available qubits,
+then we know that:
$$\begin{aligned}
- f(x_0) = f(x_0 + s) = f(x_0 + 2s) = \cdots = f(x_0 + (L-1) s)
+ f(x_0)
+ = f(x_0 + s)
+ = \cdots
+ = f(x_0 + \ell s)
+ = \cdots
+ = f(x_0 + (L-1) s)
\end{aligned}$$
Due to [entanglement](/know/concept/quantum-entanglement/),
-the unmeasured (top $$q$$) qubits change state into a superposition:
+the unmeasured (top $$q$$) qubits change state, so we now have:
$$\begin{aligned}
- \frac{1}{\sqrt{L}} \sum_{\ell = 0}^{L - 1} \Ket{x_0 + \ell s}
+ \frac{1}{\sqrt{L}} \sum_{\ell = 0}^{L - 1} \Ket{x_0 + \ell s} \Ket{f(x_0)}
\end{aligned}$$
Clearly, there is a periodic structure here,
but we cannot measure it directly,
-because we do not know the value of $$x_0$$,
-which, to make matters worse, changes every time we run the algorithm.
-This is where the QFT comes in, which outputs the following state:
+since we do not know the value of $$x_0$$,
+which, to make matters worse, changes every time we run the algorithm!
+But now we apply the QFT, which outputs the state below,
+where $$\omega_Q$$ is a $$Q$$th root of unity.
+From now on, we no longer write the measured qubits $$\Ket{f(x_0)}$$, leaving:
$$\begin{aligned}
\frac{1}{\sqrt{QL}} \sum_{k = 0}^{Q - 1} \bigg( \sum_{\ell = 0}^{L - 1} \omega_Q^{(x_0 + \ell s) k} \bigg) \Ket{k}
\end{aligned}$$
-Where $$\omega_Q$$ is a $$Q$$th root of unity.
-Measuring this state yields a $$\Ket{k}$$, with a probability $$P(k)$$:
+Measuring this state causes a collapse into some $$\Ket{k}$$
+with a probability $$P(k)$$:
$$\begin{aligned}
P(k)
@@ -116,9 +122,9 @@ $$\begin{aligned}
\end{aligned}$$
The last step holds because $$|\omega_Q| = 1$$.
-Surprisingly, this implies that we did not need
-to perform the measurement of $$f(x)$$ earlier!
-This makes sense: the period $$s$$ does not depend on $$x_0$$,
+Surprisingly, $$x_0$$ has disappeared,
+implying that we did not need to perform the measurement of $$f(x)$$ earlier!
+This makes some sense: the period $$s$$ does not depend on $$x_0$$,
so why would we need an implicit $$x_0$$ to determine $$s$$?
So, what does the above probability $$P(k)$$ work out to?
@@ -134,12 +140,13 @@ $$\begin{alignedat}{2}
Where the latter case was evaluated as a geometric series.
The condition $$\omega_Q^{sk}\!=\!1$$ is equivalent to asking
-if $$sk$$ is a multiple of $$Q$$, i.e. if $$sk = cQ$$, for an integer $$c$$.
+if $$sk$$ is a multiple of $$Q$$.
+i.e. if $$sk = cQ$$, for an integer $$c$$.
Recall that $$L$$ is the number of times that $$s$$ fits in $$Q$$,
so $$L\!=\!\lfloor Q / s \rfloor$$.
-Assuming $$Q/s$$ is an integer, then $$L\!=\!Q/s$$ and $$Q\!=\!s L$$,
-which tells us that
+For now, let us assume that $$Q/s$$ is an integer,
+then $$L\!=\!Q/s$$ and $$Q\!=\!s L$$, which tells us that
$$\omega_Q^{sk}\!=\!\omega_{s L}^{s k}\!=\!\omega_L^k$$.
This implies that if $$k$$ is a multiple of $$L$$ (i.e. $$k\!=\!c L$$),
then $$\omega_L^k\!=\!1$$, so $$P(k) = L / Q$$,
@@ -245,9 +252,11 @@ $$\begin{aligned}
= a^x \bmod N
\end{aligned}$$
-$$N$$ is the number to factorize, and $$a$$ is a random integer *coprime* to $$N$$,
+$$N$$ is the number to factorize, and $$a$$ is an integer that we can choose.
+For this to work, we should pick an $$a$$ that is *coprime* to $$N$$,
meaning $$\gcd(a, N) = 1$$.
-The fact that $$s$$ is the period of $$f$$ for a certain $$a$$-value, implies that:
+Then the fact that $$s$$ is the period of $$f$$
+for a certain $$a$$-value implies that:
$$\begin{aligned}
a^x
@@ -257,7 +266,7 @@ $$\begin{aligned}
= a^s \bmod N
\end{aligned}$$
-Suppose that $$s$$ is even. In that case,
+For now, suppose that $$s$$ is even. In that case,
we can rewrite the above equation as follows:
$$\begin{aligned}
@@ -273,7 +282,8 @@ $$\begin{aligned}
= 0 \bmod N
\end{aligned}$$
-Because $$s$$ is even by assumption, the two factors on the left are integers,
+Because $$s$$ is even by assumption (for now),
+the two factors on the left are integers,
and as just mentioned, their product is a multiple of $$N$$.
Then we only need to calculate:
diff --git a/source/know/concept/simons-algorithm/index.md b/source/know/concept/simons-algorithm/index.md
index 63bb808..6404ab0 100644
--- a/source/know/concept/simons-algorithm/index.md
+++ b/source/know/concept/simons-algorithm/index.md
@@ -16,7 +16,7 @@ the [Deutsch-Jozsa algorithm](/know/concept/deutsch-jozsa-algorithm/)
and the [Bernstein-Vazirani algorithm](/know/concept/bernstein-vazirani-algorithm/),
the problem it solves, known as **Simon's problem**,
is of no practical use,
-but nevertheless Simon's algorithm is an important landmark.
+but nevertheless Simon's algorithm is an important milestone.
Simon's problem is this:
we are given a "black box" function $$f(x)$$
@@ -27,8 +27,9 @@ We are promised that there exists an $$s$$ such that for all $$x_1$$ and $$x_2$$
$$\begin{aligned}
f(x_1)
= f(x_2)
- \quad \Leftrightarrow \quad
- x_2 = s \oplus x_1
+ \qquad \Leftrightarrow \qquad
+ x_2
+ = s \oplus x_1
\end{aligned}$$
In other words, regardless of what $$f(x)$$ does behind the scenes,
@@ -94,7 +95,8 @@ where $$x \cdot y$$ is the bitwise dot product:
$$\begin{aligned}
\frac{1}{\sqrt{2^n}} \sum_{x = 0}^{2^n - 1} \Ket{x} \Ket{f(x)}
\quad \to \boxed{H^{\otimes n}} \to \quad
- &\frac{1}{2^n} \sum_{x = 0}^{2^n - 1} \bigg( \sum_{y = 0}^{2^n - 1} (-1)^{x \cdot y} \Ket{y} \bigg) \Ket{f(x)}
+ &\frac{1}{\sqrt{2^n}} \sum_{x = 0}^{2^n - 1}
+ \bigg( \frac{1}{\sqrt{2^n}} \sum_{y = 0}^{2^n - 1} (-1)^{x \cdot y} \Ket{y} \bigg) \Ket{f(x)}
\end{aligned}$$
Next, we measure all qubits.
@@ -106,42 +108,47 @@ where $$f(x_1) = f(x_2)$$ and $$x_2 = s \oplus x_1$$:
$$\begin{alignedat}{2}
&\mathrm{if} \: s = 0: \qquad
- &&\frac{1}{\sqrt{2^{n}}} \sum_{y = 0}^{2^n - 1} (-1)^{x_1 \cdot y} \Ket{y} \Ket{f(x_1)}
+ &&\bigg( \frac{1}{\sqrt{2^{n}}} \sum_{y = 0}^{2^n - 1} (-1)^{x_1 \cdot y} \Ket{y} \bigg) \Ket{f(x_1)}
\\
&\mathrm{if} \: s \neq 0: \qquad
- &&\frac{1}{\sqrt{2^{n+1}}} \sum_{y = 0}^{2^n - 1} \Big( (-1)^{x_1 \cdot y} + (-1)^{x_2 \cdot y} \Big) \Ket{y} \Ket{f(x_1)}
+ &&\bigg( \frac{1}{\sqrt{2^n}} \sum_{y = 0}^{2^n - 1} \frac{1}{\sqrt{2}} \Big( (-1)^{x_1 \cdot y} + (-1)^{x_2 \cdot y} \Big) \Ket{y} \bigg) \Ket{f(x_1)}
\end{alignedat}$$
-If $$s = 0$$, we get an equiprobable superposition of all $$y$$.
-So, when we measure the first $$n$$ qubits, the result is a uniformly random number,
+If $$s = 0$$, we get an equal superposition of all $$y$$,
+so when we measure the first $$n$$ qubits,
+the result is a uniformly random number,
regardless of the phase $$(-1)^{x_1 \cdot y}$$.
-If $$s \neq 0$$, the situation is more interesting,
+If $$s \neq 0$$, we get an "extra superposition",
+since $$x_1 \neq x_2$$ but both are candidate inputs.
+This is a more interesting situation,
because we can only measure $$y$$-values where:
$$\begin{aligned}
- (-1)^{x_1 \cdot y} + (-1)^{x_2 \cdot y} \neq 0
+ 0
+ \neq (-1)^{x_1 \cdot y} + (-1)^{x_2 \cdot y}
\end{aligned}$$
Since $$x_2 = s \oplus x_1$$ by definition,
we can rewrite this as follows:
$$\begin{aligned}
- (-1)^{x_1 \cdot y} + (-1)^{x_1 \cdot y \oplus s \cdot y}
+ 0
+ \neq (-1)^{x_1 \cdot y} + (-1)^{x_1 \cdot y \oplus s \cdot y}
= (-1)^{x_1 \cdot y} + (-1)^{x_1 \cdot y} (-1)^{s \cdot y}
- \neq 0
\end{aligned}$$
-Clearly, the expression can only be nonzero if $$s \cdot y$$ is even.
+Clearly, this expression can only be nonzero if $$s \cdot y$$ is even.
In other words, when we measure the first $$n$$ qubits,
we get a random $$y$$-value,
for which $$s \cdot y$$ is guaranteed to be even.
In both cases $$s = 0$$ and $$s \neq 0$$,
-we measure a $$y$$-value that satisfies the equation:
+measuring the first $$n$$ qubits gives a $$y$$-value satisfying:
$$\begin{aligned}
- s \cdot y = 0 \:\:(\bmod 2)
+ s \cdot y
+ = 0 \:\bmod 2
\end{aligned}$$
This tells us something about $$s$$, albeit not much.
@@ -150,13 +157,16 @@ we get various $$y$$-values $$y_1, ..., y_N$$,
from which we can build a system of linear equations:
$$\begin{aligned}
- s \cdot y_1 &= 0 \:\:(\bmod 2)
+ s \cdot y_1
+ &= 0 \:\bmod 2
\\
- s \cdot y_2 &= 0 \:\:(\bmod 2)
+ s \cdot y_2
+ &= 0 \:\bmod 2
\\
&\:\:\vdots
\\
- s \cdot y_N &= 0 \:\:(\bmod 2)
+ s \cdot y_N
+ &= 0 \:\bmod 2
\end{aligned}$$
This can be solved efficiently by a classical computer.
diff --git a/source/know/concept/sokhotski-plemelj-theorem/index.md b/source/know/concept/sokhotski-plemelj-theorem/index.md
index 445b029..e139954 100644
--- a/source/know/concept/sokhotski-plemelj-theorem/index.md
+++ b/source/know/concept/sokhotski-plemelj-theorem/index.md
@@ -10,7 +10,7 @@ layout: "concept"
---
The goal is to evaluate integrals of the following form,
-where $$f(x)$$ is assumed to be continuous in the integration interval $$[a, b]$$:
+where $$f(x)$$ is real and continuous in the integration interval $$[a, b]$$:
$$\begin{aligned}
\lim_{\eta \to 0^+} \int_a^b \frac{f(x)}{x + i \eta} \dd{x}
@@ -56,7 +56,7 @@ $$\begin{aligned}
&= \lim_{m \to +\infty} \frac{\pi}{\pi} \int_a^b \frac{m}{1 + m^2 x^2} f(x) \dd{x}
\end{aligned}$$
-The expression $$m / \pi (1 + m^2 x^2)$$ is a so-called *nascent delta function*,
+The expression $$m / (\pi (1 + m^2 x^2))$$ is a so-called *nascent delta function*,
meaning that in the limit $$m \to +\infty$$ it converges to
the [Dirac delta function](/know/concept/dirac-delta-function/) $$\delta(x)$$:
diff --git a/source/know/concept/superdense-coding/index.md b/source/know/concept/superdense-coding/index.md
index 4338205..0ad8e9e 100644
--- a/source/know/concept/superdense-coding/index.md
+++ b/source/know/concept/superdense-coding/index.md
@@ -25,16 +25,17 @@ where $$A$$ and $$B$$ are qubits belonging to Alice and Bob, respectively.
Based on the values of the two classical bits $$(a_1, a_2)$$,
Alice performs the following operations on her side $$A$$
-of the Bell state:
+of the Bell state, where $$\hat{\sigma}_x$$ and $$\hat{\sigma}_z$$
+are Pauli matrices (see [quantum gate](/know/concept/quantum-gate/)):
| $$(a_1, a_2)$$ | **Operator** | **Result** |
| :-: | :-: | :-: |
-| $$00$$ | $$\hat{I}$$ | $$\displaystyle \ket{\Phi^{+}} = \frac{1}{\sqrt{2}} \Big(\Ket{0}_A \Ket{0}_B + \Ket{1}_A \Ket{1}_B \Big)$$ |
-| $$01$$ | $$\hat{\sigma}_z$$ | $$\displaystyle \ket{\Phi^{-}} = \frac{1}{\sqrt{2}} \Big(\Ket{0}_A \Ket{0}_B - \Ket{1}_A \Ket{1}_B \Big)$$ |
-| $$10$$ | $$\hat{\sigma}_x$$ | $$\displaystyle \ket{\Psi^{+}} = \frac{1}{\sqrt{2}} \Big(\Ket{0}_A \Ket{1}_B + \Ket{1}_A \Ket{0}_B \Big)$$ |
-| $$11$$ | $$\hat{\sigma}_x \hat{\sigma}_z$$ | $$\displaystyle \ket{\Psi^{-}} = \frac{1}{\sqrt{2}} \Big(\Ket{0}_A \Ket{1}_B - \Ket{1}_A \Ket{0}_B \Big)$$ |
+| $$00$$ | $$\hat{I}$$ | $$\displaystyle \ket{\Phi^{+}} = \frac{1}{\sqrt{2}} \Big( \:\:\: \Ket{0}_A \Ket{0}_B + \Ket{1}_A \Ket{1}_B \Big)$$ |
+| $$01$$ | $$\hat{\sigma}_x$$ | $$\displaystyle \ket{\Psi^{+}} = \frac{1}{\sqrt{2}} \Big( \:\:\: \Ket{1}_A \Ket{0}_B + \Ket{0}_A \Ket{1}_B \Big)$$ |
+| $$10$$ | $$\hat{\sigma}_z$$ | $$\displaystyle \ket{\Phi^{-}} = \frac{1}{\sqrt{2}} \Big( \:\:\: \Ket{0}_A \Ket{0}_B - \Ket{1}_A \Ket{1}_B \Big)$$ |
+| $$11$$ | $$\hat{\sigma}_x \hat{\sigma}_z$$ | $$\displaystyle \ket{\Psi^{-}} = \frac{1}{\sqrt{2}} \Big( \!-\! \Ket{1}_A \Ket{0}_B + \Ket{0}_A \Ket{1}_B \Big)$$ |
-Her actions affect the state on Bob's side $$B$$ due to entanglement.
+Her actions indirectly affect the state on Bob's side $$B$$ due to entanglement.
Alice then sends her qubit $$A$$ to Bob over the quantum channel,
so he has both sides of the entangled pair.
@@ -45,6 +46,7 @@ In the end, Alice only sent a single qubit,
and the rest of the information transfer was via entanglement.
+
## References
1. J.B. Brask,
*Quantum information: lecture notes*,
diff --git a/source/know/concept/thermodynamic-potential/index.md b/source/know/concept/thermodynamic-potential/index.md
index b3bedda..60eee78 100644
--- a/source/know/concept/thermodynamic-potential/index.md
+++ b/source/know/concept/thermodynamic-potential/index.md
@@ -12,17 +12,17 @@ layout: "concept"
whose minima or maxima represent equilibrium states of a system.
Such functions are either energies (hence *potential*) or entropies.
-Which potential (of many) decides the equilibrium states for a given system?
-That depends which variables are assumed to already be in automatic equilibrium.
-Such variables are known as the **natural variables** of that potential.
-For example, if a system can freely exchange heat with its environment,
-and is consequently assumed to be at the same temperature $$T = T_{\mathrm{env}}$$,
+Of the many options, which potential decides the equilibrium state for a given system?
+It depends on which variables are assumed to be in automatic equilibrium.
+Such variables are called the **natural variables** of that potential.
+For example, if a system can exchange heat with its environment,
+and is consequently at the same temperature $$T = T_{\mathrm{env}}$$,
then $$T$$ must be a natural variable.
The link from natural variables to potentials
is established by [thermodynamic ensembles](/know/category/thermodynamic-ensembles/).
-Once enough natural variables have been found,
+Once the natural variables have been determined,
the appropriate potential can be selected from the list below.
All non-natural variables can then be calculated
by taking partial derivatives of the potential
@@ -39,7 +39,7 @@ The **internal energy** $$U$$ represents
the capacity to do both mechanical and non-mechanical work,
and to release heat.
It is simply the integral
-of the [fundamental thermodynamic relation](/know/concept/fundamental-thermodynamic-relation/):
+of the [fundamental thermodynamic relation](/know/concept/fundamental-relation-of-thermodynamics/):
$$\begin{aligned}
\boxed{
@@ -48,8 +48,8 @@ $$\begin{aligned}
\end{aligned}$$
It is a function of the entropy $$S$$, volume $$V$$, and particle count $$N$$:
-these are its natural variables.
-An infinitesimal change $$\dd{U}$$ is as follows:
+these are its natural variables,
+so an infinitesimal change $$\dd{U}$$ is as follows:
$$\begin{aligned}
\boxed{
@@ -59,7 +59,7 @@ $$\begin{aligned}
The non-natural variables are
temperature $$T$$, pressure $$P$$, and chemical potential $$\mu$$.
-They can be recovered by differentiating $$U$$
+These can be recovered by differentiating $$U$$
with respect to the natural variables $$S$$, $$V$$, and $$N$$:
$$\begin{aligned}
@@ -92,8 +92,8 @@ $$\begin{aligned}
\end{aligned}$$
It is a function of the entropy $$S$$, pressure $$P$$, and particle count $$N$$:
-these are its natural variables.
-An infinitesimal change $$\dd{H}$$ is as follows:
+these are its natural variables,
+so an infinitesimal change $$\dd{H}$$ is as follows:
$$\begin{aligned}
\boxed{
@@ -103,7 +103,7 @@ $$\begin{aligned}
The non-natural variables are
temperature $$T$$, volume $$V$$, and chemical potential $$\mu$$.
-They can be recovered by differentiating $$H$$
+These can be recovered by differentiating $$H$$
with respect to the natural variables $$S$$, $$P$$, and $$N$$:
$$\begin{aligned}
@@ -132,8 +132,8 @@ $$\begin{aligned}
\end{aligned}$$
It depends on the temperature $$T$$, volume $$V$$, and particle count $$N$$:
-these are natural variables.
-An infinitesimal change $$\dd{H}$$ is as follows:
+these are its natural variables,
+so an infinitesimal change $$\dd{H}$$ is as follows:
$$\begin{aligned}
\boxed{
@@ -142,8 +142,8 @@ $$\begin{aligned}
\end{aligned}$$
The non-natural variables are
-entropy $$S$$, pressure $$P$$, and chemical potential $$\mu$$.
-They can be recovered by differentiating $$F$$
+the entropy $$S$$, pressure $$P$$, and chemical potential $$\mu$$.
+These can be recovered by differentiating $$F$$
with respect to the natural variables $$T$$, $$V$$, and $$N$$:
$$\begin{aligned}
@@ -171,8 +171,8 @@ $$\begin{aligned}
\end{aligned}$$
It depends on the temperature $$T$$, pressure $$P$$, and particle count $$N$$:
-they are natural variables.
-An infinitesimal change $$\dd{G}$$ is as follows:
+they are its natural variables,
+so an infinitesimal change $$\dd{G}$$ is as follows:
$$\begin{aligned}
\boxed{
@@ -181,7 +181,7 @@ $$\begin{aligned}
\end{aligned}$$
The non-natural variables are
-entropy $$S$$, volume $$V$$, and chemical potential $$\mu$$.
+the entropy $$S$$, volume $$V$$, and chemical potential $$\mu$$.
These can be recovered by differentiating $$G$$
with respect to the natural variables $$T$$, $$P$$, and $$N$$:
@@ -210,8 +210,8 @@ $$\begin{aligned}
\end{aligned}$$
It depends on temperature $$T$$, volume $$V$$, and chemical potential $$\mu$$:
-these are natural variables.
-An infinitesimal change $$\dd{\Omega}$$ is as follows:
+these are its natural variables,
+so an infinitesimal change $$\dd{\Omega}$$ is as follows:
$$\begin{aligned}
\boxed{
@@ -239,7 +239,8 @@ $$\begin{aligned}
## Entropy
The **entropy** $$S$$, in units of energy over temperature,
-is an odd duck, but nevertheless used as a thermodynamic potential.
+is an odd duck, but nevertheless used as a thermodynamic potential,
+to be maximized instead of minimized.
It is given by:
$$\begin{aligned}
@@ -249,8 +250,8 @@ $$\begin{aligned}
\end{aligned}$$
It depends on the internal energy $$U$$, volume $$V$$, and particle count $$N$$:
-they are natural variables.
-An infinitesimal change $$\dd{S}$$ is as follows:
+they are its natural variables,
+so an infinitesimal change $$\dd{S}$$ is as follows:
$$\begin{aligned}
\boxed{
diff --git a/source/know/concept/time-evolution-operator/index.md b/source/know/concept/time-evolution-operator/index.md
new file mode 100644
index 0000000..f489ac6
--- /dev/null
+++ b/source/know/concept/time-evolution-operator/index.md
@@ -0,0 +1,184 @@
+---
+title: "Time evolution operator"
+sort_title: "Time evolution operator"
+date: 2024-10-15
+categories:
+- Quantum mechanics
+- Physics
+layout: "concept"
+---
+
+In general, given a system whose governing equation is known,
+the **time evolution operator** $$\hat{U}(t, t_0)$$
+transforms the state at time $$t_0$$ to the one at time $$t$$.
+Although not specific to it,
+this is most often used in quantum mechanics,
+as governed by the Schrödinger equation:
+
+$$\begin{aligned}
+ i \hbar \dv{}{t} \ket{\psi(t)}
+ = \hat{H}(t) \ket{\psi(t)}
+\end{aligned}$$
+
+Such that the definition of $$\hat{U}(t)$$ is as follows,
+where we have set $$t_0 = 0$$:
+
+$$\begin{aligned}
+ \ket{\psi(t)}
+ = \hat{U}(t) \ket{\psi(0)}
+\end{aligned}$$
+
+Clearly, $$\hat{U}(t)$$ must be unitary.
+The goal is to find an expression that satisfies this relation.
+
+
+
+## Time-independent Hamiltonian
+
+We start by inserting the definition of $$\hat{U}(t)$$
+into the Schrödinger equation:
+
+$$\begin{aligned}
+ \dv{}{t} \hat{U}(t) \ket{\psi(0)}
+ = - \frac{i}{\hbar} \hat{H} \: \hat{U}(t) \ket{\psi(0)}
+\end{aligned}$$
+
+If we hide the state $$\ket{\psi(0)}$$,
+then $$\hat{U}(t)$$ can be said to satisfy the equation in its own right:
+
+$$\begin{aligned}
+ \dv{}{t} \hat{U}(t)
+ = - \frac{i}{\hbar} \hat{H} \: \hat{U}(t)
+\end{aligned}$$
+
+If the Hamiltonian $$\hat{H}$$ is time-independent,
+this is straightforward to integrate, yielding:
+
+$$\begin{aligned}
+ \boxed{
+ \hat{U}(t)
+ = \exp\!\bigg( \!-\! \frac{i}{\hbar} t \hat{H} \bigg)
+ }
+\end{aligned}$$
+
+And the generalization to $$t_0 \neq 0$$ is trivial,
+since we can just shift the time axis:
+
+$$\begin{aligned}
+ \hat{U}(t, t_0)
+ = \exp\!\bigg( \!-\! \frac{i}{\hbar} (t - t_0) \hat{H} \bigg)
+\end{aligned}$$
+
+
+
+## Time-dependent Hamiltonian
+
+Even when $$\hat{H}$$ is time-dependent,
+$$\hat{U}(t)$$ can be said to satisfy the Schrödinger equation:
+
+$$\begin{aligned}
+ \dv{}{t} \hat{U}(t)
+ = - \frac{i}{\hbar} \hat{H}(t) \: \hat{U}(t)
+\end{aligned}$$
+
+Integrating from $$0$$ to $$t$$,
+and using $$\hat{U}(0) = 1$$ (which should be clear from its definition):
+
+$$\begin{aligned}
+ \hat{U}(t)
+ = 1 + \frac{1}{i \hbar} \int_0^t \hat{H}(\tau_1) \: \hat{U}(\tau_1) \dd{\tau_1}
+\end{aligned}$$
+
+This is a self-consistent equation for $$\hat{U}(t)$$.
+We can recursively insert it into itself, yielding:
+
+$$\begin{aligned}
+ \hat{U}(t)
+ &= 1 + \frac{1}{i \hbar} \int_0^t \hat{H}(\tau_1)
+ \bigg( 1 + \frac{1}{i \hbar} \int_0^{\tau_1} \hat{H}(\tau_2) \: \hat{U}(\tau_2) \dd{\tau_2} \bigg) \dd{\tau_1}
+ \\
+ &= 1 + \frac{1}{i \hbar} \int_0^t \hat{H}(\tau_1) \dd{\tau_1}
+ + \frac{1}{(i \hbar)^2} \int_0^t \hat{H}(\tau_1) \int_0^{\tau_1} \hat{H}(\tau_2) \: \hat{U}(\tau_2) \dd{\tau_2} \dd{\tau_1}
+ \\
+ &= 1 + \frac{1}{i \hbar} \int_0^t \hat{H}(\tau_1) \dd{\tau_1}
+ + \frac{1}{(i \hbar)^2} \int_0^t \hat{H}(\tau_1) \int_0^{\tau_1} \hat{H}(\tau_2) \dd{\tau_2} \dd{\tau_1}
+ + \frac{1}{(i \hbar)^3} \int_0^t \cdots \: \dd{\tau_1}
+\end{aligned}$$
+
+And so on.
+Let us take a closer look at the third (i.e. second-order) term in this series,
+noting that the integrals are ordered such that $$\tau_2 < \tau_1$$ always.
+We can exploit this fact to introduce several
+[Heaviside step functions](/know/concept/heaviside-step-function/) $$\Theta(t)$$:
+
+$$\begin{aligned}
+ &\quad \int_0^t \hat{H}(\tau_1) \int_0^{\tau_1} \hat{H}(\tau_2) \dd{\tau_2} \dd{\tau_1}
+ \\
+ &= \frac{1}{2} \int_0^t \hat{H}(\tau_1) \int_0^{\tau_1} \hat{H}(\tau_2) \dd{\tau_2} \dd{\tau_1}
+ + \frac{1}{2} \int_0^t \hat{H}(\tau_2) \int_0^{\tau_2} \hat{H}(\tau_1) \dd{\tau_1} \dd{\tau_2}
+ \\
+ &= \frac{1}{2} \int_0^t \! \hat{H}(\tau_1)
+ \int_0^{\tau_1} \! \Theta(\tau_1 \!-\! \tau_2) \hat{H}(\tau_2) \dd{\tau_2} \dd{\tau_1}
+ + \frac{1}{2} \int_0^t \! \hat{H}(\tau_2)
+ \int_0^{\tau_2} \! \Theta(\tau_2 \!-\! \tau_1) \hat{H}(\tau_1) \dd{\tau_1} \dd{\tau_2}
+ \\
+ &= \frac{1}{2} \int_0^t \int_0^t
+ \bigg( \Theta(\tau_1 \!-\! \tau_2) \: \hat{H}(\tau_1) \: \hat{H}(\tau_2)
+ + \Theta(\tau_2 \!-\! \tau_1) \: \hat{H}(\tau_1) \: \hat{H}(\tau_2) \bigg) \dd{\tau_1} \dd{\tau_2}
+ \\
+ &= \frac{1}{2} \int_0^t \int_0^t \mathcal{T} \Big\{ \hat{H}(\tau_1) \: \hat{H}(\tau_2) \Big\} \dd{\tau_1} \dd{\tau_2}
+\end{aligned}$$
+
+Where we have recognized the
+[time-ordering meta-operator](/know/concept/time-ordered-product/) $$\mathcal{T}$$.
+The above procedure is easy to generalize to the higher-order terms,
+so we arrive at the following expression for $$\hat{U}(t)$$:
+
+$$\begin{aligned}
+ \hat{U}(t)
+ &= 1 + \frac{1}{i \hbar} \int_0^t \hat{H}(\tau_1) \dd{\tau_1}
+ + \frac{1}{2} \frac{1}{(i \hbar)^2} \iint_0^t \mathcal{T} \Big\{ \hat{H}(\tau_1) \: \hat{H}(\tau_2) \Big\} \dd{\tau_2} \dd{\tau_1}
+ \\
+ &\qquad+ \frac{1}{6} \frac{1}{(i \hbar)^3} \iiint_0^t
+ \mathcal{T} \Big\{ \hat{H}(\tau_1) \: \hat{H}(\tau_2) \: \hat{H}(\tau_3) \Big\} \dd{\tau_3} \dd{\tau_2} \dd{\tau_1}
+ + \: ...
+ \\
+ &= 1 + \sum_{n = 1}^\infty \frac{1}{n!} \frac{1}{(i \hbar)^n} \int_0^t \!\cdots\! \int_0^t
+ \mathcal{T} \Big\{ \hat{H}(\tau_1) \cdots \hat{H}(\tau_n) \Big\} \dd{\tau_n} \cdots \dd{\tau_1}
+\end{aligned}$$
+
+This result is sometimes called a **Dyson series**.
+Convention allows us to write it as follows,
+despite such a use of $$\mathcal{T}$$ looking a bit strange:
+
+$$\begin{aligned}
+ \hat{U}(t)
+ &= 1 + \sum_{n = 1}^\infty \frac{1}{n!} \frac{1}{(i \hbar)^n}
+ \mathcal{T} \bigg\{ \bigg( \int_0^t \hat{H}(\tau) \dd{\tau} \bigg)^n \bigg\}
+\end{aligned}$$
+
+Here, we recognize the Taylor expansion of $$\exp(x)$$,
+leading us to the desired result:
+
+$$\begin{aligned}
+ \boxed{
+ \hat{U}(t)
+ = \mathcal{T} \bigg\{ \exp\!\bigg( \!-\! \frac{i}{\hbar} \int_0^t \hat{H}(\tau) \dd{\tau} \bigg) \bigg\}
+ }
+\end{aligned}$$
+
+Where once again $$\mathcal{T}$$ is being used according to convention.
+Finally, the time axis can be shifted arbitrarily,
+so many authors write the evolution operator from $$t_0$$ to $$t$$ as $$\hat{U}(t, t_0)$$:
+
+$$\begin{aligned}
+ \hat{U}(t, t_0)
+ = \mathcal{T} \bigg\{ \exp\!\bigg( \!-\! \frac{i}{\hbar} \int_{t_0}^t \hat{H}(\tau) \dd{\tau} \bigg) \bigg\}
+\end{aligned}$$
+
+
+
+## References
+1. H. Bruus, K. Flensberg,
+ *Many-body quantum theory in condensed matter physics*,
+ 2016, Oxford.
diff --git a/source/know/concept/triple-product-rule/index.md b/source/know/concept/triple-product-rule/index.md
new file mode 100644
index 0000000..16c5440
--- /dev/null
+++ b/source/know/concept/triple-product-rule/index.md
@@ -0,0 +1,97 @@
+---
+title: "Triple product rule"
+sort_title: "Triple product rule"
+date: 2024-07-21
+categories:
+- Mathematics
+- Thermodynamics
+layout: "concept"
+---
+
+Suppose we have a function $$f(x, y, z)$$,
+whose stationary points we want to find.
+This is simple: we take the differential $$\dd{f}$$ and set it to zero:
+
+$$\begin{aligned}
+ 0
+ = \dd{f}
+ &= \bigg( \pdv{f}{x} \bigg)_{y, z} \dd{x} + \bigg( \pdv{f}{y} \bigg)_{x, z} \dd{y} + \bigg( \pdv{f}{z} \bigg)_{x, y} \dd{z}
+\end{aligned}$$
+
+But what if we have a constraint of the form $$f(x, y, z) = C$$, for some constant $$C$$?
+In that case, $$f$$ must be stationary everywhere, so the above still holds,
+but the coordinates $$(x, y, z)$$ are no longer independent:
+there exists an implicit relation $$z(x, y)$$ to satisfy the constraint.
+
+Then $$z$$ can be regarded as a height function,
+in which case we can vary $$(x, y)$$ such that $$z$$ stays constant,
+i.e. it is possible to choose $$\dd{x}$$ and $$\dd{y}$$ such that $$\dd{z} = 0$$,
+leaving:
+
+$$\begin{aligned}
+ 0
+ &= \bigg( \pdv{f}{x} \bigg)_{y, z} \dd{x} + \bigg( \pdv{f}{y} \bigg)_{x, z} \dd{y}
+\end{aligned}$$
+
+We divide this by $$\dd{y}$$. Note the subscript $$(f, z)$$,
+which says those variables are kept constant for that derivatives,
+to indicate that $$x$$ and $$y$$ are not independent:
+
+$$\begin{aligned}
+ 0
+ &= \bigg( \pdv{f}{x} \bigg)_{y, z} \bigg( \pdv{x}{y} \bigg)_{f, z} + \bigg( \pdv{f}{y} \bigg)_{x, z}
+\end{aligned}$$
+
+Rearranging this gives a form of the **triple product rule**
+heavily used in thermodynamics:
+
+$$\begin{aligned}
+ \boxed{
+ \bigg( \pdv{x}{y} \bigg)_{f, z}
+ = - \frac{ \bigg( \displaystyle\pdv{f}{y} \bigg)_{x, z} }{ \bigg( \displaystyle\pdv{f}{x} \bigg)_{y, z} }
+ }
+\end{aligned}$$
+
+If we had divided by $$\dd{x}$$ instead of $$\dd{y}$$,
+we would have arrived at an equivalent result:
+
+$$\begin{aligned}
+ \bigg( \pdv{y}{x} \bigg)_{f, z}
+ = - \frac{ \bigg( \displaystyle\pdv{f}{x} \bigg)_{y, z} }{ \bigg( \displaystyle\pdv{f}{y} \bigg)_{x, z} }
+\end{aligned}$$
+
+Comparing the two previous relations, we see that $$\ipdv{y}{x}$$
+is simply one over $$\ipdv{x}{y}$$,
+just like in an unconstrained problem:
+
+$$\begin{aligned}
+ \bigg( \pdv{y}{x} \bigg)_{f, z}
+ = \bigg( \displaystyle\pdv{x}{y} \bigg)_{f, z}^{-1}
+\end{aligned}$$
+
+You may think this is obvious,
+but it was worth checking that it holds here too.
+Applying this to either of our earlier relations
+yields the standard form of the triple product rule:
+
+$$\begin{aligned}
+ \boxed{
+ -1
+ = \bigg( \pdv{x}{y} \bigg)_{f, z} \bigg( \pdv{f}{x} \bigg)_{y, z} \bigg( \displaystyle\pdv{y}{f} \bigg)_{x, z}
+ }
+\end{aligned}$$
+
+Many authors write this relation with $$f(x, y, z) = z(x, y)$$,
+in which case it becomes:
+
+$$\begin{aligned}
+ -1
+ = \bigg( \pdv{x}{y} \bigg)_{z} \bigg( \pdv{z}{x} \bigg)_{y} \bigg( \displaystyle\pdv{y}{z} \bigg)_{x}
+\end{aligned}$$
+
+
+
+## References
+1. H.B. Callen,
+ *Thermodynamics and an introduction to thermostatistics*, 2nd edition,
+ Wiley.
diff --git a/source/know/concept/two-fluid-equations/index.md b/source/know/concept/two-fluid-equations/index.md
index e224e3e..a00a2f9 100644
--- a/source/know/concept/two-fluid-equations/index.md
+++ b/source/know/concept/two-fluid-equations/index.md
@@ -98,15 +98,17 @@ leading to the following **continuity equations**:
$$\begin{aligned}
\boxed{
- \pdv{n_i}{t} + \nabla \cdot (n_i \vb{u}_i)
- = 0
- \qquad \quad
- \pdv{n_e}{t} + \nabla \cdot (n_e \vb{u}_e)
- = 0
+ \begin{aligned}
+ 0
+ &= \pdv{n_i}{t} + \nabla \cdot (n_i \vb{u}_i)
+ \\
+ 0
+ &= \pdv{n_e}{t} + \nabla \cdot (n_e \vb{u}_e)
+ \end{aligned}
}
\end{aligned}$$
-These are 8 equations (2 scalar continuity, 2 vector momentum),
+These are 8 equations (2 scalars for continuity, 2 vectors for momentum),
but 16 unknowns $$\vb{u}_i$$, $$\vb{u}_e$$, $$\vb{E}$$, $$\vb{B}$$, $$n_i$$, $$n_e$$, $$p_i$$ and $$p_e$$.
We would like to close this system, so we need 8 more.
An obvious choice is [Maxwell's equations](/know/concept/maxwells-equations/),
@@ -115,9 +117,13 @@ in particular Faraday's and Ampère's law
$$\begin{aligned}
\boxed{
- \nabla \cross \vb{E} = - \pdv{\vb{B}}{t}
- \qquad \quad
- \nabla \cross \vb{B} = \mu_0 \Big( n_i q_i \vb{u}_i + n_e q_e \vb{u}_e + \varepsilon_0 \pdv{\vb{E}}{t} \Big)
+ \begin{aligned}
+ \nabla \cross \vb{E}
+ &= - \pdv{\vb{B}}{t}
+ \\
+ \nabla \cross \vb{B}
+ &= \mu_0 \Big( n_i q_i \vb{u}_i + n_e q_e \vb{u}_e + \varepsilon_0 \pdv{\vb{E}}{t} \Big)
+ \end{aligned}
}
\end{aligned}$$
@@ -129,7 +135,7 @@ it turns out that:
$$\begin{aligned}
\frac{\mathrm{D}}{\mathrm{D} t} \big( p V^\gamma \big) = 0
- \qquad \quad
+ \qquad \qquad
\gamma
\equiv \frac{C_P}{C_V}
= \frac{N + 2}{N}
@@ -146,7 +152,7 @@ for some constant $$C$$:
$$\begin{aligned}
\frac{\mathrm{D}}{\mathrm{D} t} \Big( \frac{p}{n^\gamma} \Big) = 0
- \quad \implies \quad
+ \qquad \implies \qquad
p = C n^\gamma
\end{aligned}$$
@@ -155,11 +161,13 @@ giving us a set of 16 equations for 16 unknowns:
$$\begin{aligned}
\boxed{
- \frac{\mathrm{D}}{\mathrm{D} t} \Big( \frac{p_i}{n_i^\gamma} \Big)
- = 0
- \qquad \quad
- \frac{\mathrm{D}}{\mathrm{D} t} \Big( \frac{p_e}{n_e^\gamma} \Big)
- = 0
+ \begin{aligned}
+ 0
+ &= \frac{\mathrm{D}}{\mathrm{D} t} \Big( \frac{p_i}{n_i^\gamma} \Big)
+ \\
+ 0
+ &= \frac{\mathrm{D}}{\mathrm{D} t} \Big( \frac{p_e}{n_e^\gamma} \Big)
+ \end{aligned}
}
\end{aligned}$$
@@ -169,15 +177,16 @@ using simple differentiation and the ideal gas law:
$$\begin{aligned}
p = C n^\gamma
- \quad \implies \quad
+ \qquad \implies \qquad
\nabla p
= \gamma \frac{C n^{\gamma}}{n} \nabla n
= \gamma p \frac{\nabla n}{n}
= \gamma k_B T \nabla n
\end{aligned}$$
-Note that the ideal gas law was not used immediately,
-to allow for $$\gamma \neq 1$$.
+Note that we waited until now to use the ideal gas law,
+in order to include the case $$\gamma \neq 1$$.
+
## Fluid drifts
diff --git a/source/know/concept/wkb-approximation/index.md b/source/know/concept/wkb-approximation/index.md
index ef57a3b..fb04414 100644
--- a/source/know/concept/wkb-approximation/index.md
+++ b/source/know/concept/wkb-approximation/index.md
@@ -8,24 +8,25 @@ categories:
layout: "concept"
---
-In quantum mechanics, the **Wentzel-Kramers-Brillouin** or simply the **WKB
-approximation** is a technique to approximate the wave function $$\psi(x)$$ of
-the one-dimensional time-independent Schrödinger equation. It is an example
-of a **semiclassical approximation**, because it tries to find a
-balance between classical and quantum physics.
+In quantum mechanics, the **Wentzel-Kramers-Brillouin**
+or simply the **WKB approximation**
+is a technique to approximate the wavefunction $$\psi(x)$$
+of the 1D time-independent Schrödinger equation.
+It is an example of a **semiclassical approximation**,
+because it tries to find a balance between classical and quantum physics.
In classical mechanics, a particle travelling in a potential $$V(x)$$
along a path $$x(t)$$ has a total energy $$E$$ as follows, which we
rearrange:
$$\begin{aligned}
- E = \frac{1}{2} m \dot{x}^2 + V(x)
- \quad \implies \quad
+ E = \frac{1}{2} m (x')^2 + V(x)
+ \qquad \implies \qquad
m^2 (x')^2 = 2 m (E - V(x))
\end{aligned}$$
The left-hand side of the rearranged version is simply the momentum squared,
-so we define the magnitude of the momentum $$p(x)$$ accordingly:
+so we know that the magnitude of the momentum $$p(x)$$ is:
$$\begin{aligned}
p(x) = \sqrt{2 m (E - V(x))}
@@ -38,8 +39,9 @@ We rewrite the Schrödinger equation:
$$\begin{aligned}
0
- = \dvn{2}{\psi}{x} + \frac{2 m}{\hbar^2} (E - V) \psi
- = \dvn{2}{\psi}{x} + \frac{p^2}{\hbar^2} \psi
+ &= \dvn{2}{\psi}{x} + \frac{2 m}{\hbar^2} (E - V) \psi
+ \\
+ &= \dvn{2}{\psi}{x} + \frac{p^2}{\hbar^2} \psi
\end{aligned}$$
If $$V(x)$$ were constant, and by extension $$p(x)$$ too, then the solution
@@ -50,20 +52,20 @@ $$\begin{aligned}
= \psi(0) \exp(\pm i p x / \hbar)
\end{aligned}$$
-This form is reminiscent of the generator of translations. In practice,
-$$V(x)$$ and $$p(x)$$ vary with $$x$$, but we can still salvage this solution
+In practice, $$V(x)$$ and $$p(x)$$ vary with $$x$$,
+but we can still salvage this solution
by assuming that $$V(x)$$ varies slowly compared to the wavelength
-$$\lambda(x) = 2 \pi / k(x)$$, where $$k(x) = p(x) / \hbar$$ is the
-wavenumber. The solution then takes the following form:
+$$2 \pi / k(x)$$, where $$k(x) = p(x) / \hbar$$ is the wavenumber.
+The solution then takes the following form:
$$\begin{aligned}
\psi(x)
= \psi(0) \exp\!\Big(\!\pm\! \frac{i}{\hbar} \int_0^x \chi(\xi) \dd{\xi} \Big)
\end{aligned}$$
-$$\chi(\xi)$$ is an unknown function, which intuitively should be related
-to $$p(x)$$. The purpose of the integral is to accumulate the change of
-$$\chi$$ from the initial point $$0$$ to the current position $$x$$.
+$$\chi(\xi)$$ is an unknown function, which intuitively should be related to $$p(x)$$.
+The purpose of the integral is to accumulate the change of $$\chi$$
+from the initial point $$0$$ to the current position $$x$$.
Let us write this as an indefinite integral for convenience:
$$\begin{aligned}
@@ -71,111 +73,118 @@ $$\begin{aligned}
= \psi(0) \exp\!\bigg( \!\pm\! \frac{i}{\hbar} \Big( \int \chi(x) \dd{x} - C \Big) \bigg)
\end{aligned}$$
-Where $$C = \int \chi(x) \dd{x} |_{x = 0}$$ is the initial point of the definite integral.
+Where $$C = \int \chi(x) \dd{x} |_{x = 0}$$ is
+the initial point of the definite integral.
For simplicity, we absorb the constant $$C$$ into $$\psi(0)$$.
We can now clearly see that:
$$\begin{aligned}
- \psi'(x) = \pm \frac{i}{\hbar} \chi(x) \psi(x)
- \quad \implies \quad
- \chi(x) = \pm \frac{\hbar}{i} \frac{\psi'(x)}{\psi(x)}
+ \psi'(x)
+ = \pm \frac{i}{\hbar} \chi(x) \psi(x)
\end{aligned}$$
-Next, we insert this ansatz for $$\psi(x)$$ into the Schrödinger equation
-to get:
+We insert this ansatz for $$\psi(x)$$ into the Schrödinger equation to get:
$$\begin{aligned}
0
&= \pm \frac{i}{\hbar} \dv{(\chi \psi)}{x} + \frac{p^2}{\hbar^2} \psi
- = \pm \frac{i}{\hbar} \chi' \psi \pm \frac{i}{\hbar} \chi \psi' + \frac{p^2}{\hbar^2} \psi
- = \pm \frac{i}{\hbar} \chi' \psi - \frac{1}{\hbar^2} \chi^2 \psi + \frac{p^2}{\hbar^2} \psi
+ \\
+ &= \pm \frac{i}{\hbar} \chi' \psi \pm \frac{i}{\hbar} \chi \psi' + \frac{p^2}{\hbar^2} \psi
+ \\
+ &= \pm \frac{i}{\hbar} \chi' \psi - \frac{1}{\hbar^2} \chi^2 \psi + \frac{p^2}{\hbar^2} \psi
\end{aligned}$$
-Dividing out $$\psi$$ and rearranging gives us the following, which is
-still exact:
+Dividing out $$\psi$$ and rearranging gives us the following, which is still exact:
$$\begin{aligned}
\pm \frac{\hbar}{i} \chi'
= p^2 - \chi^2
\end{aligned}$$
-Next, we expand this as a power series of $$\hbar$$. This is why it is
-called *semiclassical*: so far we have been using full quantum mechanics,
-but now we are treating $$\hbar$$ as a parameter which controls the
-strength of quantum effects:
+Next, we expand this as a power series of $$\hbar$$.
+This is why it is called *semiclassical*:
+so far we have been using full quantum mechanics,
+but now we are treating $$\hbar$$ as a parameter
+which controls the strength of quantum effects:
$$\begin{aligned}
- \chi(x) = \chi_0(x) + \frac{\hbar}{i} \chi_1(x) + \frac{\hbar^2}{i^2} \chi_2(x) + ...
+ \chi(x)
+ = \chi_0(x) + \frac{\hbar}{i} \chi_1(x) + \frac{\hbar^2}{i^2} \chi_2(x) + \cdots
+\end{aligned}$$
+
+The heart of the WKB approximation is its assumption that quantum effects
+are sufficiently weak that we only need to consider
+the first two terms of this expansion,
+i.e. $$\hbar^2$$ is so small that it is negligible.
+Therefore, our approximated wavefunction $$\psi(x)$$ now looks like this:
+
+$$\begin{aligned}
+ \psi(x)
+ &\approx \psi(0) \exp\!\Big( \!\pm\! \frac{i}{\hbar} \int \chi_0(x) \dd{x} \Big) \exp\!\Big( \!\pm\! \int \chi_1(x) \dd{x} \Big)
\end{aligned}$$
-The heart of the WKB approximation is its assumption that quantum effects are
-sufficiently weak (i.e. $$\hbar$$ is small enough) that we only need to
-consider the first two terms, or, more specifically, that we only go up to
-$$\hbar$$, not $$\hbar^2$$ or higher. Inserting the first two terms of this
-expansion into the equation:
+Inserting the expansion's first two terms into our equation for $$\chi(x)$$ gives:
$$\begin{aligned}
\pm \frac{\hbar}{i} \chi_0'
&= p^2 - \chi_0^2 - 2 \frac{\hbar}{i} \chi_0 \chi_1
\end{aligned}$$
-Where we have discarded all terms containing $$\hbar^2$$. At order
-$$\hbar^0$$, we then get the expected classical result for $$\chi_0(x)$$:
+Where we have discarded all terms containing $$\hbar^2$$.
+At order $$\hbar^0$$, we then get the expected classical result for $$\chi_0(x)$$:
$$\begin{aligned}
0 = p^2 - \chi_0^2
- \quad \implies \quad
- \chi_0(x) = p(x)
+ \qquad \implies \qquad
+ \chi_0(x)
+ = p(x)
\end{aligned}$$
-While at order $$\hbar$$, we get the following quantum-mechanical
-correction:
+While at order $$\hbar$$, we get the following quantum-mechanical correction:
$$\begin{aligned}
\pm \frac{\hbar}{i} \chi_0'
= - 2 \frac{\hbar}{i} \chi_0 \chi_1
- \quad \implies \quad
- \chi_1(x) = \mp \frac{1}{2} \frac{\chi_0'(x)}{\chi_0(x)}
+ \qquad \implies \qquad
+ \chi_1(x)
+ = \mp \frac{1}{2} \frac{\chi_0'(x)}{\chi_0(x)}
\end{aligned}$$
-Therefore, our approximated wave function $$\psi(x)$$ currently looks like
-this:
-
-$$\begin{aligned}
- \psi(x)
- &\approx \psi(0) \exp\!\Big( \!\pm\! \frac{i}{\hbar} \int \chi_0(x) \dd{x} \Big) \exp\!\Big( \!\pm\! \int \chi_1(x) \dd{x} \Big)
-\end{aligned}$$
-
-We can reduce the latter exponential using integration by substitution:
+We can use this to simplify the latter exponential in $$\psi(x)$$
+using integration by substitution:
$$\begin{aligned}
\exp\!\Big( \!\pm\! \int \chi_1(x) \dd{x} \Big)
&= \exp\!\Big( \!-\! \frac{1}{2} \int \frac{\chi_0'(x)}{\chi_0(x)} \dd{x} \Big)
- = \exp\!\Big( \!-\! \frac{1}{2} \int \frac{1}{\chi_0}\:d\chi_0 \Big)
+ \\
+ &= \exp\!\Big( \!-\! \frac{1}{2} \int \frac{1}{\chi_0}\:d\chi_0 \Big)
\\
&= \exp\!\Big( \!-\! \frac{1}{2} \ln\!\big(\chi_0(x)\big) \Big)
- = \frac{1}{\sqrt{\chi_0(x)}}
- = \frac{1}{\sqrt{p(x)}}
+ \\
+ &= \frac{1}{\sqrt{\chi_0(x)}}
\end{aligned}$$
-In the WKB approximation for $$E > V$$, the solution $$\psi(x)$$ is thus
-given by:
+In the WKB approximation for $$E > V$$,
+the solution $$\psi(x)$$ is therefore given by:
$$\begin{aligned}
\boxed{
- \psi(x) \approx \frac{A}{\sqrt{p(x)}} \exp\!\Big( \!\pm\! \frac{i}{\hbar} \int p(x) \dd{x} \Big)
+ \psi(x)
+ \approx \frac{A}{\sqrt{p(x)}} \exp\!\Big( \!\pm\! \frac{i}{\hbar} \int p(x) \dd{x} \Big)
}
\end{aligned}$$
-What if $$E < V$$? In classical mechanics, this is just not allowed; a ball
-cannot simply go through a potential bump without the necessary energy.
+What if $$E < V$$? In classical mechanics, this is not allowed:
+a ball cannot simply go through or over a potential bump without the necessary energy.
On the other hand, in quantum physics, particles can **tunnel** through barriers.
Luckily, the only thing we need to change for the WKB approximation
is to let the momentum take imaginary values:
$$\begin{aligned}
- p(x) = \sqrt{2 m (E - V(x))} = i \sqrt{2 m (V(x) - E)}
+ p(x)
+ = \sqrt{2 m (E - V(x))}
+ = i \sqrt{2 m (V(x) - E)}
\end{aligned}$$
And then take the absolute value in the appropriate place in front of $$\psi(x)$$:
@@ -186,12 +195,13 @@ $$\begin{aligned}
}
\end{aligned}$$
-In the classical region ($$E > V$$), the wave function oscillates, and
-in the quantum-physical region ($$E < V$$) it is exponential.
+In the classical region ($$E > V$$), the wavefunction oscillates,
+and in the quantum-physical region ($$E < V$$) it is exponential.
Note that for $$E \approx V$$ the approximation breaks down,
because of the appearance of $$p(x)$$ in the denominator.
+
## References
1. D.J. Griffiths, D.F. Schroeter,
*Introduction to quantum mechanics*, 3rd edition,