% \iffalse meta-comment
%
%% File: l3skip.dtx Copyright (C) 2004-2011 Frank Mittelbach, The LaTeX3 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
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the "expl3 bundle" (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX3 Project.
%%
%% -----------------------------------------------------------------------
%
%<*driver|package>
\RequirePackage{l3names}
\GetIdInfo$Id: l3skip.dtx 2526 2011-08-09 08:58:42Z joseph $
  {L3 Experimental dimensions and skips}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3skip} package\\ Dimensions and skips^^A
%   \thanks{This file describes v\ExplFileVersion,
%      last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
%  The \LaTeX3 Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released \ExplFileDate}
%
% \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.
%
% \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}
%   will initially be equal to $0$\,pt.
% \end{function}
%
% \begin{function}{\dim_zero:N, \dim_zero:c}
%   \begin{syntax}
%     \cs{dim_zero:N} \meta{dimension}
%   \end{syntax}
%   Sets \meta{dimension} to $0$\,pt within the scope of the current
%   \TeX{} group.
% \end{function}
%
% \begin{function}{\dim_gzero:N, \dim_gzero:c}
%   \begin{syntax}
%     \cs{dim_gzero:N} \meta{dimension}
%   \end{syntax}
%   Sets \meta{dimension} to $0$\,pt globally, \emph{i.e.}~not
%   restricted by the current \TeX{} group level.
% \end{function}
%
% \section{Setting \texttt{dim} variables}
%
% \begin{function}{\dim_add:Nn, \dim_add:cn}
%   \begin{syntax}
%     \cs{dim_add:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Adds the result of the \meta{dimension expression} to the current
%   content of the \meta{dimension}. This assignment is local.
% \end{function}
%
% \begin{function}{\dim_gadd:Nn, \dim_gadd:cn}
%   \begin{syntax}
%     \cs{dim_gadd:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Adds the result of the \meta{dimension expression} to the
%   current content of the \meta{dimension}. This assignment is global.
% \end{function}
%
% \begin{function}{\dim_set:Nn, \dim_set:cn}
%   \begin{syntax}
%     \cs{dim_set:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Sets \meta{dimension} to the value of \meta{dimension expression}, which
%   must evaluate to a length with units.  This assignment is
%   restricted to the current \TeX{} group.
% \end{function}
%
% \begin{function}{\dim_gset:Nn, \dim_gset:cn}
%   \begin{syntax}
%     \cs{dim_gset:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Sets \meta{dimension} to the value of \meta{dimension expression}, which
%   must evaluate to a length with units and may include a rubber
%   component (for example |1 cm plus 0.5 cm|.  This assignment is
%   global and is not limited to the current \TeX{} group level.
% \end{function}
% 
% \begin{function}
%   {\dim_set_eq:NN, \dim_set_eq:cN, \dim_set_eq:Nc, \dim_set_eq:cc}
%   \begin{syntax}
%     \cs{dim_set_eq:NN} \meta{dimension1} \meta{dimension2}
%   \end{syntax}
%   Sets the content of \meta{dimension1} equal to that of
%   \meta{dimension2}. This assignment is restricted to the current
%   \TeX{} group level.
% \end{function}
%
% \begin{function}
%   {\dim_gset_eq:NN, \dim_gset_eq:cN, \dim_gset_eq:Nc, \dim_gset_eq:cc}
%   \begin{syntax}
%     \cs{dim_gset_eq:NN} \meta{dimension1} \meta{dimension2}
%   \end{syntax}
%   Sets the content of \meta{dimension1} equal to that of \meta{dimension2}.
%   This assignment is global and so is not limited by the current
%   \TeX{} group level.
% \end{function}
%
% \begin{function}{\dim_set_max:Nn, \dim_set_max:cn}
%   \begin{syntax}
%     \cs{dim_set_max:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Compares the current value of the \meta{dimension} with that of the
%   \meta{dimension expression}, and sets the \meta{dimension} to the
%   larger of these two value. This assignment is local to the current
%   \TeX{} group.
% \end{function}
%
% \begin{function}{\dim_gset_max:Nn, \dim_gset_max:cn}
%   \begin{syntax}
%     \cs{dim_gset_max:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Compares the current value of the \meta{dimension} with that of the
%   \meta{dimension expression}, and sets the \meta{dimension} to the
%   larger of these two value. This assignment is global.
% \end{function}
%
% \begin{function}{\dim_set_min:Nn, \dim_set_min:cn}
%   \begin{syntax}
%     \cs{dim_set_min:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Compares the current value of the \meta{dimension} with that of the
%   \meta{dimension expression}, and sets the \meta{dimension} to the
%   smaller of these two value. This assignment is local to the current
%   \TeX{} group.
% \end{function}
%
% \begin{function}{\dim_gset_min:Nn, \dim_gset_min:cn}
%   \begin{syntax}
%     \cs{dim_gset_min:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Compares the current value of the \meta{dimension} with that of the
%   \meta{dimension expression}, and sets the \meta{dimension} to the
%   smaller of these two value. This assignment is global.
% \end{function}
%
% \begin{function}{\dim_sub:Nn, \dim_sub:cn}
%   \begin{syntax}
%     \cs{dim_sub:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Subtracts the result of the \meta{dimension expression} to the
%   current content of the \meta{dimension}. This assignment is local.
% \end{function}
%
% \begin{function}{\dim_gsub:Nn, \dim_gsub:cn}
%   \begin{syntax}
%     \cs{dim_gsub:Nn} \meta{dimension} \Arg{dimension expression}
%   \end{syntax}
%   Subtracts the result of the \meta{dimension expression} to the
%   current content of the \meta{dimension}. This assignment is global.
% \end{function}
% 
% \section{Utilities for dimension calculations}
% 
% \begin{function}[EXP]{\dim_ratio:nn}
%   \begin{syntax}
%     \cs{dim_ratio:nn} \Arg{dimexpr1} \Arg{dimexpr2}
%   \end{syntax}
%   Parses the two \meta{dimension expressions} and converts the ratio of
%   the two to a form suitable for use inside a \meta{dimension expression}.
%   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 ration 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}
%   will display |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{dimexpr1} \meta{relation} \Arg{dimexpr2}
%     \cs{dim_compare:nNnTF}
%     ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2}
%     ~~\Arg{true code} \Arg{false code}
%   \end{syntax}
%   This function first evaluates each of the \meta{dimension expressions}
%   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}
%   The branching versions then leave either \meta{true code} or
%   \meta{false code} in the input stream, as appropriate to the truth
%   of the test and the variant of the function chosen. The logical
%   truth of the test is left in the input stream by the predicate
%   version.
% \end{function}
%
% \begin{function}[EXP,pTF]{\dim_compare:n}
%   \begin{syntax}
%     \cs{dim_compare_p:n}
%     ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \}
%     \cs{dim_compare:nTF}
%     ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \}
%     ~~\Arg{true code} \Arg{false code}
%   \end{syntax}
%   This function first evaluates each of the \meta{dimension expressions}
%   as described for \cs{dim_eval:n}. The two results are then
%   compared using the \meta{relation}:
%   \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}
%   The branching versions then leave either \meta{true code} or
%   \meta{false code} in the input stream, as appropriate to the truth
%   of the test and the variant of the function chosen. The logical
%   truth of the test is left in the input stream by the predicate
%   version.
% \end{function}
%
% \section{Dimension expression loops}
%
% \begin{function}[EXP]{\dim_do_while:nNnn}
%   \begin{syntax}
%      \cs{dim_do_while:nNnn}
%      ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2} \Arg{code}
%   \end{syntax}
%   Evaluates the relationship between the two \meta{dimension expressions}
%   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 will be repeated, and a loop will occur until the test is
%   \texttt{false}.
% \end{function}
%
% \begin{function}[EXP]{\dim_do_until:nNnn}
%   \begin{syntax}
%      \cs{dim_do_until:nNnn}
%      ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2} \Arg{code}
%   \end{syntax}
%   Evaluates the relationship between the two \meta{dimension expressions}
%   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 will be repeated, and a loop will occur until the test is
%   \texttt{true}.
% \end{function}
%
% \begin{function}[EXP]{\dim_until_do:nNnn}
%   \begin{syntax}
%      \cs{dim_until_do:nNnn}
%      ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2} \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{dimension expressions} as described for \cs{dim_compare:nNnTF}.
%   If the test is \texttt{false} then the \meta{code} will be inserted
%   into the input stream again and a loop will occur until the
%   \meta{relation} is \texttt{true}.
% \end{function}
%
% \begin{function}[EXP]{\dim_while_do:nNnn}
%   \begin{syntax}
%      \cs{dim_while_do:nNnn}
%      ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2} \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{dimension expressions} as described for \cs{dim_compare:nNnTF}.
%   If the test is \texttt{true} then the \meta{code} will be inserted
%   into the input stream again and a loop will occur until the
%   \meta{relation} is \texttt{false}.
% \end{function}
%
% \begin{function}[EXP]{\dim_do_while:nn}
%   \begin{syntax}
%      \cs{dim_do_while:nNnn}
%      ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
%   \end{syntax}
%   Evaluates the relationship between the two \meta{dimension expressions}
%   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 will be repeated, and a loop will occur until the test is
%   \texttt{false}.
% \end{function}
%
% \begin{function}[EXP]{\dim_do_until:nn}
%   \begin{syntax}
%      \cs{dim_do_until:nn}
%      ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
%   \end{syntax}
%   Evaluates the relationship between the two \meta{dimension expressions}
%   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 will be repeated, and a loop will occur until the test is
%   \texttt{true}.
% \end{function}
%
% \begin{function}[EXP]{\dim_until_do:nn}
%   \begin{syntax}
%      \cs{dim_until_do:nn}
%      ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \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{dimension expressions} as described for \cs{dim_compare:nTF}.
%   If the test is \texttt{false} then the \meta{code} will be inserted
%   into the input stream again and a loop will occur until the
%   \meta{relation} is \texttt{true}.
% \end{function}
%
% \begin{function}[EXP]{\dim_while_do:nn}
%   \begin{syntax}
%      \cs{dim_while_do:nn}
%      ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \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{dimension expressions} as described for \cs{dim_compare:nTF}.
%   If the test is \texttt{true} then the \meta{code} will be inserted
%   into the input stream again and a loop will occur until the
%   \meta{relation} is \texttt{false}.
% \end{function}
%
% \section{Using \texttt{dim} expressions and variables}
%
% \begin{function}[EXP]{\dim_eval:n}
%   \begin{syntax}
%     \cs{dim_eval:n} \Arg{dimension expression}
%   \end{syntax}
%   Evaluates the \meta{dimension expression}, 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 will be
%   expressed in points (\texttt{pt}), and will require suitable
%   termination if used in a \TeX{}-style assignment as it is \emph{not}
%   an \meta{internal dimension}.
% \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 will be 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 \cs{the}: this is one of
%     several \LaTeX3 names for this primitive.
%   \end{texnote}
% \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}
%
% \section{Constant dimensions}
%
% \begin{variable}{\c_max_dim}
%   The maximum value that can be stored as a dimension or skip (these
%   are equivalent).
% \end{variable}
%
% \begin{variable}{\c_zero_dim}
%   A zero length as a dimension or a skip (these are equivalent).
% \end{variable}
%
% \section{Scratch dimensions}
%
% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim, \l_tmpc_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}
%   will initially be equal to $0$\,pt.
% \end{function}
%
% \begin{function}{\skip_zero:N, \skip_zero:c}
%   \begin{syntax}
%     \cs{skip_zero:N} \meta{skip}
%   \end{syntax}
%   Sets \meta{skip} to $0$\,pt within the scope of the current
%   \TeX{} group.
% \end{function}
%
% \begin{function}{\skip_gzero:N, \skip_gzero:c}
%   \begin{syntax}
%     \cs{skip_gzero:N} \meta{skip}
%   \end{syntax}
%   Sets \meta{skip} to $0$\,pt globally, \emph{i.e.}~not
%   restricted by the current \TeX{} group level.
% \end{function}
%
% \section{Setting \texttt{skip} variables}
%
% \begin{function}{\skip_add:Nn, \skip_add:cn}
%   \begin{syntax}
%     \cs{skip_add:Nn} \meta{skip} \Arg{skip expression}
%   \end{syntax}
%   Adds the result of the \meta{skip expression} to the current
%   content of the \meta{skip}. This assignment is local.
% \end{function}
%
% \begin{function}{\skip_gadd:Nn, \skip_gadd:cn}
%   \begin{syntax}
%     \cs{skip_gadd:Nn} \meta{skip} \Arg{skip expression}
%   \end{syntax}
%   Adds the result of the \meta{skip expression} to the
%   current content of the \meta{skip}. This assignment is global.
% \end{function}
%
% \begin{function}{\skip_set:Nn, \skip_set:cn}
%   \begin{syntax}
%     \cs{skip_set:Nn} \meta{skip} \Arg{skip expression}
%   \end{syntax}
%   Sets \meta{skip} to the value of \meta{skip expression}, which
%   must evaluate to a length with units and may include a rubber
%   component (for example |1 cm plus 0.5 cm|.  This assignment is
%   restricted to the current \TeX{} group.
% \end{function}
%
% \begin{function}
%   {\skip_gset_eq:NN, \skip_gset_eq:cN, \skip_gset_eq:Nc, \skip_gset_eq:cc}
%   \begin{syntax}
%     \cs{skip_gset_eq:NN} \meta{skip1} \meta{skip2}
%   \end{syntax}
%   Sets the content of \meta{skip1} equal to that of \meta{skip2}.
%   This assignment is global and so is not limited by the current
%   \TeX{} group level.
% \end{function}
%
% \begin{function}{\skip_gset:Nn, \skip_gset:cn}
%   \begin{syntax}
%     \cs{skip_gset:Nn} \meta{skip} \Arg{skip expression}
%   \end{syntax}
%   Sets \meta{skip} to the value of \meta{skip expression}, which
%   must evaluate to a length with units and may include a rubber
%   component (for example |1 cm plus 0.5 cm|.  This assignment is
%   global and is not limited to the current \TeX{} group level.
% \end{function}
% 
% \begin{function}
%   {\skip_set_eq:NN, \skip_set_eq:cN, \skip_set_eq:Nc, \skip_set_eq:cc}
%   \begin{syntax}
%     \cs{skip_set_eq:NN} \meta{skip1} \meta{skip2}
%   \end{syntax}
%   Sets the content of \meta{skip1} equal to that of
%   \meta{skip2}. This assignment is restricted to the current
%   \TeX{} group level.
% \end{function}
%
% \begin{function}{\skip_sub:Nn, \skip_sub:cn}
%   \begin{syntax}
%     \cs{skip_sub:Nn} \meta{skip} \Arg{skip expression}
%   \end{syntax}
%   Subtracts the result of the \meta{skip expression} to the
%   current content of the \meta{skip}. This assignment is local.
% \end{function}
%
% \begin{function}{\skip_gsub:Nn, \skip_gsub:cn}
%   \begin{syntax}
%     \cs{skip_gsub:Nn} \meta{skip} \Arg{skip expression}
%   \end{syntax}
%   Subtracts the result of the \meta{skip expression} to the
%   current content of the \meta{skip}. This assignment is global.
% \end{function}
%
% \section{Skip expression conditionals}
%
%  \begin{function}[EXP,pTF]{\skip_if_eq:nn}
%    \begin{syntax}
%      \cs{skip_if_eq_p:nn}
%      ~~\Arg{skipexpr1} \Arg{skipexpr2}
%      \cs{dim_compare:nTF}
%      ~~\Arg{skipexpr1} \Arg{skipexpr2}
%      ~~\Arg{true code} \Arg{false code}
%    \end{syntax}
%    This function first evaluates each of the
%    \meta{skip expressions} 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.  The branching versions then leave either
%    \meta{true code} or \meta{false code} in the input stream, as
%    appropriate to the truth of the test and the variant of the function
%    chosen. The logical truth of the test is left in the input stream by
%    the predicate version.
%  \end{function}
%
% \begin{function}[EXP,pTF]{\skip_if_infinite_glue:n}
%   \begin{syntax}
%     \cs{skip_if_infinite_glue_p:n} \Arg{skipexpr}
%     \cs{skip_if_infinite_glue:nTF} \Arg{skipexpr}
%     ~~\Arg{true code} \Arg{false code}
%   \end{syntax}
%   Evaluates the \meta{skip expression} as described for \cs{skip_eval:n},
%   and then tests if this contains an infinite stretch or shrink
%   component (or both).
%   The branching versions then leave either \meta{true code} or
%   \meta{false code} in the input stream, as appropriate to the truth
%   of the test and the variant of the function chosen. The logical
%   truth of the test is left in the input stream by the predicate
% \end{function}
%
% \section{Using \texttt{skip} expressions and variables}
%
% \begin{function}[EXP]{\skip_eval:n}
%   \begin{syntax}
%     \cs{skip_eval:n} \Arg{skip expression}
%   \end{syntax}
%   Evaluates the \meta{skip expression}, 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 will be expressed in points (\texttt{pt}),
%   and will require 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 will be 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{skip_eval:n}).
%   \begin{texnote}
%     \cs{skip_use:N} is the \TeX{} primitive \cs{the}: this is one of
%     several \LaTeX3 names for this primitive.
%   \end{texnote}
% \end{function}
%
% \section{Viewing \texttt{skip} variables}
%
% \begin{function}{\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}
%
% \section{Constant skips}
%
% \begin{variable}{\c_max_skip}
%   The maximum value that can be stored as a dimension or skip (these
%   are equivalent).
% \end{variable}
%
% \begin{variable}{\c_zero_skip}
%   A zero length as a dimension or a skip (these are equivalent).
% \end{variable}
%
% \section{Scratch skips}
%
% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip, \l_tmpc_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{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}
%   will initially be equal to $0$\,mu.
% \end{function}
%
% \begin{function}{\muskip_zero:N, \muskip_zero:c}
%   \begin{syntax}
%     \cs{skip_zero:N} \meta{muskip}
%   \end{syntax}
%   Sets \meta{muskip} to $0$\,mu within the scope of the current
%   \TeX{} group.
% \end{function}
%
% \begin{function}{\muskip_gzero:N, \muskip_gzero:c}
%   \begin{syntax}
%     \cs{muskip_gzero:N} \meta{muskip}
%   \end{syntax}
%   Sets \meta{muskip} to $0$\,mu globally, \emph{i.e.}~not
%   restricted by the current \TeX{} group level.
% \end{function}
%
% \section{Setting \texttt{muskip} variables}
%
% \begin{function}{\muskip_add:Nn, \muskip_add:cn}
%   \begin{syntax}
%     \cs{muskip_add:Nn} \meta{muskip} \Arg{muskip expression}
%   \end{syntax}
%   Adds the result of the \meta{muskip expression} to the current
%   content of the \meta{muskip}. This assignment is local.
% \end{function}
%
% \begin{function}{\muskip_gadd:Nn, \muskip_gadd:cn}
%   \begin{syntax}
%     \cs{muskip_gadd:Nn} \meta{muskip} \Arg{muskip expression}
%   \end{syntax}
%   Adds the result of the \meta{muskip expression} to the
%   current content of the \meta{muskip}. This assignment is global.
% \end{function}
%
% \begin{function}{\muskip_set:Nn, \muskip_set:cn}
%   \begin{syntax}
%     \cs{muskip_set:Nn} \meta{muskip} \Arg{muskip expression}
%   \end{syntax}
%   Sets \meta{muskip} to the value of \meta{muskip expression}, which
%   must evaluate to a math length with units and may include a rubber
%   component (for example |1 mu plus 0.5 mu|.  This assignment is
%   restricted to the current \TeX{} group.
% \end{function}
%
% \begin{function}{\muskip_gset:Nn, \muskip_gset:cn}
%   \begin{syntax}
%     \cs{muskip_gset:Nn} \meta{muskip} \Arg{muskip expression}
%   \end{syntax}
%   Sets \meta{muskip} to the value of \meta{muskip expression}, which
%   must evaluate to a math length with units and may include a rubber
%   component (for example |1 mu plus 0.5 mu|.  This assignment is
%   global and is not limited to the current \TeX{} group level.
% \end{function}
% 
% \begin{function}
%   {
%     \muskip_set_eq:NN, \muskip_set_eq:cN,
%     \muskip_set_eq:Nc, \muskip_set_eq:cc
%   }
%   \begin{syntax}
%     \cs{muskip_set_eq:NN} \meta{muskip1} \meta{muskip2}
%   \end{syntax}
%   Sets the content of \meta{muskip1} equal to that of
%   \meta{muskip2}. This assignment is restricted to the current
%   \TeX{} group level.
% \end{function}
%
% \begin{function}
%   {
%     \muskip_gset_eq:NN, \muskip_gset_eq:cN,
%     \muskip_gset_eq:Nc, \muskip_gset_eq:cc
%    }
%   \begin{syntax}
%     \cs{muskip_gset_eq:NN} \meta{muskip1} \meta{muskip2}
%   \end{syntax}
%   Sets the content of \meta{muskip1} equal to that of \meta{muskip2}.
%   This assignment is global and so is not limited by the current
%   \TeX{} group level.
% \end{function}
%
% \begin{function}{\muskip_sub:Nn, \muskip_sub:cn}
%   \begin{syntax}
%     \cs{muskip_sub:Nn} \meta{muskip} \Arg{muskip expression}
%   \end{syntax}
%   Subtracts the result of the \meta{muskip expression} to the
%   current content of the \meta{skip}. This assignment is local.
% \end{function}
%
% \begin{function}{\muskip_gsub:Nn, \muskip_gsub:cn}
%   \begin{syntax}
%     \cs{muskip_gsub:Nn} \meta{muskip} \Arg{muskip expression}
%   \end{syntax}
%   Subtracts the result of the \meta{muskip expression} to the
%   current content of the \meta{muskip}. This assignment is global.
% \end{function}
%
% \section{Using \texttt{muskip} expressions and variables}
%
% \begin{function}[EXP]{\muskip_eval:n}
%   \begin{syntax}
%     \cs{muskip_eval:n} \Arg{muskip expression}
%   \end{syntax}
%   Evaluates the \meta{muskip expression}, 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 will be expressed in \texttt{mu},
%   and will require 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 will be 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 \cs{the}: this is one of
%     several \LaTeX3 names for this primitive.
%   \end{texnote}
% \end{function}
%
% \section{Inserting skips into the output}
%
% \begin{function}{\skip_horizontal:N, \skip_horizontal:c, \skip_horizontal:n}
%   \begin{syntax}
%     \cs{skip_horizontal:N} \meta{skip}
%     \cs{skip_horizontal:n} \Arg{skipexpr}
%   \end{syntax}
%   Inserts a horizontal \meta{skip} into the current list.
%   \begin{texnote}
%     \cs{skip_horizontal:N} is the \TeX{} primitive \cs{hskip} renamed.
%   \end{texnote}
% \end{function}
%
% \begin{function}{\skip_vertical:N, \skip_vertical:c, \skip_vertical:n}
%   \begin{syntax}
%     \cs{skip_vertical:N} \meta{skip}
%     \cs{skip_vertical:n} \Arg{skipexpr}
%   \end{syntax}
%   Inserts a vertical \meta{skip} into the current list.
%   \begin{texnote}
%     \cs{skip_vertical:N} is the \TeX{} primitive \cs{vskip} renamed.
%   \end{texnote}
% \end{function}
%
% \section{Viewing \texttt{muskip} variables}
%
% \begin{function}{\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}
%
% \section{Internal functions}
%
% \begin{function}{\if_dim:w}
%   \begin{syntax}
%     \cs{if_dim:w} \meta{dimen1} \meta{relation} \meta{dimen1}
%     ~~\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 \cs{ifdim}.
%   \end{texnote}
% \end{function}
% 
% \begin{function}[EXP]{\dim_eval:w, \dim_eval_end:}
%   \begin{syntax}
%     \cs{dim_eval:w} \meta{dimexpr} \cs{dim_eval_end:}
%   \end{syntax}
%   Evaluates \meta{dimension expression} as described for \cs{dim_eval:n}.
%   The evaluation stops when an unexpandable token which is not a valid
%   part of a dimension is read or when \cs{dim_eval_end:} is
%   reached. The latter is gobbled by the scanner mechanism:
%   \cs{dim_eval_end:} itself is unexpandable but used correctly
%   the entire construct is expandable.
%   \begin{texnote}
%     This is the \eTeX{} primitive \cs{dimexpr}.
%   \end{texnote}
% \end{function}
%
% \section{Experimental skip functions}
%
% \begin{function}{\skip_split_finite_else_action:nnNN}
%   \begin{syntax}
%     \cs{skip_split_finite_else_action:nnNN} \Arg{skipexpr} \Arg{action}
%     ~~\meta{dimen1} \meta{dimen2}
%   \end{syntax}
%   Checks if the \meta{skipexpr} contains finite glue. If it does then it
%   assigns
%   \meta{dimen1} the stretch component and \meta{dimen2} the shrink
%   component. If
%   it contains infinite glue set \meta{dimen1} and \meta{dimen2} to $0$\,pt
%   and place |#2| into the input stream: this is usually an error or
%   warning message of some sort.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3skip} implementation}
%
%    \begin{macrocode}
%<*initex|package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage
  {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
\package_check_loaded_expl:
%</package>
%    \end{macrocode}
%
% \subsection{Length primitives renamed}
%
% \begin{macro}{\if_dim:w}
% \begin{macro}{\dim_eval:w}
% \begin{macro}{\dim_eval_end:}
%   Primitives renamed.
%    \begin{macrocode}
\cs_new_eq:NN \if_dim:w      \tex_ifdim:D
\cs_new_eq:NN \dim_eval:w    \etex_dimexpr:D
\cs_new_eq:NN \dim_eval_end: \tex_relax:D
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Creating and initialising \texttt{dim} variables}
%
% \begin{macro}{\dim_new:N,\dim_new:c}
%    Allocating \meta{dim} registers \ldots
%    \begin{macrocode}
%<*package>
\cs_new_protected_nopar:Npn \dim_new:N #1
  {
    \chk_if_free_cs:N #1
    \newdimen #1
  }
%</package>
\cs_generate_variant:Nn \dim_new:N { 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.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \dim_zero:N #1 { #1 \c_zero_dim }
\cs_new_protected_nopar:Npn \dim_gzero:N { \pref_global:D \dim_zero:N }
\cs_generate_variant:Nn \dim_zero:N  { c }
\cs_generate_variant:Nn \dim_gzero:N { c }
%    \end{macrocode}
% \end{macro}
% \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.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \dim_set:Nn #1#2
  { #1 ~ \dim_eval:w #2 \dim_eval_end: }
\cs_new_protected_nopar:Npn \dim_gset:Nn { \pref_global:D \dim_set:Nn }
\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.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \dim_set_eq:NN #1#2 { #1 = #2 }
\cs_generate_variant:Nn \dim_set_eq:NN {       c }
\cs_generate_variant:Nn \dim_set_eq:NN { Nc , cc }
\cs_new_protected_nopar:Npn \dim_gset_eq:NN #1#2 { \pref_global:D #1 = #2 }
\cs_generate_variant:Nn \dim_gset_eq:NN {       c }
\cs_generate_variant:Nn \dim_gset_eq:NN { Nc , cc }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\dim_set_max:Nn, \dim_set_max:cn}
% \begin{macro}{\dim_set_min:Nn, \dim_set_min:cn}
% \begin{macro}{\dim_gset_max:Nn, \dim_gset_max:cn}
% \begin{macro}{\dim_gset_min:Nn, \dim_gset_min:cn}
%   Setting maximum and minimum values is simply a case of so build-in
%   comparison. This only applies to dimensions as skips are not ordered.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \dim_set_max:Nn #1#2
  { \dim_compare:nNnT {#1} < {#2} { \dim_set:Nn #1 {#2} } }
\cs_new_protected_nopar:Npn \dim_gset_max:Nn #1#2
  { \dim_compare:nNnT {#1} < {#2} { \dim_gset:Nn #1 {#2} } }
\cs_new_protected_nopar:Npn \dim_set_min:Nn #1#2
  { \dim_compare:nNnT {#1} > {#2} { \dim_set:Nn #1 {#2} } }
\cs_new_protected_nopar:Npn \dim_gset_min:Nn #1#2
  { \dim_compare:nNnT {#1} > {#2} { \dim_gset:Nn #1 {#2} } }
\cs_generate_variant:Nn \dim_set_max:Nn  { c }
\cs_generate_variant:Nn \dim_gset_max:Nn { c }
\cs_generate_variant:Nn \dim_set_min:Nn  { c }
\cs_generate_variant:Nn \dim_gset_min:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \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 deals with the (incorrect) case |\dimen123|.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \dim_add:Nn #1#2
  { \tex_advance:D #1 by \dim_eval:w #2 \dim_eval_end: }
\cs_new_protected_nopar:Npn \dim_gadd:Nn { \pref_global:D \dim_add:Nn }
\cs_generate_variant:Nn \dim_add:Nn  { c }
\cs_generate_variant:Nn \dim_gadd:Nn { c }
\cs_new_protected_nopar:Npn \dim_sub:Nn #1#2
  { \tex_advance:D #1 by - \dim_eval:w #2 \dim_eval_end: }
\cs_new_protected_nopar:Npn \dim_gsub:Nn { \pref_global:D \dim_sub:Nn }
\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}{\dim_ratio:nn}
% \begin{macro}[aux]{\dim_ratio_aux:n}
%   With dimension expressions, something like |10 pt * ( 5 pt / 10 pt )| will
%   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_nopar:Npn \dim_ratio:nn #1#2
  { \dim_ratio_aux:n {#1} / \dim_ratio_aux:n {#2} }
\cs_new_nopar:Npn \dim_ratio_aux:n #1
  { \exp_after:wN \int_value:w \dim_eval:w #1 \dim_eval_end: }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Dimension expression conditionals}
%
% \begin{macro}{\dim_compare_p:nNn}
% \begin{macro}[TF]{\dim_compare:nNn}
%    \begin{macrocode}
\prg_new_conditional:Npnn \dim_compare:nNn #1#2#3 { p , T , F , TF }
  {
    \if_dim:w \dim_eval:w #1 #2 \dim_eval:w #3 \dim_eval_end:
      \prg_return_true: \else: \prg_return_false: \fi:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[pTF]{\dim_compare:n}
% \begin{macro}[aux]{\dim_compare_aux:wNN}
% \begin{macro}[aux]{\dim_compare_<:nw}
% \begin{macro}[aux]{\dim_compare_=:nw}
% \begin{macro}[aux]{\dim_compare_>:nw}
% \begin{macro}[aux]{\dim_compare_==:nw}
% \begin{macro}[aux]{\dim_compare_<=:nw}
% \begin{macro}[aux]{\dim_compare_!=:nw}
% \begin{macro}[aux]{\dim_compare_>=:nw}
%   [This code plus comments are adapted from the \cs{int_compare:nTF}
%   function.]
%   Comparison tests using a simple syntax where only one set of braces
%   is required and additional operators such as |!=| and |>=| are
%   supported. First some notes on the idea behind this. We wish to
%   support writing code like
%   \begin{verbatim}
%     \dim_compare_p:n { 5mm + \l_tmpa_dim >= 4pt - \l_tmpb_dim }
%   \end{verbatim}
%   In other words, we want to somehow add the missing |\dim_eval:w|
%   where required.  We can start evaluating from the left using
%   |\dim_use:N \dim_eval:w|, and we know that since the relation
%   symbols |<|, |>|, |=| and |!| are not allowed in such expressions,
%   they will terminate the expression. Therefore, we first let \TeX{}
%   evaluate this left hand side of the (in)equality.
%
%   Eventually, we will convert the relation symbol to the appropriate
%   version of \cs{if_dim:w}, and add \cs{dim_eval:w} after it. We
%   optimize by placing the end-code already here: this avoids needless
%   grabbing of arguments later.
%    \begin{macrocode}
\prg_new_conditional:Npnn \dim_compare:n #1 { p , T , F , TF }
  {
    \exp_after:wN \dim_compare_aux:wNN \dim_use:N \dim_eval:w #1
        \dim_eval_end:
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
%    \end{macrocode}
%
%   Contrarily to the case of integers, where we have to remove the
%   result in order to access the relation, \cs{dim_use:N} nicely
%   produces a result which ends in |pt|. We can thus use a delimited
%   argument to find the relation. \cs{tl_to_str:n} is needed to
%   convert |pt| to \enquote{other} characters.
%
%   The relation might be one character, |#2|, or two characters |#2#3|.
%   We support the following forms: |=|, |<|, |>| and the extended |!=|,
%   |==|, |<=| and |>=|. All the extended forms have an extra |=| so we
%   check if that is present as well. Then use specific function to
%   perform the (unbalanced) test.
%    \begin{macrocode}
\exp_args:Nno \use:nn
  { \cs_new:Npn \dim_compare_aux:wNN #1 }
  { \tl_to_str:n { pt } }
  #2 #3
    {
      \use:c
        {
          dim_compare_ #2
            \if_meaning:w = #3 = \fi:
          :nw
        }
      { #1 pt } #3
    }
%    \end{macrocode}
%   Here, \cs{dim_eval:w} will begin the right hand side of a dimension
%   comparison (with \cs{if_dim:w}), closed cleanly by the trailing tokens
%   we put in the definition of \cs{dim_compare:n}.
%
%   The actual comparisons take as a first argument the left-hand side
%   of the comparison (a length). In the case of normal comparisons,
%   just place the relevant \cs{if_dim:w}, with a trailing \cs{dim_eval:w}
%   to evaluate the right hand side. For extended comparisons, remove
%   the trailing |=| that we left, before evaluating with \cs{dim_eval:w}.
%   In both cases, the expansion of \cs{dim_eval:w} is stopped properly,
%   and the conditional ended correctly by the tokens we put in the
%   definition of \cs{dim_compare:n}.
%
%   Equal, less than and greater than are straighforward.
%    \begin{macrocode}
\cs_new:cpn { dim_compare_<:nw } #1 { \if_dim:w #1 < \dim_eval:w }
\cs_new:cpn { dim_compare_=:nw } #1 { \if_dim:w #1 = \dim_eval:w }
\cs_new:cpn { dim_compare_>:nw } #1 { \if_dim:w #1 > \dim_eval:w }
%    \end{macrocode}
%   For the extended syntax |==|, we remove |#2|, trailing |=| sign,
%   and otherwise act as for |=|.
%    \begin{macrocode}
\cs_new:cpn {dim_compare_==:nw} #1#2 { \if_dim:w #1 = \dim_eval:w }
%    \end{macrocode}
%
%   Not equal, greater than or equal, less than or equal follow the
%   same scheme as the extended equality syntax, with an additional
%   \cs{reverse_if:N} to get the opposite of their \enquote{simple}
%   analog.
%    \begin{macrocode}
\cs_new:cpn {dim_compare_<=:nw} #1#2 {\reverse_if:N \if_dim:w #1 > \dim_eval:w}
\cs_new:cpn {dim_compare_!=:nw} #1#2 {\reverse_if:N \if_dim:w #1 = \dim_eval:w}
\cs_new:cpn {dim_compare_>=:nw} #1#2 {\reverse_if:N \if_dim:w #1 < \dim_eval:w}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \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_set:Npn \dim_while_do:nn #1#2
  {
    \dim_compare:nT {#1}
      {
        #2
        \dim_while_do:nn {#1} {#2}
      }
  }
\cs_set:Npn \dim_until_do:nn #1#2
  {
    \dim_compare:nF {#1}
      {
        #2
        \dim_until_do:nn {#1} {#2}
      }
  }
\cs_set:Npn \dim_do_while:nn #1#2
  {
    #2
    \dim_compare:nT {#1}
      { \dim_do_while:nNnn {#1} {#2} }
  }
\cs_set: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_set: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_set: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_set: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_set: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{Using \texttt{dim} expressions and variables}
%
% \begin{macro}{\dim_eval:n}
%   Evaluating a dimension expression expandably.
%    \begin{macrocode}
\cs_new_nopar:Npn \dim_eval:n #1
  { \dim_use:N \dim_eval:w #1 \dim_eval_end: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\dim_use:N, \dim_use:c}
%   Accessing a \meta{dim}.
%    \begin{macrocode}
\cs_new_eq:NN \dim_use:N \tex_the:D
\cs_generate_variant:Nn \dim_use:N { c }
%    \end{macrocode}
% \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}
%
% \subsection{Constant dimensions}
%
% \begin{variable}{\c_zero_dim}
% \begin{variable}{\c_max_dim}
%   The source for these depends on whether we are in package mode.
%    \begin{macrocode}
%<*initex>
\dim_new:N \c_zero_dim 
\dim_new:N \c_max_dim
\dim_set:Nn \c_max_dim { 16383.99999 pt }
%</initex>
%<*package>
\cs_new_eq:NN \c_zero_dim \z@
\cs_new_eq:NN \c_max_dim  \maxdimen
%</package>
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
% \subsection{Scratch dimensions}
%
% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim, \l_tmpc_dim}
% \begin{variable}{\g_tmpa_dim, \g_tmpb_dim}
%    We provide three 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 \l_tmpc_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{macro}{\skip_new:N,\skip_new:c}
%    Allocation of a new internal registers.
%    \begin{macrocode}
%<*package>
\cs_new_protected_nopar:Npn \skip_new:N #1
  {
    \chk_if_free_cs:N #1
    \newskip #1
  }
%</package>
\cs_generate_variant:Nn \skip_new:N { 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_protected_nopar:Npn \skip_zero:N #1 { #1 \c_zero_skip }
\cs_new_protected_nopar:Npn \skip_gzero:N { \pref_global:D \skip_zero:N }
\cs_generate_variant:Nn \skip_zero:N  { c }
\cs_generate_variant:Nn \skip_gzero:N { c }
%    \end{macrocode}
% \end{macro}
% \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_nopar:Npn \skip_set:Nn #1#2
  { #1 ~ \etex_glueexpr:D #2 \scan_stop: }
\cs_new_protected_nopar:Npn \skip_gset:Nn { \pref_global:D \skip_set:Nn }
\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_nopar:Npn \skip_set_eq:NN #1#2 { #1 = #2 }
\cs_generate_variant:Nn \skip_set_eq:NN {       c }
\cs_generate_variant:Nn \skip_set_eq:NN { Nc , cc }
\cs_new_protected_nopar:Npn \skip_gset_eq:NN #1#2 { \pref_global:D #1 = #2 }
\cs_generate_variant:Nn \skip_gset_eq:NN {       c }
\cs_generate_variant:Nn \skip_gset_eq:NN { 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_nopar:Npn \skip_add:Nn #1#2
  { \tex_advance:D #1 by \etex_glueexpr:D #2 \scan_stop: }
\cs_new_protected_nopar:Npn \skip_gadd:Nn { \pref_global:D \skip_add:Nn }
\cs_generate_variant:Nn \skip_add:Nn  { c }
\cs_generate_variant:Nn \skip_gadd:Nn { c }
\cs_new_protected_nopar:Npn \skip_sub:Nn #1#2
  { \tex_advance:D #1 by - \etex_glueexpr:D #2 \scan_stop: }
\cs_new_protected_nopar:Npn \skip_gsub:Nn { \pref_global:D \skip_sub:Nn }
\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 }
  {
    \if_int_compare:w
      \pdftex_strcmp:D { \skip_eval:n { #1 } } { \skip_eval:n { #2 } }
      = \c_zero
        \prg_return_true:
    \else:
        \prg_return_false:
    \fi:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\skip_if_infinite_glue:n}
%   With \eTeX{} we all of a sudden get access to a lot information we
%   should otherwise consider ourselves lucky to get. One is
%   the stretch and shrink components of a skip register and the order
%   or those components. cs{skip_if_infinite_glue:nTF} tests it directly by
%   looking at the stretch and shrink order. If either of the predicate
%   functions return \meta{true}, |\bool_if:nTF| will return \meta{true}
%   and the logic test will take the true branch.
%    \begin{macrocode}
\prg_new_conditional:Npnn \skip_if_infinite_glue:n #1 { p , T , F , TF }
  {
    \bool_if:nTF
      {
        \int_compare_p:nNn { \etex_gluestretchorder:D #1 } > \c_zero ||
        \int_compare_p:nNn { \etex_glueshrinkorder:D  #1 } > \c_zero
      }
      { \prg_return_true: }
      { \prg_return_false: }
 }
%    \end{macrocode}
%  \end{macro}
%
% \subsection{Using \texttt{skip} expressions and variables}
%
% \begin{macro}{\skip_eval:n}
%   Evaluating a skip expression expandably.
%    \begin{macrocode}
\cs_new_nopar:Npn \skip_eval:n #1
  { \skip_use:N \etex_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 \tex_the:D
\cs_generate_variant:Nn \skip_use:N { 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_nopar:Npn \skip_horizontal:n #1
  { \skip_horizontal:N \etex_glueexpr:D #1 \scan_stop: }
\cs_new_eq:NN  \skip_vertical:N \tex_vskip:D
\cs_new_nopar:Npn \skip_vertical:n #1
  { \skip_vertical:N \etex_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}
%
% \subsection{Constant skips}
%
% \begin{macro}{\c_zero_skip}
% \begin{macro}{\c_max_skip}
%   Skips with no rubber component are just dimensions
%    \begin{macrocode}
\cs_new_eq:NN \c_zero_skip \c_zero_dim
\cs_new_eq:NN \c_max_skip  \c_max_dim
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Scratch skips}
%
% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip, \l_tmpc_skip}
% \begin{variable}{\g_tmpa_skip, \g_tmpb_skip}
%    We provide three 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 \l_tmpc_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}
%<*package>
\cs_new_protected_nopar:Npn \muskip_new:N #1
  {
    \chk_if_free_cs:N #1
    \newmuskip #1
  }
%</package>
\cs_generate_variant:Nn \muskip_new:N { 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_nopar:Npn \muskip_zero:N #1
  { #1 \c_zero_muskip }
\cs_new_protected_nopar:Npn \muskip_gzero:N { \pref_global:D \muskip_zero:N }
\cs_generate_variant:Nn \muskip_zero:N  { c }
\cs_generate_variant:Nn \muskip_gzero:N { c }
%    \end{macrocode}
% \end{macro}
% \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_nopar:Npn \muskip_set:Nn #1#2
  { #1 ~ \etex_muexpr:D #2 \scan_stop: }
\cs_new_protected_nopar:Npn \muskip_gset:Nn { \pref_global:D \muskip_set:Nn }
\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_nopar:Npn \muskip_set_eq:NN #1#2 { #1 = #2 }
\cs_generate_variant:Nn \muskip_set_eq:NN {       c }
\cs_generate_variant:Nn \muskip_set_eq:NN { Nc , cc }
\cs_new_protected_nopar:Npn \muskip_gset_eq:NN #1#2 { \pref_global:D #1 = #2 }
\cs_generate_variant:Nn \muskip_gset_eq:NN {       c }
\cs_generate_variant:Nn \muskip_gset_eq:NN { 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_nopar:Npn \muskip_add:Nn #1#2
  { \tex_advance:D #1 by \etex_muexpr:D #2 \scan_stop: }
\cs_new_protected_nopar:Npn \muskip_gadd:Nn { \pref_global:D \muskip_add:Nn }
\cs_generate_variant:Nn \muskip_add:Nn  { c }
\cs_generate_variant:Nn \muskip_gadd:Nn { c }
\cs_new_protected_nopar:Npn \muskip_sub:Nn #1#2
  { \tex_advance:D #1 by - \etex_muexpr:D #2 \scan_stop: }
\cs_new_protected_nopar:Npn \muskip_gsub:Nn { \pref_global:D \muskip_sub:Nn }
\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_nopar:Npn \muskip_eval:n #1
  { \muskip_use:N \etex_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 \tex_the:D
\cs_generate_variant:Nn \muskip_use:N { 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}
%
% \subsection{Experimental skip functions}
%
% \begin{macro}{\skip_split_finite_else_action:nnNN}
%   This macro is useful when performing error checking in certain
%   circumstances. If the \m{skip} register holds finite glue it sets
%   |#3| and |#4| to the stretch and shrink component, resp. If it holds
%   infinite glue set |#3| and |#4| to zero and issue the special action
%   |#2| which is probably an error message.
%   Assignments are global.
%    \begin{macrocode}
\cs_new_nopar:Npn \skip_split_finite_else_action:nnNN #1#2#3#4
  {
    \skip_if_infinite_glue:nTF {#1}
    {
      #3 = \c_zero_skip
      #4 = \c_zero_skip
      #2
    }
    {
      #3 = \etex_gluestretch:D #1 \scan_stop:
      #4 = \etex_glueshrink:D  #1 \scan_stop:
    }
  }
%    \end{macrocode}
%  \end{macro}
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
