%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 %D The code here has been moved from other files. Beware: the \MKII\ and %D \MKIV\ code is not gathered in files with the same name. In the %D meantime this code has been adapted to \MKIV\ but mnore is possible. %D \macros %D {definemathalignment, setupmathalignment, startmathalignment} %D %D Modules may provide additional alignment features. The following %D mechanisms are provided by the core. % n>1 ### needed, strange # interaction in recurse \newtoks\c_math_align_a \newtoks\c_math_align_b \newtoks\c_math_align_c \def\displayopenupvalue{.25\bodyfontsize} \def\math_build_eqalign {\scratchtoks\emptytoks \dorecurse{\mathalignmentparameter\c!m}\math_build_eqalign_step \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_c}}} \def\math_build_eqalign_step {\ifnum\recurselevel>\plusone \scratchtoks\expandafter{\the\scratchtoks\tabskip\mathalignmentparameter\c!distance\aligntab\tabskip\zeropoint}% \fi \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_a}}% \dorecurse{\numexpr\mathalignmentparameter\c!n-\plusone\relax} {\normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_b}}}} \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} \def\eqalign#1% why no halign here, probably because of displaywidth {\emptyhbox \mskip\thinmuskip \vcenter {\math_openup\displayopenupvalue % was: \openup\jot \mathsurround\zeropoint \ialign{% \strut \hfil \startforceddisplaymath{\alignmark\alignmark}\stopforceddisplaymath \aligntab \startforceddisplaymath{{}\alignmark\alignmark{}}\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 % i really need to redo this eqno mess ... in lua \def\math_prepare_r_eqalign_no {\c_math_align_a{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{\alignmark\alignmark}\math_right_of_eqalign\tabskip\zeropoint}% \c_math_align_b{\aligntab\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{\alignmark\alignmark}\math_right_of_eqalign\tabskip\zeropoint}% \ifnum\mathraggedstatus=\plusone \c_math_align_c{\hfil\aligntab\span\math_text_in_eqalign{\alignmark\alignmark}\tabskip\zeropoint}% \else\ifnum\mathraggedstatus=\plusthree \c_math_align_c{\hfil\tabskip\zeropoint\s!plus 1\s!fill\aligntab\span\math_text_in_eqalign{\alignmark\alignmark}\tabskip\zeropoint}% \else \c_math_align_c{\hfil\tabskip\centering\aligntab\llap{\span\math_text_in_eqalign{\alignmark\alignmark}}\tabskip\zeropoint}% \fi\fi \global\mathnumberstatus\zerocount \math_build_eqalign \the\mathdisplayaligntweaks \tabskip\centering} \def\math_prepare_l_eqalign_no % \checkeddisplaymath {\c_math_align_a{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{\alignmark\alignmark}\math_right_of_eqalign\tabskip\zeropoint}% \c_math_align_b{\aligntab\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{\alignmark\alignmark}\math_right_of_eqalign\tabskip\zeropoint}% % problem: number is handled after rest and so ends up in the margin \ifnum\mathraggedstatus=\plusone \c_math_align_c{\hfil\aligntab\kern-\displaywidth\rlap{\span\math_text_in_eqalign{\alignmark\alignmark}}\tabskip\displaywidth}% \else\ifnum\mathraggedstatus=\plusthree \c_math_align_c{\hfil\tabskip\zeropoint\s!plus 1\s!fill\aligntab\kern-\displaywidth\span\math_rlap{\span\math_text_in_eqalign{\alignmark\alignmark}}\tabskip\displaywidth}% \else \c_math_align_c{\hfil\tabskip\centering\aligntab\kern-\displaywidth\rlap{\span\math_text_in_eqalign{\alignmark\alignmark}}\tabskip\displaywidth}% \fi\fi \global\mathnumberstatus\zerocount \math_build_eqalign \the\mathdisplayaligntweaks \tabskip\centering} \def\math_both_eqalign_no_normal#1#2% {\ifmmode \the\mathdisplayaligntweaks % \let\strc_formulas_place_number\relax % strange hack \vcenter\bgroup \let\math_finish_eqalign_no\egroup \else \let\math_finish_eqalign_no\relax \fi #1% \halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi \expandafter {\the\scratchtoks\crcr#2\crcr}% \math_finish_eqalign_no} \def\math_both_eqalign_no_aligned#1% {\ifmmode \the\mathdisplayaligntweaks \global\mathnumberstatus\plusone \ifcase\mathraggedstatus \def\math_finish_eqalign_no{\crcr\egroup}% \else % we're in a mathbox \vcenter\bgroup \def\math_finish_eqalign_no{\crcr\egroup\egroup}% \fi \fi #1% \halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi \expandafter \bgroup\the\scratchtoks\crcr} \def\math_rlap#1% {\setbox\scratchbox\hbox{#1}% \ifdim\wd\scratchbox>\mathnumbercorrection \xdef\mathnumbercorrection{\the\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} \let \reqalignno \math_handle_eqalign_no_r_normal \let \leqalignno \math_handle_eqalign_no_l_normal \let\alignreqalignno \math_handle_eqalign_no_r_aligned \let\alignleqalignno \math_handle_eqalign_no_l_aligned \let \eqalignno \math_handle_eqalign_no_r_normal \let \aligneqalignno \math_handle_eqalign_no_r_aligned %D Here we implement the user interface part. We start with basic math alignments: \newcount\c_math_eqalign_column \newtoks \everymathalignment \def\math_alignment_NR_indeed[#1][#2]% {\strc_formulas_place_number_nested{#1}{#2}% to be tagged (better an attribute) \crcr \dostoptagged % finish row \noalign{\glet\math_alignment_NC\math_alignment_NC_first}} % noalign used for change state, conditional does not work here \def\math_alignment_NC_first {\glet\math_alignment_NC\math_alignment_NC_rest} \def\math_alignment_NC_rest {\aligntab} \def\math_alignment_EQ {\NC=} \def\math_alignment_NR {\aligntab \dostoptagged % finish cell \dodoubleempty\math_alignment_NR_indeed} % use xx from tabulate \appendtoks \glet\math_alignment_NC\math_alignment_NC_first \unexpanded\def\NC{\math_alignment_NC}% messy, due to lookahead (we cannot use a flag) \let\EQ\math_alignment_EQ \let\NR\math_alignment_NR \to \everymathalignment \let\math_alignment_snap_start\relax \let\math_alignment_snap_stop \relax % experimental \def\math_alignment_snap_start {\ifgridsnapping \snaptogrid[\v!both]\vbox\bgroup \fi} \def\math_alignment_snap_stop {\ifgridsnapping \egroup \fi} % end of experimental \unexpanded\def\math_alignment_start#1% {\edef\currentmathalignment{#1}% \dosingleempty\math_alignment_start_indeed} \def\math_alignment_start_indeed[#1]% {% \begingroup not permitted ($$...assignments...\halign... ) \math_alignment_snap_start \iffirstargument \setupmathalignment[\currentmathalignment][#1]% bad! ungrouped \fi \the\everymathalignment \c_math_eqalign_column\zerocount \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!mathtable\currentmathalignment \numberedeqalign} \def\math_alignment_stop {\math_finish_eqalign_no \dostoptagged \dostoptagged \math_alignment_snap_stop} \installcorenamespace{mathalignment} \installcorenamespace{mathalignmentvariant} \installcommandhandler \??mathalignment {mathalignment} \??mathalignment \appendtoks \setuevalue{\e!start\currentmathalignment}{\math_alignment_start{\currentmathalignment}}% \setvalue {\e!stop \currentmathalignment}{\math_alignment_stop}% \to \everydefinemathalignment \setupmathalignment [\c!n=2, \c!m=1, \c!distance=\emwidth] \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 \let\align_math_normal_start\startalign \let\align_math_normal_stop \stopalign \let\align_text_normal_start\startalignment \let\align_text_normal_stop \stopalignment \unexpanded\def\startalign {\ifmmode \let\stopalign\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align \expandafter\align_math_normal_start \else \let\stopalign\align_text_normal_stop \expandafter\align_text_normal_start \fi} \let\stopalign\relax \unexpanded\def\startalignment {\ifmmode \let\stopalignment\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align \expandafter\align_math_normal_start \else \let\stopalignment\align_text_normal_stop \expandafter\align_text_normal_start \fi} \let\stopalignment\relax \fi % \unexpanded\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 \dostarttagged\t!mathtablerow \empty \dostarttagged\t!mathtablecell\empty} \def\math_next_in_eqalign {\global\advance\c_math_eqalign_column\plusone \dostoptagged % finish cell \dostarttagged\t!mathtablecell\empty} \def\math_left_of_equalign {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname \ifcase\csname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname\or \relax \or \hfill \or \hfill \fi \fi} \def\math_right_of_eqalign {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname \ifcase\csname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname\or \hfill \or \relax \or \hfill \fi \fi} \def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments) {\expandafter\let\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\endcsname \csname\??mathalignmentvariant\ifcsname\??mathalignmentvariant#1\endcsname#1\else\v!normal\fi\endcsname} \letvalue{\??mathalignmentvariant\v!normal}\zerocount \letvalue{\??mathalignmentvariant\v!left }\plusone \letvalue{\??mathalignmentvariant\v!right }\plustwo \letvalue{\??mathalignmentvariant\v!middle}\plusthree \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!left={\left\{\mskip\thinmuskip}, \c!right={\right.}] \appendtoks \setuevalue{\e!start\currentmathcases}{\math_cases_start{\currentmathcases}}% \setvalue {\e!stop \currentmathcases}{\math_cases_stop}% \to \everydefinemathcases \unexpanded\def\math_cases_start#1% {\begingroup \edef\currentmathcases{#1}% \dosingleempty\math_cases_start_indeed} \def\math_cases_NC_zero {\math_cases_NC} \def\math_cases_MC_zero {\math_cases_NC \ifmmode\else \startimath \let\math_cases_end_math\stopimath \fi} \let\math_cases_end_math\relax \def\math_cases_NR_zero {\unskip \math_cases_end_math \aligntab \global\let\math_cases_NC\math_cases_NC_first \dodirectdoubleempty\math_cases_NR} \def\math_cases_NC_first {\global\let\math_cases_NC\math_cases_NC_second} \def\math_cases_NC_second {\math_cases_end_math\aligntab} \let\math_cases_NR\math_align_NR_generic \unexpanded\def\math_cases_start_indeed[#1]% {\iffirstargument \setupcurrentmathcases[#1]% \fi \edef\p_strut{\mathcasesparameter\c!strut}% \ifx\p_strut\v!yes \let\math_cases_strut\strut \else \let\math_cases_strut\relax \fi \mathcasesparameter\c!left \vcenter\bgroup \pushmacro\math_cases_NC \let\endmath\relax \let\NC\math_cases_NC_zero \let\MC\math_cases_MC_zero \let\NR\math_cases_NR_zero \global\let\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 \alignmark\alignmark \stopimath \hfil \aligntab \hskip\mathcasesparameter\c!distance\relax \popmacro\math_cases_NC \math_cases_strut % looks better \alignmark\alignmark \hfil \aligntab \hskip\mathcasesparameter\c!numberdistance\relax \let\formuladistance\!!zeropoint \span\math_text_in_eqalign{\alignmark\alignmark}% \crcr} % todo: number \def\math_cases_stop {\crcr \egroup \popmacro\math_cases_NC \egroup \mathcasesparameter\c!right \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 \installcorenamespace{mathmatrix} \installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix \setupmathmatrix [\c!distance=\emwidth, \c!left=, \c!right=, \c!align=\v!middle] \appendtoks \setuevalue{\e!start\currentmathmatrix}{\math_matrix_start{\currentmathmatrix}}% \setvalue {\e!stop \currentmathmatrix}{\math_matrix_stop}% no u else lookahead problem \to \everydefinemathmatrix \let\math_matrix_NC\relax \unexpanded\def\math_matrix_start#1% {\begingroup \edef\currentmathmatrix{#1}% \dosingleempty\math_matrix_start_indeed} \unexpanded\def\math_matrix_start_indeed[#1]% {\iffirstargument \setupcurrentmathmatrix[#1]% \fi % \emptyhbox % noted at 25-05-2014: what was that one doing here? it messed up spacing \math_matrix_align_method_analyze \mathmatrixleft % new per 13-10-2014 \edef\p_strut{\mathmatrixparameter\c!strut}% \ifx\p_strut\v!no \let\m_matrix_strut\relax \else \let\m_matrix_strut\strut \ifx\p_strut\v!yes\else \spacing\p_strut \fi \fi % \mathmatrixbox\bgroup \pushmacro\math_matrix_NC \let\endmath\relax \def\NC{\math_matrix_NC}% \def\MC{\math_matrix_NC\ifmmode\else\startimath\let\endmath\stopimath\fi}% \global\let\math_matrix_NC\math_matrix_NC_indeed \def\NR{\endmath\global\let\math_matrix_NC\math_matrix_NC_indeed\m_matrix_strut \crcr}% \normalbaselines \mathsurround\zeropoint \everycr\emptytoks \tabskip\zeropoint \c_math_eqalign_column\zerocount \processcommacommand [\mathmatrixparameter\c!align] {\advance\c_math_eqalign_column\plusone\math_eqalign_set_column}% \scratchcounter\ifnum\c_math_eqalign_column>\zerocount \c_math_eqalign_column \else \plusone \fi \global\c_math_eqalign_column\plusone \math_matrix_prepare} \def\math_matrix_stop {\crcr \mathstrut\crcr \noalign{\kern-\baselineskip}% \egroup \popmacro\math_matrix_NC \egroup \mathmatrixright \endgroup} \definemathmatrix[matrix] \definemathmatrix[\v!mathmatrix] \def\math_matrix_prepare {\c_math_align_a{\strut\math_first_in_eqalign\math_left_of_equalign\span \math_text_in_eqalign{\mathmatrixparameter\c!style\alignmark\alignmark}\math_right_of_eqalign}% \c_math_align_b{\aligntab\hskip\mathmatrixparameter\c!distance \math_next_in_eqalign\math_left_of_equalign\span \math_text_in_eqalign{\mathmatrixparameter\c!style\alignmark\alignmark}\math_right_of_eqalign}% \c_math_align_c{\aligntab\aligntab\hskip\mathmatrixparameter\c!distance \math_left_of_equalign\span \math_text_in_eqalign{\mathmatrixparameter\c!style\alignmark\alignmark}\math_right_of_eqalign}% \scratchtoks\emptytoks \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_a}}% \dorecurse{\numexpr\scratchcounter-\plusone\relax} {\normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_b}}}% \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_c}}% \halign \expandafter \bgroup\the\scratchtoks \crcr} \unexpanded\def\math_matrix_NC_indeed {\gdef\math_matrix_NC{\endmath\aligntab}} \installcorenamespace{mathmatrixalignmethod} \let\mathmatrixleft \empty % experimental hook \let\mathmatrixright\empty % experimental hook \def\math_matrix_process#1#2% {\dowithnextbox {\scratchdimen\dimexpr(\nextboxdp-\nextboxht)/2 \ifcase#2\or+\mathaxisheight\textfont2\fi\relax \ifcase#1\relax\or\lower\scratchdimen\or\or\raise\scratchdimen\fi\hbox\bgroup \normalstartimath \mathmatrixparameter\c!left \vcenter{\unvbox\nextbox}% \mathmatrixparameter\c!right \normalstopimath \egroup}% \vbox} \unexpanded\def\installmathmatrixalignmethod#1#2% {\setvalue{\??mathmatrixalignmethod#1}{#2}} \def\math_matrix_align_method_analyze {\csname\??mathmatrixalignmethod\ifcsname\??mathmatrixalignmethod\mathmatrixparameter\c!location\endcsname \mathmatrixparameter\c!location \else \v!normal \fi\endcsname} \installmathmatrixalignmethod\v!top {\def\mathmatrixbox{\math_matrix_process\plusthree\plusone }} \installmathmatrixalignmethod\v!high {\def\mathmatrixbox{\math_matrix_process\plusthree\zerocount}} \installmathmatrixalignmethod\v!lohi {\def\mathmatrixbox{\math_matrix_process\plustwo \zerocount}} \installmathmatrixalignmethod\v!low {\def\mathmatrixbox{\math_matrix_process\plusone \zerocount}} \installmathmatrixalignmethod\v!bottom{\def\mathmatrixbox{\math_matrix_process\plusone \plusone }} \installmathmatrixalignmethod\v!normal{\def\mathmatrixbox{\math_matrix_process\plustwo \zerocount}} % lohi %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: \unexpanded\def\startmatrices {\begingroup \setupmathmatrix} \unexpanded\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 \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 {\unexpanded}. \def\startintertext#1\stopintertext {\noalign{\math_intertext{#1}}} \let\stopintertext\relax \def\intertext#1% {\noalign{\math_intertext{#1}}} \unexpanded\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 \unexpanded\def\startsubstack {\begingroup \vcenter\bgroup \baselineskip\mathstacktotal \lineskip\mathstackvgap \lineskiplimit\lineskip \let\stopmathmode\relax \def\NC{\math_matrix_NC}% \def\MC{\math_matrix_NC\startmathmode}% \global\let\math_matrix_NC\math_matrix_NC_indeed \def\NR {\stopmathmode \global\let\math_matrix_NC\math_matrix_NC_indeed \crcr}% \mathsurround\zeropoint \everycr\emptytoks \halign\bgroup\hfil\normalstartimath\scriptstyle\alignmark\alignmark\normalstopimath\hfil\crcr} \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: \ifx\mathparentwd\undefined \newdimen\mathparentwd \fi \let\normalbordermatrix\bordermatrix % move that code to here instead \def\bordermatrix {\begingroup \setbox\scratchbox\hbox{\mr\char"239C}% \global\mathparentwd\wd\scratchbox \endgroup \normalbordermatrix} % to be tested % % \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 \else\ifdim\wd\scratchbox>\zeropoint \endgroup \doubleexpandafter\mathrel \else \endgroup \doubleexpandafter\firstofoneargument \fi\fi} \unexpanded\def\overset#1#2% {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}} \unexpanded\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 %D are also handled. The macros \type {\startinnermath} and %D \type {\stopinnermath} can be overloaded in specialized %D modules. \installcorenamespace{mathinnerstart} \installcorenamespace{mathinnerstop} % \unexpanded\def\startinnermath{\csname\??mathinnerstart\formulaparameter\c!align\endcsname} % \unexpanded\def\stopinnermath {\csname\??mathinnerstop \formulaparameter\c!align\endcsname} \unexpanded\def\startinnermath{\expandnamespaceparameter\??mathinnerstart\formulaparameter\c!align\v!normal} \unexpanded\def\stopinnermath {\expandnamespaceparameter\??mathinnerstop \formulaparameter\c!align\v!normal} \unexpanded\def\mathinnerstrut {\doif{\formulaparameter\c!strut}\v!yes\strut} \unexpanded\def\defineinnermathhandler#1#2#3% {\setvalue{\??mathinnerstart#1}{#2}% \setvalue{\??mathinnerstop #1}{#3}} \newif\iftracemath \def\math_hbox {\iftracemath\ruledhbox\else\hbox\fi} \newconstant\mathraggedstatus % normal left center right \newconstant\mathnumberstatus % nothing normal shift_right \let\mathnumbercorrection\!!zeropoint \let\math_the_r_eq_no\empty \let\math_the_l_eq_no\empty \unexpanded\def\startmathbox#1% {\hsize\displaywidth % \checkeddisplaymath \global\mathnumberstatus\plusone \mathraggedstatus#1\relax \let\mathnumbercorrection\!!zeropoint \global\let\math_the_r_eq_no\empty \global\let\math_the_l_eq_no\empty \def\reqno{\gdef\math_the_r_eq_no}% \def\leqno{\gdef\math_the_l_eq_no}% \let\eqno\reqno % added \let\normalreqno\reqno \let\normalleqno\leqno \let\normaleqno \eqno % added \strc_formulas_place_number \setbox\scratchbox\math_hbox to \displaywidth\bgroup % \checkeddisplaymath \mathinnerstrut \startforceddisplaymath \ifcase\mathraggedstatus\or\hfill\or\hfill\fi} \def\math_box_llapped_math_no {\ifcase\mathraggedstatus\or \math_the_r_eq_no \or \llap{\math_the_r_eq_no}% \or \llap{\math_the_r_eq_no}% \fi} \def\math_box_rlapped_math_no {\ifcase\mathraggedstatus\or \rlap{\math_the_l_eq_no}% \or \rlap{\math_the_l_eq_no}% \or \math_the_l_eq_no \fi} \unexpanded\def\stopmathbox {\stopforceddisplaymath \ifcase\mathraggedstatus\or\or\hfill\or\hfill\fi \egroup \setbox0\hbox{\unhcopy\scratchbox}% \scratchdimen\wd0 % to be tested: \scratchdimen\naturalwd\scratchbox \ifdim\scratchdimen>\displaywidth % \checkeddisplaymath \donetrue \else \donefalse \fi \hbox to \displaywidth\bgroup \ifcase\mathnumberstatus \box\scratchbox \or \ifx\math_the_l_eq_no\empty \ifx\math_the_r_eq_no\empty \box\scratchbox \else \ifdone \vpack{\box\scratchbox\hpack to \displaywidth{\hss\math_box_llapped_math_no}}% \checkeddisplaymath \else \hss\box\scratchbox\math_box_llapped_math_no % hss makes room for number \fi \fi \else \ifdone \vpack{\hpack to \displaywidth{\math_box_rlapped_math_no\hss}\box\scratchbox}% \checkeddisplaymath \else \math_box_rlapped_math_no\box\scratchbox\hss % hss makes room for number \fi \fi \or \hskip\mathnumbercorrection \box\scratchbox \hss \else \box\scratchbox \fi \egroup} \defineinnermathhandler\v!left {\startmathbox\plusone }{\stopmathbox} \defineinnermathhandler\v!middle {\startmathbox\plustwo }{\stopmathbox} \defineinnermathhandler\v!right {\startmathbox\plusthree}{\stopmathbox} \defineinnermathhandler\v!flushleft {\startmathbox\plusthree}{\stopmathbox} \defineinnermathhandler\v!center {\startmathbox\plustwo }{\stopmathbox} \defineinnermathhandler\v!flushright{\startmathbox\plusone }{\stopmathbox} \defineinnermathhandler\v!normal {} {} %defineinnermathhandler\v!normal {\startmathbox\plustwo }{\stopmathbox} %D [The examples below are in english and don't process in the %D documentation style, which will be english some day.] %D %D Normally a formula is centered, but in case you want to %D align it left or right, you can set up formulas to behave %D that way. Normally a formula will adapt is left indentation %D to the environment: %D %D \startbuffer %D \fakewords{20}{40}\epar %D \startitemize %D \item \fakewords{20}{40}\epar %D \placeformula \startformula \fakeformula \stopformula %D \item \fakewords{20}{40}\epar %D \stopitemize %D \fakewords{20}{40}\epar %D \stopbuffer %D %D % \getbuffer %D %D In the next examples we explicitly align formulas to the %D left (\type {\raggedleft}), center and right (\type %D {\raggedright}): %D %D \startbuffer %D \setupformulas[align=left] %D \startformula\fakeformula\stopformula %D \setupformulas[align=middle] %D \startformula\fakeformula\stopformula %D \setupformulas[align=right] %D \startformula\fakeformula\stopformula %D \stopbuffer %D %D \typebuffer %D %D Or in print: %D %D % {\getbuffer} %D %D With formula numbers these formulas look as follows: %D %D \startbuffer %D \setupformulas[align=left] %D \placeformula \startformula\fakeformula\stopformula %D \setupformulas[align=middle] %D \placeformula \startformula\fakeformula\stopformula %D \setupformulas[align=right] %D \placeformula \startformula\fakeformula\stopformula %D \stopbuffer %D %D % {\getbuffer} %D %D This was keyed in as: %D %D \typebuffer %D %D When tracing is turned on (\type {\tracemathtrue}) you can %D visualize the bounding box of the formula, %D %D % {\tracemathtrue\getbuffer} %D %D As you can see, the dimensions are the natural ones, but if %D needed you can force a normalized line: %D %D \startbuffer %D \setupformulas[strut=yes] %D \placeformula \startformula \fakeformula \stopformula %D \stopbuffer %D %D \typebuffer %D %D This time we get a more spacy result. %D %D % {\tracemathtrue\getbuffer} %D %D We will now show a couple of more settings and combinations %D of settings. In centered formulas, the number takes no space %D %D \startbuffer %D \setupformulas[align=middle] %D \startformula \fakeformula \stopformula %D \placeformula \startformula \fakeformula \stopformula %D \stopbuffer %D %D \typebuffer % {\tracemathtrue\getbuffer} %D %D You can influence the placement of the whole box with the %D parameters \type {leftmargin} and \type {rightmargin}. %D %D \startbuffer %D \setupformulas[align=right,leftmargin=3em] %D \startformula \fakeformula \stopformula %D \placeformula \startformula \fakeformula \stopformula %D %D \setupformulas[align=left,rightmargin=1em] %D \startformula \fakeformula \stopformula %D \placeformula \startformula \fakeformula \stopformula %D \stopbuffer %D %D \typebuffer % {\tracemathtrue\getbuffer} %D %D You can also inherit the margin from the environment. %D %D \startbuffer %D \setupformulas[align=right,margin=standard] %D \startformula \fakeformula \stopformula %D \placeformula \startformula \fakeformula \stopformula %D \stopbuffer %D %D \typebuffer % {\tracemathtrue\getbuffer} %D %D The distance between the formula and the number is only %D applied when the formula is left or right aligned. %D %D \startbuffer %D \setupformulas[align=left,distance=2em] %D \startformula \fakeformula \stopformula %D \placeformula \startformula \fakeformula \stopformula %D \stopbuffer %D %D \typebuffer % {\tracemathtrue\getbuffer} \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