%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

\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
  {\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 \displaywidth \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 \displaywidth \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

\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... )
   \iffirstargument
     \setupmathalignment[\currentmathalignment][#1]%
   \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}

\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{$\mathmatrixparameter\c!left
            \vcenter{\unvbox\nextbox}%
            \mathmatrixparameter\c!right$}}%
   \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$\scriptstyle\alignmark\alignmark$\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{$#1\mathsurround\zeropoint$}%
      \kern-\wd\scratchbox
      ${}#1{}\mathsurround\zeropoint$}%
   \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
   \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
     \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
   \ifdim\scratchdimen>\displaywidth
     \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
             \vbox{\box\scratchbox\hbox to \displaywidth{\hss\math_box_llapped_math_no}}%
           \else
             \hss\box\scratchbox\math_box_llapped_math_no % hss makes room for number
           \fi
         \fi
       \else
         \ifdone
           \vbox{\hbox to \displaywidth{\math_box_rlapped_math_no\hss}\box\scratchbox}%
         \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
