summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl')
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl1964
1 files changed, 1964 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl b/Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl
new file mode 100644
index 00000000000..2007ed83ccf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl
@@ -0,0 +1,1964 @@
+%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 \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{\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
+
+\def\math_prepare_r_eqalign_no
+ {\t_math_align_a
+ {\strut
+ \tabskip\zeropoint
+ \alignmark\alignmark % for picking up the number
+ \aligntab
+ \math_first_in_eqalign
+ \hfil
+ \math_left_of_eqalign
+ \span
+ \math_math_in_eqalign{\alignmark\alignmark}%
+ \math_right_of_eqalign
+ \tabskip\zeropoint}%
+ \t_math_align_b
+ {\aligntab
+ \math_next_in_eqalign
+ \math_left_of_eqalign
+ \span
+ \math_math_in_eqalign{\alignmark\alignmark}%
+ \math_right_of_eqalign
+ \tabskip\zeropoint}%
+ \ifnum\mathraggedstatus=\plusone
+ \t_math_align_c
+ {\hfil
+ \aligntab
+ \span
+ \math_text_in_eqalign{\alignmark\alignmark}%
+ \tabskip\zeropoint}%
+ \orelse\ifnum\mathraggedstatus=\plusthree
+ \t_math_align_c
+ {\hfil
+ \tabskip\zeropoint\s!plus 1\s!fill
+ \aligntab
+ \span
+ \math_text_in_eqalign{\alignmark\alignmark}%
+ \tabskip\zeropoint}%
+ \else
+ \t_math_align_c
+ {\hfil
+ \tabskip\centering
+ \aligntab
+ \span
+ \llap{\math_text_in_eqalign{\alignmark\alignmark}}%
+ \tabskip\zeropoint}%
+ \fi
+ \math_build_eqalign
+ \the\mathdisplayaligntweaks
+ \tabskip\centering}
+
+\def\math_prepare_l_eqalign_no % \checkeddisplaymath
+ {\t_math_align_a
+ {\strut
+ \tabskip\zeropoint
+ \alignmark\alignmark % for picking up the number
+ \aligntab
+ \math_first_in_eqalign
+ \hfil
+ \math_left_of_eqalign
+ \span
+ \math_math_in_eqalign{\alignmark\alignmark}%
+ \math_right_of_eqalign
+ \tabskip\zeropoint}%
+ \t_math_align_b
+ {\aligntab
+ \math_next_in_eqalign
+ \math_left_of_eqalign
+ \span
+ \math_math_in_eqalign{\alignmark\alignmark}%
+ \math_right_of_eqalign
+ \tabskip\zeropoint}%
+ \ifnum\mathraggedstatus=\plusone
+ \t_math_align_c
+ {\hfil
+ \aligntab
+ \kern-\displaywidth
+ \span
+ \rlap{\math_text_in_eqalign{\alignmark\alignmark}}%
+ \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{\alignmark\alignmark}}%
+ \tabskip\displaywidth}%
+ \else
+ \t_math_align_c
+ {\hfil
+ \tabskip\centering
+ \aligntab
+ \kern-\displaywidth
+ \span
+ \rlap{\math_text_in_eqalign{\alignmark\alignmark}}%
+ \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
+\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
+
+\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_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\instance\setuevalue{\e!start\currentmathalignment}{\math_alignment_start[\currentmathalignment]}%
+ \frozen\instance\setvalue {\e!stop \currentmathalignment}{\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
+ \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}
+
+\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}
+
+\letvalue{\??mathalignmentvariant\v!normal}\zerocount
+\letvalue{\??mathalignmentvariant\v!left }\plusone
+\letvalue{\??mathalignmentvariant\v!right }\plustwo
+\letvalue{\??mathalignmentvariant\v!middle}\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!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\endmath\relax
+ \enforced\let\NC\math_cases_NC_zero
+ \enforced\let\MC\math_cases_MC_zero
+ \enforced\let\NR\math_cases_NR_zero
+ \enforced\let\TB\math_common_TB
+ \global\enforced\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
+ \pop_macro_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
+
+% 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}
+
+\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
+ \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
+ \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.
+
+\protected\def\math_matrix_distance
+ {\relax
+ \ifdim\d_math_eqalign_distance>\zeropoint
+ \hskip\d_math_eqalign_distance
+ \fi
+ \relax}
+
+\def\math_matrix_preamble
+ {\math_matrix_strut
+ \global\advance\c_math_eqalign_column\plusone
+ \math_matrix_start_cell
+ \alignmark\alignmark
+ \math_matrix_stop_cell
+ \aligntab
+ \aligntab
+ \math_matrix_distance
+ \global\advance\c_math_eqalign_column\plusone
+ \math_matrix_start_cell
+ \alignmark\alignmark
+ \math_matrix_stop_cell}
+
+\newconditional\c_math_matrix_first
+
+\permanent\protected\def\math_matrix_NR
+ {\aligntab\omit
+ \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
+
+% \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
+ \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
+ \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
+
+\setvalue{\??mathmatrixalignlocation\v!top }{\raise\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax}
+\setvalue{\??mathmatrixalignlocation\v!high }{\raise\dimexpr(\nextboxdp-\nextboxht)/2\relax}
+\setvalue{\??mathmatrixalignlocation\v!center}{\relax}
+\setvalue{\??mathmatrixalignlocation\v!lohi} {\relax}
+\setvalue{\??mathmatrixalignlocation\v!normal}{\relax}
+\setvalue{\??mathmatrixalignlocation\v!bottom}{\lower\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax}
+\setvalue{\??mathmatrixalignlocation\v!low }{\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
+%D adapted to regular mathmatrices (which saves some code so it can go into
+%D the core):
+
+\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 We hook it into the normal mathmatrix code:
+
+\appendtoks
+ \edef\p_simplecommand{\mathmatrixparameter\c!simplecommand}%
+ \ifempty\p_simplecommand\else
+ \frozen\instance\setuevalue{\p_simplecommand}{\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\alignmark\alignmark\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
+
+\setvalue{\??formulaoption\v!frame}%
+ {\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}
+
+\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