summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/expl3/l3int.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3int.dtx')
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3int.dtx2240
1 files changed, 1731 insertions, 509 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3int.dtx b/Master/texmf-dist/source/latex/expl3/l3int.dtx
index 10305ee5fe1..f29c018f1e1 100644
--- a/Master/texmf-dist/source/latex/expl3/l3int.dtx
+++ b/Master/texmf-dist/source/latex/expl3/l3int.dtx
@@ -36,7 +36,7 @@
\RequirePackage{l3names}
%</driver|package>
%\fi
-\GetIdInfo$Id: l3int.dtx 2029 2010-09-19 13:59:02Z joseph $
+\GetIdInfo$Id: l3int.dtx 2070 2010-10-09 06:55:11Z joseph $
{L3 Experimental Integer module}
%\iffalse
%<*driver>
@@ -61,183 +61,774 @@
% \maketitle
%
% \begin{documentation}
-%
-% \LaTeX3 maintains two type of integer registers for internal use.
-% One (associated with the name "num") for low level uses in the
-% allocation mechanism using macros only and "int": the one described
-% here.
-%
-% The "int" type uses the built-in counter registers of \TeX{} and is
-% therefore relatively fast compared to the "num" type and should be
-% preferred in all cases as there is little chance we should ever run
-% out of registers when being based on at least \eTeX.
-%
-% \section{Functions}
-%
-% \begin{function}{ \int_new:N |
-% \int_new:c }
-% \begin{syntax}
-% "\int_new:N" <int>
-% \end{syntax}
-% Defines <int> to be a new variable of type "int".
-% \begin{texnote}
-% "\int_new:N" is the equivalent to plain \TeX{}'s \tn{newcount}.
-% \end{texnote}
+%
+%\section{Integer values}
+%
+%
+% Calculation and comparison of integer values can be carried out
+% using literal numbers, \texttt{int} registers, constants and
+% integers stored in token list variables. The standard operators
+% \texttt{+}, \texttt{-}, \texttt{/} and \texttt{*} and
+% parentheses can be used within such expressions to carry
+% arithmetic operations. This module carries out these functions
+% on \emph{integer expressions} (`\texttt{int expr}').
+%
+%\subsection{Integer expressions}
+%
+%\begin{function}{ \int_eval:n / (EXP) }
+% \begin{syntax}
+% \cs{int_eval:n} \Arg{integer expression}
+% \end{syntax}
+% Evaluates the \meta{integer expression}, expanding any
+% integer and token list variables within the \meta{expression}
+% to their content (without requiring \cs{int_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 number. For example
+% both
+% \begin{verbatim}
+% \int_eval:n { 5 + 4 * 3 - ( 3 + 4 * 5 ) }
+% \end{verbatim}
+% and
+% \begin{verbatim}
+% \tl_new:N \l_my_tl
+% \tl_set:Nn \l_my_tl { 5 }
+% \int_new:N \l_my_int
+% \int\set:Nn \l_my_int { 4 }
+% \int_eval:n { \l_my_tl + \l_my_int * 3 - ( 3 + 4 * 5 ) }
+% \end{verbatim}
+% both evaluate to \( -6 \). The \Arg{integer expression} may
+% contain the operators \texttt{+}, \texttt{-}, \texttt{*} and
+% \texttt{/}, along with parenthesis \texttt{(} and \texttt{)}.
+%\end{function}
+%
+%\begin{function}{ \int_abs:n / (EXP) }
+% \begin{syntax}
+% \cs{int_abs:n} \Arg{integer expression}
+% \end{syntax}
+% Evaluates the \meta{integer expression} as described for
+% \cs{int_eval:n} and leaves the absolute value of the result in
+% the input stream.
+%\end{function}
+%
+%\begin{function}{ \int_div_round:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_div_round:nn} \Arg{intexpr1} \Arg{intexpr2}
+% \end{syntax}
+% Evaluates the two \meta{integer expressions} as described earlier,
+% then calculates the result of dividing the first value by the
+% second, rounding any remainder. Note that division using "/"
+% is identical to this function.
+%\end{function}
+%
+%\begin{function}{ \int_div_truncate:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_div_truncate:nn} \Arg{intexpr1} \Arg{intexpr2}
+% \end{syntax}
+% Evaluates the two \meta{integer expressions} as described earlier,
+% then calculates the result of dividing the first value by the
+% second, truncating any remainder. Note that division using "/"
+% rounds the result.
+%\end{function}
+%
+%\begin{function}{
+% \int_max:nn / (EXP) |
+% \int_min:nn / (EXP) |
+%}
+% \begin{syntax}
+% \cs{int_max:nn} \Arg{intexpr1} \Arg{intexpr2}
+% \cs{int_min:nn} \Arg{intexpr1} \Arg{intexpr2}
+% \end{syntax}
+% Evaluates the \meta{integer expressions} as described for
+% \cs{int_eval:n} and leaves either the larger or smaller value
+% in the input stream, depending on the function name.
+%\end{function}
+%
+%\begin{function}{ \int_mod:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_mod:nn} \Arg{intexpr1} \Arg{intexpr2}
+% \end{syntax}
+% Evaluates the two \meta{integer expressions} as described earlier,
+% then calculates the integer remainder of dividing the first
+% expression by the second. This is left in the input stream.
+%\end{function}
+%
+%\subsection{Integer variables}
+%
+%\begin{function}{
+% \int_new:N |
+% \int_new:c |
+%}
+% \begin{syntax}
+% \cs{int_new:N} \meta{integer}
+% \end{syntax}
+% Creates a new \meta{inter} or raises an error if the name is
+% already taken. The declaration is global. The \meta{integer} will
+% initially be equal to \( 0 \).
+%\end{function}
+%
+%\begin{function}{
+% \int_set_eq:NN |
+% \int_set_eq:cN |
+% \int_set_eq:Nc |
+% \int_set_eq:cc |
+%}
+% \begin{syntax}
+% \cs{int_set_eq:NN} \meta{integer1} \meta{integer 2}
+% \end{syntax}
+% Sets the content of \meta{integer1} equal to that of
+% \meta{integer 2}. This assignment is restricted to the current
+% \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \int_gset_eq:NN |
+% \int_gset_eq:cN |
+% \int_gset_eq:Nc |
+% \int_gset_eq:cc |
+%}
+% \begin{syntax}
+% \cs{int_gset_eq:NN} \meta{integer1} \meta{integer2}
+% \end{syntax}
+% Sets the content of \meta{integer1} equal to that of \meta{integer2}.
+% This assignment is global and so is not limited by the current
+% \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \int_add:Nn |
+% \int_add:cn |
+%}
+% \begin{syntax}
+% \cs{int_add:Nn} \meta{integer} \Arg{integer expression}
+% \end{syntax}
+% Adds the result of the \meta{integer expression} to the current
+% content of the \meta{integer}. This assignment is local.
+%\end{function}
+%
+%\begin{function}{
+% \int_gadd:Nn |
+% \int_gadd:cn |
+%}
+% \begin{syntax}
+% \cs{int_gadd:Nn} \meta{integer} \Arg{integer expression}
+% \end{syntax}
+% Adds the result of the \meta{integer expression} to the current
+% content of the \meta{integer}. This assignment is global.
+%\end{function}
+%
+%\begin{function}{
+% \int_decr:N |
+% \int_decr:c |
+%}
+% \begin{syntax}
+% \cs{int_decr:N} \meta{integer}
+% \end{syntax}
+% Decreases the value stored in \meta{integer} by \( 1 \) within
+% the scope of the current \TeX\ group.
+%\end{function}
+%
+%\begin{function}{
+% \int_gdecr:N |
+% \int_gdecr:c |
+%}
+% \begin{syntax}
+% \cs{int_incr:N} \meta{integer}
+% \end{syntax}
+% Decreases the value stored in \meta{integer} by \( 1 \) globally
+% (\emph{i.e}.~not limited by the current group level).
+%\end{function}
+%
+%\begin{function}{
+% \int_incr:N |
+% \int_incr:c |
+%}
+% \begin{syntax}
+% \cs{int_incr:N} \meta{integer}
+% \end{syntax}
+% Increases the value stored in \meta{integer} by \( 1 \) within
+% the scope of the current \TeX\ group.
+%\end{function}
+%
+%\begin{function}{
+% \int_gincr:N |
+% \int_gincr:c |
+%}
+% \begin{syntax}
+% \cs{int_incr:N} \meta{integer}
+% \end{syntax}
+% Increases the value stored in \meta{integer} by \( 1 \) globally
+% (\emph{i.e}.~not limited by the current group level).
+%\end{function}
+%
+%\begin{function}{
+% \int_set:Nn |
+% \int_set:cn |
+%}
+% \begin{syntax}
+% \cs{int_set:Nn} \meta{integer} \Arg{integer expression}
+% \end{syntax}
+% Sets \meta{integer} to the value of \meta{integer expression},
+% which must evaluate to an integer (as described for
+% \cs{int_eval:n}). This assignment is restricted to the
+% current \TeX\ group.
+%\end{function}
+%
+%\begin{function}{
+% \int_gset:Nn |
+% \int_gset:cn |
+%}
+% \begin{syntax}
+% \cs{int_gset:Nn} \meta{integer} \Arg{integer expression}
+% \end{syntax}
+% Sets \meta{integer} to the value of \meta{integer expression},
+% which must evaluate to an integer (as described for
+% \cs{int_eval:n}). This assignment is global and is not limited
+% to the current \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \int_sub:Nn |
+% \int_sub:cn |
+%}
+% \begin{syntax}
+% \cs{int_sub:Nn} \meta{integer} \Arg{integer expression}
+% \end{syntax}
+% Subtracts the result of the \meta{integer expression} to the
+% current content of the \meta{integer}. This assignment is local.
+%\end{function}
+%
+%\begin{function}{
+% \int_gsub:Nn |
+% \int_gsub:cn |
+%}
+% \begin{syntax}
+% \cs{int_gsub:Nn} \meta{integer} \Arg{integer expression}
+% \end{syntax}
+% Subtracts the result of the \meta{integer expression} to the
+% current content of the \meta{integer}. This assignment is global.
+%\end{function}
+%
+%\begin{function}{
+% \int_zero:N |
+% \int_zero:c |
+%}
+% \begin{syntax}
+% \cs{int_zero:N} \meta{integer}
+% \end{syntax}
+% Sets \meta{integer} to \( 0 \) within the scope of the current
+% \TeX\ group.
+%\end{function}
+%
+%\begin{function}{
+% \int_gzero:N |
+% \int_gzero:c |
+%}
+% \begin{syntax}
+% \cs{int_gzero:N} \meta{integer}
+% \end{syntax}
+% Sets \meta{integer} to \( 0 \) globally, \emph{i.e}.~not
+% restricted by the current \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \int_show:N |
+% \int_show:c |
+%}
+% \begin{syntax}
+% \cs{int_show:N} \meta{integer}
+% \end{syntax}
+% Displays the value of the \meta{integer} on the terminal.
+%\end{function}
+%
+%\begin{function}{
+% \int_use:N / (EXP) |
+% \int_use:c / (EXP) |
+%}
+% \begin{syntax}
+% \cs{int_use:N} \meta{integer}
+% \end{syntax}
+% Recovers the content of a \meta{integer} 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{integer} is required (such as in the first and third arguments
+% of \cs{int_compare:nNnTF}).
+%\end{function}
+%
+%\subsection{Comparing integer expressions}
+%
+%\begin{function}{
+% \int_compare_p:nNn / (EXP) |
+% \int_compare:nNn / (EXP) (TF) |
+%}
+% \begin{syntax}
+% \cs{int_compare_p:nNn}
+% ~~\Arg{intexpr1} \meta{relation} \Arg{intexpr2}
+% \cs{int_compare:nNnTF}
+% ~~\Arg{intexpr1} \meta{relation} \Arg{intexpr2}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% This function first evaluates each of the \meta{integer expressions}
+% as described for \cs{int_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}{
+% \int_compare_p:n / (EXP) |
+% \int_compare:n / (EXP) (TF) |
+%}
+% \begin{syntax}
+% \cs{int_compare_p:n}
+% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \}
+% \cs{int_compare:nTF}
+% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% This function first evaluates each of the \meta{integer expressions}
+% as described for \cs{int_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}
+%
+%\begin{function}{
+% \int_if_even_p:n / (EXP) |
+% \int_if_even:n / (EXP) (TF) |
+% \int_if_odd_p:n / (EXP) |
+% \int_if_odd:n / (EXP) (TF) |
+%}
+% \begin{syntax}
+% \cs{int_if_odd_p:n} \Arg{integer expression}
+% \cs{int_if_odd:nTF} \Arg{integer expression}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% This function first evaluates the \meta{integer expression}
+% as described for \cs{int_eval:n}. It then evaluates if this
+% is odd or even, as appropriate. 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}{ \int_do_while:nNnn / (EXP) }
+% \begin{syntax}
+% \cs{int_do_while:nNnn}
+% ~~\Arg{intexpr1} \meta{relation} \Arg{intexpr2} \Arg{code}
+% \end{syntax}
+% Evaluates the relationship between the two \meta{integer expressions}
+% as described for \cs{int_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}{%
-% \int_incr:N |
-% \int_incr:c |
-% \int_gincr:N |
-% \int_gincr:c |
-% }
-% \begin{syntax}
-% "\int_incr:N" <int>
-% \end{syntax}
-% Increments <int> by one. For global variables the global versions
-% should be used.
+%
+%\begin{function}{ \int_do_until:nNnn / (EXP) }
+% \begin{syntax}
+% \cs{int_do_until:nNnn}
+% ~~\Arg{intexpr1} \meta{relation} \Arg{intexpr2} \Arg{code}
+% \end{syntax}
+% Evaluates the relationship between the two \meta{integer expressions}
+% as described for \cs{int_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}{%
-% \int_decr:N |
-% \int_decr:c |
-% \int_gdecr:N |
-% \int_gdecr:c |
-% }
-% \begin{syntax}
-% "\int_decr:N" <int>
-% \end{syntax}
-% Decrements <int> by one. For global variables the global versions
-% should be used.
+%
+%\begin{function}{ \int_until_do:nNnn / (EXP) }
+% \begin{syntax}
+% \cs{int_until_do:nNnn}
+% ~~\Arg{intexpr1} \meta{relation} \Arg{intexpr2} \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{integer expressions} as described for \cs{int_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}{%
-% \int_set:Nn |
-% \int_set:cn |
-% \int_gset:Nn |
-% \int_gset:cn |
-% }
-% \begin{syntax}
-% "\int_set:Nn" <int> \Arg{integer expr}
-% \end{syntax}
-% These functions will set the <int> register to the <integer expr>
-% value. This value can contain simple calc-like expressions as
-% provided by \eTeX.
+%
+%\begin{function}{ \int_while_do:nNnn / (EXP) }
+% \begin{syntax}
+% \cs{int_while_do:nNnn} \
+% ~~\Arg{intexpr1} \meta{relation} \Arg{intexpr2} \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{integer expressions} as described for \cs{int_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}{%
-% \int_zero:N |
-% \int_zero:c |
-% \int_gzero:N |
-% \int_gzero:c |
-% }
-% \begin{syntax}
-% "\int_zero:N" <int>
-% \end{syntax}
-% These functions sets the <int> register to zero either locally
-% or globally.
+%\begin{function}{ \int_do_while:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_do_while:nNnn}
+% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \Arg{code}
+% \end{syntax}
+% Evaluates the relationship between the two \meta{integer expressions}
+% as described for \cs{int_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}{%
-% \int_add:Nn |
-% \int_add:cn |
-% \int_gadd:Nn |
-% \int_gadd:cn |
-% }
-% \begin{syntax}
-% "\int_add:Nn" <int> \Arg{integer expr}
-% \end{syntax}
-% These functions will add to the <int> register the value <integer
-% expr>. If the second argument is a <int> register too, the
-% surrounding braces can be left out.
-% \end{function}
-%
-% \begin{function}{%
-% \int_sub:Nn |
-% \int_sub:cn |
-% \int_gsub:Nn |
-% \int_gsub:cn |
-% }
-% \begin{syntax}
-% "\int_gsub:Nn" <int> \Arg{integer expr}
-% \end{syntax}
-% These functions will subtract from the <int> register the value
-% <integer expr>. If the second argument is a <int> register too, the
-% surrounding braces can be left out.
+%
+%\begin{function}{ \int_do_until:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_do_until:nn}
+% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \Arg{code}
+% \end{syntax}
+% Evaluates the relationship between the two \meta{integer expressions}
+% as described for \cs{int_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}{%
-% \int_use:N |
-% \int_use:c |
-% }
-% \begin{syntax}
-% "\int_use:N" <int>
-% \end{syntax}
-% This function returns the integer value kept in <int> in a way
-% suitable for further processing.
-% \begin{texnote}
-% The function "\int_use:N" could be implemented directly as the \TeX{}
-% primitive "\tex_the:D" which is also responsible to produce the values for
-% other internal quantities. We have chosen to use individual functions
-% for counters, dimensions etc.\ to allow checks and to make the code
-% more self-explaining.
-% \end{texnote}
+%
+%\begin{function}{ \int_until_do:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_until_do:nn}
+% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \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{integer expressions} as described for \cs{int_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}{ \int_show:N |
-% \int_show:c }
-% \begin{syntax}
-% "\int_show:N" <int>
-% \end{syntax}
-% This function pauses the compilation and displays the integer value kept
-% in <int> in the console output and log file.
-% \begin{texnote}
-% The function "\int_show:N" could be implemented directly as the \TeX{}
-% primitive "\tex_showthe:D" which is also responsible to produce the values for
-% other internal quantities. We have chosen to use individual functions
-% for counters, dimensions etc.\ to allow checks and to make the code
-% more self-explanatory.
-% \end{texnote}
+%
+%\begin{function}{ \int_while_do:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_while_do:nn} \
+% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \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{integer expressions} as described for \cs{int_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{Formatting a counter value}
+%\subsection{Formatting integers}
+%
+% Integers can be placed into the output stream with formatting. These
+% conversions apply to any integer expressions.
+%
+%\begin{function}{ \int_to_arabic:n / (EXP) }
+% \begin{syntax}
+% \cs{int_to_arabic:n} \Arg{integer expression}
+% \end{syntax}
+% Places the value of the \meta{integer expression} in the input
+% stream as digits, with category code \( 12 \) (other).
+%\end{function}
+%
+%\begin{function}{
+% \int_to_alph:n / (EXP) |
+% \int_to_Alph:n / (EXP) |
+%}
+% \begin{syntax}
+% \cs{int_to_alph:n} \Arg{integer expression}
+% \end{syntax}
+% Evaluates the \meta{integer expression} and converts the result
+% into a series of letters, which are then left in the input stream.
+% The conversion rule uses the \( 26 \) letters of the English
+% alphabet, in order. Thus
+% \begin{verbatim}
+% \int_to_alph:n { 1 }
+% \end{verbatim}
+% places "a" in the input stream,
+% \begin{verbatim}
+% \int_to_alph:n { 26 }
+% \end{verbatim}
+% is represented as "z" and
+% \begin{verbatim}
+% \int_to_alph:n { 27 }
+% \end{verbatim}
+% is converted to `aa'. For conversions using other alphabets, use
+% \cs{int_convert_to_symbols:nnn} to define an alphabet-specific
+% function. The basic \cs{int_to_alph:n} and \cs{int_to_Alph:n}
+% functions should not be modified.
+%\end{function}
+%
+%\begin{function}{ \int_to_binary:n / (EXP) }
+% \begin{syntax}
+% \cs{int_to_binary:n} \Arg{integer expression}
+% \end{syntax}
+% Calculates the value of the \meta{integer expression} and places
+% the binary representation of the result in the input stream.
+%\end{function}
+%
+%\begin{function}{ \int_to_hexadecimal:n / (EXP) }
+% \begin{syntax}
+% \cs{int_to_binary:n} \Arg{integer expression}
+% \end{syntax}
+% Calculates the value of the \meta{integer expression} and places
+% the hexadecimal (base~\( 16 \)) representation of the result in the
+% input stream. Upper case letters are used for digits beyond \( 9 \).
+%\end{function}
+%
+%\begin{function}{ \int_to_octal:n / (EXP) }
+% \begin{syntax}
+% \cs{int_to_octal:n} \Arg{integer expression}
+% \end{syntax}
+% Calculates the value of the \meta{integer expression} and places
+% the octal (base~\( 8 \)) representation of the result in the input
+% stream.
+%\end{function}
+%
+%\begin{function}{
+% \int_to_roman:n / (EXP) |
+% \int_to_Roman:n / (EXP) |
+%}
+% \begin{syntax}
+% \cs{int_to_roman:n} \Arg{integer expression}
+% \end{syntax}
+% Places the value of the \meta{integer expression} in the input
+% stream as Roman numerals, either lower case (\cs{int_to_roman:n})
+% or upper case (\cs{int_to_Roman:n}). The numerals are letters
+% with category code \( 11 \) (letter).
+%\end{function}
+%
+%\begin{function}{ \int_to_symbol:n / (EXP) }
+% \begin{syntax}
+% \cs{int_to_symbol:n} \Arg{integer expression}
+% \end{syntax}
+% Calculates the value of the \meta{integer expression} and places
+% the symbol representation of the result in the input stream. The
+% list of symbols used is equivalent to \LaTeXe's \cs{@fnsymbol}
+% set.
+%\end{function}
+%
+%\subsection{Converting from other formats}
+%
+%\begin{function}{ \int_from_alph:n / (EXP) }
+% \begin{syntax}
+% \cs{int_from_alpa:n} \Arg{letters}
+% \end{syntax}
+% Converts the \meta{letters} into the integer (base~\( 10 \))
+% representation and leaves this in the input stream. The
+% \meta{letters} are treated using the English alphabet only, with
+% `a' equal to \( 1 \) through to `z' equal to \( 26 \). Either lower
+% or upper case letters may be used. This is the inverse function of
+% \cs{int_to_alph:n}.
+%\end{function}
+%
+%\begin{function}{ \int_from_binary:n / (EXP) }
+% \begin{syntax}
+% \cs{int_from_binary:n} \Arg{binary number}
+% \end{syntax}
+% Converts the \meta{binary number} into the integer (base~\( 10 \))
+% representation and leaves this in the input stream.
+%\end{function}
+%
+%\begin{function}{ \int_from_hexadecimal:n / (EXP) }
+% \begin{syntax}
+% \cs{int_from_binary:n} \Arg{hexadecimal number}
+% \end{syntax}
+% Converts the \meta{hexadecimal number} into the integer
+% (base~\( 10 \)) representation and leaves this in the input stream.
+% Digits greater than \( 9 \) may be represented in the
+% \meta{hexadecimal number} by upper or lower case letters.
+%\end{function}
+%
+%\begin{function}{ \int_from_octal:n / (EXP) }
+% \begin{syntax}
+% \cs{int_from_octal:n} \Arg{octal number}
+% \end{syntax}
+% Converts the \meta{octal number} into the integer (base~\( 10 \))
+% representation and leaves this in the input stream.
+%\end{function}
+%
+%\begin{function}{ \int_from_roman:n / (EXP) }
+% \begin{syntax}
+% \cs{int_from_roman:n} \Arg{roman numeral}
+% \end{syntax}
+% Converts the \meta{roman numeral} into the integer (base~\( 10 \))
+% representation and leaves this in the input stream. The
+% \meta{roman numeral} may be in upper or lower case; if the numeral
+% is not valid then the resulting value will be \( -1 \).
+%\end{function}
+%
+%\subsection{Low-level conversion functions}
+%
+% As well as the higher-level functions already documented, there
+% are a series of lower-level functions which can be used to carry out
+% generic conversions. These are used to create the higher-level
+% versions documented above.
+%
+%\begin{function}{ \int_convert_from_base_ten:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_convert_from_base_ten:nn} \Arg{integer expression}
+% ~~\Arg{base}
+% \end{syntax}
+% Calculates the value of the \meta{integer expression} and
+% converts it into the appropriate representation in the \meta{base};
+% the later may be given as an integer expression. For bases greater
+% than \( 10 \) the higher `digits' are represented by the upper case
+% letters from the English alphabet (with normal category codes). The
+% maximum \meta{base} value is \( 36 \).
+%\end{function}
+%
+%\begin{function}{ \int_convert_to_base_ten:nn / (EXP) }
+% \begin{syntax}
+% \cs{int_convert_to_base_ten:nn} \Arg{number}
+% ~~\Arg{base}
+% \end{syntax}
+% Converts the \meta{number} in \meta{base} into the appropriate
+% value in base \( 10 \). The \meta{number} should consist of
+% digits and letters (either lower or upper case), plus optionally
+% a leading sign. The maximum \meta{base} value is \( 36 \).
+%\end{function}
+%
+%\begin{function}{ \int_convert_to_symbols:nnn / (EXP) }
+% \begin{syntax}
+% \cs{int_convert_to_symbols:nnn}
+% ~~\Arg{integer expression} \Arg{total symbols}
+% ~~\meta{value to symbol mapping}
+% \end{syntax}
+% This is the low-level function for conversion of an
+% \meta{integer expression} into a symbolic form (which will often
+% be letters). The \meta{total symbols} available should be given
+% as an integer expression. Values are actually converted to symbols
+% according to the \meta{value to symbol mapping}. This should be given
+% as \meta{total symbols} pairs of entries, a number and the
+% appropriate symbol. Thus the \cs{int_to_alph:n} function is defined
+% as
+% \begin{verbatim}
+% \cs_new:Npn \int_to_alph:n #1 {
+% \int_convert_to_sybols:nnn {#1} { 26 }
+% {
+% { 1 } { a }
+% { 2 } { b }
+% { 3 } { c }
+% { 4 } { d }
+% { 5 } { e }
+% { 6 } { f }
+% { 7 } { g }
+% { 8 } { h }
+% { 9 } { i }
+% { 10 } { j }
+% { 11 } { k }
+% { 12 } { l }
+% { 13 } { m }
+% { 14 } { n }
+% { 15 } { o }
+% { 16 } { p }
+% { 17 } { q }
+% { 18 } { r }
+% { 19 } { s }
+% { 20 } { t }
+% { 21 } { u }
+% { 22 } { v }
+% { 23 } { w }
+% { 24 } { x }
+% { 25 } { y }
+% { 26 } { z }
+% }
+% }
+% \end{verbatim}
+%\end{function}
+%
+%\section{Variables and constants}
%
-% \begin{function}{
-% \int_to_arabic:n / (EXP) |
-% \int_to_alph:n / (EXP) |
-% \int_to_Alph:n / (EXP) |
-% \int_to_roman:n / (EXP) |
-% \int_to_Roman:n / (EXP) |
-% \int_to_symbol:n / (EXP) |
+% \begin{variable}{%
+% \l_tmpa_int |
+% \l_tmpb_int |
+% \l_tmpc_int |
+% \g_tmpa_int |
+% \g_tmpb_int |
% }
-% \begin{syntax}
-% "\int_to_alph:n" \Arg{integer}
-% "\int_to_alph:n" <int>
-% \end{syntax}
-% If some <integer> or the the current value of a <int> should be
-% displayed or typeset in a special ways (e.g., as uppercase roman
-% numerals) these function can be used. We need braces if the
-% argument is a simple <integer>, they can be omitted in case of a
-% <int>. By default the letters produced by "\int_to_roman:n" and
-% "\int_to_Roman:n" have catcode~11.
-%
-% All functions are fully expandable and will therefore produce the
-% correct output when used inside of deferred writes, etc. In case the
-% number in an |alph| or |Alph| function is greater than the default
-% base number (26) it follows a simple conversion rule so that 27 is
-% turned into |aa|, 50 into |ax| and so on and so forth. These two
-% functions can be modified quite easily to take a different base
-% number and conversion rule so that other languages can be supported.
-% \begin{texnote}
-% These are more or less the internal \LaTeX2 functions \tn{@arabic},
-% \tn{@alph}, \tn{Alph}, \tn{@roman}, \tn{@Roman}, and \tn{@fnsymbol}
-% except that "\int_to_symbol:n" is also allowed outside math mode.
-% \end{texnote}
-% \end{function}
+% Scratch register for immediate use. They are not used by conditionals
+% or predicate functions.
+% \end{variable}
%
-% \subsection{Internal functions}
+%\begin{function}{
+% \int_const:Nn |
+% \int_const:cn |
+%}
+% \begin{syntax}
+% \cs{int_const:Nn} \meta{integer} \Arg{integer expression}
+% \end{syntax}
+% Creates a new constant \meta{integer} or raises an error if the name
+% is already taken. The value of the \meta{integer} will be set
+% globally to the \meta{integer expression}.
+%\end{function}
+%
+%\begin{variable}{ \c_max_int }
+% The maximum value that can be stored as an integer.
+%\end{variable}
+%
+%\begin{variable}{
+% \c_minus_one |
+% \c_zero |
+% \c_one |
+% \c_two |
+% \c_three |
+% \c_four |
+% \c_five |
+% \c_six |
+% \c_seven |
+% \c_eight |
+% \c_nine |
+% \c_ten |
+% \c_eleven |
+% \c_twelve |
+% \c_thirteen |
+% \c_fourteen |
+% \c_fifteen |
+% \c_sixteen |
+% \c_thirty_two |
+% \c_hundred_one |
+% \c_twohundred_fifty_five |
+% \c_twohundred_fifty_six |
+% \c_thousand |
+% \c_ten_thousand |
+% \c_ten_thousand_one |
+% \c_ten_thousand_two |
+% \c_ten_thousand_three |
+% \c_ten_thousand_four |
+% \c_twenty_thousand |
+%}
+% Integer values used with primitive tests and assignments:
+% self-terminating nature makes these more convenient and faster than
+% literal numbers.
+%\end{variable}
+%
+% \begin{variable}{\c_max_register_int}
+% Maximum number of registers.
+% \end{variable}
+%
+%\subsection{Internal functions}
%
% \begin{function}{\int_to_roman:w / (EXP)}
% \begin{syntax}
@@ -250,17 +841,6 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}{\int_to_number:w / (EXP)}
-% \begin{syntax}
-% "\int_to_number:w" <integer> <space>
-% \end{syntax}
-% Converts <integer> to its numerical string. Note that
-% it produces a string of letters with catcode 12.
-% \begin{texnote}
-% This is the \TeX{} primitive \tn{number} renamed.
-% \end{texnote}
-% \end{function}
-%
% \begin{function}{
% \int_roman_lcuc_mapping:Nnn |
% \int_to_roman_lcuc:NN |
@@ -279,104 +859,92 @@
%
% \begin{function}{
% \int_convert_number_with_rule:nnN |
-% \int_alph_default_conversion_rule:n |
-% \int_Alph_default_conversion_rule:n |
% \int_symbol_math_conversion_rule:n |
% \int_symbol_text_conversion_rule:n |
% }
% \begin{syntax}
% "\int_convert_number_with_rule:nnN" \Arg{int1} \Arg{int2} <function>
-% "\int_alph_default_conversion_rule:n" \Arg{int}
% \end{syntax}
% "\int_convert_number_with_rule:nnN" converts <int1> into letters,
% symbols, whatever as defined by <function>. <int2> denotes the base
% number for the conversion.
% \end{function}
-%
-%
-%
-%
-%
-%
-% \section{Variable and constants}
-%
-% \begin{function}{%
-% \int_const:Nn |
-% }
-% \begin{syntax}
-% "\int_const:Nn" "\c_"<value> \Arg{value}
-% \end{syntax}
-% Defines an integer constant of a certain <value>. If the constant is negative
-% or very large it internally uses an <int> register.
-% \end{function}
-%
-% \begin{variable}{ \c_minus_one | \c_zero | \c_one | \c_two | \c_three |
-% \c_four | \c_five | \c_six | \c_seven | \c_eight |
-% \c_nine | \c_ten | \c_eleven | \c_twelve | \c_thirteen |
-% \c_fourteen | \c_fifteen | \c_sixteen | \c_thirty_two |
-% \c_hundred_one |
-% \c_twohundred_fifty_five | \c_twohundred_fifty_six |
-% \c_thousand |
-% \c_ten_thousand | \c_ten_thousand_one |
-% \c_ten_thousand_two | \c_ten_thousand_three |
-% \c_ten_thousand_four | \c_twenty_thousand }
-% Set of constants denoting useful values.
-% \begin{texnote}
-% Some of these constants have been available under \LaTeX2 under names
-% like \tn{m@ne}, \tn{z@}, \tn{@ne},\tn{tw@}, \tn{thr@@}, etc.
-% \end{texnote}
-% \end{variable}
-%
-% \begin{variable}{%
-% \c_max_int |
-% }
-% Constant that denote the maximum value which can be stored in an
-% <int> register.
-% \end{variable}
-%
-% \begin{variable}{\c_max_register_int}
-% Maximum number of registers.
-% \end{variable}
-%
-%
-% \begin{variable}{%
-% \l_tmpa_int |
-% \l_tmpb_int |
-% \l_tmpc_int |
-% \g_tmpa_int |
-% \g_tmpb_int |
-% }
-% Scratch register for immediate use. They are not used by conditionals
-% or predicate functions.
-% \end{variable}
-%
-%
-%
-%
-% \section{Conversion}
-%
-% \begin{function}{%
-% \int_convert_from_base_ten:nn |
-% }
-% \begin{syntax}
-% "\int_convert_from_base_ten:nn" \Arg{number} \Arg{base}
-% \end{syntax}
-% Converts the base~10 number <number> into its equivalent
-% representation written in base~<base>. Expandable.
-% \end{function}
-%
-%
-% \begin{function}{%
-% \int_convert_to_base_ten:nn |
-% }
-% \begin{syntax}
-% "\int_convert_to_base_ten:nn" \Arg{number} \Arg{base}
-% \end{syntax}
-% Converts the base~<base> number <number> into its equivalent
-% representation written in base~10. <number> can consist of digits
-% and ascii letters. Expandable.
-% \end{function}
-%
+%
+%\begin{function}{
+% \if_num:w / (EXP) |
+% \if_int_compare:w / (EXP)
+%}
+% \begin{syntax}
+% "\if_num:w" <number1> <rel> <number2> <true> "\else:" <false> "\fi:"
+% \end{syntax}
+% Compare two integers using <rel>, which must be one of
+% \texttt{=}, "<" or ">" with category code \(12\).
+% The \cs{else:} branch is optional.
+% \begin{texnote}
+% These are both names for the \TeX\ primitive \cs{ifnum}.
+% \end{texnote}
+%\end{function}
+%
+%\begin{function}{
+% \if_case:w / (EXP) |
+% \or: / (EXP)
+%}
+% \begin{syntax}
+% "\if_case:w" <number> <case0> "\or:" <case1> "\or:" "..." "\else:"
+% <default> "\fi:"
+% \end{syntax}
+% Selects a case to execute based on the value of <number>. The first
+% case (<case0>) is executed if <number> is \(0\), the second
+% (<case1>) if the <number> is \(1\), \emph{etc}. The
+% <number> may be a literal, a constant or an integer
+% expression (\emph{e.g}.~using \cs{int_eval:n}).
+% \begin{texnote}
+% These are the \TeX\ primitives \cs{ifcase} and \cs{or}.
+% \end{texnote}
+%\end{function}
+%
+%\begin{function}{\int_value:w / (EXP)}
+% \begin{syntax}
+% "\int_value:w" <integer>
+% "\int_value:w" <tokens> <optional space>
+% \end{syntax}
+% Expands <tokens> until an <integer> is formed. One space may be
+% gobbled in the process.
+% \begin{texnote}
+% This is the \TeX\ primitive \tn{number}.
+% \end{texnote}
+%\end{function}
+%
+%\begin{function}{
+% \int_eval:w / (EXP) |
+% \int_eval_end:
+%}
+% \begin{syntax}
+% "\int_eval:w" <int expr> "\int_eval_end:"
+% \end{syntax}
+% Evaluates <integer expression> as described for \cs{int_eval:n}.
+% The evalution stops when an unexpandable token with category code
+% other than \(12\) is read or when \cs{int_eval_end:} is
+% reached. The latter is gobbled by the scanner mechanism:
+% \cs{int_eval_end:} itself is unexpandable but used correctly
+% the entire construct is expandable.
+% \begin{texnote}
+% This is the \eTeX\ primitive \cs{numexpr}.
+% \end{texnote}
+%\end{function}
+%
+%\begin{function}{\if_int_odd:w / (EXP)}
+% \begin{syntax}
+% "\if_int_odd:w" <tokens> <true> "\else:" <false> "\fi:"
+% "\if_int_odd:w" <number> <true> "\else:" <false> "\fi:"
+% \end{syntax}
+% Expands <tokens> until a non-numeric tokens is found, and
+% tests whether the resulting <number> is odd. If so, <true code>
+% is executed. The \cs{else:} branch is optional.
+% \begin{texnote}
+% This is the \TeX\ primitive \cs{ifodd}.
+% \end{texnote}
+%\end{function}
%
% \end{documentation}
%
@@ -435,20 +1003,48 @@
%<*initex|package>
% \end{macrocode}
%
+% \begin{macro}{\int_value:w}
+% \begin{macro}{\int_eval:n,\int_eval:w,\int_eval_end:}
+% \begin{macro}{\if_int_compare:w}
+% \begin{macro}{\if_int_odd:w}
+% \begin{macro}{\if_num:w}
+% \begin{macro}{\if_case:w}
% \begin{macro}{\int_to_roman:w}
-% \begin{macro}{\int_to_number:w}
% \begin{macro}{\int_advance:w}
-% A new name for the primitives.
+% Here are the remaining primitives for number comparisons and
+% expressions.
% \begin{macrocode}
+\cs_set_eq:NN \int_value:w \tex_number:D
+\cs_set_eq:NN \int_eval:w \etex_numexpr:D
+\cs_set_protected:Npn \int_eval_end: {\tex_relax:D}
+\cs_set_eq:NN \if_int_compare:w \tex_ifnum:D
+\cs_new_eq:NN \if_num:w \tex_ifnum:D
+\cs_set_eq:NN \if_int_odd:w \tex_ifodd:D
+\cs_new_eq:NN \if_case:w \tex_ifcase:D
\cs_new_eq:NN \int_to_roman:w \tex_romannumeral:D
-\cs_new_eq:NN \int_to_number:w \tex_number:D
\cs_new_eq:NN \int_advance:w \tex_advance:D
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
-% Functions that support \LaTeX's user accessible counters should be
-% added here, too. But first the internal counters.
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macro}{\int_eval:n}
+% Wrapper for \cs{int_eval:w}. Can be used in an integer expression
+% or directly in the input stream.
+% \begin{macrocode}
+\cs_set:Npn \int_eval:n #1{
+ \int_value:w \int_eval:w #1\int_eval_end:
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
%
% \subsection{Allocation and setting}
%
@@ -481,7 +1077,7 @@
% Setting counters is again something that I would like to make
% uniform at the moment to get a better overview.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \int_set:Nn #1#2{#1 \intexpr_eval:w #2\intexpr_eval_end:
+\cs_new_protected_nopar:Npn \int_set:Nn #1#2{#1 \int_eval:w #2\int_eval_end:
%<*check>
\chk_local_or_pref_global:N #1
%</check>
@@ -499,6 +1095,39 @@
% \end{macro}
% \end{macro}
% \end{macro}
+%
+%\begin{macro}{\int_set_eq:NN}
+%\begin{macro}{\int_set_eq:cN}
+%\begin{macro}{\int_set_eq:Nc}
+%\begin{macro}{\int_set_eq:cc}
+%\begin{macro}{\int_gset_eq:NN}
+%\begin{macro}{\int_gset_eq:cN}
+%\begin{macro}{\int_gset_eq:Nc}
+%\begin{macro}{\int_gset_eq:cc}
+% Setting equal means using one integer inside the set function of
+% another.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \int_set_eq:NN #1#2 {
+ \int_set:Nn #1 {#2}
+}
+\cs_generate_variant:Nn \int_set_eq:NN { c }
+\cs_generate_variant:Nn \int_set_eq:NN { Nc }
+\cs_generate_variant:Nn \int_set_eq:NN { cc }
+\cs_new_protected_nopar:Npn \int_gset_eq:NN #1#2 {
+ \int_gset:Nn #1 {#2}
+}
+\cs_generate_variant:Nn \int_gset_eq:NN { c }
+\cs_generate_variant:Nn \int_gset_eq:NN { Nc }
+\cs_generate_variant:Nn \int_gset_eq:NN { cc }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
%
% \begin{macro}{\int_incr:N}
% \begin{macro}{\int_decr:N}
@@ -604,13 +1233,13 @@
% accessed by its number, e.g., |\count23|. Not that it should
% ever happen but\dots
% \begin{macrocode}
- \int_advance:w #1 by \intexpr_eval:w #2\intexpr_eval_end:
+ \int_advance:w #1 by \int_eval:w #2\int_eval_end:
%<*check>
\chk_local_or_pref_global:N #1
%</check>
}
\cs_new_nopar:Npn \int_sub:Nn #1#2{
- \int_advance:w #1-\intexpr_eval:w #2\intexpr_eval_end:
+ \int_advance:w #1-\int_eval:w #2\int_eval_end:
%<*check>
\chk_local_or_pref_global:N #1
%</check>
@@ -667,7 +1296,7 @@
% \begin{macro}{\int_to_arabic:n}
% Nothing exciting here.
% \begin{macrocode}
-\cs_new_nopar:Npn \int_to_arabic:n #1{ \intexpr_eval:n{#1}}
+\cs_new_nopar:Npn \int_to_arabic:n #1{ \int_eval:n{#1}}
% \end{macrocode}
% \end{macro}
%
@@ -711,15 +1340,15 @@
% The commands for producing the lower and upper case roman numerals
% run a loop on one character at a time and also carries some
% information for upper or lower case with it. We put it through
-% |\intexpr_eval:n| first which is safer and more flexible.
+% |\int_eval:n| first which is safer and more flexible.
% \begin{macrocode}
\cs_new_nopar:Npn \int_to_roman:n #1 {
\exp_after:wN \int_to_roman_lcuc:NN \exp_after:wN l
- \int_to_roman:w \intexpr_eval:n {#1} Q
+ \int_to_roman:w \int_eval:n {#1} Q
}
\cs_new_nopar:Npn \int_to_Roman:n #1 {
\exp_after:wN \int_to_roman_lcuc:NN \exp_after:wN u
- \int_to_roman:w \intexpr_eval:n {#1} Q
+ \int_to_roman:w \int_eval:n {#1} Q
}
\cs_new_nopar:Npn \int_to_roman_lcuc:NN #1#2{
\use:c {int_to_#1c_roman_#2:}
@@ -729,6 +1358,33 @@
% \end{macro}
% \end{macro}
% \end{macro}
+%
+%\begin{macro}{\int_convert_to_symbols:nnn}
+% For conversion of integers to arbitrary symbols the method is in
+% general as follows. The input number ("#1") is compared to the total
+% number of symbols available at each place ("#2"). If the input is
+% larger than the total number of symbols available then the modulus
+% is needed, with one added so that the positions don't have to number
+% from zero. Using an \texttt{f}-type expansion, this is done so that
+% the system is recursive. The actual conversion function therefore
+% gets a `nice' number at each stage. Of course, if the initial input
+% was small enough then there is no problem and everything is easy. This
+% is more or less the same as \cs{int_convert_number_with_rule:nnN} but
+% `pre-packaged'.
+% \begin{macrocode}
+\cs_new_nopar:Npn \int_convert_to_symbols:nnn #1#2#3 {
+ \int_compare:nNnTF {#1} > {#2}
+ {
+ \exp_args:Nf \int_convert_to_symbols:nnn
+ { \int_div_truncate:nn { #1 - 1 } {#2} } {#2} {#3}
+ \exp_args:Nf \prg_case_int:nnn
+ { \int_eval:n { 1 + \int_mod:nn { #1 - 1 } {#2} } }
+ {#3} { }
+ }
+ { \exp_args:Nf \prg_case_int:nnn { \int_eval:n {#1} } {#3} { } }
+}
+% \end{macrocode}
+%\end{macro}
%
%
%
@@ -754,72 +1410,97 @@
% otherwise have a tendency to grow quite large.
% \begin{macrocode}
\cs_set_nopar:Npn \int_convert_number_with_rule:nnN #1#2#3{
- \intexpr_compare:nNnTF {#1}>{#2}
+ \int_compare:nNnTF {#1}>{#2}
{
\exp_args:Nf \int_convert_number_with_rule:nnN
- { \intexpr_div_truncate:nn {#1-1}{#2} }{#2}
+ { \int_div_truncate:nn {#1-1}{#2} }{#2}
#3
% \end{macrocode}
% Note that we have to nudge our modulus function so it won't
% return~$0$ as that wouldn't work with |\if_case:w| when that
% expects a positive number to produce a letter.
% \begin{macrocode}
- \exp_args:Nf #3 { \intexpr_eval:n{1+\intexpr_mod:nn {#1-1}{#2}} }
+ \exp_args:Nf #3 { \int_eval:n{1+\int_mod:nn {#1-1}{#2}} }
}
- { \exp_args:Nf #3{ \intexpr_eval:n{#1} } }
+ { \exp_args:Nf #3{ \int_eval:n{#1} } }
}
% \end{macrocode}
% As can be seen it is even simpler to convert to number systems
% that contain 0, since then we don't have to add or subtract 1
% here and there.
% \end{macro}
-%
-% \begin{macro}{\int_alph_default_conversion_rule:n}
-% \begin{macro}{\int_Alph_default_conversion_rule:n}
-% Now we just set up a default conversion rule. Ideally every language
-% should have one such rule, as say in Danish there are 29 letters in
-% the alphabet.
-% \begin{macrocode}
-\cs_new_nopar:Npn \int_alph_default_conversion_rule:n #1{
- \if_case:w #1
- \or: a\or: b\or: c\or: d\or: e\or: f
- \or: g\or: h\or: i\or: j\or: k\or: l
- \or: m\or: n\or: o\or: p\or: q\or: r
- \or: s\or: t\or: u\or: v\or: w\or: x
- \or: y\or: z
- \fi:
-}
-\cs_new_nopar:Npn \int_Alph_default_conversion_rule:n #1{
- \if_case:w #1
- \or: A\or: B\or: C\or: D\or: E\or: F
- \or: G\or: H\or: I\or: J\or: K\or: L
- \or: M\or: N\or: O\or: P\or: Q\or: R
- \or: S\or: T\or: U\or: V\or: W\or: X
- \or: Y\or: Z
- \fi:
-}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
%
%
-% \begin{macro}{\int_to_alph:n}
-% \begin{macro}{\int_to_Alph:n}
-% The actual functions are just instances of the generic function. The
-% second argument of |\int_convert_number_with_rule:nnN| should of
-% course match the number of |\or:|s in the conversion rule.
+%\begin{macro}{\int_to_alph:n}
+%\begin{macro}{\int_to_Alph:n}
+% These both use the above function with input functions that make sense
+% for the alphabet in English.
% \begin{macrocode}
-\cs_new_nopar:Npn \int_to_alph:n #1{
- \int_convert_number_with_rule:nnN {#1}{26}
- \int_alph_default_conversion_rule:n
+\cs_new_nopar:Npn \int_to_alph:n #1 {
+ \int_convert_to_symbols:nnn {#1} { 26 }
+ {
+ { 1 } { a }
+ { 2 } { b }
+ { 3 } { c }
+ { 4 } { d }
+ { 5 } { e }
+ { 6 } { f }
+ { 7 } { g }
+ { 8 } { h }
+ { 9 } { i }
+ { 10 } { j }
+ { 11 } { k }
+ { 12 } { l }
+ { 13 } { m }
+ { 14 } { n }
+ { 15 } { o }
+ { 16 } { p }
+ { 17 } { q }
+ { 18 } { r }
+ { 19 } { s }
+ { 20 } { t }
+ { 21 } { u }
+ { 22 } { v }
+ { 23 } { w }
+ { 24 } { x }
+ { 25 } { y }
+ { 26 } { z }
+ }
}
-\cs_new_nopar:Npn \int_to_Alph:n #1{
- \int_convert_number_with_rule:nnN {#1}{26}
- \int_Alph_default_conversion_rule:n
+\cs_new_nopar:Npn \int_to_Alph:n #1 {
+ \int_convert_to_symbols:nnn {#1} { 26 }
+ {
+ { 1 } { A }
+ { 2 } { B }
+ { 3 } { C }
+ { 4 } { D }
+ { 5 } { E }
+ { 6 } { F }
+ { 7 } { G }
+ { 8 } { H }
+ { 9 } { I }
+ { 10 } { J }
+ { 11 } { K }
+ { 12 } { L }
+ { 13 } { M }
+ { 14 } { N }
+ { 15 } { O }
+ { 16 } { P }
+ { 17 } { Q }
+ { 18 } { R }
+ { 19 } { S }
+ { 20 } { T }
+ { 21 } { U }
+ { 22 } { V }
+ { 23 } { W }
+ { 24 } { X }
+ { 25 } { Y }
+ { 26 } { Z }
+ }
}
% \end{macrocode}
-% \end{macro}
-% \end{macro}
+%\end{macro}
+%\end{macro}
%
% \begin{macro}{\int_to_symbol:n}
% Turning a number into a symbol is also easy enough.
@@ -900,9 +1581,9 @@
% functions. All they do is evaluate the number in advance.
% \begin{macrocode}
\cs_set_nopar:Npn \int_pre_eval_one_arg:Nn #1#2{
- \exp_args:Nf#1{\intexpr_eval:n{#2}}}
+ \exp_args:Nf#1{\int_eval:n{#2}}}
\cs_set_nopar:Npn \int_pre_eval_two_args:Nnn #1#2#3{
- \exp_args:Nff#1{\intexpr_eval:n{#2}}{\intexpr_eval:n{#3}}
+ \exp_args:Nff#1{\int_eval:n{#2}}{\int_eval:n{#3}}
}
% \end{macrocode}
% \end{macro}
@@ -911,22 +1592,649 @@
%
%
%
+%
+%
+% \subsection{Scanning and conversion}
+%
+%
+%\begin{macro}{\int_from_roman:n}
+%\begin{macro}[aux]{\int_from_roman_aux:NN}
+%\begin{macro}[aux]{\int_from_roman_end:w}
+%\begin{macro}[aux]{\int_from_roman_clean_up:w}
+% The method here is to iterate through the input, finding the
+% appropriate value for each letter and building up a sum. This is
+% then evaluated by \TeX.
+% \begin{macrocode}
+\cs_new_nopar:Npn \int_from_roman:n #1 {
+ \tl_if_blank:nF {#1}
+ {
+ \tex_expandafter:D \int_from_roman_end:w
+ \tex_number:D \etex_numexpr:D
+ \int_from_roman_aux:NN #1 Q \q_stop
+ }
+}
+\cs_new_nopar:Npn \int_from_roman_aux:NN #1#2 {
+ \str_if_eq:nnTF {#1} { Q }
+ {#1#2}
+ {
+ \str_if_eq:nnTF {#2} { Q }
+ {
+ \cs_if_exist:cF { c_int_from_roman_ #1 _int }
+ { \int_from_roman_clean_up:w }
+ +
+ \use:c { c_int_from_roman_ #1 _int }
+ #2
+ }
+ {
+ \cs_if_exist:cF { c_int_from_roman_ #1 _int }
+ { \int_from_roman_clean_up:w }
+ \cs_if_exist:cF { c_int_from_roman_ #2 _int }
+ { \int_from_roman_clean_up:w }
+ \int_compare:nNnTF
+ { \use:c { c_int_from_roman_ #1 _int } }
+ <
+ { \use:c { c_int_from_roman_ #2 _int } }
+ {
+ + \use:c { c_int_from_roman_ #2 _int }
+ - \use:c { c_int_from_roman_ #1 _int }
+ \int_from_roman_aux:NN
+ }
+ {
+ + \use:c { c_int_from_roman_ #1 _int }
+ \int_from_roman_aux:NN #2
+ }
+ }
+ }
+}
+\cs_new_nopar:Npn \int_from_roman_end:w #1 Q #2 \q_stop {
+ \tl_if_empty:nTF {#2} {#1} {#2}
+}
+\cs_new_nopar:Npn \int_from_roman_clean_up:w #1 Q { + 0 Q -1 }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\int_convert_from_base_ten:nn}
+%\begin{macro}[aux]{\int_convert_from_base_ten_aux:nnn}
+%\begin{macro}{\int_convert_number_to_letter:n}
+% Converting from base ten ("#1") to a second base ("#2") starts with
+% a simple sign check. As the input is base \( 10 \) \TeX\ can then
+% do the actual work with the sign itself.
+% \begin{macrocode}
+\cs_new:Npn \int_convert_from_base_ten:nn #1#2 {
+ \int_compare:nNnTF {#1} < { 0 }
+ {
+ -
+ \exp_args:Nnf \int_convert_from_base_ten_aux:nnn
+ { } { \int_eval:n { 0 - ( #1 ) } } {#2}
+ }
+ {
+ \exp_args:Nnf \int_convert_from_base_ten_aux:nnn
+ { } { \int_eval:n {#1} } {#2}
+ }
+}
+% \end{macrocode}
+% Here, the idea is to provide a recursive system to deal with the
+% input. The output is build up as argument "#1", which is why it
+% starts off empty in the above. At each pass, the value in "#2" is
+% checked to see if it is less than the new base ("#3"). If it is
+% the it is converted directly and the rest of the output is added in.
+% On the other hand, if the value to convert is greater than or equal
+% to the new base then the modulus and remainder values are found. The
+% modulus is converted to a symbol and the remainder is carried forward
+% to the next round.S
+% \begin{macrocode}
+\cs_new:Npn \int_convert_from_base_ten_aux:nnn #1#2#3 {
+ \int_compare:nNnTF {#2} < {#3}
+ {
+ \int_convert_number_to_letter:n {#2}
+ #1
+ }
+ {
+ \exp_args:Nff \int_convert_from_base_ten_aux:nnn
+ {
+ \int_convert_number_to_letter:n
+ { \int_mod:nn {#2} {#3} }
+ #1
+ }
+ { \int_div_truncate:nn {#2} {#3} }
+ {#3}
+ }
+}
+% \end{macrocode}
+% Convert to a letter only if necessary, otherwise simply return the
+% value unchanged.
+% \begin{macrocode}
+\cs_new:Npn \int_convert_number_to_letter:n #1 {
+ \prg_case_int:nnn { #1 - 9 }
+ {
+ { 1 } { A }
+ { 2 } { B }
+ { 3 } { C }
+ { 4 } { D }
+ { 5 } { E }
+ { 6 } { F }
+ { 7 } { G }
+ { 8 } { H }
+ { 9 } { I }
+ { 10 } { J }
+ { 11 } { K }
+ { 12 } { L }
+ { 13 } { M }
+ { 14 } { N }
+ { 15 } { O }
+ { 16 } { P }
+ { 17 } { Q }
+ { 18 } { R }
+ { 19 } { S }
+ { 20 } { T }
+ { 21 } { U }
+ { 22 } { V }
+ { 23 } { W }
+ { 24 } { X }
+ { 25 } { Y }
+ { 26 } { Z }
+ }
+ {#1}
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\int_convert_to_base_ten:nn}
+%\begin{macro}[aux]{\int_convert_to_base_ten_aux:nn}
+%\begin{macro}[aux]{\int_convert_to_base_ten_aux:nnN}
+%\begin{macro}[aux]{\int_convert_to_base_ten_aux:N}
+%\begin{macro}{\int_get_sign_and_digits:n}
+%\begin{macro}{\int_get_sign:n}
+%\begin{macro}{\int_get_digits:n}
+%\begin{macro}[aux]{\int_get_sign_and_digits_aux:nNNN}
+%\begin{macro}[aux]{\int_get_sign_and_digits_aux:oNNN}
+% Conversion to base ten means stripping off the sign then iterating
+% through the input one token at a time. The total number is then added
+% up as the code loops.
+% \begin{macrocode}
+\cs_new:Npn \int_convert_to_base_ten:nn #1#2 {
+ \int_eval:n
+ {
+ \int_get_sign:n {#1}
+ \exp_args:Nf \int_convert_to_base_ten_aux:nn
+ { \int_get_digits:n {#1} } {#2}
+ }
+}
+\cs_new:Npn \int_convert_to_base_ten_aux:nn #1#2 {
+ \int_convert_to_base_ten_aux:nnN { 0 } { #2 } #1 \q_nil
+}
+\cs_new:Npn \int_convert_to_base_ten_aux:nnN #1#2#3 {
+ \quark_if_nil:NTF #3
+ {#1}
+ {
+ \exp_args:Nf \int_convert_to_base_ten_aux:nnN
+ { \int_eval:n { #1 * #2 + \int_convert_to_base_ten_aux:N #3 } }
+ {#2}
+ }
+}
+% \end{macrocode}
+% The conversion here will take lower or upper case letters and turn
+% them into the appropriate number, hence the two-part nature of the
+% function.
+% \begin{macrocode}
+\cs_new:Npn \int_convert_to_base_ten_aux:N #1 {
+ \int_compare:nNnTF { `#1 } < { 58 }
+ {#1}
+ {
+ \int_eval:n
+ { `#1 - \int_compare:nNnTF { `#1 } < { 91 } { 55 } { 87 } }
+ }
+}
+% \end{macrocode}
+% Finding a number and its sign requires dealing with an arbitrary
+% list of "+" and "-" symbols. This is done by working through token
+% by token until there is something else at the start of the input.
+% The sign of the input is tracked by the first Boolean used by the
+% auxiliary function.
+% \begin{macrocode}
+\cs_new:Npn \int_get_sign_and_digits:n #1 {
+ \int_get_sign_and_digits_aux:nNNN {#1}
+ \c_true_bool \c_true_bool \c_true_bool
+}
+\cs_new:Npn \int_get_sign:n #1 {
+ \int_get_sign_and_digits_aux:nNNN {#1}
+ \c_true_bool \c_true_bool \c_false_bool
+}
+\cs_new:Npn \int_get_digits:n #1 {
+ \int_get_sign_and_digits_aux:nNNN {#1}
+ \c_true_bool \c_false_bool \c_true_bool
+}
+% \end{macrocode}
+% The auxiliary loops through, finding sign tokens and removing them.
+% The sign itself is carried through as a flag.
+% \begin{macrocode}
+\cs_new:Npn \int_get_sign_and_digits_aux:nNNN #1#2#3#4 {
+ \tl_if_head_eq_charcode:fNTF {#1} -
+ {
+ \bool_if:NTF #2
+ {
+ \int_get_sign_and_digits_aux:oNNN
+ { \use_none:n #1 } \c_false_bool #3#4
+ }
+ {
+ \int_get_sign_and_digits_aux:oNNN
+ { \use_none:n #1 } \c_true_bool #3#4
+ }
+ }
+ {
+ \tl_if_head_eq_charcode:fNTF {#1} +
+ { \int_get_sign_and_digits_aux:oNNN { \use_none:n #1 } #2#3#4 }
+ {
+ \bool_if:NT #3 { \bool_if:NF #2 - }
+ \bool_if:NT #4 {#1}
+ }
+ }
+}
+\cs_generate_variant:Nn \int_get_sign_and_digits_aux:nNNN { o }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\int_from_binary:n}
+%\begin{macro}{\int_from_hexadecimal:n}
+%\begin{macro}{\int_from_octal:n}
+%\begin{macro}{\int_to_binary:n}
+%\begin{macro}{\int_to_hexadecimal:n}
+%\begin{macro}{\int_to_octal:n}
+% Wrappers around the generic function.
+% \begin{macrocode}
+\cs_new:Npn \int_from_binary:n #1 {
+ \int_convert_to_base_ten:nn {#1} { 2 }
+}
+\cs_new:Npn \int_from_hexadecimal:n #1 {
+ \int_convert_to_base_ten:nn {#1} { 16 }
+}
+\cs_new:Npn \int_from_octal:n #1 {
+ \int_convert_to_base_ten:nn {#1} { 8 }
+}
+\cs_new:Npn \int_to_binary:n #1 {
+ \int_convert_from_base_ten:nn {#1} { 2 }
+}
+\cs_new:Npn \int_to_hexadecimal:n #1 {
+ \int_convert_from_base_ten:nn {#1} { 16 }
+}
+\cs_new:Npn \int_to_octal:n #1 {
+ \int_convert_from_base_ten:nn {#1} { 8 }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\int_from_alph:n}
+%\begin{macro}[aux]{\int_from_alph_aux:n}
+%\begin{macro}[aux]{\int_from_alph_aux:nN}
+%\begin{macro}[aux]{\int_from_alph_aux:N}
+% The aim here is to iterate through the input, converting one letter at
+% a time to a number. The same approach is also used for base
+% conversion, but this needs a different final auxiliary.
+% \begin{macrocode}
+\cs_new:Npn \int_from_alph:n #1 {
+ \int_eval:n
+ {
+ \int_get_sign:n {#1}
+ \exp_args:Nf \int_from_alph_aux:n
+ { \int_get_digits:n {#1} }
+ }
+}
+\cs_new:Npn \int_from_alph_aux:n #1 {
+ \int_from_alph_aux:nN { 0 } #1 \q_nil
+}
+\cs_new:Npn \int_from_alph_aux:nN #1#2 {
+ \quark_if_nil:NTF #2
+ {#1}
+ {
+ \exp_args:Nf \int_from_alph_aux:nN
+ { \int_eval:n { #1 * 26 + \int_from_alph_aux:N #2 } }
+ }
+}
+\cs_new:Npn \int_from_alph_aux:N #1 {
+ \int_eval:n
+ { `#1 - \int_compare:nNnTF { `#1 } < { 91 } { 64 } { 96 } }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%
+% \begin{macro}{\int_compare_p:n}
+% \begin{macro}[TF]{\int_compare:n}
+% 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}
+% \int_compare_p:n { 5 + \l_tmpa_int != 4 - \l_tmpb_int }
+% \end{verbatim}
+% In other words, we want to somehow add the missing "\int_eval:w"
+% where required. We can start evaluating from the left using
+% "\int_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.
+% \begin{macrocode}
+\prg_set_conditional:Npnn \int_compare:n #1{p,TF,T,F}{
+ \exp_after:wN \int_compare_auxi:w \int_value:w
+ \int_eval:w #1\q_stop
+}
+% \end{macrocode}
+% Then the next step is to figure out which relation we should use, so
+% we have to somehow get rid of the first evaluation so that we can
+% see what stopped it. "\tex_romannumeral:D" is handy here since its
+% expansion given a non-positive number is \m{null}. We therefore
+% simply check if the first token of the left hand side evaluation is
+% a minus. If not, we insert it and issue "\tex_romannumeral:D",
+% thereby ridding us of the left hand side evaluation. We do however
+% save it for later.
+% \begin{macrocode}
+\cs_set:Npn \int_compare_auxi:w #1#2\q_stop{
+ \exp_after:wN \int_compare_auxii:w \tex_romannumeral:D
+ \if:w #1- \else: -\fi: #1#2 \q_mark #1#2 \q_stop
+}
+% \end{macrocode}
+% This leaves the first relation symbol in front and assuming the
+% right hand side has been input, at least one other token as well. 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 test.
+% \begin{macrocode}
+\cs_set:Npn \int_compare_auxii:w #1#2#3\q_mark{
+ \use:c{
+ int_compare_
+ #1 \if_meaning:w =#2 = \fi:
+ :w}
+}
+% \end{macrocode}
+% The actual comparisons are then simple function calls, using the
+% relation as delimiter for a delimited argument.
+% Equality is easy:
+% \begin{macrocode}
+\cs_set:cpn {int_compare_=:w} #1=#2\q_stop{
+ \if_int_compare:w #1=\int_eval:w #2 \int_eval_end:
+ \prg_return_true: \else: \prg_return_false: \fi:
+}
+% \end{macrocode}
+% So is the one using |==| -- we just have to use |==| in the
+% parameter text.
+% \begin{macrocode}
+\cs_set:cpn {int_compare_==:w} #1==#2\q_stop{
+ \if_int_compare:w #1=\int_eval:w #2 \int_eval_end:
+ \prg_return_true: \else: \prg_return_false: \fi:
+}
+% \end{macrocode}
+% Not equal is just about reversing the truth value.
+% \begin{macrocode}
+\cs_set:cpn {int_compare_!=:w} #1!=#2\q_stop{
+ \if_int_compare:w #1=\int_eval:w #2 \int_eval_end:
+ \prg_return_false: \else: \prg_return_true: \fi:
+}
+% \end{macrocode}
+% Less than and greater than are also straight forward.
+% \begin{macrocode}
+\cs_set:cpn {int_compare_<:w} #1<#2\q_stop{
+ \if_int_compare:w #1<\int_eval:w #2 \int_eval_end:
+ \prg_return_true: \else: \prg_return_false: \fi:
+}
+\cs_set:cpn {int_compare_>:w} #1>#2\q_stop{
+ \if_int_compare:w #1>\int_eval:w #2 \int_eval_end:
+ \prg_return_true: \else: \prg_return_false: \fi:
+}
+% \end{macrocode}
+% The less than or equal operation is just the opposite of the greater
+% than operation. Vice versa for less than or equal.
+% \begin{macrocode}
+\cs_set:cpn {int_compare_<=:w} #1<=#2\q_stop{
+ \if_int_compare:w #1>\int_eval:w #2 \int_eval_end:
+ \prg_return_false: \else: \prg_return_true: \fi:
+}
+\cs_set:cpn {int_compare_>=:w} #1>=#2\q_stop{
+ \if_int_compare:w #1<\int_eval:w #2 \int_eval_end:
+ \prg_return_false: \else: \prg_return_true: \fi:
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\int_compare_p:nNn}
+% \begin{macro}[TF]{\int_compare:nNn}
+% More efficient but less natural in typing.
+% \begin{macrocode}
+\prg_set_conditional:Npnn \int_compare:nNn #1#2#3{p}{
+ \if_int_compare:w \int_eval:w #1 #2 \int_eval:w #3
+ \int_eval_end:
+ \prg_return_true: \else: \prg_return_false: \fi:
+}
+\cs_set_nopar:Npn \int_compare:nNnT #1#2#3 {
+ \tex_ifnum:D \etex_numexpr:D #1 #2 \etex_numexpr:D #3 \scan_stop:
+ \tex_expandafter:D \use:n
+ \tex_else:D
+ \tex_expandafter:D \use_none:n
+ \tex_fi:D
+}
+\cs_set_nopar:Npn \int_compare:nNnF #1#2#3 {
+ \tex_ifnum:D \etex_numexpr:D #1 #2 \etex_numexpr:D #3 \scan_stop:
+ \tex_expandafter:D \use_none:n
+ \tex_else:D
+ \tex_expandafter:D \use:n
+ \tex_fi:D
+}
+\cs_set_nopar:Npn \int_compare:nNnTF #1#2#3 {
+ \tex_ifnum:D \etex_numexpr:D #1 #2 \etex_numexpr:D #3 \scan_stop:
+ \tex_expandafter:D \use_i:nn
+ \tex_else:D
+ \tex_expandafter:D \use_ii:nn
+ \tex_fi:D
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\int_max:nn}
+% \begin{macro}{\int_min:nn}
+% \begin{macro}{\int_abs:n}
+% Functions for $\min$, $\max$, and absolute value.
+% \begin{macrocode}
+\cs_set:Npn \int_abs:n #1{
+ \int_value:w
+ \if_int_compare:w \int_eval:w #1<\c_zero
+ -
+ \fi:
+ \int_eval:w #1\int_eval_end:
+}
+\cs_set:Npn \int_max:nn #1#2{
+ \int_value:w \int_eval:w
+ \if_int_compare:w
+ \int_eval:w #1>\int_eval:w #2\int_eval_end:
+ #1
+ \else:
+ #2
+ \fi:
+ \int_eval_end:
+}
+\cs_set:Npn \int_min:nn #1#2{
+ \int_value:w \int_eval:w
+ \if_int_compare:w
+ \int_eval:w #1<\int_eval:w #2\int_eval_end:
+ #1
+ \else:
+ #2
+ \fi:
+ \int_eval_end:
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macro}{\int_div_truncate:nn}
+% \begin{macro}{\int_div_round:nn}
+% \begin{macro}{\int_mod:nn}
+% As "\int_eval:w" rounds the result of a division we also
+% provide a version that truncates the result.
+% \begin{macrocode}
+% \end{macrocode}
+% Initial version didn't work correctly with e\TeX's implementation.
+% \begin{macrocode}
+%\cs_set:Npn \int_div_truncate_raw:nn #1#2 {
+% \int_eval:n{ (2*#1 - #2) / (2* #2) }
+%}
+% \end{macrocode}
+% New version by Heiko:
+% \begin{macrocode}
+\cs_set:Npn \int_div_truncate:nn #1#2 {
+ \int_value:w \int_eval:w
+ \if_int_compare:w \int_eval:w #1 = \c_zero
+ 0
+ \else:
+ (#1
+ \if_int_compare:w \int_eval:w #1 < \c_zero
+ \if_int_compare:w \int_eval:w #2 < \c_zero
+ -( #2 +
+ \else:
+ +( #2 -
+ \fi:
+ \else:
+ \if_int_compare:w \int_eval:w #2 < \c_zero
+ +( #2 +
+ \else:
+ -( #2 -
+ \fi:
+ \fi:
+ 1)/2)
+ \fi:
+ /(#2)
+ \int_eval_end:
+}
+% \end{macrocode}
+% For the sake of completeness:
+% \begin{macrocode}
+\cs_set:Npn \int_div_round:nn #1#2 {\int_eval:n{(#1)/(#2)}}
+% \end{macrocode}
+% Finally there's the modulus operation.
+% \begin{macrocode}
+\cs_set:Npn \int_mod:nn #1#2 {
+ \int_value:w
+ \int_eval:w
+ #1 - \int_div_truncate:nn {#1}{#2} * (#2)
+ \int_eval_end:
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\int_if_odd_p:n}
+% \begin{macro}[TF]{\int_if_odd:n}
+% \begin{macro}{\int_if_even_p:n}
+% \begin{macro}[TF]{\int_if_even:n}
+% A predicate function.
+% \begin{macrocode}
+\prg_set_conditional:Npnn \int_if_odd:n #1 {p,TF,T,F} {
+ \if_int_odd:w \int_eval:w #1\int_eval_end:
+ \prg_return_true: \else: \prg_return_false: \fi:
+}
+\prg_set_conditional:Npnn \int_if_even:n #1 {p,TF,T,F} {
+ \if_int_odd:w \int_eval:w #1\int_eval_end:
+ \prg_return_false: \else: \prg_return_true: \fi:
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\int_while_do:nn}
+% \begin{macro}{\int_until_do:nn}
+% \begin{macro}{\int_do_while:nn}
+% \begin{macro}{\int_do_until:nn}
+% These are quite easy given the above functions. The "while" versions
+% test first and then execute the body. The "do_while" does it the
+% other way round.
+% \begin{macrocode}
+\cs_set:Npn \int_while_do:nn #1#2{
+ \int_compare:nT {#1}{#2 \int_while_do:nn {#1}{#2}}
+}
+\cs_set:Npn \int_until_do:nn #1#2{
+ \int_compare:nF {#1}{#2 \int_until_do:nn {#1}{#2}}
+}
+\cs_set:Npn \int_do_while:nn #1#2{
+ #2 \int_compare:nT {#1}{\int_do_while:nNnn {#1}{#2}}
+}
+\cs_set:Npn \int_do_until:nn #1#2{
+ #2 \int_compare:nF {#1}{\int_do_until:nn {#1}{#2}}
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\int_while_do:nNnn}
+% \begin{macro}{\int_until_do:nNnn}
+% \begin{macro}{\int_do_while:nNnn}
+% \begin{macro}{\int_do_until:nNnn}
+% As above but not using the more natural syntax.
+% \begin{macrocode}
+\cs_set:Npn \int_while_do:nNnn #1#2#3#4{
+ \int_compare:nNnT {#1}#2{#3}{#4 \int_while_do:nNnn {#1}#2{#3}{#4}}
+}
+\cs_set:Npn \int_until_do:nNnn #1#2#3#4{
+ \int_compare:nNnF {#1}#2{#3}{#4 \int_until_do:nNnn {#1}#2{#3}{#4}}
+}
+\cs_set:Npn \int_do_while:nNnn #1#2#3#4{
+ #4 \int_compare:nNnT {#1}#2{#3}{\int_do_while:nNnn {#1}#2{#3}{#4}}
+}
+\cs_set:Npn \int_do_until:nNnn #1#2#3#4{
+ #4 \int_compare:nNnF {#1}#2{#3}{\int_do_until:nNnn {#1}#2{#3}{#4}}
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+
% \subsection{Defining constants}
% \begin{macro}{\int_const:Nn}
+% \begin{macro}{\int_const:cn}
% As stated, most constants can be defined as |\tex_chardef:D| or
% |\tex_mathchardef:D| but that's engine dependent.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \int_const:Nn #1#2 {
- \intexpr_compare:nTF { #2 > \c_minus_one }
+ \int_compare:nTF { #2 > \c_minus_one }
{
- \intexpr_compare:nTF { #2 > \c_max_register_int }
+ \int_compare:nTF { #2 > \c_max_register_int }
{
\int_new:N #1
\int_gset:Nn #1 {#2}
}
{
\chk_if_free_cs:N #1
- \tex_global:D \tex_mathchardef:D #1 = \intexpr_eval:n {#2}
+ \tex_global:D \tex_mathchardef:D #1 = \int_eval:n {#2}
}
}
{
@@ -934,6 +2242,16 @@
\int_gset:Nn #1 {#2}
}
}
+\cs_generate_variant:Nn \int_const:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%\begin{macro}{\c_max_register_int}
+% This is here as this particular integer is needed both in package
+% mode and to bootstrap \pkg{l3alloc}
+% \begin{macrocode}
+\tex_mathchardef:D \c_max_register_int = 32767 \scan_stop:
% \end{macrocode}
% \end{macro}
%
@@ -997,196 +2315,100 @@
\int_const:Nn \c_max_int {2147483647}
% \end{macrocode}
% \end{macro}
-%
-%
-%
-% \subsection{Scanning and conversion}
-%
-%
-% Conversion between different numbering schemes requires meticulous
-% work. A number can be preceeded by any number of |+| and/or |-|. We
-% define a generic function which will return the sign and/or the
-% remainder.
-%
-% \begin{macro}{\int_get_sign_and_digits:n}
-% \begin{macro}{\int_get_sign:n}
-% \begin{macro}{\int_get_digits:n}
-% \begin{macro}[aux]{\int_get_sign_and_digits_aux:nNNN}
-% \begin{macro}[aux]{\int_get_sign_and_digits_aux:oNNN}
-% A number may be preceeded by any number of |+|s and |-|s. Start out
-% by assuming we have a positive number.
+%
+%\begin{macro}[aux]{\c_int_from_roman_i_int}
+%\begin{macro}[aux]{\c_int_from_roman_v_int}
+%\begin{macro}[aux]{\c_int_from_roman_x_int}
+%\begin{macro}[aux]{\l_int_from_roman_l_int}
+%\begin{macro}[aux]{\c_int_from_roman_c_int}
+%\begin{macro}[aux]{\c_int_from_roman_d_int}
+%\begin{macro}[aux]{\c_int_from_roman_m_int}
+%\begin{macro}[aux]{\c_int_from_roman_I_int}
+%\begin{macro}[aux]{\c_int_from_roman_V_int}
+%\begin{macro}[aux]{\c_int_from_roman_X_int}
+%\begin{macro}[aux]{\c_int_from_roman_L_int}
+%\begin{macro}[aux]{\c_int_from_roman_C_int}
+%\begin{macro}[aux]{\c_int_from_roman_D_int}
+%\begin{macro}[aux]{\c_int_from_roman_M_int}
+% Delayed from earlier.
% \begin{macrocode}
-\cs_new_nopar:Npn \int_get_sign_and_digits:n #1{
- \int_get_sign_and_digits_aux:nNNN {#1} \c_true_bool \c_true_bool \c_true_bool
-}
-\cs_new_nopar:Npn \int_get_sign:n #1{
- \int_get_sign_and_digits_aux:nNNN {#1} \c_true_bool \c_true_bool \c_false_bool
-}
-\cs_new_nopar:Npn \int_get_digits:n #1{
- \int_get_sign_and_digits_aux:nNNN {#1} \c_true_bool \c_false_bool \c_true_bool
-}
+\int_const:cn { c_int_from_roman_i_int } { 1 }
+\int_const:cn { c_int_from_roman_v_int } { 5 }
+\int_const:cn { c_int_from_roman_x_int } { 10 }
+\int_const:cn { c_int_from_roman_l_int } { 50 }
+\int_const:cn { c_int_from_roman_c_int } { 100 }
+\int_const:cn { c_int_from_roman_d_int } { 500 }
+\int_const:cn { c_int_from_roman_m_int } { 1000 }
+\int_const:cn { c_int_from_roman_I_int } { 1 }
+\int_const:cn { c_int_from_roman_V_int } { 5 }
+\int_const:cn { c_int_from_roman_X_int } { 10 }
+\int_const:cn { c_int_from_roman_L_int } { 50 }
+\int_const:cn { c_int_from_roman_C_int } { 100 }
+\int_const:cn { c_int_from_roman_D_int } { 500 }
+\int_const:cn { c_int_from_roman_M_int } { 1000 }
% \end{macrocode}
-% Now check the first character in the string. Only a |-| can change
-% if a number is positive or negative, hence we reverse the boolean
-% governing this. Then gobble the |-| and start over.
-% \begin{macrocode}
-\cs_new_nopar:Npn \int_get_sign_and_digits_aux:nNNN #1#2#3#4{
- \tl_if_head_eq_charcode:fNTF {#1} -
- {
- \bool_if:NTF #2
- { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} \c_false_bool #3#4 }
- { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} \c_true_bool #3#4 }
- }
-% \end{macrocode}
-% The other cases are much simpler since we either just have to gobble
-% the |+| or exit immediately and insert the correct sign.
-% \begin{macrocode}
- {
- \tl_if_head_eq_charcode:fNTF {#1} +
- { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} #2#3#4}
- {
-% \end{macrocode}
-% The boolean |#3| is for printing the sign while |#4| is for printing
-% the digits.
-% \begin{macrocode}
- \bool_if:NT #3 { \bool_if:NF #2 - }
- \bool_if:NT #4 {#1}
- }
- }
-}
-\cs_generate_variant:Nn \int_get_sign_and_digits_aux:nNNN {oNNN}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-%
-% \begin{macro}{\int_convert_from_base_ten:nn}
-% \begin{macro}[aux]{\int_convert_from_base_ten_aux:nnn}
-% \begin{macro}[aux]{\int_convert_from_base_ten_aux:non}
-% \begin{macro}[aux]{\int_convert_from_base_ten_aux:fon}
-% |#1| is the base 10 number to be converted to base |#2|. We split
-% off the sign first, print if if there and then convert only the
-% number. Since this is supposedly a base~10 number we can let \TeX\
-% do the reading of |+| and |-|.
-% \begin{macrocode}
-\cs_set_nopar:Npn \int_convert_from_base_ten:nn#1#2{
- \intexpr_compare:nNnTF {#1}<\c_zero
- {
- - \int_convert_from_base_ten_aux:nfn {}
- { \intexpr_eval:n {-#1} }
- }
- {
- \int_convert_from_base_ten_aux:nfn {}
- { \intexpr_eval:n {#1} }
- }
- {#2}
-}
-% \end{macrocode}
-% The algorithm runs like this:
-% \begin{enumerate}
-% \item If the number \meta{num} is greater than \meta{base},
-% calculate modulus of \meta{num} and \meta{base} and carry that
-% over for next round. The remainder is calculated as a truncated
-% division of \meta{num} and \meta{base}. Start over with these new
-% values.
-% \item If \meta{num} is less than or equal to \meta{base} convert it
-% to the correct symbol, print the previously calculated digits and
-% exit.
-% \end{enumerate}
-% |#1| is the carried over result, |#2| the remainder and |#3| the
-% base number.
-% \begin{macrocode}
-\cs_new_nopar:Npn \int_convert_from_base_ten_aux:nnn#1#2#3{
- \intexpr_compare:nNnTF {#2}<{#3}
- { \int_convert_number_to_letter:n{#2} #1 }
- {
- \int_convert_from_base_ten_aux:ffn
- {
- \int_convert_number_to_letter:n {\intexpr_mod:nn {#2}{#3}}
- #1
- }
- { \intexpr_div_truncate:nn{#2}{#3}}
- {#3}
- }
-}
-\cs_generate_variant:Nn \int_convert_from_base_ten_aux:nnn {nfn}
-\cs_generate_variant:Nn \int_convert_from_base_ten_aux:nnn {ffn}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
%
-% \begin{macro}{\int_convert_number_to_letter:n}
-% Turning a number for a different base into a letter or digit.
-% \begin{macrocode}
-\cs_set_nopar:Npn \int_convert_number_to_letter:n #1{
- \if_case:w \intexpr_eval:w #1-10\intexpr_eval_end:
- \exp_after:wN A \or: \exp_after:wN B \or:
- \exp_after:wN C \or: \exp_after:wN D \or: \exp_after:wN E \or:
- \exp_after:wN F \or: \exp_after:wN G \or: \exp_after:wN H \or:
- \exp_after:wN I \or: \exp_after:wN J \or: \exp_after:wN K \or:
- \exp_after:wN L \or: \exp_after:wN M \or: \exp_after:wN N \or:
- \exp_after:wN O \or: \exp_after:wN P \or: \exp_after:wN Q \or:
- \exp_after:wN R \or: \exp_after:wN S \or: \exp_after:wN T \or:
- \exp_after:wN U \or: \exp_after:wN V \or: \exp_after:wN W \or:
- \exp_after:wN X \or: \exp_after:wN Y \or: \exp_after:wN Z \else:
- \use_i_after_fi:nw{ #1 }\fi: }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\int_convert_to_base_ten:nn}
-% |#1| is the number, |#2| is its base. First we get the sign, then
-% use only the digits/letters from it and pass that onto a new
-% function.
-% \begin{macrocode}
-\cs_set_nopar:Npn \int_convert_to_base_ten:nn #1#2 {
- \intexpr_eval:n{
- \int_get_sign:n{#1}
- \exp_args:Nf\int_convert_to_base_ten_aux:nn {\int_get_digits:n{#1}}{#2}
- }
-}
-% \end{macrocode}
-% This is an intermediate function to get things started.
-% \begin{macrocode}
-\cs_new_nopar:Npn \int_convert_to_base_ten_aux:nn #1#2{
- \int_convert_to_base_ten_auxi:nnN {0}{#2} #1 \q_no_value
-}
-% \end{macrocode}
-% Here we check each letter/digit and calculate the next number. |#1|
-% is the previously calculated result (to be multiplied by the base),
-% |#2| is the base and |#3| is the next letter/digit to be added.
-% \begin{macrocode}
-\cs_new_nopar:Npn \int_convert_to_base_ten_auxi:nnN#1#2#3{
- \quark_if_no_value:NTF #3
- {#1}
- {\exp_args:Nf\int_convert_to_base_ten_auxi:nnN
- {\intexpr_eval:n{ #1*#2+\int_convert_letter_to_number:N #3} }
- {#2}
- }
-}
-% \end{macrocode}
-% This is for turning a letter or digit into a number. This function
-% also takes care of handling lowercase and uppercase letters. Hence
-% |a| is turned into |11| and so is |A|.
+% Needed from the tl module:
% \begin{macrocode}
-\cs_set_nopar:Npn \int_convert_letter_to_number:N #1{
- \intexpr_compare:nNnTF{`#1}<{58}{#1}
- {
- \intexpr_eval:n{ `#1 -
- \intexpr_compare:nNnTF{`#1}<{91}{ 55 }{ 87 }
- }
- }
-}
+\int_new:N \g_tl_inline_level_int
% \end{macrocode}
-% \end{macro}
%
-% Needed from the tl module:
+% \subsection{Backwards compatibility}
% \begin{macrocode}
-\int_new:N \g_tl_inline_level_int
+\cs_set_eq:NN \intexpr_value:w \int_value:w
+\cs_set_eq:NN \intexpr_eval:w \int_eval:w
+\cs_set_eq:NN \intexpr_eval_end: \int_eval_end:
+\cs_set_eq:NN \if_intexpr_compare:w \if_int_compare:w
+\cs_set_eq:NN \if_intexpr_odd:w \if_int_odd:w
+\cs_set_eq:NN \if_intexpr_case:w \if_case:w
+\cs_set_eq:NN \intexpr_eval:n \int_eval:n
+
+\cs_set_eq:NN \intexpr_compare_p:n \int_compare_p:n
+\cs_set_eq:NN \intexpr_compare:nTF \int_compare:nTF
+\cs_set_eq:NN \intexpr_compare:nT \int_compare:nT
+\cs_set_eq:NN \intexpr_compare:nF \int_compare:nF
+
+\cs_set_eq:NN \intexpr_compare_p:nNn \int_compare_p:nNn
+\cs_set_eq:NN \intexpr_compare:nNnTF \int_compare:nNnTF
+\cs_set_eq:NN \intexpr_compare:nNnT \int_compare:nNnT
+\cs_set_eq:NN \intexpr_compare:nNnF \int_compare:nNnF
+
+\cs_set_eq:NN \intexpr_abs:n \int_abs:n
+\cs_set_eq:NN \intexpr_max:nn \int_max:nn
+\cs_set_eq:NN \intexpr_min:nn \int_min:nn
+
+\cs_set_eq:NN \intexpr_div_truncate:nn \int_div_truncate:nn
+\cs_set_eq:NN \intexpr_div_round:nn \int_div_round:nn
+\cs_set_eq:NN \intexpr_mod:nn \int_mod:nn
+
+\cs_set_eq:NN \intexpr_if_odd_p:n \int_if_odd_p:n
+\cs_set_eq:NN \intexpr_if_odd:nTF \int_if_odd:nTF
+\cs_set_eq:NN \intexpr_if_odd:nT \int_if_odd:nT
+\cs_set_eq:NN \intexpr_if_odd:nF \int_if_odd:nF
+
+\cs_set_eq:NN \intexpr_while_do:nn \int_while_do:nn
+\cs_set_eq:NN \intexpr_until_do:nn \int_until_do:nn
+\cs_set_eq:NN \intexpr_do_while:nn \int_do_while:nn
+\cs_set_eq:NN \intexpr_do_until:nn \int_do_until:nn
+
+\cs_set_eq:NN \intexpr_while_do:nNnn \int_while_do:nNnn
+\cs_set_eq:NN \intexpr_until_do:nNnn \int_until_do:nNnn
+\cs_set_eq:NN \intexpr_do_while:nNnn \int_do_while:nNnn
+\cs_set_eq:NN \intexpr_do_until:nNnn \int_do_until:nNnn
% \end{macrocode}
%
% \begin{macrocode}