% \iffalse meta-comment
%
%% File: l3skip.dtx
%
% Copyright (C) 2004-2011 Frank Mittelbach, The LaTeX Project
%           (C) 2012-2023 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    https://www.latex-project.org/lppl.txt
%
% This file is part of the "l3kernel bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/latex3/latex3
%
% for those people who are interested.
%
%<*driver>
\documentclass[full,kernel]{l3doc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3skip} package\\ Dimensions and skips^^A
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released 2023-02-22}
%
% \maketitle
%
% \begin{documentation}
%
% \LaTeX3 provides two general length variables: \texttt{dim} and
% \texttt{skip}. Lengths stored as \texttt{dim} variables have a fixed
% length, whereas \texttt{skip} lengths have a rubber (stretch/shrink)
% component. In addition, the \texttt{muskip} type is available for
% use in math mode: this is a special form of \texttt{skip} where the
% lengths involved are determined by the current math font (in
% \texttt{mu)}. There are common features in the creation and setting of
% length variables, but for clarity the functions are grouped by variable
% type.
%
% Many functions take
% \emph{dimension expressions} (\enquote{\meta{dim expr}}) or
% \emph{skip expressions} (\enquote{\meta{skip expr}}) as arguments.
%
%
% \section{Creating and initialising \texttt{dim} variables}
%
% \begin{function}{\dim_new:N, \dim_new:c}
%   \begin{syntax}
%     \cs{dim_new:N} \meta{dimension}
%   \end{syntax}
%   Creates a new \meta{dimension} or raises an error if the name is
%   already taken. The declaration is global. The \meta{dimension}
%   is initially equal to $0$\,pt.
% \end{function}
%
% \begin{function}[added = 2012-03-05]{\dim_const:Nn, \dim_const:cn}
%   \begin{syntax}
%     \cs{dim_const:Nn} \meta{dimension} \Arg{dim expr}
%   \end{syntax}
%   Creates a new constant \meta{dimension} or raises an error if the
%   name is already taken. The value of the \meta{dimension} is set
%   globally to the \meta{dim expr}.
% \end{function}
%
% \begin{function}{\dim_zero:N, \dim_zero:c, \dim_gzero:N, \dim_gzero:c}
%   \begin{syntax}
%     \cs{dim_zero:N} \meta{dimension}
%   \end{syntax}
%   Sets \meta{dimension} to $0$\,pt.
% \end{function}
%
% \begin{function}[added = 2012-01-07]
%   {\dim_zero_new:N, \dim_zero_new:c, \dim_gzero_new:N, \dim_gzero_new:c}
%   \begin{syntax}
%     \cs{dim_zero_new:N} \meta{dimension}
%   \end{syntax}
%   Ensures that the \meta{dimension} exists globally by applying
%   \cs{dim_new:N} if necessary, then applies
%   \cs[index=dim_zero:N]{dim_(g)zero:N} to leave
%   the \meta{dimension} set to zero.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]{\dim_if_exist:N, \dim_if_exist:c}
%   \begin{syntax}
%     \cs{dim_if_exist_p:N} \meta{dimension}
%     \cs{dim_if_exist:NTF} \meta{dimension} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests whether the \meta{dimension} is currently defined.  This does
%   not check that the \meta{dimension} really is a dimension variable.
% \end{function}
%
% \section{Setting \texttt{dim} variables}
%
% \begin{function}[updated = 2011-10-22]
%   {\dim_add:Nn, \dim_add:cn, \dim_gadd:Nn, \dim_gadd:cn}
%   \begin{syntax}
%     \cs{dim_add:Nn} \meta{dimension} \Arg{dim expr}
%   \end{syntax}
%   Adds the result of the \meta{dim expr} to the current
%   content of the \meta{dimension}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
%   {\dim_set:Nn, \dim_set:cn, \dim_gset:Nn, \dim_gset:cn}
%   \begin{syntax}
%     \cs{dim_set:Nn} \meta{dimension} \Arg{dim expr}
%   \end{syntax}
%   Sets \meta{dimension} to the value of \meta{dim expr}, which
%   must evaluate to a length with units.
% \end{function}
%
% \begin{function}
%   {
%     \dim_set_eq:NN,  \dim_set_eq:cN,  \dim_set_eq:Nc,  \dim_set_eq:cc,
%     \dim_gset_eq:NN, \dim_gset_eq:cN, \dim_gset_eq:Nc, \dim_gset_eq:cc
%   }
%   \begin{syntax}
%     \cs{dim_set_eq:NN} \meta{dimension_1} \meta{dimension_2}
%   \end{syntax}
%   Sets the content of \meta{dimension_1} equal to that of
%   \meta{dimension_2}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
%   {\dim_sub:Nn, \dim_sub:cn, \dim_gsub:Nn, \dim_gsub:cn}
%   \begin{syntax}
%     \cs{dim_sub:Nn} \meta{dimension} \Arg{dim expr}
%   \end{syntax}
%   Subtracts the result of the \meta{dim expr} from the
%   current content of the \meta{dimension}.
% \end{function}
%
% \section{Utilities for dimension calculations}
%
% \begin{function}[updated = 2012-09-26, EXP]{\dim_abs:n}
%   \begin{syntax}
%     \cs{dim_abs:n} \Arg{dim expr}
%   \end{syntax}
%   Converts the \meta{dim expr} to its absolute value, leaving the result
%   in the input stream as a \meta{dimension denotation}.
% \end{function}
%
% \begin{function}[added = 2012-09-09, updated = 2012-09-26, EXP]
%   {\dim_max:nn, \dim_min:nn}
%   \begin{syntax}
%     \cs{dim_max:nn} \Arg{dim expr_1} \Arg{dim expr_2}
%     \cs{dim_min:nn} \Arg{dim expr_1} \Arg{dim expr_2}
%   \end{syntax}
%   Evaluates the two \meta{dim exprs} and leaves either the
%   maximum or minimum value in the input stream as appropriate, as a
%   \meta{dimension denotation}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22, rEXP]{\dim_ratio:nn}
%   \begin{syntax}
%     \cs{dim_ratio:nn} \Arg{dim expr_1} \Arg{dim expr_2}
%   \end{syntax}
%   Parses the two \meta{dim exprs} and converts the ratio of
%   the two to a form suitable for use inside a \meta{dim expr}.
%   This ratio is then left in the input stream, allowing syntax such as
%   \begin{verbatim}
%     \dim_set:Nn \l_my_dim
%       { 10 pt * \dim_ratio:nn { 5 pt } { 10 pt } }
%   \end{verbatim}
%   The output of \cs{dim_ratio:nn} on full expansion is a ratio expression
%   between two integers, with all distances converted to scaled points.
%   Thus
%   \begin{verbatim}
%     \tl_set:Nx \l_my_tl { \dim_ratio:nn { 5 pt } { 10 pt } }
%     \tl_show:N \l_my_tl
%   \end{verbatim}
%   displays |327680/655360| on the terminal.
% \end{function}
%
% \section{Dimension expression conditionals}
%
% \begin{function}[EXP,pTF]{\dim_compare:nNn}
%   \begin{syntax}
%     \cs{dim_compare_p:nNn} \Arg{dim expr_1} \meta{relation} \Arg{dim expr_2} \\
%     \cs{dim_compare:nNnTF}
%     ~~\Arg{dim expr_1} \meta{relation} \Arg{dim expr_2}
%     ~~\Arg{true code} \Arg{false code}
%   \end{syntax}
%   This function first evaluates each of the \meta{dim exprs}
%   as described for \cs{dim_eval:n}. The two results are then
%   compared using the \meta{relation}:
%   \begin{center}
%     \begin{tabular}{ll}
%       Equal                 & |=| \\
%       Greater than          & |>| \\
%       Less than             & |<| \\
%     \end{tabular}
%   \end{center}
%   This function is less flexible than \cs{dim_compare:nTF} but around
%   $5$~times faster.
% \end{function}
%
% \begin{function}[updated = 2013-01-13, EXP, pTF]{\dim_compare:n}
%   \begin{syntax}
%     \cs{dim_compare_p:n} \\
%     ~~\{ \\
%     ~~~~\meta{dim expr_1} \meta{relation_1} \\
%     ~~~~\ldots{} \\
%     ~~~~\meta{dim expr_N} \meta{relation_N} \\
%     ~~~~\meta{dim expr_{N+1}} \\
%     ~~\} \\
%     \cs{dim_compare:nTF}
%     ~~\{ \\
%     ~~~~\meta{dim expr_1} \meta{relation_1} \\
%     ~~~~\ldots{} \\
%     ~~~~\meta{dim expr_N} \meta{relation_N} \\
%     ~~~~\meta{dim expr_{N+1}} \\
%     ~~\} \\
%     ~~\Arg{true code} \Arg{false code}
%   \end{syntax}
%   This function evaluates the \meta{dim exprs} as
%   described for \cs{dim_eval:n} and compares consecutive result using
%   the corresponding \meta{relation}, namely it compares
%   \meta{dim expr_1} and \meta{dim expr_2} using the \meta{relation_1},
%   then \meta{dim expr_2} and \meta{dim expr_3} using the
%   \meta{relation_2}, until finally comparing \meta{dim expr_N} and
%   \meta{dim expr_{N+1}} using the \meta{relation_N}.  The test yields
%   \texttt{true} if all comparisons are \texttt{true}.  Each
%   \meta{dim expr} is evaluated only once, and the
%   evaluation is lazy, in the sense that if one comparison is
%   \texttt{false}, then no other \meta{dim expr} is
%   evaluated and no other comparison is performed.  The
%   \meta{relations} can be any of the following:
%   \begin{center}
%     \begin{tabular}{ll}
%       Equal                    & |=| or |==| \\
%       Greater than or equal to & |>=|        \\
%       Greater than             & |>|         \\
%       Less than or equal to    & |<=|        \\
%       Less than                & |<|         \\
%       Not equal                & |!=|        \\
%     \end{tabular}
%   \end{center}
%   This function is more flexible than \cs{dim_compare:nNnTF} but
%   around $5$~times slower.
% \end{function}
%
% \begin{function}[added = 2013-07-24, EXP, noTF]{\dim_case:nn}
%   \begin{syntax}
%     \cs{dim_case:nnTF} \Arg{test dim expr} \\
%     ~~|{| \\
%     ~~~~\Arg{dim expr case_1} \Arg{code case_1} \\
%     ~~~~\Arg{dim expr case_2} \Arg{code case_2} \\
%     ~~~~\ldots \\
%     ~~~~\Arg{dim expr case_n} \Arg{code case_n} \\
%     ~~|}| \\
%     ~~\Arg{true code}
%     ~~\Arg{false code}
%   \end{syntax}
%   This function evaluates the \meta{test dim expr} and
%   compares this in turn to each of the
%   \meta{dim expr cases}. If the two are equal then the
%   associated \meta{code} is left in the input stream
%   and other cases are discarded. If any of the
%   cases are matched, the \meta{true code} is also inserted into the
%   input stream (after the code for the appropriate case), while if none
%   match then the \meta{false code} is inserted. The function
%   \cs{dim_case:nn}, which does nothing if there is no match, is also
%   available. For example
%   \begin{verbatim}
%     \dim_set:Nn \l_tmpa_dim { 5 pt }
%     \dim_case:nnF
%       { 2 \l_tmpa_dim }
%       {
%         { 5 pt }        { Small }
%         { 4 pt + 6 pt } { Medium }
%         { - 10 pt }     { Negative }
%       }
%       { No idea! }
%    \end{verbatim}
%    leaves \enquote{\texttt{Medium}} in the input stream.
% \end{function}
%
% \section{Dimension expression loops}
%
% \begin{function}[rEXP]{\dim_do_until:nNnn}
%   \begin{syntax}
%      \cs{dim_do_until:nNnn} \Arg{dim expr_1} \meta{relation} \Arg{dim expr_2} \Arg{code}
%   \end{syntax}
%   Places the \meta{code} in the input stream for \TeX{} to process, and
%   then evaluates the relationship between the two
%   \meta{dim exprs} as described for \cs{dim_compare:nNnTF}.
%   If the test is \texttt{false} then the \meta{code} is inserted
%   into the input stream again and a loop occurs until the
%   \meta{relation} is \texttt{true}.
% \end{function}
%
% \begin{function}[rEXP]{\dim_do_while:nNnn}
%   \begin{syntax}
%      \cs{dim_do_while:nNnn} \Arg{dim expr_1} \meta{relation} \Arg{dim expr_2} \Arg{code}
%   \end{syntax}
%   Places the \meta{code} in the input stream for \TeX{} to process, and
%   then evaluates the relationship between the two
%   \meta{dim exprs} as described for \cs{dim_compare:nNnTF}.
%   If the test is \texttt{true} then the \meta{code} is inserted
%   into the input stream again and a loop occurs until the
%   \meta{relation} is \texttt{false}.
% \end{function}
%
% \begin{function}[rEXP]{\dim_until_do:nNnn}
%   \begin{syntax}
%      \cs{dim_until_do:nNnn} \Arg{dim expr_1} \meta{relation} \Arg{dim expr_2} \Arg{code}
%   \end{syntax}
%   Evaluates the relationship between the two \meta{dim exprs}
%   as described for \cs{dim_compare:nNnTF}, and then places the
%   \meta{code} in the input stream if the \meta{relation} is
%   \texttt{false}. After the \meta{code} has been processed by \TeX{} the
%   test is repeated, and a loop occurs until the test is
%   \texttt{true}.
% \end{function}
%
% \begin{function}[rEXP]{\dim_while_do:nNnn}
%   \begin{syntax}
%      \cs{dim_while_do:nNnn} \Arg{dim expr_1} \meta{relation} \Arg{dim expr_2} \Arg{code}
%   \end{syntax}
%   Evaluates the relationship between the two \meta{dim exprs}
%   as described for \cs{dim_compare:nNnTF}, and then places the
%   \meta{code} in the input stream if the \meta{relation} is
%   \texttt{true}. After the \meta{code} has been processed by \TeX{} the
%   test is repeated, and a loop occurs until the test is
%   \texttt{false}.
% \end{function}
%
% \begin{function}[updated = 2013-01-13, rEXP]{\dim_do_until:nn}
%   \begin{syntax}
%      \cs{dim_do_until:nn} \Arg{dimension relation} \Arg{code}
%   \end{syntax}
%   Places the \meta{code} in the input stream for \TeX{} to process, and
%   then evaluates the \meta{dimension relation}
%   as described for \cs{dim_compare:nTF}.
%   If the test is \texttt{false} then the \meta{code} is inserted
%   into the input stream again and a loop occurs until the
%   \meta{relation} is \texttt{true}.
% \end{function}
%
% \begin{function}[updated = 2013-01-13, rEXP]{\dim_do_while:nn}
%   \begin{syntax}
%      \cs{dim_do_while:nn} \Arg{dimension relation} \Arg{code}
%   \end{syntax}
%   Places the \meta{code} in the input stream for \TeX{} to process, and
%   then evaluates the \meta{dimension relation}
%   as described for \cs{dim_compare:nTF}.
%   If the test is \texttt{true} then the \meta{code} is inserted
%   into the input stream again and a loop occurs until the
%   \meta{relation} is \texttt{false}.
% \end{function}
%
% \begin{function}[updated = 2013-01-13, rEXP]{\dim_until_do:nn}
%   \begin{syntax}
%      \cs{dim_until_do:nn} \Arg{dimension relation} \Arg{code}
%   \end{syntax}
%   Evaluates the \meta{dimension relation}
%   as described for \cs{dim_compare:nTF}, and then places the
%   \meta{code} in the input stream if the \meta{relation} is
%   \texttt{false}. After the \meta{code} has been processed by \TeX{} the
%   test is repeated, and a loop occurs until the test is
%   \texttt{true}.
% \end{function}
%
% \begin{function}[updated = 2013-01-13, rEXP]{\dim_while_do:nn}
%   \begin{syntax}
%      \cs{dim_while_do:nn} \Arg{dimension relation} \Arg{code}
%   \end{syntax}
%   Evaluates the \meta{dimension relation}
%   as described for \cs{dim_compare:nTF}, and then places the
%   \meta{code} in the input stream if the \meta{relation} is
%   \texttt{true}. After the \meta{code} has been processed by \TeX{} the
%   test is repeated, and a loop occurs until the test is
%   \texttt{false}.
% \end{function}
%
% \section{Dimension step functions}
%
% \begin{function}[added = 2018-02-18, rEXP]
%   {\dim_step_function:nnnN}
%   \begin{syntax}
%     \cs{dim_step_function:nnnN} \Arg{initial value} \Arg{step} \Arg{final value} \meta{function}
%   \end{syntax}
%   This function first evaluates the \meta{initial value}, \meta{step}
%   and \meta{final value}, all of which should be dimension expressions.
%   The \meta{function} is then placed in front of each \meta{value}
%   from the \meta{initial value} to the \meta{final value} in turn
%   (using \meta{step} between each \meta{value}).  The \meta{step} must
%   be non-zero.  If the \meta{step} is positive, the loop stops when
%   the \meta{value} becomes larger than the \meta{final value}.  If the
%   \meta{step} is negative, the loop stops when the \meta{value}
%   becomes smaller than the \meta{final value}.  The \meta{function}
%   should absorb one argument.
% \end{function}
%
% \begin{function}[added = 2018-02-18]
%   {\dim_step_inline:nnnn}
%   \begin{syntax}
%     \cs{dim_step_inline:nnnn} \Arg{initial value} \Arg{step} \Arg{final value} \Arg{code}
%   \end{syntax}
%   This function first evaluates the \meta{initial value}, \meta{step}
%   and \meta{final value}, all of which should be dimension expressions.
%   Then for each \meta{value} from the \meta{initial value} to the
%   \meta{final value} in turn (using \meta{step} between each
%   \meta{value}), the \meta{code} is inserted into the input stream
%   with |#1| replaced by the current \meta{value}.  Thus the
%   \meta{code} should define a function of one argument~(|#1|).
% \end{function}
%
% \begin{function}[added = 2018-02-18]
%   {\dim_step_variable:nnnNn}
%   \begin{syntax}
%     \cs{dim_step_variable:nnnNn} \\
%     ~~\Arg{initial value} \Arg{step} \Arg{final value} \meta{tl~var} \Arg{code}
%   \end{syntax}
%   This function first evaluates the \meta{initial value}, \meta{step}
%   and \meta{final value}, all of which should be dimension expressions.
%   Then for each \meta{value} from the \meta{initial value} to the
%   \meta{final value} in turn (using \meta{step} between each
%   \meta{value}), the \meta{code} is inserted into the input stream,
%   with the \meta{tl~var} defined as the current \meta{value}.  Thus
%   the \meta{code} should make use of the \meta{tl~var}.
% \end{function}
%
% \section{Using \texttt{dim} expressions and variables}
%
% \begin{function}[updated = 2011-10-22, EXP]{\dim_eval:n}
%   \begin{syntax}
%     \cs{dim_eval:n} \Arg{dim expr}
%   \end{syntax}
%   Evaluates the \meta{dim expr}, expanding any
%   dimensions and token list variables within the \meta{expression}
%   to their content (without requiring \cs{dim_use:N}/\cs{tl_use:N})
%   and applying the standard mathematical rules. The result of the
%   calculation is left in the input stream as a
%   \meta{dimension denotation} after two expansions. This is
%   expressed in points (\texttt{pt}), and requires suitable
%   termination if used in a \TeX{}-style assignment as it is \emph{not}
%   an \meta{internal dimension}.
% \end{function}
%
% \begin{function}[EXP, added = 2018-11-03]{\dim_sign:n}
%   \begin{syntax}
%     \cs{dim_sign:n} \Arg{dim expr}
%   \end{syntax}
%   Evaluates the \meta{dim expr} then leaves $1$ or $0$ or $-1$ in the
%   input stream according to the sign of the result.
% \end{function}
%
% \begin{function}[EXP]{\dim_use:N, \dim_use:c}
%   \begin{syntax}
%     \cs{dim_use:N} \meta{dimension}
%   \end{syntax}
%   Recovers the content of a \meta{dimension} and places it directly
%   in the input stream. An error is raised if the variable does
%   not exist or if it is invalid. Can be omitted in places where a
%   \meta{dimension} is required (such as in the argument of
%   \cs{dim_eval:n}).
%   \begin{texnote}
%     \cs{dim_use:N} is the \TeX{} primitive \tn{the}: this is one of
%     several \LaTeX3 names for this primitive.
%   \end{texnote}
% \end{function}
%
% \begin{function}[added = 2014-07-15, EXP]{\dim_to_decimal:n}
%   \begin{syntax}
%     \cs{dim_to_decimal:n} \Arg{dim expr}
%   \end{syntax}
%   Evaluates the \meta{dim expr}, and leaves the result,
%   expressed in points (\texttt{pt}) in the input stream, with \emph{no
%     units}.  The result is rounded by \TeX{} to four or five decimal
%   places.  If the decimal part of the result is zero, it is omitted,
%   together with the decimal marker.
%
%   For example
%   \begin{verbatim}
%     \dim_to_decimal:n { 1bp }
%   \end{verbatim}
%   leaves |1.00374| in the input stream, \emph{i.e.}~the magnitude of
%   one \enquote{big point} when converted to (\TeX{}) points.
% \end{function}
%
% \begin{function}[added = 2014-07-15, EXP]{\dim_to_decimal_in_bp:n}
%   \begin{syntax}
%     \cs{dim_to_decimal_in_bp:n} \Arg{dim expr}
%   \end{syntax}
%   Evaluates the \meta{dim expr}, and leaves the result,
%   expressed in big points (\texttt{bp}) in the input stream, with \emph{no
%   units}.  The result is rounded by \TeX{} to four or five decimal
%   places.  If the decimal part of the result is zero, it is omitted,
%   together with the decimal marker.
%
%   For example
%   \begin{verbatim}
%     \dim_to_decimal_in_bp:n { 1pt }
%   \end{verbatim}
%   leaves |0.99628| in the input stream, \emph{i.e.}~the magnitude of
%   one (\TeX{}) point when converted to big points.
% \end{function}
%
% \begin{function}[added = 2015-05-18, EXP]{\dim_to_decimal_in_sp:n}
%   \begin{syntax}
%     \cs{dim_to_decimal_in_sp:n} \Arg{dim expr}
%   \end{syntax}
%   Evaluates the \meta{dim expr}, and leaves the result,
%   expressed in scaled points (\texttt{sp}) in the input stream, with \emph{no
%   units}.  The result is necessarily an integer.
% \end{function}
%
% \begin{function}[added = 2014-07-15, EXP]
%   {\dim_to_decimal_in_unit:nn}
%   \begin{syntax}
%     \cs{dim_to_decimal_in_unit:nn} \Arg{dim expr_1} \Arg{dim expr_2}
%   \end{syntax}
%   Evaluates the \meta{dim exprs}, and leaves the value of
%   \meta{dim expr_1}, expressed in a unit given by \meta{dim expr_2}, in
%   the input stream.  The result is a decimal number, rounded by \TeX{}
%   to four or five decimal places.  If the decimal part of the result
%   is zero, it is omitted, together with the decimal marker.
%
%   For example
%   \begin{verbatim}
%     \dim_to_decimal_in_unit:nn { 1bp } { 1mm }
%   \end{verbatim}
%   leaves |0.35277| in the input stream, \emph{i.e.}~the magnitude of
%   one big point when converted to millimetres.
%
%   Note that this function is not optimised for any particular output
%   and as such may give different results to \cs{dim_to_decimal_in_bp:n}
%   or \cs{dim_to_decimal_in_sp:n}. In particular, the latter is able to
%   take a wider range of input values as it is not limited by the ability
%   to calculate a ratio using \eTeX{} primitives, which is required
%   internally by \cs{dim_to_decimal_in_unit:nn}.
% \end{function}
%
% \begin{function}[EXP, added = 2012-05-08, tested = m3fp-convert002]
%   {\dim_to_fp:n}
%   \begin{syntax}
%     \cs{dim_to_fp:n} \Arg{dim expr}
%   \end{syntax}
%   Expands to an internal floating point number equal to the value of
%   the \meta{dim expr} in \texttt{pt}.  Since dimension expressions are
%   evaluated much faster than their floating point equivalent,
%   \cs{dim_to_fp:n} can be used to speed up parts of a computation
%   where a low precision and a smaller range are acceptable.
% \end{function}
%
% \section{Viewing \texttt{dim} variables}
%
% \begin{function}{\dim_show:N, \dim_show:c}
%   \begin{syntax}
%     \cs{dim_show:N} \meta{dimension}
%    \end{syntax}
%   Displays the value of the \meta{dimension} on the terminal.
% \end{function}
%
% \begin{function}[added = 2011-11-22, updated = 2015-08-07]{\dim_show:n}
%   \begin{syntax}
%     \cs{dim_show:n} \Arg{dim expr}
%    \end{syntax}
%   Displays the result of evaluating the \meta{dim expr}
%   on the terminal.
% \end{function}
%
% \begin{function}[added = 2014-08-22, updated = 2015-08-03]{\dim_log:N, \dim_log:c}
%   \begin{syntax}
%     \cs{dim_log:N} \meta{dimension}
%    \end{syntax}
%   Writes the value of the \meta{dimension} in the log file.
% \end{function}
%
% \begin{function}[added = 2014-08-22, updated = 2015-08-07]{\dim_log:n}
%   \begin{syntax}
%     \cs{dim_log:n} \Arg{dim expr}
%    \end{syntax}
%   Writes the result of evaluating the \meta{dim expr}
%   in the log file.
% \end{function}
%
% \section{Constant dimensions}
%
% \begin{variable}{\c_max_dim}
%   The maximum value that can be stored as a dimension.  This can also
%   be used as a component of a skip.
% \end{variable}
%
% \begin{variable}{\c_zero_dim}
%   A zero length as a dimension.  This can also be used as a component
%   of a skip.
% \end{variable}
%
% \section{Scratch dimensions}
%
% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim}
%   Scratch dimension for local assignment. These are never used by
%   the kernel code, and so are safe for use with any \LaTeX3-defined
%   function. However, they may be overwritten by other non-kernel
%   code and so should only be used for short-term storage.
% \end{variable}
%
% \begin{variable}{\g_tmpa_dim, \g_tmpb_dim}
%   Scratch dimension for global assignment. These are never used by
%   the kernel code, and so are safe for use with any \LaTeX3-defined
%   function. However, they may be overwritten by other non-kernel
%   code and so should only be used for short-term storage.
% \end{variable}
%
% \section{Creating and initialising \texttt{skip} variables}
%
% \begin{function}{\skip_new:N, \skip_new:c}
%   \begin{syntax}
%     \cs{skip_new:N} \meta{skip}
%   \end{syntax}
%   Creates a new \meta{skip} or raises an error if the name is
%   already taken. The declaration is global. The \meta{skip}
%   is initially equal to $0$\,pt.
% \end{function}
%
% \begin{function}[added = 2012-03-05]{\skip_const:Nn, \skip_const:cn}
%   \begin{syntax}
%     \cs{skip_const:Nn} \meta{skip} \Arg{skip expr}
%   \end{syntax}
%   Creates a new constant \meta{skip} or raises an error if the
%   name is already taken. The value of the \meta{skip} is set
%   globally to the \meta{skip expr}.
% \end{function}
%
% \begin{function}{\skip_zero:N, \skip_zero:c, \skip_gzero:N, \skip_gzero:c}
%   \begin{syntax}
%     \cs{skip_zero:N} \meta{skip}
%   \end{syntax}
%   Sets \meta{skip} to $0$\,pt.
% \end{function}
%
% \begin{function}[added = 2012-01-07]
%   {\skip_zero_new:N, \skip_zero_new:c, \skip_gzero_new:N, \skip_gzero_new:c}
%   \begin{syntax}
%     \cs{skip_zero_new:N} \meta{skip}
%   \end{syntax}
%   Ensures that the \meta{skip} exists globally by applying
%   \cs{skip_new:N} if necessary, then applies
%   \cs[index=skip_zero:N]{skip_(g)zero:N} to leave
%   the \meta{skip} set to zero.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]
%   {\skip_if_exist:N, \skip_if_exist:c}
%   \begin{syntax}
%     \cs{skip_if_exist_p:N} \meta{skip}
%     \cs{skip_if_exist:NTF} \meta{skip} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests whether the \meta{skip} is currently defined.  This does not
%   check that the \meta{skip} really is a skip variable.
% \end{function}
%
% \section{Setting \texttt{skip} variables}
%
% \begin{function}[updated = 2011-10-22]
%   {\skip_add:Nn, \skip_add:cn, \skip_gadd:Nn, \skip_gadd:cn}
%   \begin{syntax}
%     \cs{skip_add:Nn} \meta{skip} \Arg{skip expr}
%   \end{syntax}
%   Adds the result of the \meta{skip expr} to the current
%   content of the \meta{skip}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
%   {\skip_set:Nn, \skip_set:cn, \skip_gset:Nn, \skip_gset:cn}
%   \begin{syntax}
%     \cs{skip_set:Nn} \meta{skip} \Arg{skip expr}
%   \end{syntax}
%   Sets \meta{skip} to the value of \meta{skip expr}, which
%   must evaluate to a length with units and may include a rubber
%   component (for example |1 cm plus 0.5 cm|.
% \end{function}
%
% \begin{function}
%   {
%     \skip_set_eq:NN,  \skip_set_eq:cN,  \skip_set_eq:Nc,  \skip_set_eq:cc,
%     \skip_gset_eq:NN, \skip_gset_eq:cN, \skip_gset_eq:Nc, \skip_gset_eq:cc
%   }
%   \begin{syntax}
%     \cs{skip_set_eq:NN} \meta{skip_1} \meta{skip_2}
%   \end{syntax}
%   Sets the content of \meta{skip_1} equal to that of \meta{skip_2}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
%   {\skip_sub:Nn, \skip_sub:cn, \skip_gsub:Nn, \skip_gsub:cn}
%   \begin{syntax}
%     \cs{skip_sub:Nn} \meta{skip} \Arg{skip expr}
%   \end{syntax}
%   Subtracts the result of the \meta{skip expr} from the
%   current content of the \meta{skip}.
% \end{function}
%
% \section{Skip expression conditionals}
%
% \begin{function}[EXP,pTF]{\skip_if_eq:nn}
%   \begin{syntax}
%     \cs{skip_if_eq_p:nn} \Arg{skip expr_1} \Arg{skip expr_2}
%     \cs{skip_if_eq:nnTF}
%     ~~\Arg{skip expr_1} \Arg{skip expr_2}
%     ~~\Arg{true code} \Arg{false code}
%   \end{syntax}
%   This function first evaluates each of the
%   \meta{skip exprs} as described for \cs{skip_eval:n}.
%   The two results are then compared for exact equality,
%   \emph{i.e.}~both the fixed and rubber components must be the same
%   for the test to be true.
% \end{function}
%
% \begin{function}[EXP, pTF, added = 2012-03-05]{\skip_if_finite:n}
%   \begin{syntax}
%     \cs{skip_if_finite_p:n} \Arg{skip expr}
%     \cs{skip_if_finite:nTF} \Arg{skip expr} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Evaluates the \meta{skip expr} as described for \cs{skip_eval:n},
%   and then tests if all of its components are finite.
% \end{function}
%
% \section{Using \texttt{skip} expressions and variables}
%
% \begin{function}[updated = 2011-10-22, EXP]{\skip_eval:n}
%   \begin{syntax}
%     \cs{skip_eval:n} \Arg{skip expr}
%   \end{syntax}
%   Evaluates the \meta{skip expr}, expanding any skips
%   and token list variables within the \meta{expression}
%   to their content (without requiring \cs{skip_use:N}/\cs{tl_use:N})
%   and applying the standard mathematical rules. The result of the
%   calculation is left in the input stream as a \meta{glue denotation}
%   after two expansions. This is expressed in points (\texttt{pt}),
%   and requires suitable termination if used in a \TeX{}-style
%   assignment as it is \emph{not} an \meta{internal glue}.
% \end{function}
%
% \begin{function}[EXP]{\skip_use:N, \skip_use:c}
%   \begin{syntax}
%     \cs{skip_use:N} \meta{skip}
%   \end{syntax}
%   Recovers the content of a \meta{skip} and places it directly
%   in the input stream. An error is raised if the variable does
%   not exist or if it is invalid. Can be omitted in places where a
%   \meta{dimension} or \meta{skip} is required (such as in the argument of
%   \cs{skip_eval:n}).
%   \begin{texnote}
%     \cs{skip_use:N} is the \TeX{} primitive \tn{the}: this is one of
%     several \LaTeX3 names for this primitive.
%   \end{texnote}
% \end{function}
%
% \section{Viewing \texttt{skip} variables}
%
% \begin{function}[updated = 2015-08-03]{\skip_show:N, \skip_show:c}
%   \begin{syntax}
%     \cs{skip_show:N} \meta{skip}
%    \end{syntax}
%   Displays the value of the \meta{skip} on the terminal.
% \end{function}
%
% \begin{function}[added = 2011-11-22, updated = 2015-08-07]{\skip_show:n}
%   \begin{syntax}
%     \cs{skip_show:n} \Arg{skip expr}
%    \end{syntax}
%   Displays the result of evaluating the \meta{skip expr}
%   on the terminal.
% \end{function}
%
% \begin{function}[added = 2014-08-22, updated = 2015-08-03]{\skip_log:N, \skip_log:c}
%   \begin{syntax}
%     \cs{skip_log:N} \meta{skip}
%    \end{syntax}
%   Writes the value of the \meta{skip} in the log file.
% \end{function}
%
% \begin{function}[added = 2014-08-22, updated = 2015-08-07]{\skip_log:n}
%   \begin{syntax}
%     \cs{skip_log:n} \Arg{skip expr}
%    \end{syntax}
%   Writes the result of evaluating the \meta{skip expr}
%   in the log file.
% \end{function}
%
% \section{Constant skips}
%
% \begin{variable}[updated = 2012-11-02]{\c_max_skip}
%   The maximum value that can be stored as a skip (equal to
%   \cs{c_max_dim} in length), with no stretch nor shrink component.
% \end{variable}
%
% \begin{variable}[updated = 2012-11-01]{\c_zero_skip}
%   A zero length as a skip, with no stretch nor shrink component.
% \end{variable}
%
% \section{Scratch skips}
%
% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip}
%   Scratch skip for local assignment. These are never used by
%   the kernel code, and so are safe for use with any \LaTeX3-defined
%   function. However, they may be overwritten by other non-kernel
%   code and so should only be used for short-term storage.
% \end{variable}
%
% \begin{variable}{\g_tmpa_skip, \g_tmpb_skip}
%   Scratch skip for global assignment. These are never used by
%   the kernel code, and so are safe for use with any \LaTeX3-defined
%   function. However, they may be overwritten by other non-kernel
%   code and so should only be used for short-term storage.
% \end{variable}
%
% \section{Inserting skips into the output}
%
% \begin{function}[updated = 2011-10-22]
%   {\skip_horizontal:N, \skip_horizontal:c, \skip_horizontal:n}
%   \begin{syntax}
%     \cs{skip_horizontal:N} \meta{skip}
%     \cs{skip_horizontal:n} \Arg{skip expr}
%   \end{syntax}
%   Inserts a horizontal \meta{skip} into the current list.
%   The argument can also be a \meta{dim}.
%   \begin{texnote}
%     \cs{skip_horizontal:N} is the \TeX{} primitive \tn{hskip} renamed.
%   \end{texnote}
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
%   {\skip_vertical:N, \skip_vertical:c, \skip_vertical:n}
%   \begin{syntax}
%     \cs{skip_vertical:N} \meta{skip}
%     \cs{skip_vertical:n} \Arg{skip expr}
%   \end{syntax}
%   Inserts a vertical \meta{skip} into the current list.
%   The argument can also be a \meta{dim}.
%   \begin{texnote}
%     \cs{skip_vertical:N} is the \TeX{} primitive \tn{vskip} renamed.
%   \end{texnote}
% \end{function}
%
% \section{Creating and initialising \texttt{muskip} variables}
%
% \begin{function}{\muskip_new:N, \muskip_new:c}
%   \begin{syntax}
%     \cs{muskip_new:N} \meta{muskip}
%   \end{syntax}
%   Creates a new \meta{muskip} or raises an error if the name is
%   already taken. The declaration is global. The \meta{muskip}
%   is initially equal to $0$\,mu.
% \end{function}
%
% \begin{function}[added = 2012-03-05]{\muskip_const:Nn, \muskip_const:cn}
%   \begin{syntax}
%     \cs{muskip_const:Nn} \meta{muskip} \Arg{muskip expr}
%   \end{syntax}
%   Creates a new constant \meta{muskip} or raises an error if the
%   name is already taken. The value of the \meta{muskip} is set
%   globally to the \meta{muskip expr}.
% \end{function}
%
% \begin{function}
%   {\muskip_zero:N, \muskip_zero:c, \muskip_gzero:N, \muskip_gzero:c}
%   \begin{syntax}
%     \cs{skip_zero:N} \meta{muskip}
%   \end{syntax}
%   Sets \meta{muskip} to $0$\,mu.
% \end{function}
%
% \begin{function}[added = 2012-01-07]
%   {
%     \muskip_zero_new:N,  \muskip_zero_new:c,
%     \muskip_gzero_new:N, \muskip_gzero_new:c
%   }
%   \begin{syntax}
%     \cs{muskip_zero_new:N} \meta{muskip}
%   \end{syntax}
%   Ensures that the \meta{muskip} exists globally by applying
%   \cs{muskip_new:N} if necessary, then applies
%   \cs[index=muskip_zero:N]{muskip_(g)zero:N}
%   to leave the \meta{muskip} set to zero.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]
%   {\muskip_if_exist:N, \muskip_if_exist:c}
%   \begin{syntax}
%     \cs{muskip_if_exist_p:N} \meta{muskip}
%     \cs{muskip_if_exist:NTF} \meta{muskip} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests whether the \meta{muskip} is currently defined.  This does not
%   check that the \meta{muskip} really is a muskip variable.
% \end{function}
%
% \section{Setting \texttt{muskip} variables}
%
% \begin{function}[updated = 2011-10-22]
%   {\muskip_add:Nn, \muskip_add:cn, \muskip_gadd:Nn, \muskip_gadd:cn}
%   \begin{syntax}
%     \cs{muskip_add:Nn} \meta{muskip} \Arg{muskip expr}
%   \end{syntax}
%   Adds the result of the \meta{muskip expr} to the current
%   content of the \meta{muskip}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
%   {\muskip_set:Nn, \muskip_set:cn, \muskip_gset:Nn, \muskip_gset:cn}
%   \begin{syntax}
%     \cs{muskip_set:Nn} \meta{muskip} \Arg{muskip expr}
%   \end{syntax}
%   Sets \meta{muskip} to the value of \meta{muskip expr}, which
%   must evaluate to a math length with units and may include a rubber
%   component (for example |1 mu plus 0.5 mu|.
% \end{function}
%
% \begin{function}
%   {
%     \muskip_set_eq:NN,  \muskip_set_eq:cN,
%     \muskip_set_eq:Nc,  \muskip_set_eq:cc,
%     \muskip_gset_eq:NN, \muskip_gset_eq:cN,
%     \muskip_gset_eq:Nc, \muskip_gset_eq:cc
%   }
%   \begin{syntax}
%     \cs{muskip_set_eq:NN} \meta{muskip_1} \meta{muskip_2}
%   \end{syntax}
%   Sets the content of \meta{muskip_1} equal to that of
%   \meta{muskip_2}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
%   {\muskip_sub:Nn, \muskip_sub:cn, \muskip_gsub:Nn, \muskip_gsub:cn}
%   \begin{syntax}
%     \cs{muskip_sub:Nn} \meta{muskip} \Arg{muskip expr}
%   \end{syntax}
%   Subtracts the result of the \meta{muskip expr} from the
%   current content of the \meta{muskip}.
% \end{function}
%
% \section{Using \texttt{muskip} expressions and variables}
%
% \begin{function}[updated = 2011-10-22, EXP]{\muskip_eval:n}
%   \begin{syntax}
%     \cs{muskip_eval:n} \Arg{muskip expr}
%   \end{syntax}
%   Evaluates the \meta{muskip expr}, expanding any skips
%   and token list variables within the \meta{expression}
%   to their content (without requiring \cs{muskip_use:N}/\cs{tl_use:N})
%   and applying the standard mathematical rules. The result of the
%   calculation is left in the input stream as a \meta{muglue denotation}
%   after two expansions. This is expressed in \texttt{mu},
%   and requires suitable termination if used in a \TeX{}-style
%   assignment as it is \emph{not} an \meta{internal muglue}.
% \end{function}
%
% \begin{function}[EXP]{\muskip_use:N, \muskip_use:c}
%   \begin{syntax}
%     \cs{muskip_use:N} \meta{muskip}
%   \end{syntax}
%   Recovers the content of a \meta{skip} and places it directly
%   in the input stream. An error is raised if the variable does
%   not exist or if it is invalid. Can be omitted in places where a
%   \meta{dimension} is required (such as in the argument of
%   \cs{muskip_eval:n}).
%   \begin{texnote}
%     \cs{muskip_use:N} is the \TeX{} primitive \tn{the}: this is one of
%     several \LaTeX3 names for this primitive.
%   \end{texnote}
% \end{function}
%
% \section{Viewing \texttt{muskip} variables}
%
% \begin{function}[updated = 2015-08-03]{\muskip_show:N, \muskip_show:c}
%   \begin{syntax}
%     \cs{muskip_show:N} \meta{muskip}
%    \end{syntax}
%   Displays the value of the \meta{muskip} on the terminal.
% \end{function}
%
% \begin{function}[added = 2011-11-22, updated = 2015-08-07]{\muskip_show:n}
%   \begin{syntax}
%     \cs{muskip_show:n} \Arg{muskip expr}
%    \end{syntax}
%   Displays the result of evaluating the \meta{muskip expr}
%   on the terminal.
% \end{function}
%
% \begin{function}[added = 2014-08-22, updated = 2015-08-03]{\muskip_log:N, \muskip_log:c}
%   \begin{syntax}
%     \cs{muskip_log:N} \meta{muskip}
%    \end{syntax}
%   Writes the value of the \meta{muskip} in the log file.
% \end{function}
%
% \begin{function}[added = 2014-08-22, updated = 2015-08-07]{\muskip_log:n}
%   \begin{syntax}
%     \cs{muskip_log:n} \Arg{muskip expr}
%    \end{syntax}
%   Writes the result of evaluating the \meta{muskip expr}
%   in the log file.
% \end{function}
%
% \section{Constant muskips}
%
% \begin{variable}{\c_max_muskip}
%   The maximum value that can be stored as a muskip, with no stretch
%   nor shrink component.
% \end{variable}
%
% \begin{variable}{\c_zero_muskip}
%   A zero length as a muskip, with no stretch nor shrink component.
% \end{variable}
%
% \section{Scratch muskips}
%
% \begin{variable}{\l_tmpa_muskip, \l_tmpb_muskip}
%   Scratch muskip for local assignment. These are never used by
%   the kernel code, and so are safe for use with any \LaTeX3-defined
%   function. However, they may be overwritten by other non-kernel
%   code and so should only be used for short-term storage.
% \end{variable}
%
% \begin{variable}{\g_tmpa_muskip, \g_tmpb_muskip}
%   Scratch muskip for global assignment. These are never used by
%   the kernel code, and so are safe for use with any \LaTeX3-defined
%   function. However, they may be overwritten by other non-kernel
%   code and so should only be used for short-term storage.
% \end{variable}
%
% \section{Primitive conditional}
%
% \begin{function}[EXP]{\if_dim:w}
%   \begin{syntax}
%     \cs{if_dim:w} \meta{dimen_1} \meta{relation} \meta{dimen_2}
%     ~~\meta{true code}
%     \cs{else:}
%     ~~\meta{false}
%     \cs{fi:}
%   \end{syntax}
%   Compare two dimensions. The \meta{relation} is one of
%   |<|, |=| or |>| with category code $12$.
%   \begin{texnote}
%     This is the \TeX{} primitive \tn{ifdim}.
%   \end{texnote}
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3skip} implementation}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<@@=dim>
%    \end{macrocode}
%
% \subsection{Length primitives renamed}
%
% \begin{macro}{\if_dim:w}
% \begin{macro}{\@@_eval:w}
% \begin{macro}{\@@_eval_end:}
%   Primitives renamed.
%    \begin{macrocode}
\cs_new_eq:NN \if_dim:w      \tex_ifdim:D
\cs_new_eq:NN \@@_eval:w      \tex_dimexpr:D
\cs_new_eq:NN \@@_eval_end:   \tex_relax:D
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Internal auxiliaries}
%
% \begin{variable}{\s_@@_mark,\s_@@_stop}
%   Internal scan marks.
%    \begin{macrocode}
\scan_new:N \s_@@_mark
\scan_new:N \s_@@_stop
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}[EXP]{\@@_use_none_delimit_by_s_stop:w}
%   Functions to gobble up to a scan mark.
%    \begin{macrocode}
\cs_new:Npn \@@_use_none_delimit_by_s_stop:w #1 \s_@@_stop { }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Creating and initialising \texttt{dim} variables}
%
% \begin{macro}{\dim_new:N, \dim_new:c}
%    Allocating \meta{dim} registers \ldots
%    \begin{macrocode}
\cs_new_protected:Npn \dim_new:N #1
  {
    \__kernel_chk_if_free_cs:N #1
    \cs:w newdimen \cs_end: #1
  }
