% \iffalse meta-comment % %% File: l3int.dtx Copyright (C) 1990-2011 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this %% license or (at your option) any later version. The latest version %% of this license is in the file %% %% http://www.latex-project.org/lppl.txt %% %% This file is part of the "expl3 bundle" (The Work in LPPL) %% and all files in that bundle must be distributed together. %% %% The released version of this bundle is available from CTAN. %% %% ----------------------------------------------------------------------- %% %% The development version of the bundle can be found at %% %% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% %%%%%%%%%%% %% NOTE: %% %%%%%%%%%%% %% %% Snapshots taken from the repository represent work in progress and may %% not work or may contain conflicting material! We therefore ask %% people _not_ to put them into distributions, archives, etc. without %% prior consultation with the LaTeX3 Project. %% %% ----------------------------------------------------------------------- % %<*driver|package> \RequirePackage{l3names} \GetIdInfo$Id: l3int.dtx 2600 2011-08-16 22:31:24Z bruno $ {L3 Experimental integers} % %<*driver> \documentclass[full]{l3doc} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{^^A % The \pkg{l3int} package\\ Integers^^A % \thanks{This file describes v\ExplFileVersion, % last revised \ExplFileDate.}^^A % } % % \author{^^A % The \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % % \date{Released \ExplFileDate} % % \maketitle % % \begin{documentation} % % 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} (\enquote{\texttt{int expr}}). % % \section{Integer expressions} % % \begin{function}[EXP]{\int_eval:n} % \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. 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{)}. % After two expansions, \cs{int_eval:n} yields a % \meta{integer denotation} which is left in the input stream. This is % \emph{not} an \meta{internal integer}, and therefore requires % suitable termination if used in a \TeX{}-style integer assignment. % \end{function} % % \begin{function}[EXP]{\int_abs:n} % \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 as an \meta{integer denotation} after two % expansions. % \end{function} % % \begin{function}[EXP]{\int_div_round:nn} % \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, round any remainder. Note that this is identical to using % |/| directly in an \meta{integer expression}. The result is left in % the input stream as a \meta{integer denotation} after two expansions. % \end{function} % % \begin{function}[EXP]{\int_div_truncate:nn} % \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. The result is left in the input stream as a % \meta{integer denotation} after two expansions. % \end{function} % % \begin{function}[EXP]{\int_max:nn, \int_min:nn} % \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 as an \meta{integer denotation} after two % expansions. % \end{function} % % \begin{function}[EXP]{\int_mod:nn} % \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 as an % \meta{integer denotation} after two expansions. % \end{function} % % \section{Creating and initialising integers} % % \begin{function}{\int_new:N, \int_new:c} % \begin{syntax} % \cs{int_new:N} \meta{integer} % \end{syntax} % Creates a new \meta{integer} 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_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{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_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{integer2} % \end{syntax} % Sets the content of \meta{integer1} equal to that of % \meta{integer2}. 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} % % \section{Setting and incrementing integers} % % \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} % % \section{Using integers} % % \begin{function}[EXP]{\int_use:N, \int_use:c} % \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}). % \begin{texnote} % \cs{int_use:N} is the \TeX{} primitive \cs{the}: this is one of % several \LaTeX3 names for this primitive. % \end{texnote} % \end{function} % % \section{Integer expression conditionals} % % \begin{function}[EXP,pTF]{\int_compare:nNn} % \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}[EXP,pTF]{\int_compare:n} % \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}[EXP,pTF]{\int_if_even:n, \int_if_odd:n} % \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} % % \section{Integer expression loops} % % \begin{function}[EXP]{\int_do_while:nNnn} % \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}[EXP]{\int_do_until:nNnn} % \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}[EXP]{\int_until_do:nNnn} % \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}[EXP]{\int_while_do:nNnn} % \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}[EXP]{\int_do_while:nn} % \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}[EXP]{\int_do_until:nn} % \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}[EXP]{\int_until_do:nn} % \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}[EXP]{\int_while_do:nn} % \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 integers} % % Integers can be placed into the output stream with formatting. These % conversions apply to any integer expressions. % % \begin{function}[EXP]{\int_to_arabic:n} % \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}[EXP]{\int_to_alph:n, \int_to_Alph:n} % \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}[EXP]{\int_to_symbols:nnn} % \begin{syntax} % \cs{int_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} % % \begin{function}[EXP]{\int_to_binary:n} % \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}[EXP]{\int_to_hexadecimal:n} % \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}[EXP]{\int_to_octal:n} % \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}[EXP]{\int_to_base:nn} % \begin{syntax} % \cs{int_to_base: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 \enquote{digits} are represented by the upper case % letters from the English alphabet. % The maximum \meta{base} value is $36$. % \begin{texnote} % This is a generic version of \cs{int_to_binary:n}, \emph{etc.} % \end{texnote} % \end{function} % % \begin{function}[EXP]{\int_to_roman:n, \int_to_Roman:n} % \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 Roman numerals are letters % with category code $11$ (letter). % \end{function} % % \section{Converting from other formats to integers} % % \begin{function}[EXP]{\int_from_alph:n} % \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 % \enquote{a} equal to $1$ through to \enquote{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}[EXP]{\int_from_binary:n} % \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}[EXP]{\int_from_hexadecimal:n} % \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}[EXP]{\int_from_octal:n} % \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}[EXP]{\int_from_roman:n} % \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} % % \begin{function}[EXP]{\int_from_base:nn} % \begin{syntax} % \cs{int_from_base: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} % % \section{Viewing integers} % % \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} % % \section{Constant integers} % % \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_one_hundred , % \c_two_hundred_fifty_five , % \c_two_hundred_fifty_six , % \c_one_thousand , % \c_ten_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_int} % The maximum value that can be stored as an integer. % \end{variable} % % \begin{variable}{\c_max_register_int} % Maximum number of registers. % \end{variable} % % \section{Scratch integers} % % \begin{variable}{\l_tmpa_int, \l_tmpb_int, \l_tmpc_int} % Scratch integer for local assignment. These are never used by % the kernel code, and so are safe for use with any \LaTeX3-defined % function. However, they may be overwritten by other non-kernel % code and so should only be used for short-term storage. % \end{variable} % % \begin{variable}{\g_tmpa_int, \g_tmpb_int} % Scratch integer for global assignment. These are never used by % the kernel code, and so are safe for use with any \LaTeX3-defined % function. However, they may be overwritten by other non-kernel % code and so should only be used for short-term storage. % \end{variable} % % \section{Internal functions} % % \begin{function}[EXP]{int_get_digits:n} % \begin{syntax} % \cs{int_get_digits:n} \meta{value} % \end{syntax} % Parses the \meta{value} to leave the absolute \meta{value} % in the input stream. This may therefore be used % to remove multiple sign tokens from the \meta{value} % (which may be symbolic). % \end{function} % % \begin{function}[EXP]{int_get_sign:n} % \begin{syntax} % \cs{int_get_sign:n} \meta{value} % \end{syntax} % Parses the \meta{value} to leave a single sign token % (either |+| or |-|) in the input stream. This may therefore be used % to sanitise sign tokens from the \meta{value} (which may be symbolic). % \end{function} % % \begin{function}[EXP]{int_to_letter:n} % \begin{syntax} % \cs{int_to_letter:n} \meta{integer value} % \end{syntax} % For \meta{integer values} from $0$ to $9$, leaves the \meta{value} % in the input stream unchanged. For \meta{integer values} from % $10$ to $35$, leaves the appropriate upper case letter (from the % standard English alphabet) in the input stream: for example, % $10$ is converted to |A|, $11$ to |B|, \emph{etc.} % \end{function} % % \begin{function}[EXP]{\int_to_roman:w} % \begin{syntax} % \cs{int_to_roman:w} \meta{integer} % ~~\meta{space} \textit{or} \meta{non-expandable token} % \end{syntax} % Converts \meta{integer} to it lower case Roman representation. Expansion % ends when a space or non-expandable token is found. % Note that this function produces a string of letters with category code % $12$ and that protected functions \emph{are} expanded by this % process. Negative \meta{integer} values result in no output, although % the function does not terminate expansion until a suitable endpoint % is found in the same way as for positive numbers. % \begin{texnote} % This is the \TeX{} primitive \tn{romannumeral} renamed. % \end{texnote} % \end{function} % % \begin{function}[EXP]{\if_num:w, \if_int_compare:w} % \begin{syntax} % \cs{if_num:w} \meta{integer1} \meta{relation} \meta{integer2} % ~~\meta{true code} % \cs{else:} % ~~\meta{false code} % \cs{fi:} % \end{syntax} % Compare two integers using \meta{relation}, which must be one of % |=|, |<| 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}[EXP]{\if_case:w, \or:} % \begin{syntax} % \cs{if_case:w} \meta{integer} \meta{case0} % ~~\cs{or:} \meta{case1} % ~~\cs{or:} |...| % ~~\cs{else:} \meta{default} % \cs{fi:} % \end{syntax} % Selects a case to execute based on the value of the \meta{integer}. The % first case (\meta{case0}) is executed if \meta{integer} is $0$, the second % (\meta{case1}) if the \meta{integer} is $1$, \emph{etc.} The % \meta{integer} 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}[EXP]{\int_value:w} % \begin{syntax} % \cs{int_value:w} \meta{integer} % \cs{int_value:w} \meta{tokens} \meta{optional space} % \end{syntax} % Expands \meta{tokens} until an \meta{integer} is formed. One space may be % gobbled in the process. % \begin{texnote} % This is the \TeX{} primitive \cs{number}. % \end{texnote} % \end{function} % % \begin{function}[EXP]{\int_eval:w, \int_eval_end:} % \begin{syntax} % \cs{int_eval:w} \meta{intexpr} \cs{int_eval_end:} % \end{syntax} % Evaluates \meta{integer expression} as described for \cs{int_eval:n}. % The evaluation stops when an unexpandable token which is not a valid % part of an integer 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}[EXP]{\if_int_odd:w} % \begin{syntax} % \cs{if_int_odd:w} \meta{tokens} \meta{optional space} % ~~\meta{true code} % \cs{else:} % ~~\meta{true code} % \cs{fi:} % \end{syntax} % Expands \meta{tokens} until a non-numeric token or a space is found, and % tests whether the resulting \meta{integer} is odd. If so, \meta{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} % % \begin{implementation} % % \section{\pkg{l3int} implementation} % % \begin{macrocode} %<*initex|package> % \end{macrocode} % % \TestFiles{m3int001,m3int002,m3int03} % % \begin{macrocode} %<*package> \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} \package_check_loaded_expl: % % \end{macrocode} % % \begin{macro}{\int_to_roman:w} % \begin{macro}{\if_int_compare:w} % Done in \pkg{l3basics}. % \end{macro} % \end{macro} % % \begin{macro}{\int_value:w} % \begin{macro}{\int_eval:w} % \begin{macro}{\int_eval_end:} % \begin{macro}{\if_num:w} % \begin{macro}{\if_int_odd:w} % \begin{macro}{\if_case:w} % Here are the remaining primitives for number comparisons and % expressions. % \begin{macrocode} \cs_new_eq:NN \int_value:w \tex_number:D \cs_new_eq:NN \int_eval:w \etex_numexpr:D \cs_new_eq:NN \int_eval_end: \tex_relax:D \cs_new_eq:NN \if_num:w \tex_ifnum:D \cs_new_eq:NN \if_int_odd:w \tex_ifodd:D \cs_new_eq:NN \if_case:w \tex_ifcase:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Integer expressions} % % \begin{macro}{\int_eval:n} % Wrapper for \cs{int_eval:w}. Can be used in an integer expression % or directly in the input stream. In format mode, there is already % a definition in \pkg{l3alloc} for bookstrapping, which is therefore % corrected to the \enquote{real} version here. % \begin{macrocode} %<*initex> \cs_set:Npn \int_eval:n #1 { \int_value:w \int_eval:w #1 \int_eval_end: } % %<*package> \cs_new:Npn \int_eval:n #1 { \int_value:w \int_eval:w #1 \int_eval_end: } % % \end{macrocode} % \end{macro} % % \begin{macro}{\int_max:nn} % \UnitTested % \begin{macro}{\int_min:nn} % \UnitTested % \begin{macro}{\int_abs:n} % \UnitTested % Functions for $\min$, $\max$, and absolute value. % \begin{macrocode} \cs_new: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_new: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_new: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} % \UnitTested % \begin{macro}{\int_div_round:nn} % \UnitTested % \begin{macro}{\int_mod:nn} % \UnitTested % As \cs{int_eval:w} rounds the result of a division we also % provide a version that truncates the result. This version is thanks % to Heiko Oberdiek: getting things right in all cases is not so easy. % \begin{macrocode} \cs_new: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_new:Npn \int_div_round:nn #1#2 { \int_eval:n { ( #1 ) / ( #2 ) } } % \end{macrocode} % Finally there's the modulus operation. % \begin{macrocode} \cs_new: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} % % \subsection{Creating and initialising integers} % % \begin{macro}{\int_new:N, \int_new:c} % \UnitTested % Two ways to do this: one for the format and one for the \LaTeXe{} % package. % \begin{macrocode} %<*package> \cs_new_protected_nopar:Npn \int_new:N #1 { \chk_if_free_cs:N #1 \newcount #1 } % \cs_generate_variant:Nn \int_new:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\int_const:Nn, \int_const:cn} % \UnitTested % As stated, most constants can be defined as \cs{tex_chardef:D} or % \cs{tex_mathchardef:D} but that's engine dependent. % \begin{macrocode} \cs_new_protected_nopar:Npn \int_const:Nn #1#2 { \int_compare:nNnTF {#2} > \c_minus_one { \int_compare:nNnTF {#2} > \c_max_register_int { \int_new:N #1 \int_gset:Nn #1 {#2} } { \chk_if_free_cs:N #1 \pref_global:D \tex_mathchardef:D #1 = \int_eval:w #2 \int_eval_end: } } { \int_new:N #1 \int_gset:Nn #1 {#2} } } \cs_generate_variant:Nn \int_const:Nn { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\int_zero:N, \int_zero:c} % \UnitTested % \begin{macro}{\int_gzero:N, \int_gzero:c} % \UnitTested % Functions that reset an \meta{integer} register to zero. % \begin{macrocode} \cs_new_protected_nopar:Npn \int_zero:N #1 { #1 = \c_zero } \cs_new_protected_nopar:Npn \int_gzero:N #1 { \pref_global:D #1 = \c_zero } \cs_generate_variant:Nn \int_zero:N { c } \cs_generate_variant:Nn \int_gzero:N { c } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\int_set_eq:NN,\int_set_eq:cN, \int_set_eq:Nc,\int_set_eq:cc} % \UnitTested % \begin{macro} % {\int_gset_eq:NN,\int_gset_eq:cN, \int_gset_eq:Nc,\int_gset_eq:cc} % \UnitTested % 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 { #1 = #2 } \cs_generate_variant:Nn \int_set_eq:NN { c } \cs_generate_variant:Nn \int_set_eq:NN { Nc , cc } \cs_new_protected_nopar:Npn \int_gset_eq:NN #1#2 { \pref_global:D #1 = #2 } \cs_generate_variant:Nn \int_gset_eq:NN { c } \cs_generate_variant:Nn \int_gset_eq:NN { Nc , cc } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Setting and incrementing integers} % % \begin{macro}{\int_add:Nn, \int_add:cn} % \UnitTested % \begin{macro}{\int_gadd:Nn, \int_gadd:cn} % \UnitTested % \begin{macro}{\int_sub:Nn, \int_sub:cn} % \UnitTested % \begin{macro}{\int_gsub:Nn, \int_gsub:cn} % \UnitTested % Adding and subtracting to and from a counter \ldots % \begin{macrocode} \cs_new_protected_nopar:Npn \int_add:Nn #1#2 { \tex_advance:D #1 by \int_eval:w #2 \int_eval_end: } \cs_new_nopar:Npn \int_sub:Nn #1#2 { \tex_advance:D #1 by - \int_eval:w #2 \int_eval_end: } \cs_new_protected_nopar:Npn \int_gadd:Nn { \pref_global:D \int_add:Nn } \cs_new_protected_nopar:Npn \int_gsub:Nn { \pref_global:D \int_sub:Nn } \cs_generate_variant:Nn \int_add:Nn { c } \cs_generate_variant:Nn \int_gadd:Nn { c } \cs_generate_variant:Nn \int_sub:Nn { c } \cs_generate_variant:Nn \int_gsub:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\int_incr:N, \int_incr:c} % \UnitTested % \begin{macro}{\int_gincr:N, \int_gincr:c} % \UnitTested % \begin{macro}{\int_decr:N, \int_decr:c} % \UnitTested % \begin{macro}{\int_gdecr:N, \int_gdecr:c} % \UnitTested % Incrementing and decrementing of integer registers is done with % the following functions. % \begin{macrocode} \cs_new_protected_nopar:Npn \int_incr:N #1 { \tex_advance:D #1 \c_one } \cs_new_protected_nopar:Npn \int_decr:N #1 { \tex_advance:D #1 \c_minus_one } \cs_new_protected_nopar:Npn \int_gincr:N { \pref_global:D \int_incr:N } \cs_new_protected_nopar:Npn \int_gdecr:N { \pref_global:D \int_decr:N } \cs_generate_variant:Nn \int_incr:N { c } \cs_generate_variant:Nn \int_decr:N { c } \cs_generate_variant:Nn \int_gincr:N { c } \cs_generate_variant:Nn \int_gdecr:N { c } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\int_set:Nn, \int_set:cn} % \UnitTested % \begin{macro}{\int_gset:Nn, \int_gset:cn} % \UnitTested % As integers are register-based \TeX{} will issue an error % if they are not defined. Thus there is no need for the checking % code seen with token list variables. % \begin{macrocode} \cs_new_protected_nopar:Npn \int_set:Nn #1#2 { #1 ~ \int_eval:w #2\int_eval_end: } \cs_new_protected_nopar:Npn \int_gset:Nn { \pref_global:D \int_set:Nn } \cs_generate_variant:Nn \int_set:Nn { c } \cs_generate_variant:Nn \int_gset:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Using integers} % % \begin{macro}{\int_use:N, \int_use:c} % \UnitTested % Here is how counters are accessed: % \begin{macrocode} \cs_new_eq:NN \int_use:N \tex_the:D \cs_new_nopar:Npn \int_use:c #1 { \int_use:N \cs:w #1 \cs_end: } % \end{macrocode} % \end{macro} % % \subsection{Integer expression conditionals} % % \begin{macro}[pTF]{\int_compare:n} % \begin{macro}[aux]{\int_compare_aux:nw} % \begin{macro}[aux]{\int_compare_aux:Nw} % \begin{macro}[aux]{int_compare_=:w} % \begin{macro}[aux]{int_compare_==:w} % \begin{macro}[aux]{int_compare_!=:w} % \begin{macro}[aux]{int_compare_<:w} % \begin{macro}[aux]{int_compare_>:w} % \begin{macro}[aux]{int_compare_<=:w} % \begin{macro}[aux]{int_compare_>=:w} % 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 \cs{int_eval:w} % where required. We can start evaluating from the left using % \cs{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_new_conditional:Npnn \int_compare:n #1 { p , T , F , TF } { \exp_after:wN \int_compare_aux:nw \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. \cs{int_to_roman:w} is handy here since its % expansion given a non-positive number is \meta{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 \cs{int_to_roman:w}, % thereby ridding us of the left hand side evaluation. We do however % save it for later. % \begin{macrocode} \cs_new:Npn \int_compare_aux:nw #1#2 \q_stop { \exp_after:wN \int_compare_aux:Nw \int_to_roman:w \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_new:Npn \int_compare_aux:Nw #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_new: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_new: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_new: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_new: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_new: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. \emph{Vice versa} for less than or equal. % \begin{macrocode} \cs_new: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_new: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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}[pTF]{\int_compare:nNn} % \UnitTested % More efficient but less natural in typing. % \begin{macrocode} \prg_new_conditional:Npnn \int_compare:nNn #1#2#3 { p , T , F , TF} { \if_int_compare:w \int_eval:w #1 #2 \int_eval:w #3 \int_eval_end: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF]{\int_if_odd:n} % \UnitTested % \begin{macro}[pTF]{\int_if_even:n} % \UnitTested % A predicate function. % \begin{macrocode} \prg_new_conditional:Npnn \int_if_odd:n #1 { p , T , F , TF} { \if_int_odd:w \int_eval:w #1 \int_eval_end: \prg_return_true: \else: \prg_return_false: \fi: } \prg_new_conditional:Npnn \int_if_even:n #1 { p , T , F , TF} { \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} % % \subsection{Integer expression loops} % % \begin{macro}{\int_while_do:nn} % \UnitTested % \TestMissing{Boundary cases} % \begin{macro}{\int_until_do:nn} % \UnitTested % \TestMissing{Boundary cases} % \begin{macro}{\int_do_while:nn} % \UnitTested % \TestMissing{Boundary cases} % \begin{macro}{\int_do_until:nn} % \UnitTested % \TestMissing{Boundary cases} % 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_new:Npn \int_while_do:nn #1#2 { \int_compare:nT {#1} { #2 \int_while_do:nn {#1} {#2} } } \cs_new:Npn \int_until_do:nn #1#2 { \int_compare:nF {#1} { #2 \int_until_do:nn {#1} {#2} } } \cs_new:Npn \int_do_while:nn #1#2 { #2 \int_compare:nT {#1} { \int_do_while:nNnn {#1} {#2} } } \cs_new: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_new: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_new: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_new: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_new: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{Formatting integers} % % \begin{macro}{\int_to_arabic:n} % \UnitTested % Nothing exciting here. % \begin{macrocode} \cs_new_nopar:Npn \int_to_arabic:n #1 { \int_eval:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\int_to_symbols:nnn} % \UnitTested % 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 \enquote{pre-packaged}. % \begin{macrocode} \cs_new_nopar:Npn \int_to_symbols:nnn #1#2#3 { \int_compare:nNnTF {#1} > {#2} { \exp_args:Nf \int_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} % % \begin{macro}{\int_to_alph:n,\int_to_Alph:n} % \UnitTested % These both use the above function with input functions that make sense % for the alphabet in English. % \begin{macrocode} \cs_new:Npn \int_to_alph:n #1 { \int_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:Npn \int_to_Alph:n #1 { \int_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} % % \begin{macro}{\int_to_base:nn} % \UnitTested % \begin{macro}[aux]{\int_to_base_aux_i:nn, % \int_to_base_aux_ii:nnN,\int_to_base_aux_iii:nnnN} % \begin{macro}[int]{\int_to_letter:n} % \UnitTested % Converting from base ten (|#1|) to a second base (|#2|) starts with % computing |#1|: if it is a complicated calculation, we shouldn't % perform it twice. Then check the sign, store it, either \texttt{-} % or \cs{c_empty_tl}, and feed the absolute value to the next auxiliary % function. % \begin{macrocode} \cs_new:Npn \int_to_base:nn #1 { \exp_args:Nf \int_to_base_aux_i:nn { \int_eval:n {#1} } } \cs_new:Npn \int_to_base_aux_i:nn #1#2 { \int_compare:nNnTF {#1} < \c_zero { \exp_args:No \int_to_base_aux_ii:nnN { \use_none:n #1 } {#2} - } { \int_to_base_aux_ii:nnN {#1} {#2} \c_empty_tl } } % \end{macrocode} % Here, the idea is to provide a recursive system to deal with the % input. The output is built up after the end of the function. % At each pass, the value in |#1| is checked to see if it is less % than the new base (|#2|). If it is, then it is converted directly, % putting the sign back in front. % 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 put on the right, % and the remainder is carried forward to the next round. % \begin{macrocode} \cs_new:Npn \int_to_base_aux_ii:nnN #1#2#3 { \int_compare:nNnTF {#1} < {#2} { \exp_last_unbraced:Nf #3 { \int_to_letter:n {#1} } } { \exp_args:Nf \int_to_base_aux_iii:nnnN { \int_to_letter:n { \int_mod:nn {#1} {#2} } } {#1} {#2} #3 } } \cs_new:Npn \int_to_base_aux_iii:nnnN #1#2#3#4 { \exp_args:Nf \int_to_base_aux_ii:nnN { \int_div_truncate:nn {#2} {#3} } {#3} #4 #1 } % \end{macrocode} % Convert to a letter only if necessary, otherwise simply return the % value unchanged. It would be cleaner to use \cs{prg_case_int:nnn}, % but in our case, the cases are contiguous, so it is forty times faster % to use the \cs{if_case:w} primitive. The first \cs{exp_after:wN} % expands the conditional, jumping to the correct case, the second one % expands after the resulting character to close the conditional. % \begin{macrocode} \cs_new:Npn \int_to_letter:n #1 { \exp_after:wN \exp_after:wN \if_case:w \int_eval:w #1 - \c_ten \int_eval_end: 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 \else: #1 \fi: } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % % \begin{macro}{\int_to_binary:n, \int_to_hexadecimal:n, \int_to_octal:n} % \UnitTested % Wrappers around the generic function. % \begin{macrocode} \cs_new:Npn \int_to_binary:n #1 { \int_to_base:nn {#1} { 2 } } \cs_new:Npn \int_to_hexadecimal:n #1 { \int_to_base:nn {#1} { 16 } } \cs_new:Npn \int_to_octal:n #1 { \int_to_base:nn {#1} { 8 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\int_to_roman:n, \int_to_Roman:n} % \UnitTested % \begin{macro}[aux]{\int_to_roman_aux:N, \int_to_roman_aux:N} % \begin{macro}[aux] % { % \int_to_roman_i:w, \int_to_roman_v:w, \int_to_roman_x:w, % \int_to_roman_l:w, \int_to_roman_c:w, \int_to_roman_d:w, % \int_to_roman_m:w, \int_to_roman_Q:w, % \int_to_Roman_i:w, \int_to_Roman_v:w, \int_to_Roman_x:w, % \int_to_Roman_l:w, \int_to_Roman_c:w, \int_to_Roman_d:w, % \int_to_Roman_m:w, \int_to_Roman_Q:w, % } % The \cs{int_to_roman:w} primitive creates tokens of category % code $12$ (other). Usually, what is actually wanted is letters. % The approach here is to convert the output of the primitive into % letters using appropriate control sequence names. That keeps % everything expandable. The loop will be terminated by the conversion % of the |Q|. % \begin{macrocode} \cs_new_nopar:Npn \int_to_roman:n #1 { \exp_after:wN \int_to_roman_aux:N \int_to_roman:w \int_eval:n {#1} Q } \cs_new_nopar:Npn \int_to_roman_aux:N #1 { \use:c { int_to_roman_ #1 :w } \int_to_roman_aux:N } \cs_new_nopar:Npn \int_to_Roman:n #1 { \exp_after:wN \int_to_Roman_aux:N \int_to_roman:w \int_eval:n {#1} Q } \cs_new_nopar:Npn \int_to_Roman_aux:N #1 { \use:c { int_to_Roman_ #1 :w } \int_to_Roman_aux:N } \cs_new_nopar:Npn \int_to_roman_i:w { i } \cs_new_nopar:Npn \int_to_roman_v:w { v } \cs_new_nopar:Npn \int_to_roman_x:w { x } \cs_new_nopar:Npn \int_to_roman_l:w { l } \cs_new_nopar:Npn \int_to_roman_c:w { c } \cs_new_nopar:Npn \int_to_roman_d:w { d } \cs_new_nopar:Npn \int_to_roman_m:w { m } \cs_new_nopar:Npn \int_to_roman_Q:w #1 { } \cs_new_nopar:Npn \int_to_Roman_i:w { I } \cs_new_nopar:Npn \int_to_Roman_v:w { V } \cs_new_nopar:Npn \int_to_Roman_x:w { X } \cs_new_nopar:Npn \int_to_Roman_l:w { L } \cs_new_nopar:Npn \int_to_Roman_c:w { C } \cs_new_nopar:Npn \int_to_Roman_d:w { D } \cs_new_nopar:Npn \int_to_Roman_m:w { M } \cs_new_nopar:Npn \int_to_Roman_Q:w #1 { } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Converting from other formats to integers} % % \begin{macro}[int]{\int_get_sign:n} % \begin{macro}[int]{\int_get_digits:n} % \begin{macro}[aux] % {\int_get_sign_and_digits_aux:nNNN, \int_get_sign_and_digits_aux:oNNN} % 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: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 { \exp_args:Nf \tl_if_head_eq_charcode:nNTF {#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 } } { \exp_args:Nf \tl_if_head_eq_charcode:nNTF {#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} % % \begin{macro}{\int_from_alph:n} % \UnitTested % \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_from_base:nn} % \UnitTested % \begin{macro}[aux]{\int_from_base_aux:nn} % \begin{macro}[aux]{\int_from_base_aux:nnN} % \begin{macro}[aux]{\int_from_base_aux:N} % 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_from_base:nn #1#2 { \int_eval:n { \int_get_sign:n {#1} \exp_args:Nf \int_from_base_aux:nn { \int_get_digits:n {#1} } {#2} } } \cs_new:Npn \int_from_base_aux:nn #1#2 { \int_from_base_aux:nnN { 0 } { #2 } #1 \q_nil } \cs_new:Npn \int_from_base_aux:nnN #1#2#3 { \quark_if_nil:NTF #3 {#1} { \exp_args:Nf \int_from_base_aux:nnN { \int_eval:n { #1 * #2 + \int_from_base_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_from_base_aux:N #1 { \int_compare:nNnTF { `#1 } < { 58 } {#1} { \int_eval:n { `#1 - \int_compare:nNnTF { `#1 } < { 91 } { 55 } { 87 } } } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\int_from_binary:n, \int_from_hexadecimal:n, \int_from_octal:n} % \UnitTested % Wrappers around the generic function. % \begin{macrocode} \cs_new:Npn \int_from_binary:n #1 { \int_from_base:nn {#1} \c_two } \cs_new:Npn \int_from_hexadecimal:n #1 { \int_from_base:nn {#1} \c_sixteen } \cs_new:Npn \int_from_octal:n #1 { \int_from_base:nn {#1} \c_eight } % \end{macrocode} % \end{macro} % % \begin{variable}[aux] % { % \c_int_from_roman_i_int, \c_int_from_roman_v_int, % \c_int_from_roman_x_int, \c_int_from_roman_l_int, % \c_int_from_roman_c_int, \c_int_from_roman_d_int, % \c_int_from_roman_m_int, % \c_int_from_roman_I_int, \c_int_from_roman_V_int, % \c_int_from_roman_X_int, \c_int_from_roman_L_int, % \c_int_from_roman_C_int, \c_int_from_roman_D_int, % \c_int_from_roman_M_int % } % Constants used to convert from Roman numerals to integers. % \begin{macrocode} \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} % \end{variable} % % \begin{macro}{\int_from_roman:n} % \UnitTested % \TestMissing{boundary cases / wrong input?} % \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} { \exp_after:wN \int_from_roman_end:w \int_value:w \int_eval:w \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} % % \subsection{Viewing integer} % % \begin{macro}{\int_show:N,\int_show:c} % \UnitTested % \begin{macrocode} \cs_new_eq:NN \int_show:N \kernel_register_show:N \cs_new_eq:NN \int_show:c \kernel_register_show:c % \end{macrocode} % \end{macro} % % \subsection{Constant integers} % % \begin{variable}{\c_minus_one} % This is needed early, and so is in \pkg{l3basics} % \end{variable} % % \begin{variable}{\c_zero} % Again, one in \pkg{l3basics} for obvious reasons. % \end{variable} % % \begin{variable}{\c_six, \c_seven} % \begin{variable}{\c_twelve} % \begin{variable}{\c_sixteen} % Once again, in \pkg{l3basics}. % \end{variable} % \end{variable} % \end{variable} % % \begin{variable} % { % \c_one, \c_two, \c_three, \c_four, \c_five, \c_eight, \c_nine, \c_ten, % \c_eleven, \c_thirteen, \c_fourteen, \c_fifteen, % } % Low-number values not previously defined. % \begin{macrocode} \int_const:Nn \c_one { 1 } \int_const:Nn \c_two { 2 } \int_const:Nn \c_three { 3 } \int_const:Nn \c_four { 4 } \int_const:Nn \c_five { 5 } \int_const:Nn \c_eight { 8 } \int_const:Nn \c_nine { 9 } \int_const:Nn \c_ten { 10 } \int_const:Nn \c_eleven { 11 } \int_const:Nn \c_thirteen { 13 } \int_const:Nn \c_fourteen { 14 } \int_const:Nn \c_fifteen { 15 } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_thirty_two} % One middling value. % \begin{macrocode} \int_const:Nn \c_thirty_two { 32 } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_two_hundred_fifty_five, \c_two_hundred_fifty_six} % Two classic mid-range integer constants. % \begin{macrocode} \int_const:Nn \c_two_hundred_fifty_five { 255 } \int_const:Nn \c_two_hundred_fifty_six { 256 } % \end{macrocode} %\end{variable} % % \begin{variable} % {\c_one_hundred, \c_one_thousand, \c_ten_thousand} % Simple runs of powers of ten. % \begin{macrocode} \int_const:Nn \c_one_hundred { 100 } \int_const:Nn \c_one_thousand { 1000 } \int_const:Nn \c_ten_thousand { 10000 } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_max_int} % The largest number allowed is $2^{31}-1$ % \begin{macrocode} \int_const:Nn \c_max_int { 2 147 483 647 } % \end{macrocode} % \end{variable} % % \subsection{Scratch integers} % % \begin{variable}{\l_tmpa_int, \l_tmpb_int, \l_tmpc_int} % \begin{variable}{\g_tmpa_int, \g_tmpb_int} % We provide four local and two global scratch counters, maybe we % need more or less. % \begin{macrocode} \int_new:N \l_tmpa_int \int_new:N \l_tmpb_int \int_new:N \l_tmpc_int \int_new:N \g_tmpa_int \int_new:N \g_tmpb_int % \end{macrocode} % \end{variable} % \end{variable} % % \subsection{Registers for earlier modules} % % Needed from other modules: % \begin{macrocode} \int_new:N \g_seq_nesting_depth_int \int_new:N \g_tl_inline_level_int % \end{macrocode} % % \subsection{Deprecated functions} % % Deprecated on 2011-05-27, for removal by 2011-08-31. % % \begin{macro}{\int_convert_from_base_ten:nn} % \begin{macro}{\int_convert_to_symbols:nnn} % \begin{macro}{\int_convert_to_base_ten:nn} % Some simple renames. % \begin{macrocode} \cs_new_eq:NN \int_convert_from_base_ten:nn \int_to_base:nn \cs_new_eq:NN \int_convert_to_symbols:nnn \int_to_symbols:nnn \cs_new_eq:NN \int_convert_to_base_ten:nn \int_from_base:nn % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\int_to_symbol:n} % \begin{macro}[aux]{\int_to_symbol_math:n} % \begin{macro}[aux]{\int_to_symbol_text:n} % \UnitTested % This is rather too tied to \LaTeXe{}. % \begin{macrocode} \cs_new_nopar:Npn \int_to_symbol:n { \mode_if_math:TF { \int_to_symbol_math:n } { \int_to_symbol_text:n } } \cs_new:Npn \int_to_symbol_math:n #1 { \int_to_symbols:nnn {#1} { 9 } { { 1 } { * } { 2 } { \dagger } { 3 } { \ddagger } { 4 } { \mathsection } { 5 } { \mathparagraph } { 6 } { \| } { 7 } { ** } { 8 } { \dagger \dagger } { 9 } { \ddagger \ddagger } } } \cs_new:Npn \int_to_symbol_text:n #1 { \int_to_symbols:nnn {#1} { 9 } { { 1 } { \textasteriskcentered } { 2 } { \textdagger } { 3 } { \textdaggerdbl } { 4 } { \textsection } { 5 } { \textparagraph } { 6 } { \textbardbl } { 7 } { \textasteriskcentered \textasteriskcentered } { 8 } { \textdagger \textdagger } { 9 } { \textdaggerdbl \textdaggerdbl } } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \PrintIndex