% \iffalse meta-comment
%
% Copyright 2011–2020 by Philipp Stephani, Joseph Wright, and Will Robertson
% Copyright 2021, 2022 Google LLC
%
% This file may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either
% version 1.3c of this license or (at your option) any later
% version.  The latest version of this license is in:
%
%    http://www.latex-project.org/lppl.txt
%
% and version 1.3c or later is part of all distributions of
% LaTeX version 2009/09/24 or later.
%
% \fi
%
% \iffalse
%<*driver>
\documentclass[a4paper, 10pt, ngerman, american]{phst-doc}

\usepackage{lualatex-math}
\newcommand*{\thispackage}{\textsf{lualatex-math}\xspace}

\begin{document}

\DocInput{lualatex-math.dtx}
\PrintChanges
\PrintIndex

\end{document}
%</driver>
% \fi
%
% \CheckSum{322}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
%
% \changes{v0.1}{2011/04/22}{Initial version}
% \changes{v0.3a}{2011/09/13}{Updated for changes in \pkg{l3kernel}}
% \changes{v1.0}{2012/08/27}{Switched to \pkg{l3docstrip}}
%
% \GetFileInfo{lualatex-math.sty}
%
% \title{The \thispackage package\thanks{This document corresponds to
%     \thispackage{}~\fileversion, dated~\filedate.}}
%
% \author{Philipp Stephani \\ \texttt{p.stephani2@gmail.com}}
% \date{\filedate}
%
%
% \maketitle
% \tableofcontents
%
%
% \section{Introduction}
%
% \Hologo{LuaTeX} brings major improvements to all areas of \hologo{TeX}
% typesetting and programming.  They are made available through new primitives
% or the embedded Lua interpreter, and combining them with existing
% \hologo{LaTeX2e} packages is not a task the average \hologo{LaTeX} user
% should have to care about.  Therefore a multitude of \hologo{LaTeX2e}
% packages have been written to bridge the gap between documents and the new
% features.  The \thispackage package focuses on the additional possibilities
% for mathematical typesetting.  The most eminent of the new features is the
% ability to use Unicode and OpenType fonts, as provided by \Robertson’s
% \pkg{unicode-math} package.  However, there is a smaller group of changes
% unrelated to Unicode: these are to be dealt with in this package.  While in
% principle most \hologo{TeX} documents written for traditional engines should
% work just fine with \hologo{LuaTeX}, there is a small number of breaking
% changes that require the attention of package authors.  The \thispackage
% package tries to fix some of the issues encountered while porting traditional
% macro packages to \hologo{LuaLaTeX}.
%
% The decision to write patches for existing macro packages should not be
% made lightly: monkey patching done by somebody different from the original
% package author ties the patching package to the implementation details of
% the patched functionality and breaks all rules of encapsulation.  However,
% due to the lack of alternatives, it has become an accepted way of providing
% new functionality in \hologo{LaTeX}.  To keep the negative impact as small
% as possible, the \thispackage package patches only the \hologo{LaTeX2e}
% kernel and a small number of popular packages.  In general, this package
% should be regarded as a temporary kludge that should be removed once the
% math-related packages are updated to be usable with \hologo{LuaTeX}.  By
% its very nature, the package is likely to cause problems; in such cases,
% please refer to the issue
% tracker\footnote{\url{https://github.com/phst/lualatex-math/issues}}.
%
%
% \section{Interface}
%
% The \thispackage package can be loaded with \cmd{\usepackage} or
% \cmd{\RequirePackage}, as usual.  It has no options and no public
% interface; the patching is always done when the package is loaded and
% cannot be controlled.  As a matter of course, the \thispackage package
% needs \hologo{LuaLaTeX} to function; it will produce error messages and
% refuse to load under other engines and formats.  The package depends on the
% \pkg{expl3} bundle, the \pkg{etoolbox} package and the
% \pkg{filehook} package. The \thispackage package is independent of
% the \pkg{unicode-math} package; the fixes provided here are valid for both
% Unicode and legacy math typesetting.
%
% Currently patches for the \hologo{LaTeX2e} kernel and the \pkg{amsmath},
% \pkg{mathtools} and \pkg{icomma} packages are provided.  It is not relevant
% whether you load these packages before or after \thispackage.  They should
% work as expected (and ideally you shouldn’t notice anything), but if you load
% other packages that by themselves overwrite commands patched by this package,
% bad things may happen, as it is usual with \hologo{LaTeX}.
%
% One user-visible change is that the new
% \DescribeMacros{\mathstyle}\cmd{\mathstyle} primitive
% should work in
% all cases after the \thispackage package has been loaded, provided you use
% the high-level macros \DescribeMacros{\frac\binom\genfrac}\cmd{\frac},
% \cmd{\binom}, and \cmd{\genfrac}.  The fraction-like \hologo{TeX}
% primitives like \cmd{\over} or \cmd{\atopwithdelims} and the
% \hologo{plainTeX} leftovers like \cmd{\brack} or \cmd{\choose} cannot be
% patched, and you shouldn’t use them.
%
% \StopEventually{}
%
%
% \section{Implementation of the \hologo{LaTeX2e} package}
%
% \changes{v1.4a}{2015/08/24}{Use \pkg{expl3} versions of \hologo{LuaTeX}
%   math primitives}
% \changes{v1.4a}{2015/08/24}{Avoid \cs{RequireLuaModule}}
% \changes{v1.4a}{2015/09/16}{Load \pkg{luatexbase} only if required}
% \changes{v1.9}{2020/09/25}{Require 2020 version of \hologo{LaTeX2e}}
% \changes{v1.9}{2020/09/25}{Use builtin \hologo{LaTeX2e} hooks if available}
%
% \subsection{Requirements}
%
%    \begin{macrocode}
%<*package>
%<@@=lltxmath>
\NeedsTeXFormat{LaTeX2e}[2020/02/02]
\RequirePackage{expl3}[2018/06/18]
\ProvidesExplPackage{lualatex-math}{2022/01/01}{1.12}%
  {Patches for mathematics typesetting with LuaLaTeX}
\RequirePackage { etoolbox } [ 2007/10/08 ]
\cs_if_exist:NF \newluabytecode
  { \RequirePackage { luatexbase } [ 2010/05/27 ] }
\directlua{require("lualatex-math")}
%    \end{macrocode}
%
% \begin{macro}{\@@_restore_catcode:N}
%   Executing the exhaustive expansion of
%   \cmd{\@@_restore_catcode:N}\meta{character token} restores the category
%   code of the \meta{character token} to its current value.
%    \begin{macrocode}
\cs_new_nopar:Npn \@@_restore_catcode:N #1 {
  \char_set_catcode:nn { \int_eval:n { `#1 } }
    { \char_value_catcode:n { `#1 } }
}
%    \end{macrocode}
% \end{macro}
% We use the macro defined above to restore the category code of the dollar
% sign.  There are packages that make the dollar sign active; hopefully they
% get loaded after the packages we are trying to patch.
%    \begin{macrocode}
\exp_args:Nx \AtEndOfPackage {
  \@@_restore_catcode:N \$
}
\char_set_catcode_math_toggle:N \$
%    \end{macrocode}
%
%
% \subsection{Messages}
%
% \begin{l3message}{luatex-required}
%   Issued when not running under \hologo{LuaTeX}.
%    \begin{macrocode}
\msg_new:nnn { lualatex-math } { luatex-required } {
  The~ lualatex-math~ package~ requires~ LuaTeX. \\
  I~ will~ stop~ loading~ now.
}
%    \end{macrocode}
% \end{l3message}
%
% \begin{l3message}{macro-expected}
%   Issued when trying to patch a non-macro.  The first argument must be the
%   detokenized macro name.
%    \begin{macrocode}
\msg_new:nnn { lualatex-math } { macro-expected } {
  I've~ expected~ that~ #1~ is~ a~ macro,~ but~ it~ isn't.
}
%    \end{macrocode}
% \end{l3message}
%
% \begin{l3message}{wrong-meaning}
%   Issued when trying to patch a macro with an unexpected meaning.  The first
%   argument must be the detokenized macro name; the second argument must be
%   the actual detokenized meaning; and the third argument must be the expected
%   detokenized meaning.
%    \begin{macrocode}
\msg_new:nnn { lualatex-math } { wrong-meaning } {
  I've~ expected~ #1~ to~ have~ the~ meaning \\
  #3, \\
  but~ it~ has~ the~ meaning \\
  #2.
}
%    \end{macrocode}
% \end{l3message}
%
% \begin{l3message}{patch-macro}
%   Issued when a macro is patched.  The first argument must be the detokenized
%   macro name.
%    \begin{macrocode}
\msg_new:nnn { lualatex-math } { patch-macro } {
  I'm~ going~ to~ patch~ macro~ #1.
}
%    \end{macrocode}
% \end{l3message}
%
%
% \subsection{Initialization}
%
% Unless we are running under \hologo{LuaTeX}, we issue an error and quit
% immediately.
%    \begin{macrocode}
\sys_if_engine_luatex:F {
  \msg_error:nn { lualatex-math } { luatex-required }
  \endinput
}
%    \end{macrocode}
%
% \subsection{Patching}
%
% \begin{macro}{\@@_temp:w}
%   A scratch macro.
%    \begin{macrocode}
\cs_new_eq:NN \@@_temp:w \prg_do_nothing:
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_patch:NNnnn}
% \begin{macro}{\@@_patch:cNnnn}
%   The auxiliary macro \cmd{\@@_patch:NNnnn}\meta{command}\meta{factory
%   command}\marg{parameter text}\marg{expected replacement text}\marg{new
%   replacement text} tries to patch \meta{command}.  If \meta{command} is
%   undefined, do nothing.  Otherwise it must be a macro with the given
%   \meta{parameter text} and \meta{expected replacement text}, created by the
%   given \meta{factory command} or equivalent.  In this case it will be
%   overwritten using the \meta{parameter text} and the \meta{new replacement
%   text}.  Otherwise issue a warning and don’t overwrite.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_patch:NNnnn #1 #2 #3 #4 #5 {
  \cs_if_exist:NT #1 {
    \token_if_macro:NTF #1 {
      \group_begin:
      #2 \@@_temp:w #3 { #4 }
      \cs_if_eq:NNTF #1 \@@_temp:w {
        \msg_info:nnx { lualatex-math } { patch-macro }
          { \token_to_str:N #1 }
        \group_end:
        #2 #1 #3 { #5 }
      } {
        \msg_warning:nnxxx { lualatex-math } { wrong-meaning }
          { \token_to_str:N #1 } { \token_to_meaning:N #1 }
          { \token_to_meaning:N \@@_temp:w }
        \group_end:
      }
    } {
      \msg_warning:nnx { lualatex-math } { macro-expected }
        { \token_to_str:N #1 }
    }
  }
}
\cs_generate_variant:Nn \@@_patch:NNnnn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_set_mathchar:NN}
%   The macro \cmd{\@@_set_mathchar:NN}\meta{control sequence}\meta{token}
%   defines the \meta{control sequence} as an extended mathematical character
%   shorthand whose mathematical code is given by the mathematical code of the
%   character \texttt{\textasciigrave}\meta{token}.  We cannot use the
%   |\Umathcharnumdef| primitive here since we would then rely on the
%   |\Umathcodenum| primitive which is currently
%   broken.\footnote{\url{http://tug.org/pipermail/luatex/2012-October/003794.html}}
%   \changes{v0.3c}{2012/08/23}{\pkg{l3kernel} renamed \cs{lua_now:x} to
%   \cs{lua_now_x:n}}
%   \changes{v1.1}{2012/10/13}{Update reasoning why \cs{Umathcharnumdef} is not
%   used here}
%   \changes{v1.3a}{2014/06/18}{\pkg{l3kernel} has (currently) dropped
%     \cs{lua_now_x:n}}
%   \changes{v1.4a}{2015/08/24}{\cs{lua_now_x:n} is back}
%   \changes{v1.8}{2019/01/21}{\cs{lua_now_x:n} is now called \cs{lua_now:e}}
%   \changes{v1.8}{2019/01/21}{Stop using \cs{…:D} control sequences}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_set_mathchar:NN #1 #2 {
  \Umathchardef #1
  \lua_now:e {
    lualatex.math.print_class_fam_slot( \int_eval:n { `#2 } )
  }
  \scan_stop:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_before_package:nn}
% \begin{macro}{\@@_after_package:nn}
%   The macro \cmd{\@@_before_package:nn}\marg{package}\marg{code} executes the
%   \meta{code} before the \meta{package} is loaded.  Accordingly,
%   \cmd{\@@_after_package:nn}\marg{package}\marg{code} executes the
%   \meta{code} after the \meta{package} is loaded.  If the \meta{package} is
%   already loaded, nothing happens.  We prefer using native \hologo{LaTeX2e}
%   hooks if possible.
%   \changes{v1.12}{2022-01-01}{Use the new generic hook names if available}
%    \begin{macrocode}
\@ifl@t@r \fmtversion { 2021/11/15 } {
  \cs_new_protected_nopar:Npn \@@_before_package:nn #1 #2 {
    \AddToHook { package/#1/before } { #2 }
  }
  \cs_new_protected_nopar:Npn \@@_after_package:nn #1 #2 {
    \AddToHook { package/#1/after } { #2 }
  }
}{
  \@ifl@t@r \fmtversion { 2020/10/01 } {
    \cs_new_protected_nopar:Npn \@@_before_package:nn #1 #2 {
      \AddToHook { package/before/#1 } { #2 }
    }
    \cs_new_protected_nopar:Npn \@@_after_package:nn #1 #2 {
      \AddToHook { package/after/#1 } { #2 }
    }
  } {
    \RequirePackage { filehook } [ 2011/03/09 ]
    \cs_new_protected_nopar:Npn \@@_before_package:nn #1 #2 {
      \AtBeginOfPackageFile { #1 } { #2 }
    }
    \cs_new_protected_nopar:Npn \@@_after_package:nn #1 #2 {
      \AtEndOfPackageFile { #1 } { #2 }
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_after_package_or_now:nn}
%   The macro \cmd{\@@_after_package_or_now:nn}\marg{package}\marg{code}
%   executes the \meta{code} after the \meta{package} is loaded.  If the
%   \meta{package} is already loaded, the \meta{code} is executed immediately.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_after_package_or_now:nn #1 #2 {
  \@ifpackageloaded { #1 } { #2 } { \@@_after_package:nn { #1 } { #2 } }
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{\Hologo{LaTeX2e} kernel}
%
% \changes{v0.3}{2011/08/07}{Patched math group allocation to gain access to
% all families}
% \changes{v1.4}{2015/04/04}{Removed patch for math group allocation; the
% kernel itself now supports all available math families}
% \Hologo{LuaTeX} enables access to the current mathematical style via the
% \cmd{\mathstyle} primitive.  For this to work, fraction-like constructs (\eg,
% \meta{numerator} \cmd{\over} \meta{denominator}) have to be enclosed in a
% \cmd{\Ustack} group.  \cmd{\frac} can be patched to do this, but the
% \hologo{plainTeX} remnants \cmd{\choose}, \cmd{\brack} and \cmd{\brace}
% should be discouraged.
%
% \begin{macro}{\frac}
%   Here we assume that nobody except \pkg{amsmath} redefines \cmd{\frac}.
%   This is obviously not the case, but we ignore other packages (\eg,
%   \pkg{nath}) for the moment.  We only patch the \hologo{LaTeX2e} kernel
%   definition if the \pkg{amsmath} package is not loaded; the corresponding
%   patch for \pkg{amsmath} follows below.  Since \cmd{\frac} is declared by
%   \cmd{\DeclareRobustCommand}, we must patch the macro
%   \cmd{\frac\textvisiblespace}.
%   \changes{v1.9}{2020/09/25}{Adapt to changes in \hologo{LaTeX2e} kernel}
%    \begin{macrocode}
\AtEndPreamble {
  \@ifpackageloaded { amsmath } { } {
    \@@_patch:cNnnn { frac~ } \cs_set:Npn { #1 #2 } {
      {
        \begingroup #1 \endgroup \over #2
      }
    } {
%    \end{macrocode}
% To do: do we need the additional set of braces around \cmd{\Ustack}?
%   \changes{v1.8}{2019/01/21}{Stop using \cs{…:D} control sequences}
%    \begin{macrocode}
      {
        \Ustack { \group_begin: #1 \group_end: \over #2 }
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{\pkg{amsmath}}
%
% The popular \pkg{amsmath} package is subject to three \hologo{LuaTeX}-related problems:
% \begin{itemize}
% \item The \cmd{\mathcode} primitive is used several times, which fails for
%   Unicode math characters.  \cmd{\Umathcode} should be used instead.
% \item Legacy font dimensions are used for constructing stacks in the
%   \cmd{\substack} command and the \env{subarray} environment.  This doesn’t
%   work if a Unicode math font is selected.
% \item The fraction commands \cmd{\frac} and \cmd{\genfrac} don’t use the
%   \cmd{\Ustack} primitive.
% \end{itemize}
% These problems have been fixed in version~2.17i of \pkg{amsmath}, so we don’t
% attempt to patch it if that version is loaded.
%
% \begin{macro}{\c_@@_std_minus_mathcode_int}
% \begin{macro}{\c_@@_std_equal_mathcode_int}
%   These constants contain the standard \hologo{TeX} mathematical codes for
%   the minus and the equal signs.  We temporarily set the math codes to these
%   constants before loading the \pkg{amsmath} package so that it can request
%   the legacy math code without error.
%    \begin{macrocode}
\int_const:Nn \c_@@_std_minus_mathcode_int { "2200 }
\int_const:Nn \c_@@_std_equal_mathcode_int { "303D }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \changes{v1.5}{2016/03/07}{Removed unused helper macro \cs{@@_char_dim:NN}}
%
% \begin{macro}{\l_@@_minus_mathchar}
% \begin{macro}{\l_@@_equal_mathchar}
%   These mathematical characters are saved before \pkg{amsmath} is loaded so
%   that we can temporarily assign the \hologo{TeX} values to the mathematical
%   codes of the minus and equals signs.  The \pkg{amsmath} package queries
%   these codes, and if they represent Unicode characters, the package loading
%   will fail.  If \pkg{amsmath} has already been loaded, there is nothing we
%   can do, therefore we use the non-starred version of
%   \cmd{\AtBeginOfPackageFile}.
%   \changes{v1.2}{2013/01/13}{Replace removed macro \cs{chk_if_free_cs:N}}
%   \changes{v1.9}{2020/09/25}{Don’t patch newer versions of \pkg{amsmath}}
%    \begin{macrocode}
\tl_new:N \l_@@_minus_mathchar
\tl_new:N \l_@@_equal_mathchar
\@@_before_package:nn { amsmath } {
  \@ifpackagelater { amsmath } { 2020/08/24 } { } {
    \@@_set_mathchar:NN \l_@@_minus_mathchar \-
    \@@_set_mathchar:NN \l_@@_equal_mathchar \=
%    \end{macrocode}
% \end{macro}
% \end{macro}
% Now we temporarily reset the mathematical codes.
%    \begin{macrocode}
    \char_set_mathcode:nn { `\- } { \c_@@_std_minus_mathcode_int }
    \char_set_mathcode:nn { `\= } { \c_@@_std_equal_mathcode_int }
    \@@_after_package:nn { amsmath } {
%    \end{macrocode}
% \begin{macro}{\std@minus}
% \begin{macro}{\std@equals}
%   The \pkg{amsmath} package defines the control sequences \cmd{\std@minus}
%   and \cmd{\std@equal} as mathematical character shorthands while loading,
%   but uses our restored mathematical codes, which must be fixed.
%    \begin{macrocode}
      \cs_set_eq:NN \std@minus \l_@@_minus_mathchar
      \cs_set_eq:NN \std@equal \l_@@_equal_mathchar
%    \end{macrocode}
% \end{macro}
% \end{macro}
% Finally, we restore the original mathematical codes of the two signs.
% \changes{v1.8}{2019/01/21}{Stop using \cs{…:D} control sequences}
%    \begin{macrocode}
      \Umathcodenum `\- \l_@@_minus_mathchar
      \Umathcodenum `\= \l_@@_equal_mathchar
    }
  }
}
%    \end{macrocode}
% All of the following fixes work even if \pkg{amsmath} is already loaded.
% \begin{macro}{\@begindocumenthook}
%   \changes{v0.3b}{2011/09/18}{Another update for a change in \pkg{l3kernel}}
%   \pkg{amsmath} repeats the definiton of \cmd{\std@minus} and
%   \cmd{\std@equal} at the beginning of the document, so we also have to patch
%   the internal kernel macro \cmd{\@begindocumenthook} which contains the hook
%   code.
%   \changes{v1.9}{2020/09/25}{Don’t patch newer versions of \pkg{amsmath}}
%    \begin{macrocode}
\@@_after_package_or_now:nn { amsmath } {
  \@ifpackagelater { amsmath } { 2020/08/24 } { } {
    \tl_replace_once:Nnn \@begindocumenthook {
      \mathchardef \std@minus \mathcode `\- \relax
      \mathchardef \std@equal \mathcode `\= \relax
    } {
      \@@_set_mathchar:NN \std@minus \-
      \@@_set_mathchar:NN \std@equal \=
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \changes{v1.5}{2016/03/07}{Removed patch for \cs{Mathstrutbox@};
% \pkg{amsmath} now has a definition usable in \Hologo{LuaLaTeX}}
%
% \begin{environment}{subarray}
%   The \env{subarray} environment uses legacy font dimensions.  We simply
%   patch it to use \hologo{LuaTeX} font parameters (and \hologo{LaTeX3}
%   expressions instead of \hologo{TeX} arithmetic).  Since subscript arrays
%   are conceptually vertical stacks, we use the sum of top and bottom shift
%   for the default vertical baseline distance (\cmd{\baselineskip}) and the
%   minimum vertical gap for stack for the minimum baseline distance
%   (\cmd{\lineskip}).
%   \changes{v1.8}{2019/01/21}{Stop using \cs{…:D} control sequences}
%   \changes{v1.9}{2020/09/25}{Don’t patch newer versions of \pkg{amsmath}}
%   \changes{v1.9}{2020/09/25}{Stop using \cs{…:D} control sequences}
%    \begin{macrocode}
  \@ifpackagelater { amsmath } { 2020/09/23 } { } {
    \@@_patch:NNnnn \subarray \cs_set:Npn { #1 } {
      \vcenter
      \bgroup
      \Let@
      \restore@math@cr
      \default@tag
      \baselineskip \fontdimen 10~ \scriptfont \tw@
      \advance \baselineskip \fontdimen 12~ \scriptfont \tw@
%<@@=>
      \lineskip \thr@@ \fontdimen 8~ \scriptfont \thr@@
%<@@=lltxmath>
      \lineskiplimit \lineskip
      \ialign
      \bgroup
      \ifx c #1 \hfil \fi
      $ \m@th \scriptstyle ## $
      \hfil
      \crcr
    } {
      \vcenter
      \c_group_begin_token
      \Let@
      \restore@math@cr
      \default@tag
      \skip_set:Nn \baselineskip {
        \Umathstacknumup \scriptstyle
        + \Umathstackdenomdown \scriptstyle
      }
      \lineskip \Umathstackvgap \scriptstyle
      \lineskiplimit \lineskip
      \ialign
      \c_group_begin_token
      \token_if_eq_meaning:NNT c #1 { \hfil }
      \Ustartmath
      \m@th
      \scriptstyle
      \alignmark \alignmark
      \Ustopmath
      \hfil
      \crcr
    }
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{\frac}
%   Since \cmd{\frac} is declared by \cmd{\DeclareRobustCommand}, we must patch
%   the macro \cmd{\frac\textvisiblespace}.
%   \changes{v1.8}{2019/01/21}{Stop using \cs{…:D} control sequences}
%    \begin{macrocode}
    \@@_patch:cNnnn { frac~ } \cs_set:Npn { #1 #2 } {
      {
%<@@=>
        \begingroup #1 \endgroup \@@over #2
      }
    } {
      {
        \Ustack { \group_begin: #1 \group_end: \@@over #2 }
%<@@=lltxmath>
      }
    }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\genfrac}
%   Generalized fractions are typeset by the \cmd{\genfrac} command.
%   Since \cmd{\genfrac} is declared by \cmd{\DeclareRobustCommand},
%   we have to patch the macro \cmd{\genfrac\textvisiblespace}.
%   \changes{v1.7}{2017/06/15}{Adapt patch to changes in \pkg{amsmath}}
%   \changes{v1.8}{2019/01/21}{Stop using \cs{…:D} control sequences}
%    \begin{macrocode}
    \@@_patch:cNnnn { genfrac~ } \cs_set:Npn {
      #1 #2 #3 #4 #5 #6
    } {
      {
        \@mathstyle { #4 }
        \genfrac@choice o { #1 }
        {
          \begingroup #5 \endgroup
%<@@=>
          \ifx @ #3 @ \@@over \else \@@above \fi #3 \relax
          #6
        }
        \genfrac@choice c { #2 }
      }
    } {
      {
        \@mathstyle { #4 }
        \genfrac@choice o { #1 }
        {
          \Ustack {
            \group_begin: #5 \group_end:
            \tl_if_empty:nTF { #3 } {
              \@@over
            } {
              \@@above #3 \scan_stop:
            }
%<@@=lltxmath>
            #6
          }
        }
        \genfrac@choice c { #2 }
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
%
% \changes{v1.1}{2012/10/13}{Add fix and unit test for \pkg{amsopn}}
% \changes{v1.6}{2016/04/16}{Removed patch for \cs{newmcodes@};
% \pkg{amsmath} now has a definition usable in \Hologo{LuaLaTeX}}
%
%
% \subsection{\pkg{mathtools}}
%
% \pkg{mathtools}’ \cmd{\cramped} command and others that make use of its
% internal version use a hack involving a null radical.  \Hologo{LuaTeX} has
% primitives for setting material in cramped mode, so we make use of them.
%
% In newer versions of \pkg{mathtools}, this issue is fixed, in which case we
% skip the patch.
% \changes{v1.10}{2021/03/28}{Skip patch if \pkg{mathtools} is recent enough}
% \changes{v1.11}{2021/07/05}{Adapt to March 2021 changes to \pkg{mathtools}}
%
% \begin{macro}{\MT_cramped_internal:Nn}
%   The macro \cmd{\MT_cramped_internal:Nn}\meta{style}\marg{expression}
%   typesets the \meta{expression} in the cramped style corresponding to the
%   given \meta{style} (\cmd{\displaystyle} etc.); all we have to do in
%   \hologo{LuaTeX} is to select the correct primitive.  Rewriting the
%   user-level \cmd{\cramped} command and employing \cmd{\mathstyle} would be
%   possible as well, but we avoid this way since we want to patch only a
%   single command.
%    \begin{macrocode}
\@@_after_package_or_now:nn { mathtools } {
  \@ifpackagelater { mathtools } { 2021/03/28 } { } {
    \@@_patch:NNnnn \MT_cramped_internal:Nn
      \cs_set_nopar:Npn { #1 #2 } {
      \setbox \z@ \hbox {
        $
        \m@th
        #1
        \kern -\nulldelimiterspace
        \radical \z@ { #2 }
        $
      }
      \ifx #1 \displaystyle
        \dimen@ = \fontdimen 8 \textfont 3
        \advance \dimen@ .25 \fontdimen 5 \textfont 2
      \else
        \dimen@ = 1.25 \fontdimen 8
        \ifx #1 \textstyle
          \textfont
        \else
          \ifx #1 \scriptstyle
            \scriptfont
          \else
            \scriptscriptfont
          \fi
        \fi
        3
      \fi
      \advance \dimen@ -\ht\z@
      \ht\z@ = -\dimen@
      \ifvmode \leavevmode \fi
      { }
      \box\z@
    } {
%    \end{macrocode}
% \changes{v1.4}{2014/08/18}{Added \cs{ensuremath} to work around
% \href{https://github.com/phst/lualatex-math/issues/11}{issue~11}}
% Here the additional set of braces is absolutely necessary, otherwise the
% changed mathematical style would be applied to the material after the
% \cmd{\mathchoice} construct.  As the original command works in both text and
% math mode, we use |\ensuremath| here.
%   \changes{v1.9}{2020/09/25}{Stop using \cs{…:D} control sequences}
%    \begin{macrocode}
      {
        \ensuremath {
          \use:c { cramped \cs_to_str:N #1 } #2
        }
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{\pkg{icomma}}
%
% \changes{v0.2}{2011/07/03}{Added patch for the \pkg{icomma} package}
% The \pkg{icomma} package uses |\mathchardef| to save the mathematical code of
% the comma character.  This breaks for Unicode fonts.  The incompatibility was
% noticed by
% \Breitfeld.\footnote{\url{https://groups.google.com/forum/\#!topic/de.comp.text.tex/Cputk-AJS5I/discussion}}
% \changes{v1.10}{2021/03/28}{Use new \Hologo{LaTeX2e} hook management if
% available}
%
% \begin{macro}{\mathcomma}
%   \pkg{icomma} defines the mathemathical character shorthand \cmd{\icomma} at
%   the beginning of the document, therefore we again patch
%   \cmd{\@begindocumenthook}.
%    \begin{macrocode}
\@@_after_package_or_now:nn { icomma } {
  \@ifl@t@r \fmtversion { 2020/10/01 } {
    \hook_gput_code:nnn { begindocument } { lualatex-math } {
      \@@_set_mathchar:NN \mathcomma \,
      \mathcode `\, = "8000 ~
    }
    \hook_gset_rule:nnnn
      { begindocument } { lualatex-math } { voids } { icomma }
  } {
    \tl_replace_once:Nnn \@begindocumenthook {
      \mathchardef \mathcomma \mathcode `\,
    } {
      \@@_set_mathchar:NN \mathcomma \,
    }
  }
}
%</package>
%    \end{macrocode}
% \end{macro}
%
%
% \section{Implementation of the \hologo{LuaLaTeX} module}
%
% For the Lua module, we use the standard \pkg{luatexbase-modutils} template.
% \changes{v1.3}{2013/08/03}{Stop using the deprecated \func{module} function}
% \changes{v1.4a}{2015/08/24}{Load all of \pkg{luatexbase}}
%    \begin{macrocode}
%<*lua>
lualatex = lualatex or {}
lualatex.math = lualatex.math or {}
luatexbase.provides_module({
  name = "lualatex-math",
  date = "2013/08/03",
  version = 1.3,
  description = "Patches for mathematics typesetting with LuaLaTeX",
  author = "Philipp Stephani",
  licence = "LPPL v1.3+"
})
%    \end{macrocode}
% \begin{function}{unpack}
%   \changes{v1.3}{2013/08/03}{Integrate Philipp Gesang’s patch to make the
%   \func{unpack} function compatible with Lua~5.2}
%   The function \func{unpack} needs to be treated specially as it got moved
%   around in Lua~5.2.
%    \begin{macrocode}
local unpack = unpack or table.unpack
%    \end{macrocode}
% \end{function}
%   \changes{v1.4a}{2015/08/24}{Pick up new name for string catcode table
%     where available}
%    \begin{macrocode}
local cctb = luatexbase.catcodetables or
  {string = luatexbase.registernumber("catcodetable@string")}
%    \end{macrocode}
%
% \changes{v1.5}{2016/03/07}{Removed unused Lua function \func{print_fam_slot}}
%
% \begin{function}{print_class_fam_slot}
%   The function \func{print_class_fam_slot} takes one argument which must be a
%   number.  It interprets the argument as a Unicode code point whose
%   mathematical code is printed in the form
%   \meta{class}\texttt{\textvisiblespace}\meta{family}\texttt{\textvisiblespace}\meta{slot},
%   suitable for the right-hand side of \cmd{\Umathchardef}.
%    \begin{macrocode}
function lualatex.math.print_class_fam_slot(char)
  local code = tex.getmathcode(char)
  local class, family, slot = unpack(code)
  local result = string.format("%i %i %i ", class, family, slot)
  tex.sprint(cctb.string, result)
end
%    \end{macrocode}
% \end{function}
%    \begin{macrocode}
return lualatex.math
%</lua>
%    \end{macrocode}
%
% \Finale
\endinput

% Local Variables:
% mode: doctex
% coding: utf-8-unix
% TeX-engine: luatex
% End:
