% \iffalse %% File: l3num.dtx Copyright (C) 2005-2008 Frank Mittelbach, 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/cgi-bin/cvsweb.cgi/ %% %% 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 LaTeX Project Team. %% %% ----------------------------------------------------------------------- % %<*driver|package> \RequirePackage{l3names} % %\fi \GetIdInfo$Id: l3num.dtx 741 2008-08-01 13:37:16Z morten $ {L3 Experimental token numbers} %\iffalse %<*driver> %\fi \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse \documentclass{l3doc} \begin{document} \DocInput{\filename.\filenameext} \end{document} % % \fi % % % \title{The \textsf{l3num} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % Integer in macros} % \author{\Team} % \date{\filedate} % \maketitle % % \section{Macro Counters} % % Instead of using counter registers for manipulation of % integer values it is sometimes useful to keep such values in % macros. For this \LaTeX3 offers the type ``num''. % % One reason is the limited number of registers inside % \TeX{}. However, when using \eTeX{} this is no longer an issue. It % remains to be seen if there are other compelling reasons to keep % this module. % % It turns out there might be as with a \meta{num} data type, the % allocation module can do its bookkeeping without the aid of % \meta{int} registers. % % \subsection{Functions} % % \begin{function}{% % \num_new:N | % \num_new:c | % } % \begin{syntax} % "\num_new:N" % \end{syntax} % Defines to be a new variable of type "num" (initialized to % zero). There is no way to % define constant counters with these functions. % \end{function} % % \begin{function}{% % \num_incr:N | % \num_incr:c | % \num_gincr:N | % \num_gincr:c % } % \begin{syntax} % "\num_incr:N" % \end{syntax} % Increments by one. For global variables the global versions % should be used. % \end{function} % % \begin{function}{% % \num_decr:N | % \num_decr:c | % \num_gdecr:N | % \num_gdecr:c | % } % \begin{syntax} % "\num_decr:N" % \end{syntax} % Decrements by one. For global variables the global versions % should be used. % \end{function} % % \begin{function}{% % \num_zero:N | % \num_zero:c | % \num_gzero:N | % \num_gzero:c | % } % \begin{syntax} % "\num_zero:N" % \end{syntax} % Resets to zero. For global variables the global versions % should be used. % \end{function} % % \begin{function}{% % \num_set:Nn | % \num_set:cn | % \num_gset:Nn | % \num_gset:cn | % } % \begin{syntax} % "\num_set:Nn" "{" "}" % \end{syntax} % These functions will set the register to the value. % \end{function} % % \begin{function}{% % \num_gset_eq:NN | % \num_gset_eq:cN | % \num_gset_eq:Nc | % \num_gset_eq:cc | % } % \begin{syntax} % "\num_gset_eq:NN" % \end{syntax} % These functions will set the register equal to . % \end{function} % % \begin{function}{% % \num_add:Nn | % \num_add:cn | % \num_gadd:Nn | % \num_gadd:cn | % } % \begin{syntax} % "\num_add:Nn" "{" "}" % \end{syntax} % These functions will add to the register the value . If % the second argument is a register too, the surrounding braces % can be left out. % % \end{function} % % % \begin{function}{% % \num_use:N | % \num_use:c | % } % \begin{syntax} % "\num_use:N" % \end{syntax} % This function returns the integer value kept in in a way % suitable for further processing. % \begin{texnote} % Since these s are implemented as macros, the function % "\num_use:N" is effectively a noop and mainly there for % consistency with similar functions in other modules. % \end{texnote} % \end{function} % % % \begin{function}{% % \num_eval:n | % } % \begin{syntax} % "\num_eval:n" "{" "}" % \end{syntax} % Evaluates the integer expression allowing normal mathematical % operators like |+-/*|. % \end{function} % % % \begin{function}{% % \num_compare:nNnTF | % \num_compare:cNcTF | % \num_compare:nNnT | % \num_compare:nNnF | % } % \begin{syntax} % "\num_compare:nNnTF" "{""}" "{""}" % "{""}" "{""}" % \end{syntax} % These functions test two \m{num} expressions against each other. They % are both evaluated by "\num_eval:n". % \end{function} % % \begin{function}{% % \num_compare_p:nNn | % } % \begin{syntax} % "\num_compare_p:nNn" "{""}" "{""}" % \end{syntax} % A predicate version of the above functions. % \end{function} % % \begin{function}{% % \num_max_of:nn | % \num_min_of:nn | % } % \begin{syntax} % "\num_max_of:nn" "{""}" "{""}" % \end{syntax} % Return the largest or smallest of two \m{num} expressions. % \end{function} % % \begin{function}{% % \num_abs:n | % } % \begin{syntax} % "\num_abs:n" "{""}" % \end{syntax} % Return the numerical value of a \m{num} expression. % \end{function} % % \begin{function}{% % \num_elt_count:n | % } % \begin{syntax} % "\num_elt_count:n" "{""}" % \end{syntax} % Discards \m{balanced text} and puts a "+1" in the input stream. Used % to count elements in a token list. % \end{function} % % \subsection{Formatting a counter value} % % See the \textsf{l3int} module for ways of doing this. % % \subsection{Variable and constants} % % \begin{function}{% % \const_new:Nn | % } % \begin{syntax} % "\const_new:Nn" "\c_" "{" "}" % \end{syntax} % Defines a constant with . If the constant is negative % or very large it requires an register. % \end{function} % % \begin{variable}{% % \c_minus_one | % \c_zero | % \c_one | % \c_two | % \c_three | % \c_four | % \c_six | % \c_seven | % \c_nine | % \c_ten | % \c_eleven | % \c_sixteen | % \c_hundred_one | % \c_twohundred_fifty_five | % \c_twohundred_fifty_six | % \c_thousand | % \c_ten_thousand | % \c_twenty_thousand % } % \\ % Set of constants denoting useful values. % \begin{texnote} % Most of these constants have been available under \LaTeX2 under names % like \tn{tw@}, \tn{thr@@} etc. % \end{texnote} % \end{variable} % % \begin{variable}{% % \l_tmpa_num | % \l_tmpb_num | % \l_tmpc_num | % \g_tmpa_num | % \g_tmpb_num | % } % \\ % Scratch register for immediate use. They are not used by conditionals % or predicate functions. % \end{variable} % % \subsection{Primitive functions} % % % \begin{function}{% % \num_value:w | % } % \begin{syntax} % "\num_value:w" \\ % "\num_value:w" % \end{syntax} % Expands until an is formed. One space may be % gobbled in the process. Preferably use with "\num_eval:n". % \begin{texnote} % This is the \TeX{} primitive \tn{number}. % \end{texnote} % \end{function} % % \begin{function}{% % \num_eval:w | % } % \begin{syntax} % "\num_eval:w" "\num_eval_end:" % \end{syntax} % Evaluates . The evaluation stops when an % unexpandable token of catcode other than 12 is reached or % "\num_eval_end:" is read. The latter is gobbled by the scanner % mechanism. % \begin{texnote} % This is the \eTeX{} primitive \tn{numexpr}. % \end{texnote} % \end{function} % % \begin{function}{% % \if_num:w | % } % \begin{syntax} % "\if_num:w" "\else:" "\fi:" % \end{syntax} % Compare two numbers. It is recommended to use "\num_eval:n" to % correctly evaluate and terminate these numbers. is one of % "<", "=" or ">" with catcode 12. % \begin{texnote} % This is the \TeX{} primitive \tn{ifnum}. % \end{texnote} % \end{function} % % \begin{function}{% % \if_num_odd:w | % } % \begin{syntax} % "\if_num_odd:w" "\else:" "\fi:" % \end{syntax} % Execute if is odd, otherwise. % \begin{texnote} % This is the \TeX{} primitive \tn{ifodd}. % \end{texnote} % \end{function} % % \begin{function}{% % \if_case:w | % \or: | % } % \begin{syntax} % "\if_case:w" "\or:" "\or:" "..." "\else:" % "\fi:" % \end{syntax} % Chooses case. If you wish to use negative numbers as well, % you can offset them with "\num_eval:n". % \begin{texnote} % These are the \TeX{} primitives \tn{ifcase} and \tn{or}. % \end{texnote} % \end{function} % % \StopEventually{} % % \subsection{The Implementation} % % % We start by ensuring that the required packages are loaded. % \begin{macrocode} %\ProvidesExplPackage % {\filename}{\filedate}{\fileversion}{\filedescription} %\RequirePackage{l3expan}\par %\RequirePackage{l3chk}\par %<*initex|package> % \end{macrocode} % % \begin{macro}{\num_value:w} % \begin{macro}{\num_eval:w} % \begin{macro}{\num_eval_end:} % \begin{macro}{\if_num:w} % \begin{macro}{\if_num_odd:w} % \begin{macro}{\if_case:w} % \begin{macro}{\or:} % Here are the remaining primitives for number comparisons and % expressions. % \begin{macrocode} \let_new:NN \num_value:w \tex_number:D \let_new:NN \num_eval:w \etex_numexpr:D \let_new:NN \num_eval_end: \scan_stop: \let_new:NN \if_num:w \tex_ifnum:D \let_new:NN \if_num_odd:w \tex_ifodd:D \let_new:NN \if_case:w \tex_ifcase:D \let_new:NN \or: \tex_or:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % Functions that support \LaTeX's user accessible counters should be % added here, too. But first the internal counters. % % \begin{macro}{\num_incr:N} % \begin{macro}{\num_decr:N} % \begin{macro}{\num_gincr:N} % \begin{macro}{\num_gdecr:N} % Incrementing and decrementing of integer registers is done with % the following functions. % \begin{macrocode} \def:Npn \num_incr:N #1{\num_add:Nn#1 1} \def:Npn \num_decr:N #1{\num_add:Nn#1 \c_minus_one} \def:Npn \num_gincr:N #1{\num_gadd:Nn#1 1} \def:Npn \num_gdecr:N #1{\num_gadd:Nn#1 \c_minus_one} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\num_incr:c} % \begin{macro}{\num_decr:c} % \begin{macro}{\num_gincr:c} % \begin{macro}{\num_gdecr:c} % We also need \ldots % \begin{macrocode} \def_new:Npn \num_incr:c {\exp_args:Nc \num_incr:N} \def_new:Npn \num_decr:c {\exp_args:Nc \num_decr:N} \def_new:Npn \num_gincr:c {\exp_args:Nc \num_gincr:N} \def_new:Npn \num_gdecr:c {\exp_args:Nc \num_gdecr:N} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\num_zero:N} % \begin{macro}{\num_zero:c} % \begin{macro}{\num_gzero:N} % \begin{macro}{\num_gzero:c} % We also need \ldots % \begin{macrocode} \def_new:Npn \num_zero:N #1 {\num_set:Nn #1 0} \def_new:Npn \num_gzero:N #1 {\num_gset:Nn #1 0} \def_new:Npn \num_zero:c {\exp_args:Nc \num_zero:N} \def_new:Npn \num_gzero:c {\exp_args:Nc \num_gzero:N} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % \begin{macro}{\num_new:N} % \begin{macro}{\num_new:c} % Allocate a new \m{num} variable and initialize it with zero. % \begin{macrocode} \def_new:Npn \num_new:N #1{\tlp_new:Nn #1{0}} \def_new:Npn \num_new:c {\exp_args:Nc \num_new:N} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\num_eval:n} % This function enables us to do all the operations without the aid of % an \m{int} register. % \begin{macrocode} \def_new:Npn \num_eval:n #1{\num_eval:w #1\num_eval_end:} % \end{macrocode} % \end{macro} % % \begin{macro}{\num_set:Nn} % \begin{macro}{\num_set:cn} % \begin{macro}{\num_gset:Nn} % \begin{macro}{\num_gset:cn} % Assigning values to \m{num} registers. % \begin{macrocode} \def_new:Npn \num_set:Nn #1#2{ \tlp_set:No #1{ \tex_number:D \num_eval:n {#2} } } \def_new:Npn \num_gset:Nn {\pref_global:D \num_set:Nn} \def_new:Npn \num_set:cn {\exp_args:Nc \num_set:Nn } \def_new:Npn \num_gset:cn {\exp_args:Nc \num_gset:Nn } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\num_set_eq:NN} % \begin{macro}{\num_set_eq:cN} % \begin{macro}{\num_set_eq:Nc} % \begin{macro}{\num_set_eq:cc} % Setting \m{num} registers equal to each other. % \begin{macrocode} \let_new:NN \num_set_eq:NN \tlp_set_eq:NN \def_new:Npn \num_set_eq:cN {\exp_args:Nc \num_set_eq:NN} \def_new:Npn \num_set_eq:Nc {\exp_args:NNc \num_set_eq:NN} \def_new:Npn \num_set_eq:cc {\exp_args:Ncc \num_set_eq:NN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\num_gset_eq:NN} % \begin{macro}{\num_gset_eq:cN} % \begin{macro}{\num_gset_eq:Nc} % \begin{macro}{\num_gset_eq:cc} % Setting \m{num} registers equal to each other. % \begin{macrocode} \let_new:NN \num_gset_eq:NN \tlp_gset_eq:NN \def_new:Npn \num_gset_eq:cN {\exp_args:Nc \num_gset_eq:NN} \def_new:Npn \num_gset_eq:Nc {\exp_args:NNc \num_gset_eq:NN} \def_new:Npn \num_gset_eq:cc {\exp_args:Ncc \num_gset_eq:NN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\num_add:Nn} % \begin{macro}{\num_add:cn} % \begin{macro}{\num_gadd:Nn} % \begin{macro}{\num_gadd:cn} % Adding is easily done as the second argument goes through % |\num_eval:n|. % \begin{macrocode} \def_new:Npn \num_add:Nn #1#2 {\num_set:Nn #1{#1+#2}} \def_new:Npn \num_add:cn {\exp_args:Nc\num_add:Nn} \def_new:Npn \num_gadd:Nn {\pref_global:D \num_add:Nn} \def_new:Npn \num_gadd:cn {\exp_args:Nc\num_gadd:Nn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\num_use:N} % \begin{macro}{\num_use:c} % Here is how num macros are accessed: % \begin{macrocode} \let_new:NN\num_use:N \use_arg_i:n \let_new:NN\num_use:c \cs_use:c % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\num_compare:nNnTF} % \begin{macro}{\num_compare:nNnT} % \begin{macro}{\num_compare:nNnF} % Simple comparison tests. % \begin{macrocode} \def_test_function_new:npn {num_compare:nNn}#1#2#3{ \if_num:w \num_eval:n {#1}#2\num_eval:n {#3} } \def_new:Npn \num_compare:cNcTF { \exp_args:NcNc\num_compare:nNnTF } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\num_compare_p:nNn} % A predicate function. % \begin{macrocode} \def_new:Npn \num_compare_p:nNn #1#2#3{ \if_num:w \num_eval:n {#1}#2\num_eval:n {#3} \c_true \else: \c_false \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}{\num_max_of:nn} % \begin{macro}{\num_min_of:nn} % \begin{macro}{\num_abs:n} % Functions for $\min$, $\max$, and absolute value. % \begin{macrocode} \def_new:Npn \num_abs:n#1{ \if_num:w \num_eval:n{#1}<\c_zero \exp_after:NN -\fi: #1 } \def_new:Npn \num_max_of:nn#1#2{\num_compare:nNnTF {#1}>{#2}{#1}{#2}} \def_new:Npn \num_min_of:nn#1#2{\num_compare:nNnTF {#1}<{#2}{#1}{#2}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\num_elt_count:n} % \begin{macro}{\num_elt_count_prop:Nn} % Helper function for counting elements in a list. % \begin{macrocode} \def_long_new:Npn \num_elt_count:n #1 { + 1 } \def_long_new:Npn \num_elt_count_prop:Nn #1#2 { + 1 } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\l_tmpa_num} % \begin{macro}{\l_tmpb_num} % \begin{macro}{\l_tmpc_num} % \begin{macro}{\g_tmpa_num} % \begin{macro}{\g_tmpb_num} % We provide an number local and two global \m{num}s, maybe we % need more or less. % \begin{macrocode} \num_new:N \l_tmpa_num \num_new:N \l_tmpb_num \num_new:N \l_tmpc_num \num_new:N \g_tmpa_num \num_new:N \g_tmpb_num % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsubsection{Defining constants} % As stated, most constants can be defined as |\tex_chardef:D| or % |\tex_mathchardef:D| but that's engine dependent. Omega/Aleph % allows |\tex_chardef:D|s up to 65535 which is also the maximum % number of registers of all types. % \begin{macro}{\const_new:Nn} % \begin{macro}{\c_max_register_num} % \begin{macro}{\const_new_aux:Nw} % \begin{macrocode} % \begin{macrocode} \engine_if_aleph:TF { \let_new:NN \const_new_aux:Nw \tex_chardef:D \const_new_aux:Nw \c_max_register_num = 65535 \scan_stop: } { \let_new:NN \const_new_aux:Nw \tex_mathchardef:D \const_new_aux:Nw \c_max_register_num = 32767 \scan_stop: } \def_new:Npn \const_new:Nn #1#2 { \num_compare:nNnTF {#2} > \c_minus_one { \num_compare:nNnTF {#2} > \c_max_register_num {\int_new:N #1 \int_set:Nn #1{#2}} {\chk_new_cs:N #1 \const_new_aux:Nw #1 = #2 \scan_stop: } } {\int_new:N #1 \int_set:Nn #1{#2}} } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\c_minus_one} % \begin{macro}{\c_zero} % \begin{macro}{\c_one} % \begin{macro}{\c_two} % \begin{macro}{\c_three} % \begin{macro}{\c_four} % \begin{macro}{\c_six} % \begin{macro}{\c_seven} % \begin{macro}{\c_nine} % \begin{macro}{\c_ten} % \begin{macro}{\c_eleven} % \begin{macro}{\c_sixteen} % \begin{macro}{\c_thirty_two} % \begin{macro}{\c_hundred_one} % \begin{macro}{\c_twohundred_fifty_five} % \begin{macro}{\c_twohundred_fifty_six} % \begin{macro}{\c_thousand} % \begin{macro}{\c_ten_thousand} % \begin{macro}{\c_ten_thousand_one} % \begin{macro}{\c_ten_thousand_two} % \begin{macro}{\c_ten_thousand_three} % \begin{macro}{\c_ten_thousand_four} % \begin{macro}{\c_twenty_thousand} % And the usual constants, others are still missing. Please, make % every constant a real constant at least for the moment. We can % easily convert things in the end when we have found what % constants are used in critical places and what not. % \begin{macrocode} %% \tex_countdef:D \c_minus_one = 10 \scan_stop: %% \c_minus_one = -1 \scan_stop: %% in l3basics %% \tex_chardef:D \c_sixteen = 16\scan_stop: %% in l3basics \const_new:Nn \c_zero {0} \const_new:Nn \c_one {1} \const_new:Nn \c_two {2} \const_new:Nn \c_three {3} \const_new:Nn \c_four {4} \const_new:Nn \c_six {6} \const_new:Nn \c_seven {7} \const_new:Nn \c_nine {9} \const_new:Nn \c_ten {10} \const_new:Nn \c_eleven {11} \const_new:Nn \c_thirty_two {32} % \end{macrocode} % The next one may seem a little odd (obviously!) but is useful when % dealing with logical operators. % \begin{macrocode} \const_new:Nn \c_hundred_one {101} \const_new:Nn \c_twohundred_fifty_five {255} \const_new:Nn \c_twohundred_fifty_six {256} \const_new:Nn \c_thousand {1000} \const_new:Nn \c_ten_thousand {10000} \const_new:Nn \c_ten_thousand_one {10001} \const_new:Nn \c_ten_thousand_two {10002} \const_new:Nn \c_ten_thousand_three {10003} \const_new:Nn \c_ten_thousand_four {10004} \const_new:Nn \c_twenty_thousand {20000} % \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macrocode} % % \end{macrocode} % % \endinput % % $Log$ % Revision 1.17 2006/03/20 18:26:37 braams % Updated the copyright notice (2006) and demoted all implementation % sections to subsections and so on to clean up the toc for source3.tex % % Revision 1.16 2005/12/27 10:03:01 morten % Changed RCS information retrieval % % Revision 1.15 2005/12/06 13:41:02 morten % Added a few functions to ease processing with \if_case:w % % Revision 1.14 2005/12/03 12:57:36 morten % Minor touch-ups. % % Revision 1.13 2005/10/27 22:39:02 morten % Forgot to add \if_num_odd:w % % Revision 1.12 2005/10/27 22:34:26 morten % Added \if_num:w, \if_case:w and \or: as they really belong here. % % Revision 1.11 2005/04/06 22:36:53 braams % Missed one occurence of \c_max_register_int % % Revision 1.10 2005/04/06 21:38:46 morten % Removed dependency on l3prg and added a missing function. % % Revision 1.9 2005/04/05 22:05:38 braams % Renamed \c_max_regsiter_int to \c_max_register_num, % Fixed const_new to allow 32767 as a value for \tex_mathchardef:D % Added \c_ten and \c_eleven as constants % % Revision 1.8 2005/03/26 21:06:35 morten % Update documentation % % Revision 1.7 2005/03/22 23:21:32 morten % Now independent of l3int and can be used as a very primitive module. % % Revision 1.6 2005/03/16 22:36:20 braams % Added the tweaks necessary to be able to load with initex % % Revision 1.5 2005/03/11 21:39:47 braams % Fixed the use of RCS information; added \StopEventually %