diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3int.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3int.dtx | 2240 |
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} |