\cs_generate_variant:Nn \dim_new:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\dim_const:Nn, \dim_const:cn}
%   Contrarily to integer constants, we cannot avoid using a register,
%   even for constants.  We cannot use \cs{dim_gset:Nn} because
%   debugging code would complain that the constant is not a global
%   variable.  Since \cs{dim_const:Nn} does not need to be fast, use
%   \cs{dim_eval:n} to avoid needing a debugging patch that wraps the
%   expression in checking code.
%    \begin{macrocode}
\cs_new_protected:Npn \dim_const:Nn #1#2
  {
    \dim_new:N #1
    \tex_global:D #1 = \dim_eval:n {#2} \scan_stop:
  }
\cs_generate_variant:Nn \dim_const:Nn { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\dim_zero:N, \dim_zero:c}
% \begin{macro}{\dim_gzero:N, \dim_gzero:c}
%   Reset the register to zero.  Using \cs{c_zero_skip} deals with the
%   case where the variable passed is incorrectly a skip (for example a
%   \LaTeXe{} length).  Besides, these functions are then simply copied
%   for \cs{skip_zero:N} and related functions.
%    \begin{macrocode}
\cs_new_protected:Npn \dim_zero:N #1 { #1 = \c_zero_skip }
\cs_new_protected:Npn \dim_gzero:N #1
  { \tex_global:D #1 = \c_zero_skip }
\cs_generate_variant:Nn \dim_zero:N  { c }
\cs_generate_variant:Nn \dim_gzero:N { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {\dim_zero_new:N, \dim_zero_new:c, \dim_gzero_new:N, \dim_gzero_new:c}
%   Create a register if needed, otherwise clear it.
%    \begin{macrocode}
\cs_new_protected:Npn \dim_zero_new:N  #1
  { \dim_if_exist:NTF #1 { \dim_zero:N #1 } { \dim_new:N #1 } }
\cs_new_protected:Npn \dim_gzero_new:N #1
  { \dim_if_exist:NTF #1 { \dim_gzero:N #1 } { \dim_new:N #1 } }
\cs_generate_variant:Nn \dim_zero_new:N  { c }
\cs_generate_variant:Nn \dim_gzero_new:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\dim_if_exist:N, \dim_if_exist:c}
%   Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
%    \begin{macrocode}
\prg_new_eq_conditional:NNn \dim_if_exist:N \cs_if_exist:N
  { TF , T , F , p }
\prg_new_eq_conditional:NNn \dim_if_exist:c \cs_if_exist:c
  { TF , T , F , p }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Setting \texttt{dim} variables}
%
% \begin{macro}{\dim_set:Nn, \dim_set:cn}
% \begin{macro}{\dim_gset:Nn, \dim_gset:cn}
%   Setting dimensions is easy enough but when debugging we want both to
%   check that the variable is correctly local/global and to wrap the
%   expression in some code.  The \cs{scan_stop:} deals with the case
%   where the variable passed is a skip (for example a \LaTeXe{}
%   length).
%    \begin{macrocode}
\cs_new_protected:Npn \dim_set:Nn #1#2
  { #1 = \@@_eval:w #2 \@@_eval_end: \scan_stop: }
\cs_new_protected:Npn \dim_gset:Nn #1#2
  { \tex_global:D #1 = \@@_eval:w #2 \@@_eval_end: \scan_stop: }
\cs_generate_variant:Nn \dim_set:Nn  { c }
\cs_generate_variant:Nn \dim_gset:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\dim_set_eq:NN, \dim_set_eq:cN, \dim_set_eq:Nc, \dim_set_eq:cc}
% \begin{macro}
%   {\dim_gset_eq:NN, \dim_gset_eq:cN, \dim_gset_eq:Nc, \dim_gset_eq:cc}
%   All straightforward, with a \cs{scan_stop:} to deal with the case
%   where |#1| is (incorrectly) a skip.
%    \begin{macrocode}
\cs_new_protected:Npn \dim_set_eq:NN #1#2
  { #1 = #2 \scan_stop: }
\cs_generate_variant:Nn \dim_set_eq:NN { c , Nc , cc }
\cs_new_protected:Npn \dim_gset_eq:NN #1#2
  { \tex_global:D #1 = #2 \scan_stop: }
\cs_generate_variant:Nn \dim_gset_eq:NN { c , Nc , cc }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\dim_add:Nn, \dim_add:cn}
% \begin{macro}{\dim_gadd:Nn, \dim_gadd:cn}
% \begin{macro}{\dim_sub:Nn, \dim_sub:cn}
% \begin{macro}{\dim_gsub:Nn, \dim_gsub:cn}
%   Using |by| here would slow things down just to detect nonsensical
%   cases such as passing |\dimen 123| as the first argument.
%   Using \cs{scan_stop:} deals with skip variables.  Since
%   debugging checks that the variable is correctly local/global, the
%   global versions cannot be defined as \cs{tex_global:D} followed by
%   the local versions.
%    \begin{macrocode}
\cs_new_protected:Npn \dim_add:Nn #1#2
  { \tex_advance:D #1 \@@_eval:w #2 \@@_eval_end: \scan_stop: }
\cs_new_protected:Npn \dim_gadd:Nn #1#2
  {
    \tex_global:D \tex_advance:D #1
      \@@_eval:w #2 \@@_eval_end: \scan_stop:
  }
\cs_generate_variant:Nn \dim_add:Nn  { c }
\cs_generate_variant:Nn \dim_gadd:Nn { c }
\cs_new_protected:Npn \dim_sub:Nn #1#2
  { \tex_advance:D #1 - \@@_eval:w #2 \@@_eval_end: \scan_stop: }
\cs_new_protected:Npn \dim_gsub:Nn #1#2
  {
    \tex_global:D \tex_advance:D #1
      -\@@_eval:w #2 \@@_eval_end: \scan_stop:
  }
\cs_generate_variant:Nn \dim_sub:Nn  { c }
\cs_generate_variant:Nn \dim_gsub:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Utilities for dimension calculations}
%
% \begin{macro}[EXP]{\dim_abs:n}
% \begin{macro}[EXP]{\@@_abs:N}
% \UnitTested
% \begin{macro}[EXP]{\dim_max:nn}
% \begin{macro}[EXP]{\dim_min:nn}
% \begin{macro}[EXP]{\@@_maxmin:wwN}
% \UnitTested
% \UnitTested
%   Functions for $\min$, $\max$, and absolute value with only one evaluation.
%   The absolute value is evaluated by removing a leading~|-| if present.
%    \begin{macrocode}
\cs_new:Npn \dim_abs:n #1
  {
    \exp_after:wN \@@_abs:N
    \dim_use:N \@@_eval:w #1 \@@_eval_end:
  }
\cs_new:Npn \@@_abs:N #1
  { \if_meaning:w - #1 \else: \exp_after:wN #1 \fi: }
\cs_new:Npn \dim_max:nn #1#2
  {
    \dim_use:N \@@_eval:w \exp_after:wN \@@_maxmin:wwN
      \dim_use:N \@@_eval:w #1 \exp_after:wN ;
      \dim_use:N \@@_eval:w #2 ;
      >
    \@@_eval_end:
  }
\cs_new:Npn \dim_min:nn #1#2
  {
    \dim_use:N \@@_eval:w \exp_after:wN \@@_maxmin:wwN
      \dim_use:N \@@_eval:w #1 \exp_after:wN ;
      \dim_use:N \@@_eval:w #2 ;
      <
    \@@_eval_end:
  }
\cs_new:Npn \@@_maxmin:wwN #1 ; #2 ; #3
  {
    \if_dim:w #1 #3 #2 ~
      #1
    \else:
      #2
    \fi:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\dim_ratio:nn}
% \begin{macro}{\@@_ratio:n}
%   With dimension expressions, something like |10 pt * ( 5 pt / 10 pt )| does
%   not work. Instead, the ratio part needs to be converted to an integer
%   expression. Using \cs{int_value:w} forces everything into |sp|, avoiding
%   any decimal parts.
%    \begin{macrocode}
\cs_new:Npn \dim_ratio:nn #1#2
  { \@@_ratio:n {#1} / \@@_ratio:n {#2} }
\cs_new:Npn \@@_ratio:n #1
  { \int_value:w \@@_eval:w (#1) \@@_eval_end: }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Dimension expression conditionals}
%
% \begin{macro}[pTF, EXP]{\dim_compare:nNn}
%   Simple comparison.
%    \begin{macrocode}
\prg_new_conditional:Npnn \dim_compare:nNn #1#2#3 { p , T , F , TF }
  {
    \if_dim:w \@@_eval:w #1 #2 \@@_eval:w #3 \@@_eval_end:
      \prg_return_true: \else: \prg_return_false: \fi:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF, EXP]{\dim_compare:n}
% \begin{macro}[EXP]{\@@_compare:w, \@@_compare:wNN}
% \begin{macro}[EXP]
%   {
%     \@@_compare_=:w,
%     \@@_compare_!:w,
%     \@@_compare_<:w,
%     \@@_compare_>:w
%   }
% \begin{macro}{\@@_compare_error:}
%   This code is adapted from the \cs{int_compare:nTF} function.  First
%   make sure that there is at least one relation operator, by
%   evaluating a dimension expression with a trailing
%   \cs{@@_compare_error:}.  Just like for integers, the looping
%   auxiliary \cs{@@_compare:wNN} closes a primitive conditional and
%   opens a new one.  It is actually easier to grab a dimension operand
%   than an integer one, because once evaluated, dimensions all end with
%   \texttt{pt} (with category other).  Thus we do not need specific
%   auxiliaries for the three \enquote{simple} relations |<|, |=|,
%   and~|>|.
%    \begin{macrocode}
\prg_new_conditional:Npnn \dim_compare:n #1 { p , T , F , TF }
  {
    \exp_after:wN \@@_compare:w
    \dim_use:N \@@_eval:w #1 \@@_compare_error:
  }
\cs_new:Npn \@@_compare:w #1 \@@_compare_error:
  {
    \exp_after:wN \if_false: \exp:w \exp_end_continue_f:w
      \@@_compare:wNN #1 ? { = \@@_compare_end:w \else: } \s_@@_stop
  }
\exp_args:Nno \use:nn
  { \cs_new:Npn \@@_compare:wNN #1 } { \tl_to_str:n {pt} #2#3 }
  {
      \if_meaning:w = #3
        \use:c { @@_compare_#2:w }
      \fi:
        #1 pt \exp_stop_f:
      \prg_return_false:
      \exp_after:wN \@@_use_none_delimit_by_s_stop:w
    \fi:
    \reverse_if:N \if_dim:w #1 pt #2
      \exp_after:wN \@@_compare:wNN
      \dim_use:N \@@_eval:w #3
  }
\cs_new:cpn { @@_compare_ ! :w }
    #1 \reverse_if:N #2 ! #3 = { #1 #2 = #3 }
\cs_new:cpn { @@_compare_ = :w }
    #1 \@@_eval:w = { #1 \@@_eval:w }
\cs_new:cpn { @@_compare_ < :w }
    #1 \reverse_if:N #2 < #3 = { #1 #2 > #3 }
\cs_new:cpn { @@_compare_ > :w }
    #1 \reverse_if:N #2 > #3 = { #1 #2 < #3 }
\cs_new:Npn \@@_compare_end:w #1 \prg_return_false: #2 \s_@@_stop
  { #1 \prg_return_false: \else: \prg_return_true: \fi: }
\cs_new_protected:Npn \@@_compare_error:
  {
    \if_int_compare:w \c_zero_int \c_zero_int \fi:
    =
    \@@_compare_error:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP, noTF]{\dim_case:nn}
% \begin{macro}{\@@_case:nnTF}
% \begin{macro}{\@@_case:nw, \@@_case_end:nw}
%   For dimension cases, the first task to fully expand the check
%   condition. The over all idea is then much the same as for
%   \cs{str_case:nnTF} as described in \pkg{l3basics}.
%    \begin{macrocode}
\cs_new:Npn \dim_case:nnTF #1
  {
    \exp:w
    \exp_args:Nf \@@_case:nnTF { \dim_eval:n {#1} }
  }
\cs_new:Npn \dim_case:nnT #1#2#3
  {
    \exp:w
    \exp_args:Nf \@@_case:nnTF { \dim_eval:n {#1} } {#2} {#3} { }
  }
\cs_new:Npn \dim_case:nnF #1#2
  {
    \exp:w
    \exp_args:Nf \@@_case:nnTF { \dim_eval:n {#1} } {#2} { }
  }
\cs_new:Npn \dim_case:nn #1#2
  {
    \exp:w
    \exp_args:Nf \@@_case:nnTF { \dim_eval:n {#1} } {#2} { } { }
  }
\cs_new:Npn \@@_case:nnTF #1#2#3#4
  { \@@_case:nw {#1} #2 {#1} { } \s_@@_mark {#3} \s_@@_mark {#4} \s_@@_stop }
\cs_new:Npn \@@_case:nw #1#2#3
  {
    \dim_compare:nNnTF {#1} = {#2}
      { \@@_case_end:nw {#3} }
      { \@@_case:nw {#1} }
  }
\cs_new:Npn \@@_case_end:nw #1#2#3 \s_@@_mark #4#5 \s_@@_stop
  { \exp_end: #1 #4 }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Dimension expression loops}
%
% \begin{macro}{\dim_while_do:nn}
% \begin{macro}{\dim_until_do:nn}
% \begin{macro}{\dim_do_while:nn}
% \begin{macro}{\dim_do_until:nn}
%   |while_do| and |do_while| functions for dimensions. Same as for the
%   |int| type only the names have changed.
%    \begin{macrocode}
\cs_new:Npn \dim_while_do:nn #1#2
  {
    \dim_compare:nT {#1}
      {
        #2
        \dim_while_do:nn {#1} {#2}
      }
  }
\cs_new:Npn \dim_until_do:nn #1#2
  {
    \dim_compare:nF {#1}
      {
        #2
        \dim_until_do:nn {#1} {#2}
      }
  }
\cs_new:Npn \dim_do_while:nn #1#2
  {
    #2
    \dim_compare:nT {#1}
      { \dim_do_while:nn {#1} {#2} }
  }
\cs_new:Npn \dim_do_until:nn #1#2
  {
    #2
    \dim_compare:nF {#1}
      { \dim_do_until:nn {#1} {#2} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\dim_while_do:nNnn}
% \begin{macro}{\dim_until_do:nNnn}
% \begin{macro}{\dim_do_while:nNnn}
% \begin{macro}{\dim_do_until:nNnn}
%   |while_do| and |do_while| functions for dimensions. Same as for the
%   |int| type only the names have changed.
%    \begin{macrocode}
\cs_new:Npn \dim_while_do:nNnn #1#2#3#4
  {
    \dim_compare:nNnT {#1} #2 {#3}
      {
        #4
        \dim_while_do:nNnn {#1} #2 {#3} {#4}
      }
  }
\cs_new:Npn \dim_until_do:nNnn #1#2#3#4
  {
  \dim_compare:nNnF {#1} #2 {#3}
    {
      #4
      \dim_until_do:nNnn {#1} #2 {#3} {#4}
    }
  }
\cs_new:Npn \dim_do_while:nNnn #1#2#3#4
  {
    #4
    \dim_compare:nNnT {#1} #2 {#3}
      { \dim_do_while:nNnn {#1} #2 {#3} {#4} }
  }
\cs_new:Npn \dim_do_until:nNnn #1#2#3#4
  {
    #4
    \dim_compare:nNnF {#1} #2 {#3}
      { \dim_do_until:nNnn {#1} #2 {#3} {#4} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Dimension step functions}
%
% \begin{macro}{\dim_step_function:nnnN}
% \begin{macro}{\@@_step:wwwN, \@@_step:NnnnN}
%   Before all else, evaluate the initial value, step, and final value.
%   Repeating a function by steps first needs a check on the direction
%   of the steps. After that, do the function for the start value then
%   step and loop around. It would be more symmetrical to test for a
%   step size of zero before checking the sign, but we optimize for the
%   most frequent case (positive step).
%    \begin{macrocode}
\cs_new:Npn \dim_step_function:nnnN #1#2#3
  {
    \exp_after:wN \@@_step:wwwN
    \tex_the:D \@@_eval:w #1 \exp_after:wN ;
    \tex_the:D \@@_eval:w #2 \exp_after:wN ;
    \tex_the:D \@@_eval:w #3 ;
  }
\cs_new:Npn \@@_step:wwwN #1; #2; #3; #4
  {
    \dim_compare:nNnTF {#2} > \c_zero_dim
      { \@@_step:NnnnN > }
      {
        \dim_compare:nNnTF {#2} = \c_zero_dim
          {
            \msg_expandable_error:nnn { kernel } { zero-step } {#4}
            \use_none:nnnn
          }
          { \@@_step:NnnnN < }
      }
      {#1} {#2} {#3} #4
  }
\cs_new:Npn \@@_step:NnnnN #1#2#3#4#5
  {
    \dim_compare:nNnF {#2} #1 {#4}
      {
        #5 {#2}
        \exp_args:NNf \@@_step:NnnnN
          #1 { \dim_eval:n { #2 + #3 } } {#3} {#4} #5
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\dim_step_inline:nnnn}
% \begin{macro}{\dim_step_variable:nnnNn}
% \begin{macro}{\@@_step:NNnnnn}
%   The approach here is to build a function, with a global integer
%   required to make the nesting safe (as seen in other in line
%   functions), and map that function using \cs{dim_step_function:nnnN}.
%   We put a \cs{prg_break_point:Nn} so that \texttt{map_break}
%   functions from other modules correctly decrement \cs{g__kernel_prg_map_int}
%   before looking for their own break point.  The first argument is
%   \cs{scan_stop:}, so that no breaking function recognizes this break
%   point as its own.
%    \begin{macrocode}
\cs_new_protected:Npn \dim_step_inline:nnnn
  {
    \int_gincr:N \g__kernel_prg_map_int
    \exp_args:NNc \@@_step:NNnnnn
      \cs_gset_protected:Npn
      { @@_map_ \int_use:N \g__kernel_prg_map_int :w }
  }
\cs_new_protected:Npn \dim_step_variable:nnnNn #1#2#3#4#5
  {
    \int_gincr:N \g__kernel_prg_map_int
    \exp_args:NNc \@@_step:NNnnnn
      \cs_gset_protected:Npx
      { @@_map_ \int_use:N \g__kernel_prg_map_int :w }
      {#1}{#2}{#3}
      {
        \tl_set:Nn \exp_not:N #4 {##1}
        \exp_not:n {#5}
      }
  }
\cs_new_protected:Npn \@@_step:NNnnnn #1#2#3#4#5#6
  {
    #1 #2 ##1 {#6}
    \dim_step_function:nnnN {#3} {#4} {#5} #2
    \prg_break_point:Nn \scan_stop: { \int_gdecr:N \g__kernel_prg_map_int }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Using \texttt{dim} expressions and variables}
%
% \begin{macro}{\dim_eval:n}
%   Evaluating a dimension expression expandably.
%    \begin{macrocode}
\cs_new:Npn \dim_eval:n #1
  { \dim_use:N \@@_eval:w #1 \@@_eval_end: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\dim_sign:n, \@@_sign:Nw}
%   See \cs{dim_abs:n}.  Contrarily to \cs{int_sign:n} the case of a
%   zero dimension cannot be distinguished from a positive dimension by
%   looking only at the first character, since |0.2pt| and |0pt| start
%   the same way.  We need explicit comparisons.  We start by
%   distinguishing the most common case of a positive dimension.
%    \begin{macrocode}
\cs_new:Npn \dim_sign:n #1
  {
    \int_value:w \exp_after:wN \@@_sign:Nw
      \dim_use:N \@@_eval:w #1 \@@_eval_end: ;
    \exp_stop_f:
  }
\cs_new:Npn \@@_sign:Nw #1#2 ;
  {
    \if_dim:w #1#2 > \c_zero_dim
      1
    \else:
      \if_meaning:w - #1
        -1
      \else:
        0
      \fi:
    \fi:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\dim_use:N, \dim_use:c}
%   Accessing a \meta{dim}.  We hand-code the |c| variant for some speed gain.
%    \begin{macrocode}
\cs_new_eq:NN \dim_use:N \tex_the:D
\cs_new:Npn \dim_use:c #1 { \tex_the:D \cs:w #1 \cs_end: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\dim_to_decimal:n}
% \begin{macro}[EXP]{\@@_to_decimal:w}
%   A function which comes up often enough to deserve a place in the
%   kernel.  Evaluate the dimension expression~|#1| then remove the
%   trailing \texttt{pt}.  When debugging is enabled, the argument is
%   put in parentheses as this prevents the dimension expression from
%   terminating early and leaving extra tokens lying around.  This is
%   used a lot by low-level manipulations.
%    \begin{macrocode}
\cs_new:Npn \dim_to_decimal:n #1
  {
    \exp_after:wN
      \@@_to_decimal:w \dim_use:N \@@_eval:w #1 \@@_eval_end:
  }
\use:x
  {
    \cs_new:Npn \exp_not:N \@@_to_decimal:w
      ##1 . ##2 \tl_to_str:n { pt }
  }
      {
        \int_compare:nNnTF {#2} > \c_zero_int
          { #1 . #2 }
          { #1 }
      }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\dim_to_decimal_in_bp:n}
%   Conversion to big points is done using a scaling inside \cs{@@_eval:w}
%   as \eTeX{} does that using $64$-bit precision. Here, $800/803$ is the
%   integer fraction for $72/72.27$. This is a common case so is hand-coded
%   for accuracy (and speed).
%    \begin{macrocode}
\cs_new:Npn \dim_to_decimal_in_bp:n #1
  { \dim_to_decimal:n { ( #1 ) * 800 / 803 } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\dim_to_decimal_in_sp:n}
%   Another hard-coded conversion: this one is necessary to avoid things going
%   off-scale.
%    \begin{macrocode}
\cs_new:Npn \dim_to_decimal_in_sp:n #1
  { \int_value:w \@@_eval:w #1 \@@_eval_end: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\dim_to_decimal_in_unit:nn}
%   An analogue of \cs{dim_ratio:nn} that produces a decimal number as its
%   result, rather than a rational fraction for use within dimension
%   expressions.
%    \begin{macrocode}
\cs_new:Npn \dim_to_decimal_in_unit:nn #1#2
  {
    \dim_to_decimal:n
      {
        1pt *
        \dim_ratio:nn {#1} {#2}
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\dim_to_fp:n}
%   Defined in \pkg{l3fp-convert}, documented here.
% \end{macro}
%
% \subsection{Viewing \texttt{dim} variables}
%
% \begin{macro}{\dim_show:N, \dim_show:c}
%   Diagnostics.
%    \begin{macrocode}
\cs_new_eq:NN  \dim_show:N \__kernel_register_show:N
\cs_generate_variant:Nn \dim_show:N { c }
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\dim_show:n}
%   Diagnostics.  We don't use the \TeX{} primitive \tn{showthe} to show
%   dimension expressions: this gives a more unified output.
%    \begin{macrocode}
\cs_new_protected:Npn \dim_show:n
  { \msg_show_eval:Nn \dim_eval:n }
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\dim_log:N, \dim_log:c, \dim_log:n}
%   Diagnostics.  Redirect output of \cs{dim_show:n} to the log.
%    \begin{macrocode}
\cs_new_eq:NN \dim_log:N \__kernel_register_log:N
\cs_new_eq:NN \dim_log:c \__kernel_register_log:c
\cs_new_protected:Npn \dim_log:n
  { \msg_log_eval:Nn \dim_eval:n }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Constant dimensions}
%
% \begin{variable}{\c_zero_dim, \c_max_dim}
%   Constant dimensions.
%    \begin{macrocode}
\dim_const:Nn \c_zero_dim { 0 pt }
\dim_const:Nn \c_max_dim { 16383.99999 pt }
%    \end{macrocode}
% \end{variable}
%
% \subsection{Scratch dimensions}
%
% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim}
% \begin{variable}{\g_tmpa_dim, \g_tmpb_dim}
%    We provide two local and two global scratch registers, maybe we
%    need more or less.
%    \begin{macrocode}
\dim_new:N \l_tmpa_dim
\dim_new:N \l_tmpb_dim
\dim_new:N \g_tmpa_dim
\dim_new:N \g_tmpb_dim
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
% \subsection{Creating and initialising \texttt{skip} variables}
%
%    \begin{macrocode}
%<@@=skip>
%    \end{macrocode}
%
% \begin{variable}{\s_@@_stop}
%   Internal scan marks.
%    \begin{macrocode}
\scan_new:N \s_@@_stop
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\skip_new:N, \skip_new:c}
%    Allocation of a new internal registers.
%    \begin{macrocode}
\cs_new_protected:Npn \skip_new:N #1
  {
    \__kernel_chk_if_free_cs:N #1
    \cs:w newskip \cs_end: #1
  }
\cs_generate_variant:Nn \skip_new:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\skip_const:Nn, \skip_const:cn}
%   Contrarily to integer constants, we cannot avoid using a register,
%   even for constants.  See \cs{dim_const:Nn} for why we cannot use
%   \cs{skip_gset:Nn}.
%    \begin{macrocode}
\cs_new_protected:Npn \skip_const:Nn #1#2
  {
    \skip_new:N #1
    \tex_global:D #1 = \skip_eval:n {#2} \scan_stop:
  }
\cs_generate_variant:Nn \skip_const:Nn { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\skip_zero:N, \skip_zero:c}
% \begin{macro}{\skip_gzero:N, \skip_gzero:c}
%   Reset the register to zero.
%    \begin{macrocode}
\cs_new_eq:NN \skip_zero:N  \dim_zero:N
\cs_new_eq:NN \skip_gzero:N \dim_gzero:N
\cs_generate_variant:Nn \skip_zero:N  { c }
\cs_generate_variant:Nn \skip_gzero:N { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {\skip_zero_new:N, \skip_zero_new:c, \skip_gzero_new:N, \skip_gzero_new:c}
%   Create a register if needed, otherwise clear it.
%    \begin{macrocode}
\cs_new_protected:Npn \skip_zero_new:N  #1
  { \skip_if_exist:NTF #1 { \skip_zero:N #1 } { \skip_new:N #1 } }
\cs_new_protected:Npn \skip_gzero_new:N #1
  { \skip_if_exist:NTF #1 { \skip_gzero:N #1 } { \skip_new:N #1 } }
\cs_generate_variant:Nn \skip_zero_new:N  { c }
\cs_generate_variant:Nn \skip_gzero_new:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\skip_if_exist:N, \skip_if_exist:c}
%   Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
%    \begin{macrocode}
\prg_new_eq_conditional:NNn \skip_if_exist:N \cs_if_exist:N
  { TF , T , F , p }
\prg_new_eq_conditional:NNn \skip_if_exist:c \cs_if_exist:c
  { TF , T , F , p }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Setting \texttt{skip} variables}
%
% \begin{macro}{\skip_set:Nn, \skip_set:cn}
% \begin{macro}{\skip_gset:Nn, \skip_gset:cn}
%   Much the same as for dimensions.
%    \begin{macrocode}
\cs_new_protected:Npn \skip_set:Nn #1#2
  { #1 = \tex_glueexpr:D #2 \scan_stop: }
\cs_new_protected:Npn \skip_gset:Nn #1#2
  { \tex_global:D #1 = \tex_glueexpr:D #2 \scan_stop: }
\cs_generate_variant:Nn \skip_set:Nn  { c }
\cs_generate_variant:Nn \skip_gset:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {\skip_set_eq:NN, \skip_set_eq:cN, \skip_set_eq:Nc, \skip_set_eq:cc}
% \begin{macro}
%   {\skip_gset_eq:NN, \skip_gset_eq:cN, \skip_gset_eq:Nc, \skip_gset_eq:cc}
%   All straightforward.
%    \begin{macrocode}
\cs_new_protected:Npn \skip_set_eq:NN #1#2 { #1 = #2 }
\cs_generate_variant:Nn \skip_set_eq:NN { c , Nc , cc }
\cs_new_protected:Npn \skip_gset_eq:NN #1#2 { \tex_global:D #1 = #2 }
\cs_generate_variant:Nn \skip_gset_eq:NN { c , Nc , cc }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\skip_add:Nn, \skip_add:cn}
% \begin{macro}{\skip_gadd:Nn, \skip_gadd:cn}
% \begin{macro}{\skip_sub:Nn, \skip_sub:cn}
% \begin{macro}{\skip_gsub:Nn, \skip_gsub:cn}
%   Using |by| here deals with the (incorrect) case |\skip123|.
%    \begin{macrocode}
\cs_new_protected:Npn \skip_add:Nn #1#2
  { \tex_advance:D #1 \tex_glueexpr:D #2 \scan_stop: }
\cs_new_protected:Npn \skip_gadd:Nn #1#2
  { \tex_global:D \tex_advance:D #1 \tex_glueexpr:D #2 \scan_stop: }
\cs_generate_variant:Nn \skip_add:Nn  { c }
\cs_generate_variant:Nn \skip_gadd:Nn { c }
\cs_new_protected:Npn \skip_sub:Nn #1#2
  { \tex_advance:D #1 - \tex_glueexpr:D #2 \scan_stop: }
\cs_new_protected:Npn \skip_gsub:Nn #1#2
  { \tex_global:D \tex_advance:D #1 - \tex_glueexpr:D #2 \scan_stop: }
\cs_generate_variant:Nn \skip_sub:Nn  { c }
\cs_generate_variant:Nn \skip_gsub:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Skip expression conditionals}
%
% \begin{macro}[pTF]{\skip_if_eq:nn}
%   Comparing skips means doing two expansions to make strings, and then
%   testing them. As a result, only equality is tested.
%    \begin{macrocode}
\prg_new_conditional:Npnn \skip_if_eq:nn #1#2 { p , T , F , TF }
  {
    \str_if_eq:eeTF { \skip_eval:n {#1} } { \skip_eval:n {#2} }
       { \prg_return_true: }
       { \prg_return_false: }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP,pTF]{\skip_if_finite:n}
% \begin{macro}[EXP]{\@@_if_finite:wwNw}
%   With \eTeX{}, we have an easy access to the order of infinities of
%   the stretch and shrink components of a skip.  However, to access
%   both, we either need to evaluate the expression twice, or evaluate
%   it, then call an auxiliary to extract both pieces of information
%   from the result.  Since we are going to need an auxiliary anyways,
%   it is quicker to make it search for the string \texttt{fil} which
%   characterizes infinite glue.
%    \begin{macrocode}
\cs_set_protected:Npn \@@_tmp:w #1
  {
    \prg_new_conditional:Npnn \skip_if_finite:n ##1 { p , T , F , TF }
      {
        \exp_after:wN \@@_if_finite:wwNw
        \skip_use:N \tex_glueexpr:D ##1 ; \prg_return_false:
        #1 ; \prg_return_true: \s_@@_stop
      }
    \cs_new:Npn \@@_if_finite:wwNw ##1 #1 ##2 ; ##3 ##4 \s_@@_stop {##3}
  }
\exp_args:No \@@_tmp:w { \tl_to_str:n { fil } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Using \texttt{skip} expressions and variables}
%
% \begin{macro}{\skip_eval:n}
%   Evaluating a skip expression expandably.
%    \begin{macrocode}
\cs_new:Npn \skip_eval:n #1
  { \skip_use:N \tex_glueexpr:D #1 \scan_stop: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\skip_use:N, \skip_use:c}
%   Accessing a \meta{skip}.
%    \begin{macrocode}
\cs_new_eq:NN \skip_use:N \dim_use:N
\cs_new_eq:NN \skip_use:c \dim_use:c
%    \end{macrocode}
% \end{macro}
%
% \subsection{Inserting skips into the output}
%
% \begin{macro}{\skip_horizontal:N, \skip_horizontal:c, \skip_horizontal:n}
% \begin{macro}{\skip_vertical:N, \skip_vertical:c, \skip_vertical:n}
%    Inserting skips.
%    \begin{macrocode}
\cs_new_eq:NN  \skip_horizontal:N \tex_hskip:D
\cs_new:Npn \skip_horizontal:n #1
  { \skip_horizontal:N \tex_glueexpr:D #1 \scan_stop: }
\cs_new_eq:NN  \skip_vertical:N \tex_vskip:D
\cs_new:Npn \skip_vertical:n #1
  { \skip_vertical:N \tex_glueexpr:D #1 \scan_stop: }
\cs_generate_variant:Nn \skip_horizontal:N { c }
\cs_generate_variant:Nn \skip_vertical:N { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Viewing \texttt{skip} variables}
%
% \begin{macro}{\skip_show:N, \skip_show:c}
%   Diagnostics.
%    \begin{macrocode}
\cs_new_eq:NN  \skip_show:N \__kernel_register_show:N
\cs_generate_variant:Nn \skip_show:N { c }
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\skip_show:n}
%   Diagnostics.  We don't use the \TeX{} primitive \tn{showthe} to show
%   skip expressions: this gives a more unified output.
%    \begin{macrocode}
\cs_new_protected:Npn \skip_show:n
  { \msg_show_eval:Nn \skip_eval:n }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\skip_log:N, \skip_log:c, \skip_log:n}
%   Diagnostics.  Redirect output of \cs{skip_show:n} to the log.
%    \begin{macrocode}
\cs_new_eq:NN \skip_log:N \__kernel_register_log:N
\cs_new_eq:NN \skip_log:c \__kernel_register_log:c
\cs_new_protected:Npn \skip_log:n
  { \msg_log_eval:Nn \skip_eval:n }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Constant skips}
%
% \begin{macro}{\c_zero_skip, \c_max_skip}
%   Skips with no rubber component are just dimensions but need to terminate
%   correctly.
%    \begin{macrocode}
\skip_const:Nn \c_zero_skip { \c_zero_dim }
\skip_const:Nn \c_max_skip { \c_max_dim }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Scratch skips}
%
% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip}
% \begin{variable}{\g_tmpa_skip, \g_tmpb_skip}
%    We provide two local and two global scratch registers, maybe we
%    need more or less.
%    \begin{macrocode}
\skip_new:N \l_tmpa_skip
\skip_new:N \l_tmpb_skip
\skip_new:N \g_tmpa_skip
\skip_new:N \g_tmpb_skip
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
% \subsection{Creating and initialising \texttt{muskip} variables}
%
% \begin{macro}{\muskip_new:N, \muskip_new:c}
% And then we add muskips.
%    \begin{macrocode}
\cs_new_protected:Npn \muskip_new:N #1
  {
    \__kernel_chk_if_free_cs:N #1
    \cs:w newmuskip \cs_end: #1
  }
\cs_generate_variant:Nn \muskip_new:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\muskip_const:Nn, \muskip_const:cn}
%   See \cs{skip_const:Nn}.
%    \begin{macrocode}
\cs_new_protected:Npn \muskip_const:Nn #1#2
  {
    \muskip_new:N #1
    \tex_global:D #1 = \muskip_eval:n {#2} \scan_stop:
  }
\cs_generate_variant:Nn \muskip_const:Nn { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\muskip_zero:N, \muskip_zero:c}
% \begin{macro}{\muskip_gzero:N, \muskip_gzero:c}
%   Reset the register to zero.
%    \begin{macrocode}
\cs_new_protected:Npn \muskip_zero:N #1
  { #1 = \c_zero_muskip }
\cs_new_protected:Npn \muskip_gzero:N #1
  { \tex_global:D #1 = \c_zero_muskip }
\cs_generate_variant:Nn \muskip_zero:N  { c }
\cs_generate_variant:Nn \muskip_gzero:N { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \muskip_zero_new:N, \muskip_zero_new:c,
%     \muskip_gzero_new:N, \muskip_gzero_new:c
%   }
%   Create a register if needed, otherwise clear it.
%    \begin{macrocode}
\cs_new_protected:Npn \muskip_zero_new:N  #1
  { \muskip_if_exist:NTF #1 { \muskip_zero:N #1 } { \muskip_new:N #1 } }
\cs_new_protected:Npn \muskip_gzero_new:N #1
  { \muskip_if_exist:NTF #1 { \muskip_gzero:N #1 } { \muskip_new:N #1 } }
\cs_generate_variant:Nn \muskip_zero_new:N  { c }
\cs_generate_variant:Nn \muskip_gzero_new:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\muskip_if_exist:N, \muskip_if_exist:c}
%   Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
%    \begin{macrocode}
\prg_new_eq_conditional:NNn \muskip_if_exist:N \cs_if_exist:N
  { TF , T , F , p }
\prg_new_eq_conditional:NNn \muskip_if_exist:c \cs_if_exist:c
  { TF , T , F , p }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Setting \texttt{muskip} variables}
%
% \begin{macro}{\muskip_set:Nn, \muskip_set:cn}
% \begin{macro}{\muskip_gset:Nn, \muskip_gset:cn}
%   This should be pretty familiar.
%    \begin{macrocode}
\cs_new_protected:Npn \muskip_set:Nn #1#2
  { #1 = \tex_muexpr:D #2 \scan_stop: }
\cs_new_protected:Npn \muskip_gset:Nn #1#2
  { \tex_global:D #1 = \tex_muexpr:D #2 \scan_stop: }
\cs_generate_variant:Nn \muskip_set:Nn  { c }
\cs_generate_variant:Nn \muskip_gset:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \muskip_set_eq:NN, \muskip_set_eq:cN,
%     \muskip_set_eq:Nc, \muskip_set_eq:cc
%   }
% \begin{macro}
%   {
%     \muskip_gset_eq:NN, \muskip_gset_eq:cN,
%     \muskip_gset_eq:Nc, \muskip_gset_eq:cc
%   }
%   All straightforward.
%    \begin{macrocode}
\cs_new_protected:Npn \muskip_set_eq:NN #1#2 { #1 = #2 }
\cs_generate_variant:Nn \muskip_set_eq:NN { c , Nc , cc }
\cs_new_protected:Npn \muskip_gset_eq:NN #1#2 { \tex_global:D #1 = #2 }
\cs_generate_variant:Nn \muskip_gset_eq:NN { c , Nc , cc }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\muskip_add:Nn, \muskip_add:cn}
% \begin{macro}{\muskip_gadd:Nn, \muskip_gadd:cn}
% \begin{macro}{\muskip_sub:Nn, \muskip_sub:cn}
% \begin{macro}{\muskip_gsub:Nn, \muskip_gsub:cn}
%   Using |by| here deals with the (incorrect) case |\muskip123|.
%    \begin{macrocode}
\cs_new_protected:Npn \muskip_add:Nn #1#2
  { \tex_advance:D #1 \tex_muexpr:D #2 \scan_stop: }
\cs_new_protected:Npn \muskip_gadd:Nn #1#2
  { \tex_global:D \tex_advance:D #1 \tex_muexpr:D #2 \scan_stop: }
\cs_generate_variant:Nn \muskip_add:Nn  { c }
\cs_generate_variant:Nn \muskip_gadd:Nn { c }
\cs_new_protected:Npn \muskip_sub:Nn #1#2
  { \tex_advance:D #1 - \tex_muexpr:D #2 \scan_stop: }
\cs_new_protected:Npn \muskip_gsub:Nn #1#2
  { \tex_global:D \tex_advance:D #1 - \tex_muexpr:D #2 \scan_stop: }
\cs_generate_variant:Nn \muskip_sub:Nn  { c }
\cs_generate_variant:Nn \muskip_gsub:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Using \texttt{muskip} expressions and variables}
%
% \begin{macro}{\muskip_eval:n}
%   Evaluating a muskip expression expandably.
%    \begin{macrocode}
\cs_new:Npn \muskip_eval:n #1
  { \muskip_use:N \tex_muexpr:D #1 \scan_stop: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\muskip_use:N, \muskip_use:c}
%   Accessing a \meta{muskip}.
%    \begin{macrocode}
\cs_new_eq:NN \muskip_use:N \dim_use:N
\cs_new_eq:NN \muskip_use:c \dim_use:c
%    \end{macrocode}
% \end{macro}
%
% \subsection{Viewing \texttt{muskip} variables}
%
% \begin{macro}{\muskip_show:N, \muskip_show:c}
%   Diagnostics.
%    \begin{macrocode}
\cs_new_eq:NN  \muskip_show:N \__kernel_register_show:N
\cs_generate_variant:Nn \muskip_show:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\muskip_show:n}
%   Diagnostics.  We don't use the \TeX{} primitive \tn{showthe} to show
%   muskip expressions: this gives a more unified output.
%    \begin{macrocode}
\cs_new_protected:Npn \muskip_show:n
  { \msg_show_eval:Nn \muskip_eval:n }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\muskip_log:N, \muskip_log:c, \muskip_log:n}
%   Diagnostics.  Redirect output of \cs{muskip_show:n} to the log.
%    \begin{macrocode}
\cs_new_eq:NN \muskip_log:N \__kernel_register_log:N
\cs_new_eq:NN \muskip_log:c \__kernel_register_log:c
\cs_new_protected:Npn \muskip_log:n
  { \msg_log_eval:Nn \muskip_eval:n }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Constant muskips}
%
% \begin{macro}{\c_zero_muskip}
% \begin{macro}{\c_max_muskip}
%   Constant muskips given by their value.
%    \begin{macrocode}
\muskip_const:Nn \c_zero_muskip { 0 mu }
\muskip_const:Nn \c_max_muskip  { 16383.99999 mu }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Scratch muskips}
%
% \begin{variable}{\l_tmpa_muskip, \l_tmpb_muskip}
% \begin{variable}{\g_tmpa_muskip, \g_tmpb_muskip}
%    We provide two local and two global scratch registers, maybe we
%    need more or less.
%    \begin{macrocode}
\muskip_new:N \l_tmpa_muskip
\muskip_new:N \l_tmpb_muskip
\muskip_new:N \g_tmpa_muskip
\muskip_new:N \g_tmpb_muskip
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
