% uni-math.tex %%%%%%%%%%%%%%%%%%%%%%%% % Petr Olsak 2016, 2019 % Benjamin Barenblat 2022 \def\unimathversion{Jan. 2022} % Warning: this is at beta testing state % Macros for loading Unicode math fonts in XeTeX or LuaTeX % usage: \def\unimathfont{Font Name} \input uni-math % \setmathsizes[text/script/scriptscript]\normalmath % Example: \setmathsizes[12/8.4/6]\normalmath ... loads fonts at given sizes % Full example: % \let\loadmathfonts=\relax % don't load 8bit math fonts % \input cs-pagella % load Pagella Text fonts % \def\unimathfont{[texgyrepagella-math]} % declare Pagella Math font % \input uni-math % load Pagella Math font % If you are using OPmac then you can set sizes of math+text fonts as usual: % \typosize[12/14.4] ... \ifx\Umathcode\undefined \message{uni-math WARNING: Unicoded engine not detected. Macro-file ignored...} \endinput\fi \ifx\directlua\undefined \else \ifx\luafonts\undefined \input luafonts \fi\fi % lua code to re-define \font primitive \def\umathname#1#2{"#1:\mfontfeatures#2"} \ifx\directlua\undefined \def\mfontfeatures{script=math;} % XeTeX \else \def\mfontfeatures{mode=base;script=math;} % LuaTeX \fi \ifx\unimathfont\relax\else % \relax ... font will be declared later \ifx\unimathfont\undefined \def\unimathfont{??}\fi \suppressfontnotfounderror=1 \font\mF=\umathname{\unimathfont}{} \relax \suppressfontnotfounderror=0 \ifx\mF\nullfont \message{uni-math WARNING: \string\unimathfont{\unimathfont} isn't loadable.} \bgroup \toks0={Examples:^^J \def\unimathfont{[XITSMath-Regular]} ... XITS MATH^^J \def\unimathfont{[latinmodern-math]} ... Latin Modern Math^^J \def\unimathfont{[texgyretermes-math]} ... TeXGyre Termes Math^^J \def\unimathfont{[texgyrebonum-math]} ... TeXGyre Bonum Math^^J \def\unimathfont{[texgyrepagella-math]} ... TeXGyre Pagella Math^^J \def\unimathfont{[texgyreschola-math]} ... TeXGyre Schola Math^^J \def\unimathfont{[texgyredejavu-math]} ... TeXGyre DeJaVu Math^^J \def\unimathfont{[LibertinusMath-Regular]} ... Libertinus Math^^J \def\unimathfont{[FiraMath-Regular]} ... Fira Math^^J \def\unimathfont{[Asana-Math]} ... Asana Math^^J \let\unimathfont=\relax ... Don't load the font right now.^^J Note brackets if direct file name is used. Don't use quotes "...". }\newlinechar=`^^J \message{\the\toks0}\message{Macrofile ignored...} \egroup \endinput\fi \fi \message{FONT: \unimathfont\space - Unicode Math (v. \unimathversion) prepared.} \let\mathpreloaded=U \ifx\directlua\undefined \else \ifx\luafonts\undefined \input luafonts \fi\fi \def\normalmath{% \loadumathfamily 1 {\unimathfont}{} % Base font \loadmathfamily 4 rsfs % script \setmathdimens } \def\boldmath{% \loadumathfamily 1 {\unimathfont}{embolden=1.7;} \fakeboldwarn \loadmathfamily 4 rsfs % script \setmathdimens } \def\fakeboldwarn{\ifx\directlua\undefined\else \message{WARNING: Fake-bold font is not supported by LuaTeX.}\fi} \ifx\regtmf\undefined \input ff-mac \fi \regtfm rsfs 0 rsfs5 6 rsfs7 8.5 rsfs10 * \count18=4 % Note: if you want to combine more Math fonts at another math family slots, % don't use family 2 and 3. They are reserved for \fontdimens. \def\loadumathfamily #1 #2#3 { \let\dgsize=\sizemtext \font\mF=\umathname{#2}{#3} at\dgsize \textfont#1=\mF \ifnum#1=1 \textfont2=\mF \textfont3=\mF \fi \let\dgsize=\sizemscript \font\mF=\umathname{#2}{+ssty=0;#3} at\dgsize \scriptfont#1=\mF \ifnum#1=1 \scriptfont2=\mF \scriptfont3=\mF \fi \let\dgsize=\sizemsscript \font\mF=\umathname{#2}{+ssty=1;#3} at\dgsize \scriptscriptfont#1=\mF \ifnum#1=1 \scriptscriptfont2=\mF \scriptscriptfont3=\mF \fi \let\dgsize=\undefined } \def\loadmathfamily #1 #2 {\chardef\tmp#1\corrmsizes \let\dgsize=\sizemtext \font\mF=\whichtfm{#2} at\dgsize \textfont#1=\mF \let\dgsize=\sizemscript \font\mF=\whichtfm{#2} at\dgsize \scriptfont#1=\mF \let\dgsize=\sizemsscript \font\mF=\whichtfm{#2} at\dgsize \scriptscriptfont#1=\mF \let\dgsize=\undefined } \def\corrmsizes{\ptmunit=1\ptunit\relax} \def\setmathsizes[#1/#2/#3]{% \def\sizemtext{#1\ptmunit}\def\sizemscript{#2\ptmunit}% \def\sizemsscript{#3\ptmunit}% } \ifx\ptuint\undefined \def\ptunit{pt}\fi \ifx\ptmunit\undefined \csname newdimen\endcsname\ptmunit\fi \ptmunit=1\ptunit \ifx\sizemtext\undefined \setmathsizes[10/7/5]\fi \def\setmathdimens{% PlainTeX sets these dimens for 10pt size only: \delimitershortfall=0.5\fontdimen6\textfont3 \nulldelimiterspace=0.12\fontdimen6\textfont3 \scriptspace=0.05\fontdimen6\textfont3 \skewchar\textfont1=127 \skewchar\scriptfont1=127 \skewchar\scriptscriptfont1=127 \skewchar\textfont2=48 \skewchar\scriptfont2=48 \skewchar\scriptscriptfont2=48 } % load the fonts: \ifx\normalmathloading\relax\else \ifx\unimathfont\relax\else \normalmath \fi\fi \newcount\umathnumA \newcount\umathnumB \def\umathcorr#1#2{\expandafter#1\expandafter{\the#2}} \def\umathprepare#1{\def\umathscanholes##1[#1]##2##3\relax{##2}} \def\umathvalue#1{\expandafter\umathscanholes\umathcharholes[#1]{#1}\relax} \def\umathcharholes{% holes in math alphabets: [119893]{"210E}[119965]{"212C}[119968]{"2130}[119969]{"2131}% [119971]{"210B}[119972]{"2110}[119975]{"2112}[119976]{"2133}[119981]{"211B}% [119994]{"212F}[119996]{"210A}[120004]{"2134}% [120070]{"212D}[120075]{"210C}[120076]{"2111}[120085]{"211C}[120093]{"2128}% [120122]{"2102}[120127]{"210D}[120133]{"2115}[120135]{"2119} [120136]{"211A}[120137]{"211D}[120145]{"2124}% } \def\umathrange#1#2{\umathnumB=#2\relax \umathrangeA#1} \def\umathrangeA#1-#2{\umathnumA=`#1\relax \loop \umathcorr\umathprepare\umathnumB \Umathcode \umathnumA = 7 1 \umathcorr\umathvalue{\umathnumB} \ifnum\umathnumA<`#2\relax \advance\umathnumA by1 \advance\umathnumB by1 \repeat } \def\umathrangeGREEK{\begingroup \lccode`A="0391 \lccode`Z="03A9 \lowercase{\endgroup\umathrange{A-Z}}} \def\umathrangegreek{\begingroup \lccode`A="03B1 \lccode`Z="03D0 \lowercase{\endgroup\umathrange{A-Z}}} \def\greekdef#1{\ifx#1\relax \else \begingroup \lccode`X=\umathnumB \lowercase{\endgroup \def#1{X}}% \advance\umathnumB by 1 \expandafter\greekdef \fi } \umathnumB="0391 \greekdef \Alpha \Beta \Gamma \Delta \Epsilon \Zeta \Eta \Theta \Iota \Kappa \Lambda \Mu \Nu \Xi \Omicron \Pi \Rho \varTheta \Sigma \Tau \Upsilon \Phi \Chi \Psi \Omega \relax \umathnumB="03B1 \greekdef \alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \omicron \pi \rho \varsigma \sigma \tau \upsilon \varphi \chi \psi \omega \vardelta \varepsilon \vartheta \varkappa \phi \varrho \varpi \relax % Unfortunately, this order of Greek letters only holds for the Mathematical % Alphanumeric Symbols block; a couple of symbols are different in the Greek and % Coptic block. In particular, % % - GREEK CAPITAL THETA SYMBOL (\varTheta) is U+03F4 rather than U+03A2. % U+03A2 is unassigned. % % - PARTIAL DIFFERENTIAL (which is assigned to \varbeta here) is U+2202 rather % than U+03CA. U+03CA is GREEK SMALL LETTER IOTA WITH DIALYTIKA. % % - GREEK LUNATE EPSILON SYMBOL (which is assigned to \varepsilon here) is % U+03F5 rather than U+03CB. U+03CB is GREEK SMALL LETTER UPSILON WITH % DIALYTIKA. % % - GREEK THETA SYMBOL (\vartheta) is U+03D1 rather than U+03CC. U+03CC is % GREEK SMALL LETTER OMICRON WITH TONOS. % % - GREEK KAPPA SYMBOL (\varkappa) is U+03F0 rather than U+03CD. U+03CD is % GREEK SMALL LETTER UPSILON WITH TONOS. % % - GREEK PHI SYMBOL (the non-squiggly \phi) is U+03D5 rather than U+03CE. % U+03CE is GREEK SMALL LETTER OMEGA WITH TONOS. % % - GREEK RHO SYMBOL (\varrho) is U+03F1 rather than U+03CF. U+03CF is GREEK % CAPITAL KAI SYMBOL. % % - GREEK PI SYMBOL (\varpi) is U+03D6 rather than U+03D0. U+03D0 is GREEK % BETA SYMBOL. % % These macros apply these corrections. Fortunately, the characters they make % inaccessible are seldom used in mathematics typesetting. (They're also still % accessible in \textfont2 and \textfont3.) \def\umathfixgreekromanuppercase{% \Umathcode "03A2 = 7 1 "03F4 % \varTheta } \def\umathfixgreekromanlowercase{% \Umathcode "03CA = 7 1 "2202 % \varbeta \Umathcode "03CB = 7 1 "03F5 % \varepsilon \Umathcode "03CC = 7 1 "03D1 % \vartheta \Umathcode "03CD = 7 1 "03F0 % \varkappa \Umathcode "03CE = 7 1 "03D5 % \phi \Umathcode "03CF = 7 1 "03F1 % \varrho \Umathcode "03D0 = 7 1 "03D6 % \varpi } \chardef\ncharrmA=`A \chardef\ncharrma=`a \chardef\ncharbfA="1D400 \chardef\ncharbfa="1D41A \chardef\ncharitA="1D434 \chardef\ncharita="1D44E \chardef\ncharbiA="1D468 \chardef\ncharbia="1D482 \chardef\ncharclA="1D49C \chardef\ncharcla="1D4B6 \chardef\ncharbcA="1D4D0 \chardef\ncharbca="1D4EA \chardef\ncharfrA="1D504 \chardef\ncharfra="1D51E \chardef\ncharbrA="1D56C \chardef\ncharbra="1D586 \chardef\ncharbbA="1D538 \chardef\ncharbba="1D552 \chardef\ncharsnA="1D5A0 \chardef\ncharsna="1D5BA \chardef\ncharbsA="1D5D4 \chardef\ncharbsa="1D5EE \chardef\ncharsiA="1D608 \chardef\ncharsia="1D622 \chardef\ncharsxA="1D63C \chardef\ncharsxa="1D656 \chardef\ncharttA="1D670 \chardef\nchartta="1D68A \protected\def\rmvariables {\umathrange{A-Z}\ncharrmA \umathrange{a-z}\ncharrma} \protected\def\bfvariables {\umathrange{A-Z}\ncharbfA \umathrange{a-z}\ncharbfa} \protected\def\nitvariables {\umathrange{A-Z}\ncharitA \umathrange{a-z}\ncharita} \protected\def\bivariables {\umathrange{A-Z}\ncharbiA \umathrange{a-z}\ncharbia} \protected\def\calvariables {\umathrange{A-Z}\ncharclA \umathrange{a-z}\ncharcla} \protected\def\bcalvariables {\umathrange{A-Z}\ncharbcA \umathrange{a-z}\ncharbca} \protected\def\frakvariables {\umathrange{A-Z}\ncharfrA \umathrange{a-z}\ncharfra} \protected\def\bfrakvariables {\umathrange{A-Z}\ncharbrA \umathrange{a-z}\ncharbra} \protected\def\bbvariables {\umathrange{A-Z}\ncharbbA \umathrange{a-z}\ncharbba} \protected\def\sansvariables {\umathrange{A-Z}\ncharsnA \umathrange{a-z}\ncharsna} \protected\def\bsansvariables {\umathrange{A-Z}\ncharbsA \umathrange{a-z}\ncharbsa} \protected\def\isansvariables {\umathrange{A-Z}\ncharsiA \umathrange{a-z}\ncharsia} \protected\def\bisansvariables {\umathrange{A-Z}\ncharsxA \umathrange{a-z}\ncharsxa} \protected\def\ttvariables {\umathrange{A-Z}\ncharttA \umathrange{a-z}\nchartta} \chardef\greekrmA="0391 \chardef\greekrma="03B1 \chardef\greekbfA="1D6A8 \chardef\greekbfa="1D6C2 \chardef\greekitA="1D6E2 \chardef\greekita="1D6FC \chardef\greekbiA="1D71C \chardef\greekbia="1D736 \chardef\greeksnA="1D756 \chardef\greeksna="1D770 \chardef\greeksiA="1D790 \chardef\greeksia="1D7AA \protected\def\nitgreek{% \umathrangeGREEK\greekrmA \umathfixgreekromanuppercase \umathrangegreek\greekita } \protected\def\rmgreek{% \umathrangeGREEK\greekrmA \umathfixgreekromanuppercase \umathrangegreek\greekrma \umathfixgreekromanlowercase } \protected\def\bfgreek {\umathrangeGREEK\greekbfA \umathrangegreek\greekbfa} \protected\def\bigreek {\umathrangeGREEK\greekbfA \umathrangegreek\greekbia} \protected\def\sansgreek {\umathrangeGREEK\greeksnA \umathrangegreek\greeksna} \protected\def\isansgreek {\umathrangeGREEK\greeksnA \umathrangegreek\greeksia} % Another possibility (slanted capitals in \nitgreek, \bigreek, \isansgreek): %\protected\def\nitgreek {\umathrangeGREEK\greekitA \umathrangegreek\greekita} %\protected\def\rmgreek{% % \umathrangeGREEK\greekrmA \fixgreekromanuppercase % \umathrangegreek\greekrma \fixgreekromanlowercase %} %\protected\def\bfgreek {\umathrangeGREEK\greekbfA \umathrangegreek\greekbfa} %\protected\def\bigreek {\umathrangeGREEK\greekbiA \umathrangegreek\greekbia} %\protected\def\sansgreek {\umathrangeGREEK\greeksnA \umathrangegreek\greeksna} %\protected\def\isansgreek {\umathrangeGREEK\greeksiA \umathrangegreek\greeksia} \chardef\digitrmO=`0 \chardef\digitbfO="1D7CE \chardef\digitbbO="1D7D8 \chardef\digitsnO="1D7E2 \chardef\digitbsO="1D7EC \chardef\digitttO="1D7F6 \protected\def\rmdigits {\umathrange{0-9}\digitrmO} \protected\def\bfdigits {\umathrange{0-9}\digitbfO} \protected\def\bbdigits {\umathrange{0-9}\digitbbO} \protected\def\sansdigits {\umathrange{0-9}\digitsnO} \protected\def\bsansdigits {\umathrange{0-9}\digitbsO} \protected\def\ttdigits {\umathrange{0-9}\digitttO} \protected\def\inmath#1{\relax \ifmmode#1\fi} % to keep off \loop processing in text mode % You can redefine these macros to follow your wishes. % For example you need upgright lowercase greek letters, you don't need % \bf and \bi behaves as sans serif in math, ... \def\rm {\tenrm \inmath{\rmvariables \rmdigits}} \def\it {\tenit \inmath{\nitvariables}} \def\bf {\tenbf \inmath{\bsansvariables \sansgreek \bsansdigits}} \def\bi {\tenbi \inmath{\bisansvariables \isansgreek \bsansdigits}} \def\tt {\tentt \inmath{\ttvariables \ttdigits}} \def\bbchar {\bbvariables \bbdigits} \def\cal {\calvariables} \def\frak {\frakvariables} \def\misans {\isansvariables \isansgreek \sansdigits} \def\mbisans {\bisansvariables \isansgreek \bsansdigits} \def\script {\rmvariables \fam4 } % Math codes: \begingroup % \input MathClass.txt: \def\p#1;#2{\edef\tmp{\pB#2}\ifx\tmp\empty \else\pA#1....\end#2\fi} \def\pA#1..#2..#3\end#4{% \ifx\relax#2\relax \pset{"#1}{#4}\else \umathnumA="#1 \loop \pset{\umathnumA}{#4}% \ifnum\umathnumA<"#2 \advance\umathnumA by1 \repeat \fi } \def\pB#1{\if#1L1\fi \if#1B2\fi \if#1V2\fi \if#1R3\fi \if#1N0\fi \if#1U0\fi \if#1F0\fi \if#1O4\fi \if#1C5\fi \if#1P6\fi \if#1A7\fi} \def\pset#1#2{\global\Umathcode#1=\tmp\space 1 #1\relax \if#2O\global\Udelcode#1=1 #1\relax\fi \if#2C\global\Udelcode#1=1 #1\relax\fi \if#2F\global\Udelcode#1=1 #1\relax\fi } \catcode`#=14 \everypar={\setbox0=\lastbox \par \p} \input MathClass-15.txt \endgroup \begingroup % \input unicode-math-table.tex: \def\UnicodeMathSymbol #1#2#3#4{% \global\Umathcharnumdef#2=\Umathcodenum#1\relax \ifx#3\mathopen \gdef#2{\Udelimiter 4 1 #1 }\fi \ifx#3\mathclose \gdef#2{\Udelimiter 5 1 #1 }\fi \ifx#3\mathaccent \gdef#2{\Umathaccent fixed 7 1 #1 }\fi } \input unicode-math-table \endgroup \nitgreek \nitvariables \rmdigits % default setting \Umathcode `- = 2 1 "2212 \Umathcode `\/ = 0 1 "2215 \let\{=\lbrace \let\}=\rbrace \def\sqrt {\Uradical 1 "0221A } \def\cuberoot {\Uradical 1 "0221B } \def\fourthroot {\Uradical 1 "0221C } \def\intwithnolimits#1{\ifx#1\relax \escapechar=`\\ \else \escapechar=-1 \expandafter\let\csname\string#1op\endcsname=#1% \expandafter\def\expandafter#1\expandafter{\csname\string#1op\endcsname \nolimits}% \expandafter \intwithnolimits \fi } \intwithnolimits \int \iint \iiint \oint \oiint \oiiint \intclockwise \varointclockwise \ointctrclockwise \sumint \iiiint \intbar \intBar \fint \pointint \sqint \intlarhk \intx \intcap \intcup \upint \lowint \relax \def\vert {\Udelimiter 0 1 "07C } \def\Vert {\Udelimiter 0 1 "02016 } \def\Vvert {\Udelimiter 0 1 "02980 } \def\overbrace #1{\mathop {\Umathaccent 7 1 "023DE{#1}}\limits} \def\underbrace #1{\mathop {\Umathaccent bottom 7 1 "023DF{#1}}\limits} \def\overparen #1{\mathop {\Umathaccent 7 1 "023DC{#1}}\limits} \def\underparen #1{\mathop {\Umathaccent bottom 7 1 "023DD{#1}}\limits} \def\overbracket #1{\mathop {\Umathaccent 7 1 "023B4{#1}}\limits} \def\underbracket #1{\mathop {\Umathaccent bottom 7 1 "023B5{#1}}\limits} \def\widehat {\Umathaccent 7 1 "00302 } \def\widetilde {\Umathaccent 7 1 "00303 } \def\overleftharpoon {\Umathaccent 7 1 "020D0 } \def\overrightharpoon {\Umathaccent 7 1 "020D1 } \def\overleftarrow {\Umathaccent 7 1 "020D6 } \def\overrightarrow {\Umathaccent 7 1 "020D7 } \def\overleftrightarrow {\Umathaccent 7 1 "020E1 } % corrections: \mathchardef\ldotp="612E \let\|=\Vert \let\setminus=\smallsetminus \let\diamond=\smwhtdiamond \let\bullet=\smblkcircle \let\circ=\vysmwhtcircle \let\bigcirc=\mdlgwhtcircle \let\to=\rightarrow \let\le=\leq \let\ge=\geq \let\neq=\ne \protected\def\triangle{\mathord{\bigtriangleup}} \let\emptyset=\varnothing \let\hbar=\hslash \let\land=\wedge \let\lor=\vee \let\owns=\ni \let\gets=\leftarrow \let\mathring=\ocirc \let\lnot=\neg \let\longdivision=\longdivisionsign \let\backepsilon=\upbackepsilon \let\eth=\matheth \let\dbkarow=\dbkarrow \let\drbkarow=\drbkarrow \let\hksearow=\hksearrow \let\hkswarow=\hkswarrow \let\varepsilon=\epsilon \let\upalpha=\mupalpha \let\upbeta=\mupbeta \let\upgamma=\mupgamma \let\updelta=\mupdelta \let\upepsilon=\mupvarepsilon \let\upvarepsilon=\mupvarepsilon \let\upzeta=\mupzeta \let\upeta=\mupeta \let\uptheta=\muptheta \let\upiota=\mupiota \let\upkappa=\mupkappa \let\uplambda=\muplambda \let\upmu=\mupmu \let\upnu=\mupnu \let\upxi=\mupxi \let\upomicron=\mupomicron \let\uppi=\muppi \let\uprho=\muprho \let\upvarrho=\mupvarrho \let\upvarsigma=\mupvarsigma \let\upsigma=\mupsigma \let\uptau=\muptau \let\upupsilon=\mupupsilon \let\upvarphi=\mupvarphi \let\upchi=\mupchi \let\uppsi=\muppsi \let\upomega=\mupomega \let\upvartheta=\mupvartheta \let\upphi=\mupphi \let\upvarpi=\mupvarpi \protected\def\not#1{% \expandafter\ifx \csname not!\string#1\endcsname \relax \mathrel{\mathord{\rlap{\kern1pt/}}\mathord{#1}}% \else \csname not!\string#1\endcsname \fi } \def\negationof#1#2{\expandafter\let \csname not!\string#1\endcsname =#2} \negationof = \neq \negationof < \nless \negationof > \ngtr \negationof \gets \nleftarrow \negationof \simeq \nsime \negationof \equal \ne \negationof \le \nleq \negationof \ge \ngeq \negationof \greater \ngtr \negationof \forksnot \forks \negationof \in \notin % we need no more 8bit math fonts \let\loadmathfonts=\relax \endinput -------------------------------------------- You can combine more fonts, if you register them to another math families (5, 6, 7, etc.) in \normalmath macro. The default value of \normalmath shows a combination of base Unicode Math font with 8bit Math font at family 4. See definition of \script macro where \fam4 is used. Of course, we need to set \rmvariables too, because 8bit font accepts only codes less than 255. See http://tex.stackexchange.com/questions/308749/ for more technical details. The poor bold is used for complete bold vaiant of the font. If the selected font has its bold vaiant (like xits-math), you can re-define \boldmath macro by: \def\boldmath{% \loadumathfamily 1 {[xitsmath-bold]}{} % Base font \loadmathfamily 4 rsfs % script \setmathdimens } XITSmath-bold needs correction: the norm symbol ||x|| is missing here. So, you can define: \def\boldmath{% \loadumathfamily 1 {[xitsmath-bold]}{} % Base font \loadmathfamily 4 rsfs % script \loadumathfamily 5 {[xitsmath-regular]}{} \def\|{\Udelimiter 0 5 "02016 }% % norm delimiter from family 5 \setmathdimens }