%D \module %D [ file=math-ali, %D version=2008.10.20, %D title=\CONTEXT\ Math Macros, %D subtitle=Math Alignments, %D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan}, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Math Macros / Math Alignments} \unprotect \registerctxluafile{math-ali}{autosuffix} %D The code here has been moved from other files. Beware: the \MKII\ and \MKIV\ code %D is not gathered in files with the same name. In the meantime this code has been %D adapted to \MKIV\ but more is possible. The code is somewhat complicated by the %D fact that alignments are tricky with rspect to tagging. % export: % % alignment : ok % cases : % matrix : ok % substack : %D \macros %D {definemathalignment, setupmathalignment, startmathalignment} %D %D Modules may provide additional alignment features. The following kind of plain %D mechanisms are provided by the core. \newtoks\t_math_align_a \newtoks\t_math_align_b \newtoks\t_math_align_c \newskip\d_math_eqalign_distance \newskip\d_math_eqalign_rulethickness \protected\def\math_eqalign_distance {\relax \ifdim\d_math_eqalign_distance>\zeropoint % \hskip\d_math_eqalign_distance \tabskip\d_math_eqalign_distance \fi \mathalignmentparameter\c!separator \relax} \mutable\def\displayopenupvalue{.25\bodyfontsize} \def\math_build_eqalign {\scratchtoks\emptytoks \d_math_eqalign_distance\mathalignmentparameter\c!distance\relax \scratchcounterone\mathalignmentparameter\c!m \scratchcountertwo\mathalignmentparameter\c!n \etoksapp\scratchtoks{\the\t_math_align_a}% \scratchcounter\plusone \dorecurse{\numexpr\scratchcounterone*\scratchcountertwo-\plusone\relax} {\ifnum\scratchcounter=\scratchcountertwo \scratchcounter\plusone \etoksapp\scratchtoks{\math_eqalign_distance}% \etoksapp\scratchtoks{\global\c_math_eqalign_column\zerocount}% \else \advance\scratchcounter\plusone \fi \etoksapp\scratchtoks{\the\t_math_align_b}}% \etoksapp\scratchtoks{\the\t_math_align_c}} \def\math_math_in_eqalign#1% {\startforceddisplaymath \tabskip\zeropoint \everycr\emptytoks {{}#1{}}% \stopforceddisplaymath} \def\math_text_in_eqalign#1% {\startimath \tabskip\zeropoint \everycr\emptytoks #1% \stopimath} \permanent\protected\def\eqalign#1% why no halign here, probably because of displaywidth {\emptyhbox % why no \dontleavehmode \mskip\thinmuskip \vcenter {\math_openup\displayopenupvalue % was: \openup\jot \mathsurround\zeropoint \ialign{% \strut \hfil \startforceddisplaymath{\aligncontent}\stopforceddisplaymath \aligntab \startforceddisplaymath{{}\aligncontent{}}\stopforceddisplaymath \hfil\crcr #1\crcr}% }% \mskip\thinmuskip} % preamble is scanned for tabskips so we need the span to prevent an error message \setnewconstant\eqalignmode\plusone % use zeroskipplusfill \def\math_prepare_r_eqalign_no {\t_math_align_a {\strut \tabskip\zeropoint \aligncontent % for picking up the number \aligntab \math_first_in_eqalign \hfil \math_left_of_eqalign \span \math_math_in_eqalign{\aligncontent}% \math_right_of_eqalign \tabskip\zeropoint}% \t_math_align_b {\aligntab \math_next_in_eqalign \math_left_of_eqalign \span \math_math_in_eqalign{\aligncontent}% \math_right_of_eqalign \tabskip\zeropoint}% \ifnum\mathraggedstatus=\plusone \t_math_align_c {\hfil \aligntab \span \math_text_in_eqalign{\aligncontent}% \tabskip\zeropoint}% \orelse\ifnum\mathraggedstatus=\plusthree \t_math_align_c {\hfil \tabskip\zeropoint\s!plus 1\s!fill \aligntab \span \math_text_in_eqalign{\aligncontent}% \tabskip\zeropoint}% \else \t_math_align_c {\hfil \tabskip\centering \aligntab \span \llap{\math_text_in_eqalign{\aligncontent}}% \tabskip\zeropoint}% \fi \math_build_eqalign \the\mathdisplayaligntweaks \tabskip\centering} \def\math_prepare_l_eqalign_no % \checkeddisplaymath {\t_math_align_a {\strut \tabskip\zeropoint \aligncontent % for picking up the number \aligntab \math_first_in_eqalign \hfil \math_left_of_eqalign \span \math_math_in_eqalign{\aligncontent}% \math_right_of_eqalign \tabskip\zeropoint}% \t_math_align_b {\aligntab \math_next_in_eqalign \math_left_of_eqalign \span \math_math_in_eqalign{\aligncontent}% \math_right_of_eqalign \tabskip\zeropoint}% \ifnum\mathraggedstatus=\plusone \t_math_align_c {\hfil \aligntab \kern-\displaywidth \span \rlap{\math_text_in_eqalign{\aligncontent}} \tabskip\displaywidth}% \orelse\ifnum\mathraggedstatus=\plusthree \t_math_align_c {\hfil \tabskip\zeropoint\s!plus 1\s!fill \aligntab \kern-\displaywidth \span \math_rlap{\math_text_in_eqalign{\aligncontent}}% \tabskip\displaywidth}% \else \t_math_align_c {\hfil \tabskip\centering \aligntab \kern-\displaywidth \span \rlap{\math_text_in_eqalign{\aligncontent}}% \tabskip\displaywidth}% \fi \math_build_eqalign \the\mathdisplayaligntweaks \tabskip\centering} \def\math_halign_checked {\halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi} \def\math_both_eqalign_no_normal#1#2% {\ifmmode \the\mathdisplayaligntweaks \vcenter\bgroup \enforced\let\math_finish_eqalign_no\egroup \else \enforced\let\math_finish_eqalign_no\relax \fi #1% \math_halign_checked\expandafter\bgroup\the\scratchtoks\crcr#2\crcr\egroup \math_finish_eqalign_no} \installcorenamespace {mathalignlocation} \defcsname\??mathalignlocation\v!top \endcsname{\let\math_alignment_halign_method\halign\tpack} \defcsname\??mathalignlocation\v!bottom\endcsname{\let\math_alignment_halign_method\halign\vpack} \defcsname\??mathalignlocation\v!center\endcsname{\let\math_alignment_halign_method\halign\vcenter} \let\math_alignment_halign_method\relax \def\math_both_eqalign_no_aligned#1% {\let\math_alignment_halign_method\math_halign_checked \ifmmode \the\mathdisplayaligntweaks \global\mathnumberstatus\plusone \ifcase\mathraggedstatus \def\math_finish_eqalign_no{\crcr\egroup}% \else % we're in a mathbox \ifcsname\??mathalignlocation\mathalignmentparameter\c!location\endcsname \lastnamedcs % top|bottom|center as suggested by HM \else \vcenter \fi \bgroup \def\math_finish_eqalign_no{\crcr\egroup\egroup}% \fi \fi #1% \math_alignment_halign_method\expandafter\bgroup\the\scratchtoks\crcr} \def\math_rlap#1% {\setbox\scratchbox\hbox{#1}% \ifdim\wd\scratchbox>\d_math_number_correction \global\d_math_number_correction\wd\scratchbox \fi \box\scratchbox \global\mathnumberstatus\plustwo} \def\math_handle_eqalign_no_r_normal {\math_both_eqalign_no_normal \math_prepare_r_eqalign_no} \def\math_handle_eqalign_no_l_normal {\math_both_eqalign_no_normal \math_prepare_l_eqalign_no} \def\math_handle_eqalign_no_r_aligned{\math_both_eqalign_no_aligned\math_prepare_r_eqalign_no} \def\math_handle_eqalign_no_l_aligned{\math_both_eqalign_no_aligned\math_prepare_l_eqalign_no} \def\math_finish_eqalign_no {\crcr\egroup} \aliased\let\reqalignno\relax % just in case someone used that \aliased\let\leqalignno\relax % just in case someone used that \aliased\let\eqalignno \relax % just in case someone used that %D Here we implement the user interface part. We start with basic math alignments: \newcount \c_math_eqalign_column \newcount \c_math_eqalign_row \newconditional\c_math_eqalign_first \newtoks \everymathalignment \newtoks \everymathalignmentdone \permanent\tolerant\protected\def\math_alignment_NN[#1]#*[#2]% {\aligntab \strc_formulas_place_number_nested{#1}{#2}} \permanent\tolerant\protected\def\math_alignment_NR[#1]#*[#2]% {\aligntab \dostoptagged % finish cell \strc_formulas_place_number_nested{#1}{#2}% \math_number_right_of_eqalign \global\settrue\c_math_eqalign_first \crcr \noalign{\dostoptagged}} % finish row \permanent\protected\def\math_alignment_NC {\relax \ifconditional\c_math_eqalign_first \ifx\p_math_alignment_number\v!auto \strc_formulas_place_number_nested{+}{}% \fi \global\setfalse\c_math_eqalign_first \fi \math_number_left_of_eqalign \aligntab} \permanent\protected\def\math_alignment_EQ {\NC=} \noaligned\tolerant\protected\def\math_common_TB[#1]% {\noalign{\blank[#1]}} \installmacrostack\NC % maybe more to shared table definitions \installmacrostack\NN % maybe more to shared table definitions \installmacrostack\EQ % maybe more to shared table definitions \installmacrostack\NR % maybe more to shared table definitions \installmacrostack\BC % maybe more to shared table definitions \installmacrostack\EC % maybe more to shared table definitions \installmacrostack\TB % maybe more to shared table definitions \appendtoks \push_macro_NC \push_macro_NN \push_macro_EQ \push_macro_NR \push_macro_TB \enforced\let\NC\math_alignment_NC \enforced\let\NN\math_alignment_NN \enforced\let\EQ\math_alignment_EQ \enforced\let\NR\math_alignment_NR \enforced\let\TB\math_common_TB \global\settrue\c_math_eqalign_first \to \everymathalignment \appendtoks \pop_macro_TB \pop_macro_NR \pop_macro_EQ \pop_macro_NN \pop_macro_NC \to \everymathalignmentdone \let\math_alignment_snap_start\relax \let\math_alignment_snap_stop \relax % % experimental: % % \def\math_alignment_snap_start % {\ifgridsnapping % \edef\p_math_alignment_grid{\mathalignmentparameter\c!grid}% % \ifx\p_math_alignment_grid\v!no\else % \snaptogrid[\p_math_alignment_grid]\vbox\bgroup % \fi % \fi} % % \def\math_alignment_snap_stop % {\ifgridsnapping % \ifx\p_math_alignment_grid\v!no\else % \egroup % \fi % \fi} % % % doesn't work well, so: \let\math_alignment_snap_start\relax \let\math_alignment_snap_stop \relax % end of experimental \newconditional\c_math_alignment_auto_number % \begingroup not permitted ($$...assignments...\halign... ).. check in luametatex % \definemathmatrix % [pmatrix] % [matrix:parentheses] % % [align=1:right] % [align=all:right] % % [align=2:right] % % [align={1:left,2:middle,3:right}] \permanent\tolerant\protected\def\math_alignment_start[#1]#*[#2]% {\edef\currentmathalignment{#1}% \ifarguments\or\or \setupmathalignment[#1][#2]% bad! ungrouped \fi \math_alignment_snap_start \the\everymathalignment \c_math_eqalign_row \zerocount \c_math_eqalign_column\zerocount \edef\p_math_alignment_number{\mathalignmentparameter\c!number}% \processcommacommand [\mathalignmentparameter\c!align]% {\advance\c_math_eqalign_column\plusone\math_eqalign_set_column}% takes argument \global\c_math_eqalign_column\plusone \dostarttagged\t!math\empty \dostarttagged\t!mtable\currentmathalignment \numberedeqalign} \def\math_alignment_stop % can be protected {\math_finish_eqalign_no \dostoptagged \dostoptagged \the\everymathalignmentdone \math_alignment_snap_stop} \installcorenamespace{mathalignment} \installcorenamespace{mathalignmentvariant} \installcommandhandler \??mathalignment {mathalignment} \??mathalignment \appendtoks \frozen\protected\instance\edefcsname\e!start\currentmathalignment\endcsname{\math_alignment_start[\currentmathalignment]}% \noaligned\frozen\protected\instance \defcsname\e!stop \currentmathalignment\endcsname{\math_alignment_stop}% can this be protected now? \to \everydefinemathalignment % to be tested % % \appendtoks % \frozen\instance\protected\defcsname\e!start\currentmathalignment\endcsname{\math_alignment_start[\currentmathalignment]}% % \noaligned\frozen\instance\protected\defcsname\e!stop \currentmathalignment\endcsname{\math_alignment_stop}% % \to \everydefinemathalignment \setupmathalignment [\c!n=2, \c!m=1, \c!distance=\emwidth, \c!grid=\v!math] \definemathalignment[align] % default case (this is what amstex users expect) \definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing) % special case.. in case one mistypes .. \ifdefined \startalignment \pushoverloadmode \aliased\let\align_math_normal_start\startalign \aliased\let\align_math_normal_stop \stopalign \aliased\let\align_text_normal_start\startalignment \aliased\let\align_text_normal_stop \stopalignment \permanent\overloaded\protected\def\startalign {\ifmmode \enforced\let\stopalign\align_math_normal_stop % cannot be a protected def ... lookahead in align \expandafter\align_math_normal_start \orelse\ifinformula \enforced\let\stopalign\align_math_normal_stop \expandafter\align_math_normal_start \else \enforced\let\stopalign\align_text_normal_stop \expandafter\align_text_normal_start \fi} \aliased\let\stopalign\relax \permanent\overloaded\protected\def\startalignment {\ifmmode \enforced\let\stopalignment\align_math_normal_stop % cannot be a protected def ... lookahead in align \expandafter\align_math_normal_start \orelse\ifinformula \enforced\let\stopalignment\align_math_normal_stop % cannot be a protected def ... lookahead in align \expandafter\align_math_normal_start \else \enforced\let\stopalignment\align_text_normal_stop \expandafter\align_text_normal_start \fi} \aliased\let\stopalignment\relax \pushoverloadmode \fi % \permanent\protected\def\numberedeqalign {\doifelse{\formulaparameter\c!location}\v!left \math_handle_eqalign_no_l_aligned \math_handle_eqalign_no_r_aligned} \def\math_first_in_eqalign {\global\c_math_eqalign_column\plusone \global\advance\c_math_eqalign_row\plusone \dostarttagged\t!mtablerow \empty \dostarttagged\t!mtablecell\empty} \def\math_next_in_eqalign {\global\advance\c_math_eqalign_column\plusone \dostoptagged % finish cell \dostarttagged\t!mtablecell\empty} % \def\math_left_of_eqalign % {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname % \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi % \fi} % \def\math_right_of_eqalign % {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname % \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi % \fi} \def\math_left_of_eqalign {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi \orelse\ifcsname\??mathalignmentvariant\number\zerocount\endcsname \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi \fi} \def\math_right_of_eqalign {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi \orelse\ifcsname\??mathalignmentvariant\number\zerocount\endcsname \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi \fi} \newconditional\c_math_alignment_local_number % not used but when true puts in front (todo) \def\math_number_right_of_eqalign {\ifcase\wd\b_strc_formulas_number\else \ifconditional\c_math_alignment_local_number \ifcase\c_strc_math_number_location\or\or \box\b_strc_formulas_number \fi \else \box\b_strc_formulas_number \fi \fi} \def\math_number_left_of_eqalign {\ifcase\wd\b_strc_formulas_number\else \ifconditional\c_math_alignment_local_number \ifcase\c_strc_math_number_location\or \box\b_strc_formulas_number \fi \fi \fi} % \def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments) % {\expandafter\chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\expandafter\expandafter\endcsname % \ifcsname\??mathalignmentvariant#1\endcsname\lastnamedcs\else\zerocount\fi\relax} % \def\math_eqalign_set_column_indeed[#1:#2:#3]% we don't really check for all (so * will do too) ... yet % {\expandafter\chardef\csname\??mathalignmentvariant\number % \ifcstok{#2}\emptytoks\c_math_eqalign_column\orelse\ifchknum#1\or#1\else\zerocount\fi % \endcsname % \ifcsname\??mathalignmentvariant#2\endcsname\lastnamedcs\else\zerocount\fi\relax} \def\math_eqalign_set_column_indeed[#1:#2:#3]% we don't really check for all (so * will do too) ... yet {\ifcstok{#2}\emptytoks % current counter \orelse\ifchknum#1\or \c_math_eqalign_column#1\relax \else \c_math_eqalign_column\zerocount \fi \chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname \ifcsname\??mathalignmentvariant#2\endcsname\lastnamedcs\else\zerocount\fi\relax} \def\math_eqalign_set_column#1% {\normalexpanded{\math_eqalign_set_column_indeed[#1::]}} \letcsname\??mathalignmentvariant\v!normal\endcsname\zerocount \letcsname\??mathalignmentvariant\v!left \endcsname\plusone \letcsname\??mathalignmentvariant\v!right \endcsname\plustwo \letcsname\??mathalignmentvariant\v!middle\endcsname\plusthree \permanent\protected\def\math_align_NR_generic[#1][#2]% {\strc_formulas_place_number_nested{#1}{#2}\crcr} %D \starttyping %D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0] %D \placeformula[eqn1]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn1] %D \placeformula \startformula \startalign[n=1] a\NR[eqn2] \stopalign \stopformula See \in[eqn2] %D \placeformula[eqn3]\startformula \startalign[n=1] a\NR[+] \stopalign \stopformula See \in[eqn3] %D \stoptyping %D \startbuffer %D \placeformula \startformula \eqalignno { %D a &= b & \formulanumber \cr %D c &= d \cr %D &= e \cr %D &= f & \formulanumber %D } \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula \startalign %D \NC a \EQ b \NR[+] %D \NC c \EQ d \NR %D \NC \EQ f \NR[for:demo-a-1] %D \NC \EQ g \NR[for:demo-a-2][a] %D \NC \EQ h \NR[for:demo-a-3][b] %D \NC \EQ i \NR %D \stopalign \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula \startalign %D \NC a \EQ b \NR[+] %D \NC c \EQ d \NR %D \NC \EQ f \NR %D \NC \EQ g \NR %D \NC \EQ h \NR %D \NC \EQ i \NR[+] %D \stopalign \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula \startalign %D \NC a \NC \eq b \NR[+] %D \NC c \NC \neq d \NR %D \NC \NC \neq f \NR[for:demo-b-1] %D \NC \NC \geq g \NR[for:demo-b-2][a] %D \NC \NC \leq h \NR[for:demo-b-3][b] %D \NC \NC \neq i \NR %D \stopalign \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula \startalign[n=3,align={left,middle,right}] %D \NC l \NC = \NC r \NR %D \NC left \NC = \NC right \NR %D \stopalign \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula \startalign[n=3,align={right,middle,left}] %D \NC l \NC = \NC r \NR %D \NC left \NC = \NC right \NR %D \stopalign \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula \startalign[n=3,align={middle,middle,middle}] %D \NC l \NC = \NC r \NR %D \NC left \NC = \NC right \NR %D \stopalign \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula %D \startformula %D \startalign[n=3,align={middle,middle,middle}] %D \NC a \NC = \NC b \NR[+] %D \NC 2a \NC = \NC 2b \NR %D \stopalign %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula %D \startformulas %D \setupmathalignment[n=3,align={middle,middle,middle}]% %D \startformula %D \startalign %D \NC a \NC = \NC b \NR[+] %D \NC 2a \NC = \NC 2b \NR %D \stopalign %D \stopformula %D \startformula %D \startalign %D \NC a \NC = \NC b \NR[+] %D \NC 2a \NC = \NC 2b \NR %D \stopalign %D \stopformula %D \stopformulas %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula %D \startformulas %D \dorecurse{5}{\startformula %D \startalign[n=3,align={middle,middle,middle}] %D \NC a \NC = \NC b \NR[+] %D \NC 2a \NC = \NC 2b \NR %D \stopalign %D \stopformula} %D \stopformulas %D \stopbuffer %D %D \typebuffer \getbuffer %D \macros %D {definemathcases, setupmathcases, startmathcases} %D %D Another wish \unknown \installcorenamespace{mathcases} \installcommandhandler \??mathcases {mathcases} \??mathcases \setupmathcases [\c!distance=\emwidth, \c!strut=\v!yes, % new %\c!numberdistance=2.5\emwidth, \c!numberdistance=\zeropoint, % pending an extension wrt placement (Aditya/Hans) \c!left={\left\{\mskip\thinmuskip}, \c!right={\right.}] \appendtoks \frozen\instance\protected\edefcsname\e!start\currentmathcases\endcsname{\math_cases_start[\currentmathcases]}% \frozen\instance \defcsname \e!stop \currentmathcases\endcsname{\math_cases_stop}% \to \everydefinemathcases % \permanent\protected\def\math_cases_NC_zero % {\math_cases_NC} % % \permanent\protected\def\math_cases_MC_zero % {\math_cases_NC % \ifmmode\else % \startimath % \enforced\let\math_cases_end_math\stopimath % \fi} % % \let\math_cases_end_math\relax % % \permanent\protected\def\math_cases_NR_zero % {\unskip % \math_cases_end_math % \aligntab % \global\enforced\let\math_cases_NC\math_cases_NC_first % \dodirectdoubleempty\math_cases_NR} % % \permanent\protected\def\math_cases_NC_first % {\global\enforced\let\math_cases_NC\math_cases_NC_second} % % \permanent\protected\def\math_cases_NC_second % {\math_cases_end_math\aligntab} % % \let\math_cases_NR\math_align_NR_generic % % \installmacrostack\math_cases_NC % % \let\math_cases_strut\relax % % \permanent\tolerant\protected\def\math_cases_start[#1]#*[#2]% % {\begingroup % \edef\currentmathcases{#1}% % \ifarguments\or\or % \setupcurrentmathcases[#2]% % \fi % \edef\p_strut{\mathcasesparameter\c!strut}% % \ifx\p_strut\v!yes % \enforced\let\math_cases_strut\strut % \else % \enforced\let\math_cases_strut\relax % \fi % \mathcasesparameter\c!left % \vcenter\bgroup % \push_macro_math_cases_NC % \enforced\let\MC\math_cases_MC_zero % \enforced\let\NR\math_cases_NR_zero % \enforced\let\TB\math_common_TB % \enforced\glet\math_cases_NC\math_cases_NC_first % \normalbaselines % \mathsurround\zeropoint % \everycr\emptytoks % \tabskip\zeropoint % \global\c_math_eqalign_column\plusone % \halign\bgroup % \startimath % \mathcasesparameter\c!style % \aligncontent % \stopimath % \hfil % \aligntab % \hskip\mathcasesparameter\c!distance\relax % \pop_macro_math_cases_NC % \math_cases_strut % looks better % \aligncontent % \hfil % \aligntab % \hskip\mathcasesparameter\c!numberdistance\relax % % \let\formuladistance\!!zeropoint % \span\math_text_in_eqalign{\aligncontent}% % \crcr} % todo: number % % % When we have just protected we get an extra row but we can no flag % % this as a proper alignment related command which means that uit gets % % expanded. % % \noaligned\permanent\protected\def\math_cases_stop % {\crcr % \egroup % \pop_macro_math_cases_NC % \egroup % \mathcasesparameter\c!right % \endgroup} \let\math_cases_strut\relax \newcount\c_math_cases_nc \def\math_cases_NC_zero {\ifmmode\else\startimath\fi} \def\math_cases_NC_one {\ifmmode\stopimath\fi \aligntab \ifmmode\else\startimath\fi} \def\math_cases_NC_two {\ifmmode\stopimath\fi} \def\math_cases_TC_zero {} \def\math_cases_TC_one {\ifmmode\stopimath\fi \aligntab} \permanent\protected\def\math_cases_NC {\ifcase\c_math_cases_nc \expandafter\math_cases_NC_zero \or \expandafter\math_cases_NC_one \or \expandafter\math_cases_NC_zero \else % error \fi \global\advance\c_math_cases_nc\plusone} \permanent\protected\def\math_cases_TC {\ifcase\c_math_cases_nc \expandafter\math_cases_TC_zero \or \expandafter\math_cases_TC_one \or \expandafter\math_cases_TC_two \else % error \fi \global\advance\c_math_cases_nc\plusone} \noaligned\tolerant\permanent\protected\def\math_cases_NR[#1]#*[#2]% {\unskip \ifmmode\stopimath\fi \aligntab \global\c_math_cases_nc\zerocount \math_align_NR_generic[#1][#2]} \installglobalmacrostack\c_math_cases_nc \permanent\tolerant\protected\def\math_cases_start[#1]#*[#2]% {\begingroup \edef\currentmathcases{#1}% \ifarguments\or\or \setupcurrentmathcases[#2]% \fi \edef\p_strut{\mathcasesparameter\c!strut}% \ifx\p_strut\v!yes \enforced\let\math_cases_strut\strut \else \enforced\let\math_cases_strut\relax \fi \push_macro_c_math_cases_nc \mathcasesparameter\c!left \vcenter\bgroup \enforced\let\MC\math_cases_NC \enforced\let\NC\math_cases_NC \enforced\let\NR\math_cases_NR \enforced\let\TC\math_cases_TC \enforced\let\TB\math_common_TB \normalbaselines \mathsurround\zeropoint \everycr\emptytoks \tabskip\zeropoint \global\c_math_eqalign_column\plusone \global\c_math_eqalign_row\plusone \global\c_math_cases_nc\zerocount \halign\bgroup \ifmmode\else\startimath\fi \mathcasesparameter\c!style \aligncontent \ifmmode\stopimath\fi \hfil \aligntab \hskip\mathcasesparameter\c!distance\relax \math_cases_strut % looks better \aligncontent \hfil \aligntab \hskip\mathcasesparameter\c!numberdistance\relax \span\math_text_in_eqalign{\aligncontent}% \crcr} % todo: number \noaligned\permanent\protected\def\math_cases_stop {\crcr \egroup \egroup \mathcasesparameter\c!right \pop_macro_c_math_cases_nc \endgroup} \definemathcases[cases] \definemathcases[\v!mathcases] %D \startbuffer %D \placeformula \startformula \startcases %D \NC 2 \NC $ y > 0 $ \NR %D \NC 7 \NC $ x = 7 $ \NR[+] %D \NC 4 \NC otherwise \NR %D \stopcases \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula x \startcases %D \NC 2 \NC $ y > 0 $ \NR[+] %D \NC 7 \NC $ x = 7 $ \NR %D \NC 4 \NC otherwise \NR %D \stopcases \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula \startcases %D \NC 2 \NC $ y > 0 $ \NR %D \NC 7 \NC $ x = 7 $ \NR %D \NC 4 \NC otherwise \NR %D \stopcases \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \placeformula \startformula x \startcases %D \NC 2 \NC $ y > 0 $ \NR %D \NC 7 \NC $ x = 7 $ \NR %D \NC 4 \NC otherwise \NR %D \stopcases \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D \macros %D {definemathmatrix, setupmathmatrix, startmathmatrix} %D %D Yet another one \unknown. This time we implement the lot a bit %D different which is a side effect of getting the tagging right. In %D retrospect the main alignment could be done this way but \unknown \installcorenamespace{mathmatrix} \installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix \setupmathmatrix [\c!distance=\emwidth, \c!left=, \c!right=, \c!align=\v!middle, \c!rulecolor=, \c!rulethickness=\linewidth] \appendtoks \frozen\instance\protected\edefcsname\e!start\currentmathmatrix\endcsname{\math_matrix_start[\currentmathmatrix]}% % \noaligned\protected should work here: \frozen\instance \defcsname \e!stop \currentmathmatrix\endcsname{\math_matrix_stop}% no u else lookahead problem \to \everydefinemathmatrix \def\math_matrix_start_table {\global\c_math_eqalign_column\zerocount \global\c_math_eqalign_row\zerocount \dostarttagged\t!math\empty \dostarttagged\t!mtable\empty} \def\math_matrix_stop_table {\dostoptagged \dostoptagged} % \def\math_matrix_start_row % {\noalign{\global\c_math_eqalign_column\zerocount}% % \dostarttagged\t!mtablerow\empty} % % \def\math_matrix_stop_row % {\dostoptagged} \def\math_matrix_start_row {\beginlocalcontrol \global\c_math_eqalign_column\zerocount \global\advance\c_math_eqalign_row\plusone \dostarttagged\t!mtablerow\empty \endlocalcontrol} \def\math_matrix_stop_row {\beginlocalcontrol \dostoptagged \endlocalcontrol} \protected\def\math_matrix_start_cell {\dostarttagged\t!mtablecell\empty \hss \math_left_of_eqalign \startimath \math_matrix_set_style \tabskip\zeropoint \everycr\emptytoks} \protected\def\math_matrix_stop_cell {\stopimath \math_right_of_eqalign \hss \dostoptagged} % We could construct a preamble with alignment and such embedded but the number % of matrices with many rows is normally so low that it doesn't pay of at all. \newconditional\c_math_matrix_first \newconstant \c_math_matrix_anchor_mode % enabled : 1 % left/both : 2 % right/both : 4 % \c_math_matrix_anchor_mode3 \permanent\protected\def\setmathmatrixanchoring[#1]% {\c_math_matrix_anchor_mode\zerocount \processaction [#1] [ \v!left=>\bitwiseflip\c_math_matrix_anchor_mode\numexpr\plusone+\plustwo\relax, \v!right=>\bitwiseflip\c_math_matrix_anchor_mode\numexpr\plusone+\plusfour\relax, \v!both=>\bitwiseflip\c_math_matrix_anchor_mode\numexpr\plusone+\plustwo+\plusfour\relax, \v!yes=>\bitwiseflip\c_math_matrix_anchor_mode\numexpr\plusone]} \def\math_matrix_anchor {\ifbitwiseand\c_math_matrix_anchor_mode\plusone \markanchor{matrix}{\numexpr\c_math_eqalign_column+1\relax}\c_math_eqalign_row \fi} \protected\def\math_matrix_distance {\relax \ifdim\d_math_eqalign_distance>\zeropoint \hskip.5\d_math_eqalign_distance \fi \math_matrix_anchor \ifdim\d_math_eqalign_distance>\zeropoint \hskip.5\d_math_eqalign_distance \fi \relax} \protected\def\math_matrix_distance_first {\relax \ifbitwiseand\c_math_matrix_anchor_mode\plusone \math_matrix_anchor \fi \ifdim\d_math_eqalign_distance>\zeropoint \ifbitwiseand\c_math_matrix_anchor_mode\plustwo \hskip.5\d_math_eqalign_distance \fi \fi \relax} \protected\def\math_matrix_distance_last {\relax \ifdim\d_math_eqalign_distance>\zeropoint \ifbitwiseand\c_math_matrix_anchor_mode\plusfour \hskip.5\d_math_eqalign_distance \fi \fi \ifbitwiseand\c_math_matrix_anchor_mode\plusone \math_matrix_anchor \fi \relax} \def\math_matrix_preamble {\math_matrix_strut \math_matrix_distance_first \global\advance\c_math_eqalign_column\plusone \math_matrix_start_cell \aligncontent \math_matrix_stop_cell \aligntab \aligntab \math_matrix_distance \global\advance\c_math_eqalign_column\plusone \math_matrix_start_cell \aligncontent \math_matrix_stop_cell} \permanent\protected\def\math_matrix_NR {\aligntab\omit \math_matrix_distance_last \math_matrix_stop_row \math_matrix_pickup \crcr \math_matrix_start_row} \permanent\protected\def\math_matrix_NC {\ifconditional\c_math_matrix_first \expandafter\math_matrix_NC_yes \else \expandafter\math_matrix_NC_nop \fi} \permanent\protected\def\math_matrix_pickup{\global\settrue \c_math_matrix_first} \permanent\protected\def\math_matrix_NC_yes{\global\setfalse\c_math_matrix_first} \permanent\protected\def\math_matrix_NC_nop{\aligntab} % avoids lookahead % \def\math_matrix_stop_wrapup % {\crcr % \strut % \crcr % \noalign{\vskip-\struthtdp}} \def\math_matrix_check_rule_step#1% {\doifelsenumber{#1} {\scratchdimen#1\d_math_eqalign_rulethickness} {\edef\p_rulecolor{#1}}} \def\math_matrix_check_rule[#1]% {\d_math_eqalign_rulethickness\mathmatrixparameter\c!rulethickness\relax \scratchdimen\d_math_eqalign_rulethickness \edef\p_rulecolor{\mathmatrixparameter\c!rulecolor}% \iftok{#1}\emptytoks\else \rawprocesscommalist[#1]\math_matrix_check_rule_step \fi \ifempty\p_rulecolor\else \dousecolorparameter\p_rulecolor \fi} \noaligned\permanent\tolerant\protected\def\math_matrix_HL[#1]#*% {\noalign\bgroup \math_matrix_check_rule[#1]% \divide\scratchdimen\plustwo \autorule\s!height\scratchdimen\s!depth\scratchdimen\relax \egroup} \permanent\tolerant\protected\def\math_matrix_VL[#1]#*% {\NC \math_matrix_check_rule[#1]% \divide\d_math_eqalign_distance\plustwo \hskip-\d_math_eqalign_distance \autorule\s!width\scratchdimen\relax \hskip-\d_math_eqalign_distance \NC} \newtoks\everymathmatrix \appendtoks \enforced\let\NR\math_matrix_NR \enforced\let\NC\math_matrix_NC \enforced\let\MC\math_matrix_NC \enforced\let\HL\math_matrix_HL \enforced\let\VL\math_matrix_VL \enforced\let\TB\math_common_TB \to \everymathmatrix \def\math_matrix_start_processing {\dontleavehmode \bgroup \tabskip\zeropoint \math_matrix_pickup \the\everymathmatrix % % \enforced\let\endmath\relax % \setbox\nextbox\vbox\bgroup \math_matrix_start_table \halign \bgroup % preamble \span\math_matrix_preamble % done \crcr \math_matrix_start_row} \def\math_matrix_stop_processing {%\math_matrix_stop_wrapup % optional \math_matrix_stop_row \egroup \math_matrix_stop_table \egroup \mathmatrixleft \math_matrix_finish_nextbox \mathmatrixright \egroup} \let\math_matrix_strut \strut \let\math_matrix_set_style\relax \def\math_matrix_check_settings {\edef\p_strut{\mathmatrixparameter\c!strut}% \ifx\p_strut\v!no \enforced\let\math_matrix_strut\relax \else \enforced\let\math_matrix_strut\strut \ifx\p_strut\v!yes\else \spacing\p_strut \fi \fi \d_math_eqalign_distance\mathmatrixparameter\c!distance\relax % \d_math_eqalign_rulethickness\mathmatrixparameter\c!rulethickness\relax % \edef\p_rulecolor{\mathmatrixparameter\c!rulecolor} \edef\math_matrix_set_style{\mathmatrixparameter\c!style}} \def\math_matrix_set_defaults {\normalbaselines % hm, spacing ? \mathsurround\zeropoint \tabskip\zeropoint} \def\math_matrix_set_columns_step {\advance\c_math_eqalign_column\plusone %\c_math_matrix_columns\c_math_eqalign_column \math_eqalign_set_column} \def\math_matrix_set_columns {\c_math_eqalign_column\zerocount \rawprocesscommacommand[\mathmatrixparameter\c!align]\math_matrix_set_columns_step} \newcount\c_math_eqalign_column_saved \newcount\c_math_eqalign_row_saved % \installglobalmacrostack\c_math_matrix_first \tolerant\protected\def\math_matrix_start[#1]#*[#2]% {\begingroup \globalpushmacro\c_math_matrix_first % hm, does that work? \c_math_eqalign_column_saved\c_math_eqalign_column \c_math_eqalign_row_saved\c_math_eqalign_row \globalpushmacro\c_math_eqalign_first \edef\currentmathmatrix{#1}% \setupcurrentmathmatrix[#2]% \math_matrix_check_settings \math_matrix_set_defaults \math_matrix_set_columns \math_matrix_start_processing} \def\math_matrix_stop {\math_matrix_stop_processing \globalpushmacro\c_math_eqalign_first \global\c_math_eqalign_column\c_math_eqalign_column_saved \global\c_math_eqalign_row\c_math_eqalign_row_saved \globalpopmacro\c_math_matrix_first \endgroup} % vcenter: % % delta = (height(v) + depth(v))/2 % axis = math_axis_size(cur_size) % height(v) = delta + axis % depth(v) = delta - axis \installcorenamespace{mathmatrixalignlocation} \mutable\let\mathmatrixleft \empty % experimental hook \mutable\let\mathmatrixright\empty % experimental hook \defcsname\??mathmatrixalignlocation\v!top \endcsname{\raise\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax} \defcsname\??mathmatrixalignlocation\v!high \endcsname{\raise\dimexpr(\nextboxdp-\nextboxht)/2\relax} \defcsname\??mathmatrixalignlocation\v!center\endcsname{\relax} \defcsname\??mathmatrixalignlocation\v!lohi \endcsname{\relax} \defcsname\??mathmatrixalignlocation\v!normal\endcsname{\relax} \defcsname\??mathmatrixalignlocation\v!bottom\endcsname{\lower\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax} \defcsname\??mathmatrixalignlocation\v!low \endcsname{\lower\dimexpr(\nextboxdp-\nextboxht)/2\relax} \def\math_matrix_finish_nextbox {\begincsname\??mathmatrixalignlocation\mathmatrixparameter\c!location\endcsname\hbox\bgroup \normalstartimath \mathmatrixparameter\c!left \vcenter{\box\nextbox}% \mathmatrixparameter\c!right \normalstopimath \egroup} \definemathmatrix[matrix] \definemathmatrix[\v!mathmatrix] %D \startbuffer %D \placeformula \startformula[-] \startmatrix %D \NC 1 \NC x \NC a \NR %D \NC 2 \NC y \NC b \NR %D \NC 3 \NC z \NC c \NR %D \stopmatrix \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \definemathmatrix[bmatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]},strut=1.25] %D %D \startbuffer %D \placeformula \startformula[-] \startbmatrix %D \NC 1 \NC x \NC a \NR %D \NC 2 \NC y \NC b \NR %D \NC 3 \NC z \NC c \NR %D \stopbmatrix \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D Taco added some code (dedicated to Aditya Mahajan) that gives more %D control over aligments: %D \startbuffer %D \startformula %D \startmatrix %D \NC a + x \NC = \NC a + d \NR %D \NC y \NC = \NC d \NR %D \stopmatrix %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D \startbuffer %D \startformula %D \startmatrix [distance=3pt,align={right,left}] %D \NC a + x \NC = a + d \NR %D \NC y \NC = d \NR %D \stopmatrix %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D \startbuffer %D \startformula %D \startmatrix [left=\left(,right=\right)] %D \NC a + x \NR %D \NC y \NR %D \stopmatrix %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D A bit more complex code: %D %D \startbuffer %D \startformula %D \text{Let }{\cal R} = \bigcup_{P_{X_1},P_{X_2}} %D \left\{ (R_1, R_2) : %D \startmatrix[distance=1em,align={left,left,right}] %D \NC R_1 \NC < I(X_1 ; Y \mid X_2) \NC R_1 \NR %D \NC \hfill Q_2 \NC < I(X_2 ; Y \mid X_1) \NC R_2 \NR %D \NC R_1 + R_2 \NC < I(X_1 ; Y) \NC R_1 + R_2 \NR %D \stopmatrix %D \right\} %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D \macros %D {startmatrices} %D %D Just a handy keystroke safer: \permanent\protected\def\startmatrices {\begingroup \setupmathmatrix} \permanent\protected\def\stopmatrices {\endgroup} %D \startbuffer %D \startformula %D \startmatrix[left={\left(},right={\right)}] %D \NC A \NC B \NR \NC C \NC D \NR %D \stopmatrix %D = %D \startmatrix[left={\left(},right={\right)},location=low] %D \NC A \NC B \NR \NC C \NC D \NR %D \stopmatrix %D = %D \startmatrix[left={\left(},right={\right)},location=high] %D \NC A \NC B \NR \NC C \NC D \NR %D \stopmatrix %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \startformula %D \startmatrices[left={\left(},right={\right)}] %D \startmatrix %D \NC A \NC B \NR \NC C \NC D \NR %D \stopmatrix %D = %D \startmatrix[location=bottom] %D \NC A \NC B \NR \NC C \NC D \NR %D \stopmatrix %D = %D \startmatrix[location=top] %D \NC A \NC B \NR \NC C \NC D \NR %D \stopmatrix %D \stopmatrices %D \stopformula %D \stopbuffer %D %D \typebuffer % does not run well: \getbuffer %D Handy for the \type {m-matrix} module: \permanent\tolerant\protected\def\startnamedmatrix[#1]#*[#2]% {\begingroup \edef\currentmathmatrix{#1}% \setupcurrentmathmatrix[#2]% \math_matrix_start[\currentmathmatrix]} \noaligned\permanent\protected\def\stopnamedmatrix {\math_matrix_stop \endgroup} %D The following code is derived from Aditya's simplematrix prototype but adapted to %D regular mathmatrices: % We keep this as reference: % % \def\math_matrix_simple_row#1% % {\rawprocesscommalist[#1]\math_matrix_simple_col % \toksapp\scratchtoks{\NR}} % % \def\math_matrix_simple_col#1% % {\toksapp\scratchtoks{\NC#1}} % % \permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#2]#:#3% % {\begingroup % \edef\currentmathmatrix{#1}% % \setupcurrentmathmatrix[#2]% % \scratchtoks\emptytoks % \processlist[];\math_matrix_simple_row[#3]% % \math_matrix_start[\currentmathmatrix]% % \the\scratchtoks % \math_matrix_stop % \endgroup} %D With a little help from \LUA\ we now have this: %D %D \startbuffer %D \definemathmatrix [Pmatrix] [matrix:parentheses] %D [align={all:right}, %D simplecommand=Pmatrix] %D %D \definemathmatrix [Tmatrix] [Pmatrix] %D [action=transpose, %D simplecommand=Tmatrix] %D %D \definemathmatrix [Nmatrix] [Pmatrix] %D [action=negate, %D simplecommand=Nmatrix] %D %D \startformula %D \Pmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 } \neq %D \Tmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 } \neq %D \Nmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 } %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer \permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#2]#:#3% {\begingroup \edef\currentmathmatrix{#1}% \setupcurrentmathmatrix[#2]% \math_matrix_start[\currentmathmatrix]% \clf_simplematrix{\mathmatrixparameter\c!action}{#3}% \math_matrix_stop \endgroup} %D We hook it into the normal mathmatrix code: \appendtoks \edef\p_simplecommand{\mathmatrixparameter\c!simplecommand}% \ifempty\p_simplecommand\else \frozen\protected\instance\edefcsname\p_simplecommand\endcsname{\math_matrix_simple[\currentmathmatrix]}% \fi \to \everydefinemathmatrix %D And predefine some matrices: \definemathmatrix[matrix:parentheses][\c!left={\left(\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right)},\c!align=\v!middle] \definemathmatrix[matrix:brackets] [\c!left={\left[\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right]},\c!align=\v!middle] \definemathmatrix[matrix:bars] [\c!left={\left|\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right|},\c!align=\v!middle] \definemathmatrix[thematrix][matrix:parentheses][\c!simplecommand=thematrix] %D \startbuffer %D \startformula %D \thematrix{1,2,3,4;5,6,7,8;9,10,11,12} %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D %D \startbuffer %D \startformula %D \startthematrix %D \NC 1\NC 2\NC 3\NC 4\NR %D \NC 5\NC 6\NC 7\NC 8\NR %D \NC 9\NC10\NC11\NC12\NR %D \stopthematrix %D \stopformula %D \stopbuffer %D %D \typebuffer \getbuffer %D \macros %D {startintertext} %D %D Preliminary feature: %D %D {\em example code} %D %D The intertext commands have to be expandable (in aligment lookahead) so %D we cannot use \type {\protected}. \permanent\def\startintertext#1\stopintertext {\noalign{\math_intertext{#1}}} \permanent\let\stopintertext\relax \permanent\def\intertext#1% {\noalign{\math_intertext{#1}}} \protected\def\math_intertext#1% {\penalty\postdisplaypenalty \afterdisplayspace \vbox{\forgetall\noindent#1\par}% \penalty\predisplaypenalty \beforedisplayspace} %D \macros %D {substack} %D %D Preliminary code: %D %D \startbuffer %D \startformula %D \sum_{% %D \startsubstack %D i = 1 \NR %D i \neq n \NR %D i \neq m %D \stopsubstack %D }a_i %D \stopformula %D \stopbuffer %D %D \getbuffer which was typed as \typebuffer %D %D Notice that these macros give the correct spacing for %D subscripts. Compare for example %D %D \startbuffer %D \startformula %D \sum_{\startsubstack a \NR b \NR \stopsubstack} %D \text{ and } %D \sum_{\scriptstyle a \atop \scriptstyle} %D \stopformula %D \stopbuffer %D %D \typebuffer which gives \getbuffer % no tagging yet : how is it supposed to be coded? \permanent\protected\def\startsubstack {\begingroup \vcenter\bgroup \baselineskip\mathstacktotal \lineskip\mathstackvgap \lineskiplimit\lineskip \mathsurround\zeropoint \everycr\emptytoks \enforced\let\NC\relax \enforced\let\MC\relax \enforced\let\NR\crcr \halign\bgroup\hfil\normalstartimath\scriptstyle\aligncontent\normalstopimath\hfil\crcr} \noaligned\permanent\protected\def\stopsubstack {\crcr \egroup \egroup \endgroup} % %D \macros % %D {bordermatrix} % %D % %D In \PLAIN\ \TEX\ the width of a parenthesis is stored in % %D the \DIMENSION\ \type{\mathparentwd}. This value is derived from % %D the width of \type{\tenrm B}, so let's take care of it now: % % \ifdefined\mathparentwd \else \newdimen\mathparentwd \fi % % \let\normalbordermatrix\bordermatrix % move that code to here instead % % \protected\def\bordermatrix % {\begingroup % \setbox\scratchbox\hbox{\mr\char"239C}% % \global\mathparentwd\wd\scratchbox % \endgroup % \normalbordermatrix} % % \def\bordermatrix % {\begingroup % \mr % \global\mathparentwd\fontcharwd\font"239C\relax % \endgroup % \normalbordermatrix} %D \macros{overset, underset} %D %D The macros \type{\overset} and \type{\underset} are provided by %D \AMS\ packages in \LATEX. These macro allows you to place a symbol %D above or below another symbol, irrespective of whether the other %D symbol is a relation or something else, and without influencing the %D spacing. For most cases there is a better way to do such things %D (declaring a math command with limop option, or using accents), but %D occasionally these macros can be useful, for example: %D %D \startbuffer %D \startformula %D \overset{*}{X} \underset{*}{X} %D \stopformula %D \stopbuffer %D \typebuffer \getbuffer %D %D Use these macros sparingly. Remember, \TEX\ was designed for %D mathematics, so there is usually a proper method for typesetting %D common math notation. %D %D These macros are a cleaner version of \type {\binrel@} and %D \type {\binrel@@} macros in \AMSTEX\ packages. \def\math_binrel_apply#1% {\begingroup \setbox\scratchbox\hbox {\thinmuskip 0mu \medmuskip -1mu \thickmuskip -1mu \setbox\scratchbox\hbox{\normalstartimath#1\mathsurround\zeropoint\normalstopimath}% \kern-\wd\scratchbox \normalstartimath{}#1{}\mathsurround\zeropoint\normalstopimath}% \ifdim\wd\scratchbox<\zeropoint \endgroup \expandafter\mathbin \orelse\ifdim\wd\scratchbox>\zeropoint \endgroup \doubleexpandafter\mathrel \else \endgroup \doubleexpandafter\firstofoneargument \fi} \permanent\protected\def\overset#1#2% {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}} \permanent\protected\def\underset#1#2% {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsubscript {#1}}} %D The following code comes from \type {math-str.mkiv}. %D %D Here we implement a basic math alignment mechanism. Numbers are also handled. The macros %D \type {\startinnermath} and \type {\stopinnermath} can be overloaded in specialized %D modules. \installcorenamespace{mathinnerstart} \installcorenamespace{mathinnerstop} % \protected\def\startinnermath{\csname\??mathinnerstart\formulaparameter\c!align\endcsname} % \protected\def\stopinnermath {\csname\??mathinnerstop \formulaparameter\c!align\endcsname} \permanent\protected\def\startinnermath{\expandnamespaceparameter\??mathinnerstart\formulaparameter\c!align\v!normal} \permanent\protected\def\stopinnermath {\expandnamespaceparameter\??mathinnerstop \formulaparameter\c!align\v!normal} \permanent\protected\def\mathinnerstrut {\doif{\formulaparameter\c!strut}\v!yes\strut} \permanent\protected\def\defineinnermathhandler#1#2#3% {\defcsname\??mathinnerstart#1\endcsname{#2}% \defcsname\??mathinnerstop #1\endcsname{#3}} \installtextracker {formulas.boxes} {\enforced\let\math_hbox\ruledhbox} {\enforced\let\math_hbox\hbox} \let\math_hbox\hbox \newconstant\mathraggedstatus % normal left center right \newconstant\mathnumberstatus % nothing normal shift_right \newdimen\d_math_number_correction \def\math_box_llapped_math_no {\ifcase\mathraggedstatus\or \box\b_strc_formulas_number \or \llap{\box\b_strc_formulas_number}% \or \llap{\box\b_strc_formulas_number}% \fi} \def\math_box_rlapped_math_no {\ifcase\mathraggedstatus\or \rlap{\box\b_strc_formulas_number}% \or \rlap{\box\b_strc_formulas_number}% \or \box\b_strc_formulas_number \fi} \newconditional\c_strc_math_has_number \newconditional\c_strc_math_display_overflow \newconstant \c_strc_math_number_location \newdimen \d_strc_math_number_width \newdimen \d_strc_math_display_width \newbox \b_strc_math_display \newconstant \c_strc_formulas_frame_mode \newdimen \d_strc_math_indent \newconditional\c_strc_math_indent \newdimen\d_strc_math_framed_width \defcsname\??formulaoption\v!frame\endcsname {\edef\p_frame{\formulaparameter\c!frame}% \ifx\p_frame\v!number \c_strc_formulas_frame_mode\plustwo % inside frame \else \c_strc_formulas_frame_mode\plusone % outside frame \fi} % mode: 0=no frame | 1=number inside frame | 2=number outside frame \def\strc_math_flush_aligned {\ifcase\c_strc_math_vertical \ifcase\mathraggedstatus\or\hfill\or\hfill\fi \box\b_strc_math_display \ifcase\mathraggedstatus\or\or\hfill\or\hfill\fi \else \ifconditional\c_strc_math_indent \ifzeropt\d_strc_math_indent\else \hangafter\plusone \hangindent\d_strc_math_indent \fi \fi \edef\p_interlinespace{\formulaparameter\c!interlinespace}% \ifempty\p_interlinespace\else\baselineskip\p_interlinespace\fi \global\d_strc_math_indent\zeropoint \ifcase\mathraggedstatus\or\raggedleft\or\raggedcenter\or\raggedright\fi \unhbox\b_strc_math_display \fi} \def\strc_math_flush_box_normal {\ifcase\c_strc_math_vertical \hbox to \displaywidth\bgroup \strc_math_flush_aligned \egroup \else \strc_math_flush_aligned \fi} \def\strc_math_flush_box_framed_common {\d_strc_math_framed_width\displaywidth \setformulaframedparameter\c!align{\formulaparameter\c!align}% \letformulaframedparameter\c!strut\v!no \d_framed_formula\ht\b_strc_math_display \ifcase\mathraggedstatus\or\hfill\or\hfill \fi \inheritedformulaframedframed{\box\b_strc_math_display}% \ifcase\mathraggedstatus\or \or\hfill\or\hfill\fi} \def\strc_math_flush_box_framed_display {\let\currentformulaframed\currentformula \letformulaframedparameter\c!location\v!formula \setformulaframedparameter\c!width{\d_strc_math_framed_width}% \strc_math_flush_box_framed_common} \def\strc_math_flush_box_framed_fit_inline {\let\currentformulaframed\currentformula \letformulaframedparameter\c!location\empty \letformulaframedparameter\c!width\v!fit \strc_math_flush_box_framed_common} \def\strc_math_flush_box_framed_fit_display {\let\currentformulaframed\currentformula \letformulaframedparameter\c!location\v!formula \letformulaframedparameter\c!width\v!fit \strc_math_flush_box_framed_common} % combiners \def\strc_math_flush_box {\ifcase\c_strc_formulas_frame_mode \strc_math_flush_box_normal \else \strc_math_flush_box_framed_display \fi} \def\strc_math_number_right_normal {\strc_math_flush_aligned \hss % hss makes room for number \math_box_llapped_math_no} \def\strc_math_number_left_normal {\math_box_rlapped_math_no \strc_math_flush_aligned \hss} % hss makes room for number \def\strc_math_number_right_normal_outside {\ifconditional\c_strc_formulas_tight \strc_math_flush_box_framed_fit_display \else \strc_math_flush_box_framed_display \fi \hss % hss makes room for number \math_box_llapped_math_no} \def\strc_math_number_left_normal_outside {\math_box_rlapped_math_no \hss % hss makes room for number \ifconditional\c_strc_formulas_tight \strc_math_flush_box_framed_fit_display \else \strc_math_flush_box_framed_display \fi} \def\strc_math_number_right_normal_inside {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup \strc_math_flush_aligned \hss \math_box_llapped_math_no \egroup \strc_math_flush_box_framed_fit_inline} \def\strc_math_number_left_normal_inside {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup \math_box_rlapped_math_no \hss \strc_math_flush_aligned \egroup \strc_math_flush_box_framed_fit_inline} \def\strc_math_number_right_overflow {\vpack\bgroup \strc_math_flush_box \par \hpack to \displaywidth\bgroup \hss \math_box_llapped_math_no \egroup \egroup} \def\strc_math_number_left_overflow {\vpack\bgroup \hpack to \displaywidth\bgroup \math_box_rlapped_math_no \hss \egroup \strc_math_flush_box \egroup} \def\strc_math_number_right_overflow_outside {\vpack\bgroup \strc_math_flush_box_framed_fit_inline %\hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why \hpack to \displaywidth\bgroup \hss \math_box_llapped_math_no \egroup \egroup} \def\strc_math_number_left_overflow_outside {\vpack\bgroup \hpack to \dimexpr\displaywidth-\d_framed_locator_lo\relax\bgroup \math_box_rlapped_math_no \hss \egroup \hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why \strc_math_flush_box_framed_fit_inline \egroup} \def\strc_math_number_right_overflow_inside {\setbox\b_strc_math_display\vpack\bgroup \box\b_strc_math_display \hpack to \displaywidth\bgroup \hss \math_box_llapped_math_no \hskip\d_framed_locator_ro \egroup \egroup \strc_math_flush_box_framed_fit_inline} \def\strc_math_number_left_overflow_inside {\setbox\b_strc_math_display\vpack\bgroup \hpack to \displaywidth\bgroup % \hskip\d_framed_locator_lo \math_box_rlapped_math_no \hss \egroup \box\b_strc_math_display \egroup \strc_math_flush_box_framed_fit_inline} % checkers \def\strc_math_number_check {\d_strc_math_display_width\wd\b_strc_math_display \ifconditional\c_strc_formulas_tight \ifdim\d_strc_math_display_width>\displaywidth \settrue\c_strc_math_display_overflow \else \displaywidth\d_strc_math_display_width \setfalse\c_strc_math_display_overflow \fi \else \ifdim\d_strc_math_display_width>\displaywidth \settrue\c_strc_math_display_overflow \else \setfalse\c_strc_math_display_overflow \fi \fi} \def\strc_math_number_check_outside {\d_strc_math_display_width\naturalwd\b_strc_math_display \ifdim\dimexpr\d_strc_math_display_width+\d_framed_locator_lo+\d_framed_locator_ro\relax>\displaywidth \settrue\c_strc_math_display_overflow \else \setfalse\c_strc_math_display_overflow \fi % still ok? \ifnum\mathraggedstatus=\plustwo \d_strc_math_framed_width\dimexpr\displaywidth-2\wd\b_strc_formulas_number\relax \else \d_strc_math_framed_width\dimexpr\displaywidth- \wd\b_strc_formulas_number\relax \fi} \let\strc_math_number_check_inside\strc_math_number_check_outside % offsets \def\strc_math_number_check_offsets {\begingroup \setbox\scratchbox\hbox {\inheritedformulaframedframed {\pack_framed_locator_set_lo\pack_framed_locator_set_ro}}% \endgroup} % tracing \def\strc_math_traced_state_yes {\llap{\setbox\scratchbox\hbox{\infofont \ifcase\mathraggedstatus unset\or right\or middle\or left\fi \space \ifcase\c_strc_formulas_frame_mode no\or out\or in\fi \space \ifconditional\c_strc_math_display_overflow overflow\else fit\fi \quad}\ht\scratchbox\zeropoint\dp\scratchbox\zeropoint\box\scratchbox}} \let\strc_math_traced_state\relax \installtextracker {formulas.framed} {\let\strc_math_traced_state\strc_math_traced_state_yes} {\let\strc_math_traced_state\relax} % packaging \protected\def\strc_math_box_start#1% {\hsize\displaywidth % \checkeddisplaymath \global\mathnumberstatus\plusone \mathraggedstatus#1\relax % \global\d_math_number_correction\zeropoint % \edef\p_location{\formulaparameter\c!location}% \useformulacolorparameter\c!color \c_strc_math_number_location\ifx\p_location\v!left\plusone\orelse\ifx\p_location\v!right\plustwo\else\zerocount\fi % %\strc_formulas_place_number % not here as we can have inner alignment numbers \dontcomplain \setbox\b_strc_math_display\math_hbox\bgroup % \checkeddisplaymath \mathinnerstrut \startforceddisplaymath} \def\strc_math_flush_number_no {\ifcase\c_strc_math_vertical \ifconditional\c_strc_math_display_overflow \ifcase\c_strc_formulas_frame_mode \strc_math_flush_box_normal \else \strc_math_flush_box_framed_fit_inline \fi \else \ifcase\c_strc_formulas_frame_mode %\ifconditional\c_strc_formulas_tight % \strc_math_flush_box_normal %\else \strc_math_flush_box_normal %\fi \else \ifconditional\c_strc_formulas_tight \strc_math_flush_box_framed_fit_inline \else \strc_math_flush_box_framed_display \fi \fi \fi \else \strc_math_flush_box \fi} \def\strc_math_flush_number_left {\ifcase\c_strc_math_vertical \ifconditional\c_strc_math_display_overflow \ifcase\c_strc_formulas_frame_mode \strc_math_number_left_overflow \or \strc_math_number_left_overflow_outside \or \strc_math_number_left_overflow_inside \fi \else \ifcase\c_strc_formulas_frame_mode \strc_math_number_left_normal \or \strc_math_number_left_normal_outside \or \strc_math_number_left_normal_inside \fi \fi \else \box\b_strc_formulas_number \hfill \strc_math_flush_aligned \fi} \def\strc_math_flush_number_right {\ifcase\c_strc_math_vertical \ifconditional\c_strc_math_display_overflow \ifcase\c_strc_formulas_frame_mode \strc_math_number_right_overflow \or \strc_math_number_right_overflow_outside \or \strc_math_number_right_overflow_inside \fi \else \ifcase\c_strc_formulas_frame_mode \strc_math_number_right_normal \or \strc_math_number_right_normal_outside \or \strc_math_number_right_normal_inside \fi \fi \else \strc_math_flush_aligned \hfill \box\b_strc_formulas_number \fi} \protected\def\strc_math_box_stop {\stopforceddisplaymath \egroup % check number \d_strc_math_number_width\wd\b_strc_formulas_number % \ifcase\mathnumberstatus \setfalse\c_strc_math_has_number \or\ifzeropt\d_strc_math_number_width \setfalse\c_strc_math_has_number \else \settrue\c_strc_math_has_number \fi\fi % preroll left and right offsets \ifcase\c_strc_formulas_frame_mode % no frame \else \strc_math_number_check_offsets \fi \ifcase\c_strc_formulas_frame_mode \strc_math_number_check \or \strc_math_number_check_outside \else \strc_math_number_check_inside \fi \noindent % \noindentation % not \dontleavehmode \hskip\d_strc_formulas_display_margin_left % was kern but that doesn't indent \strc_math_traced_state \ifcase\c_strc_math_vertical \hbox to \displaywidth \bgroup \or \vbox \bgroup \hsize\displaywidth \or \bgroup \hsize\displaywidth \fi \ifcase\mathnumberstatus \strc_math_flush_box \or % status 1 \ifcase\c_strc_math_number_location \strc_math_flush_box \or % number left \ifzeropt\wd\b_strc_formulas_number \strc_math_flush_number_no \else \strc_math_flush_number_left \fi \else % number right \ifzeropt\wd\b_strc_formulas_number \strc_math_flush_number_no \else \strc_math_flush_number_right \fi \fi \or % status 2 \hskip\d_math_number_correction % probably no longer used \strc_math_flush_box \hss \else \strc_math_flush_box \fi \ifcase\c_strc_math_vertical \or \or \par \fi \egroup} \defineinnermathhandler\v!left {\strc_math_box_start\plusone }{\strc_math_box_stop} \defineinnermathhandler\v!middle {\strc_math_box_start\plustwo }{\strc_math_box_stop} \defineinnermathhandler\v!right {\strc_math_box_start\plusthree}{\strc_math_box_stop} \defineinnermathhandler\v!flushleft {\strc_math_box_start\plusthree}{\strc_math_box_stop} \defineinnermathhandler\v!center {\strc_math_box_start\plustwo }{\strc_math_box_stop} \defineinnermathhandler\v!flushright{\strc_math_box_start\plusone }{\strc_math_box_stop} \defineinnermathhandler\v!normal {\strc_math_box_start\plustwo }{\strc_math_box_stop} %D Some inline math tweak. \appendtoks \ifcase\mathnestinglevel\or % 4=disable 6=only when no spaces \mathsurroundskip\mathematicsparameter\c!textdistance\relax \ifzeropt\mathsurroundskip \ifzeropt\gluestretch\mathsurroundskip \ifzeropt\glueshrink\mathsurroundskip \mathsurroundmode\plussix \else \mathsurroundskip\zeropoint \mathsurroundmode\plusfour \fi \else \mathsurroundmode\plussix \fi \else \mathsurroundmode\plussix \fi \else \mathsurroundmode\plusfour \mathsurroundskip\zeropoint \fi \to \everymathematics \setupmathematics [\c!textdistance=\zeropoint] %D This is an experiment. No fancy spacing and alignments here. If we ever %D go that route it might result in incompatible rendering. \permanent\protected\def\startsplitformula {\ifhmode \par \fi \begingroup \beforedisplayspace % subset of \everydisplay: \c_attr_mathmode\plusone \settrue \indisplaymath % end of subset \informulatrue} \permanent\protected\def\stopsplitformula {\afterdisplayspace \endgroup} %D Kind of new (February 2022): \installcorenamespace {maththreshold} \setupmathematics[\c!threshold=\zeropoint] \permanent\protected\def\installmaththreshold#1#2% {\expandafter\gluespecdef\csname\??maththreshold#1\endcsname#2\relax} \installmaththreshold\v!none {\zeropoint} \installmaththreshold\v!small {3\emwidth plus 0.50\emwidth minus 0.25\emwidth} \installmaththreshold\v!medium{4\emwidth plus 0.75\emwidth minus 0.50\emwidth} \installmaththreshold\v!big {5\emwidth plus 1.00\emwidth minus 0.75\emwidth} \appendtoks \edef\p_threshold{\mathematicsparameter\c!threshold}% \maththreshold\ifcsname\??maththreshold\p_threshold\endcsname\lastnamedcs\else\p_threshold\fi\relax \to \everymath % \everyemathematics \protect \endinput % \placeformula \startformula[-] \startmatrix % \NC 1 \NC x \NC a \NR % \NC 2 \NC y \NC b \NR % \NC 3 \NC z \NC c \NR % \stopmatrix \stopformula % \definemathmatrix[bordermatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}] % \placeformula \startformula[-] \startbordermatrix % \NC 1 \NC x \NC a \NR % \NC 2 \NC y \NC b \NR % \NC 3 \NC z \NC c \NR % \stopbordermatrix \stopformula