diff options
author | Karl Berry <karl@freefriends.org> | 2007-05-22 17:46:23 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2007-05-22 17:46:23 +0000 |
commit | f4eb27d3314d15838f674a3872000159d029f88b (patch) | |
tree | 6e9ab33c5a2d702912b4a969ade4e4e2ac586d62 /Master/texmf-dist/source/latex/expl3/l3int.dtx | |
parent | 14af3f447439750920f754792b89f113d019076a (diff) |
update expl3
git-svn-id: svn://tug.org/texlive/trunk@4335 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3int.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3int.dtx | 1222 |
1 files changed, 857 insertions, 365 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3int.dtx b/Master/texmf-dist/source/latex/expl3/l3int.dtx index d219a9d27bb..f4e582ec12f 100644 --- a/Master/texmf-dist/source/latex/expl3/l3int.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3int.dtx @@ -1,15 +1,50 @@ % \iffalse -%% File: l3int.dtx Copyright (C) 1990-1998 LaTeX3 project -% +%% File: l3int.dtx Copyright (C) 1990-2006 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. +%% +%% ----------------------------------------------------------------------- +% +%<package>\RequirePackage{l3names} %<*dtx> - \ProvidesFile{l3int.dtx} +%\fi +\def\GetIdInfo$Id: #1.dtx #2 #3-#4-#5 #6 #7$#8{% + \def\fileversion{#2}% + \def\filedate{#3/#4/#5}% + \ProvidesFile{#1.dtx}[#3/#4/#5 v#2 #8]% +} +%\iffalse %</dtx> -%<package>\NeedsTeXFormat{LaTeX2e} -%<package>\ProvidesPackage{l3int} -%<driver> \ProvidesFile{l3int.drv} -% \fi -% \ProvidesFile{l3int.dtx} - [1998/04/20 v1.0c L3 Experimental Integer module] +%\fi +\GetIdInfo$Id: l3int.dtx 573 2006-08-21 20:59:37Z morten $ + {L3 Experimental Integer module} % % \iffalse %<*driver> @@ -22,7 +57,6 @@ % \fi % % -% \GetFileInfo{l3int.dtx} % \title{The \textsf{l3int} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ @@ -31,40 +65,32 @@ % \date{\filedate} % \maketitle % -% \section{Counters} +% \section{Integers} % % \LaTeX3 maintains two type of integer registers for internal use. -% One (associated with the name "int") uses the builtin counter -% registers of \TeX{} and is therefore relatively fast and one -% (associated with the name "fint" for fake counter) that implements the -% operations within the \TeX{} macro language and is therefore much -% slower in processing. This type of counter is also far more restricted -% in its range. -% -% The fake counter should be used for variables that are not accessed -% very often since this saves the important fast internal registers -% (\TeX{} has only 255 of those). For example, all allocation routines -% in \LaTeX3 make use of fake counters to remember the values of recent -% allocated register numbers etc. -% -% Since all functions for both types are very similar (they usually -% differ only in the initial "f") we describe them together. But -% remember that you need to use "fint" variables when using "fint" -% functions. +% 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. % % \subsection{Functions} % % \begin{function}{% % \int_new:N | % \int_new:c | -% \fint_new:N | +% \int_new_l:N | % } % \begin{syntax} % "\int_new:N" <int> -% "\fint_new:N" <fint> % \end{syntax} -% Defines <int> to be a new variable of type "int". There is no way to -% define constant counters with these functions. +% Globally defines <int> to be a new variable of type "int" although +% you can still choose if it should be a an "\l_" or "\g_" type. +% There is no way to define constant counters with these functions. +% The function "\int_new_l:N" defines <int> locally only. % \begin{texnote} % "\int_new:N" is the equivalent to plain \TeX{}'s \tn{newcount}. % However, the internal register allocation is done differently. @@ -75,12 +101,9 @@ % \int_incr:N | % \int_gincr:N | % \int_gincr:c | -% \fint_incr:N | -% \fint_gincr:N | % } % \begin{syntax} % "\int_incr:N" <int> -% "\fint_incr:N" <fint> % \end{syntax} % Increments <int> by one. For global variables the global versions % should be used. @@ -90,12 +113,9 @@ % \int_decr:N | % \int_gdecr:N | % \int_gdecr:c | -% \fint_decr:N | -% \fint_gdecr:N | % } % \begin{syntax} % "\int_decr:N" <int> -% "\fint_decr:N" <fint> % \end{syntax} % Decrements <int> by one. For global variables the global versions % should be used. @@ -106,119 +126,101 @@ % \int_set:cn | % \int_gset:Nn | % \int_gset:cn | -% \fint_set:Nn | -% \fint_gset:Nn | % } % \begin{syntax} -% "\int_set:Nn" <int> "{" <integer> "}" -% "\fint_set:Nn" <fint> "{" <integer> "}" +% "\int_set:Nn" <int> "{" <integer expr> "}" % \end{syntax} -% These functions will set the <int> register to the <integer> value. +% These functions will set the <int> register to the <integer expr> +% value. This value can contain simple calc-like expressions as +% provided by \eTeX. % \end{function} % +% % \begin{function}{% -% \fint_set_eq:NN | -% \fint_gset_eq:NN | +% \int_zero:N | +% \int_zero:c | +% \int_gzero:N | +% \int_gzero:c | % } % \begin{syntax} -% "\fint_set_eq:NN" <fint1> <fint2> +% "\int_zero:N" <int> % \end{syntax} -% Fast form for -% \begin{syntax} -% "\fint_set:No" <fint1> "{\fint_use:N" <fint2> "}" -% \end{syntax} -% when <fint2> is known to be a variable of fake counter. Note that a -% corresponding function for real counters is not implemented since the -% "\int_set:Nn" function does this operation sufficiently when then second -% argument is a <int> instead of "{"<integer>"}" value. +% These functions sets the <int> register to zero either locally +% or globally. % \end{function} % +% % \begin{function}{% % \int_add:Nn | % \int_add:cn | % \int_gadd:Nn | -% \fint_add:Nn | -% \fint_gadd:Nn | % } % \begin{syntax} -% "\int_add:Nn" <int> "{" <integer> "}" -% "\fint_add:Nn" <fint> "{" <integer> "}" +% "\int_add:Nn" <int> "{" <integer expr> "}" % \end{syntax} -% These functions will add to the <int> register the value <integer>. If -% the second argument is a <int> register too, the surrounding braces -% can be left out. -% -% It not allowed to use a <fint> instead of the <integer>. If a fake -% counter should be used as the second argument one needs to turn the -% <fint> first into an <integer> by applying "\fint_use:N". +% 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_gsub:Nn | -% \fint_sub:Nn | -% \fint_gsub:Nn | % } % \begin{syntax} -% "\int_gsub:Nn" <int> "{" <integer> "}" -% "\fint_gsub:Nn" <fint> "{" <integer> "}" +% "\int_gsub:Nn" <int> "{" <integer expr> "}" % \end{syntax} % These functions will subtract from the <int> register the value -% <integer>. If the second argument is a <int> register too, the +% <integer expr>. If the second argument is a <int> register too, the % surrounding braces can be left out. -% -% It is not allowed to use a <fint> instead of the <integer>. If a fake -% counter should be used as the second argument one needs to turn the -% <fint> first into an <integer> by applying "\fint_use:N". % \end{function} % % \begin{function}{% % \int_use:N | % \int_use:c | -% \fint_use:N | % } % \begin{syntax} % "\int_use:N" <int> -% "\fint_use:N" <fint> % \end{syntax} % This function returns the integer value kept in <int> in a way -% suitable for further processing. Be sure to use "\fint_use:N" if you -% are accessing the value of a fake counter because otherwise your -% result will be to some surprise to you (there is no check). +% 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, dimenions etc.\ to allow checks and to make the code -% more selfexplaining. +% for counters, dimensions etc.\ to allow checks and to make the code +% more self-explaining. % \end{texnote} % \end{function} % % \subsection{Formatting a counter value} % -% \begin{function}{\int_to_arabic:n | -% \int_to_alph:n | -% \int_to_Alph:n | -% \int_to_roman:n | -% \int_to_Roman:n | -% \int_to_symbol:n | +% \begin{function}{ +% \int_to_arabic:n | +% \int_to_alph:n | +% \int_to_Alph:n | +% \int_to_roman:n | +% \int_to_Roman:n | +% \int_to_symbol:n | % } % \begin{syntax} % "\int_to_alph:n" "{" <integer> "}" % "\int_to_alph:n" <int> -% "\int_to_alph:n" "{" "\fint_use:N" <fint> "}" % \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>. -% -% To format <fint>s with these functions it is necessary to turn the -% value of the <fint> first into an <integer> by applying "\fint_use:N" -% within the argument braces. +% 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. +% 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} @@ -226,36 +228,65 @@ % \end{texnote} % \end{function} % -% \subsection{Variable and constants} +% \subsubsection{Internal functions} % -% \begin{variable}{% -% \c_int_max | -% \c_fint_max | +% \begin{function}{\int_to_roman:w} +% \begin{syntax} +% "\int_to_roman:w" <integer> <space> \textit{or} <non-expandable token> +% \end{syntax} +% Converts <integer> to it lowercase roman representation. Note that +% it produces a string of letters with catcode 12. +% \begin{texnote} +% This is the \TeX{} primitive \tn{romannumeral} renamed. +% \end{texnote} +% \end{function} +% \begin{function}{ +% \int_roman_lcuc_mapping:Nnn | +% \int_to_roman_lcuc:NN | % } -% Constant that denote the maximum value which can be stored in a <int> -% or <fint> register. -% \end{variable} +% \begin{syntax} +% "\int_roman_lcuc_mapping:Nnn" <roman_char> "{"<licr>"}" "{"<LICR>"}" +% "\int_to_roman_lcuc:NN" <roman_char> <char> +% \end{syntax} +% "\int_roman_lcuc_mapping:Nnn" specifies how the roman +% numeral <roman\_ char> (i, v, x, l, c, d, or m) should be +% interpreted when converting the number. <licr> is the lower case and +% <LICR> is the uppercase mapping. "\int_to_roman_lcuc:NN" is a +% recursive function converting the roman numerals. +% \end{function} +% +% +% \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" "{"<int1>"}" "{"<int2>"}" <function> +% "\int_alph_default_conversion_rule:n" "{"<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} +% +% +% +% +% +% +% \subsection{Variable and constants} % % \begin{variable}{% -% \c_minus_one | -% \c_zero | -% \c_one | -% \c_two | -% \c_three | -% \c_sixteen | -% \c_twohundred_fifty_five | -% \c_twohundredfiftysix | -% \c_thousand | -% \c_ten_thousand | -% \c_twenty_thousand | +% \c_max_int | % } -% 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} +% Constant that denote the maximum value which can be stored in an +% <int> register. % \end{variable} % +% % \begin{variable}{% % \l_tmpa_int | % \l_tmpb_int | @@ -268,16 +299,143 @@ % \end{variable} % % -% \section{Integer registers} +% \subsection{Testing and evaluating integer expressions} +% +% \begin{function}{% +% \int_eval:n | +% \int_div_truncate:nn | +% \int_div_round:nn | +% \int_mod:nn | +% } +% \begin{syntax} +% "\int_eval:n" "{"<int~expr>"}" \\ +% "\int_div_truncate:n" "{"<int~expr>"}" "{"<int~expr>"}" \\ +% "\int_mod:nn" "{"<int~expr>"}" "{"<int~expr>"}" +% \end{syntax} +% Evaluates the value of a integer expression so that +% "\int_eval:n {3*5/4}" puts "4" back into the input stream. Note that +% the results of divisions are rounded by the primitive operations. If +% you want the result of a division to be truncated use +% "\int_div_truncate:nn". "\int_div_round:nn" is added for +% completeness. "\int_mod:nn" returns the remainder of a division. All +% of these functions are expandable. +% \begin{texnote} +% "\int_eval:n" is the \eTeX primitive \tn{numexpr} turned into a function +% taking an argument. +% \end{texnote} +% \end{function} +% +% \begin{function}{% +% \int_compare:nNnTF | +% \int_compare:nNnT | +% \int_compare:nNnF | +% } +% \begin{syntax} +% "\int_compare:nNnTF" "{"<int~expr>"}" <rel> "{"<int~expr>"}" +% "{"<true>"}" "{"<false>"}" +% \end{syntax} +% These functions test two integer expressions against each other. They +% are both evaluated by "\int_eval:n". Note that if both expressions +% are normal integer variables as in +% \begin{quote} +% "\int_compare:nNnTF \l_temp_int < \c_zero {negative}{non-negative}" +% \end{quote} +% you can safely omit the braces. +% \begin{texnote} +% This is the \TeX{} primitive \tn{ifnum} turned into a function. +% \end{texnote} +% \end{function} +% +% \begin{function}{% +% \int_compare_p:nNn | +% } +% \begin{syntax} +% "\int_compare_p:nNn" "{"<int~expr>"}" <rel> "{"<int~expr>"}" +% \end{syntax} +% A predicate version of the above mentioned functions. +% \end{function} +% +% \begin{function}{% +% \int_if_odd:nTF | +% \int_if_odd_p:n | +% } +% \begin{syntax} +% "\int_if_odd:nTF" "{"<int~expr>"}" "{"<true>"}" "{"<false>"}" +% \end{syntax} +% These functions test if an integer expression is even or odd. We +% also define a predicate version of it. +% \begin{texnote} +% This is the \TeX{} primitive \tn{ifodd} turned into a function. +% \end{texnote} +% \end{function} +% +% \begin{function}{% +% \int_whiledo:nNnT | +% \int_whiledo:nNnF | +% \int_dowhile:nNnT | +% \int_dowhile:nNnF | +% } +% \begin{syntax} +% "\int_whiledo:nNnT" <int expr> <rel> <int~expr> "{"<true>"}" +% \end{syntax} +% "\int_whiledo:nNnT" tests the integer expressions and if true performs +% the body "T" until the test fails. "\int_dowhile:nNnT" is similar +% but executes the body first and then performs the check, thus +% ensuring that the body is executed at least once. The "F" versions +% are similar but continue the loop as long as the test is false. They +% could be omitted as it is just a matter of switching the arguments +% in the test. +% \end{function} +% + +% \subsection{Conversion} +% +% \begin{function}{% +% \int_convert_from_base_ten:nn | +% } +% \begin{syntax} +% "\int_convert_from_base_ten:nn" "{"<number>"}""{"<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" "{"<number>"}""{"<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} +% +% +% \StopEventually{} +% \subsection{The Implementation} +% % -% % We start by ensuring that the required packages are loaded. % \begin{macrocode} -%<package&!check>\RequirePackage{l3basics}\par -%<package&check>\RequirePackage{l3chk}\par -%<*package> +%<package&!check>\RequirePackage{l3num} +%<package&check>\RequirePackage{l3chk} +%<*initex|package> % \end{macrocode} % +% \begin{macro}{\int_to_roman:w} +% \begin{macro}{\int_to_number:w} +% \begin{macro}{\int_advance:w} +% A new name for the primitives. +% \begin{macrocode} +\let_new:NN \int_to_roman:w \tex_romannumeral:D +\let_new:NN \int_to_number:w \tex_number:D +\let_new: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. % @@ -288,12 +446,12 @@ % Incrementing and decrementing of integer registers is done with % the following functions. % \begin{macrocode} -\def_new:Npn \int_incr:N #1{\tex_advance:D#1\c_one +\def_new:Npn \int_incr:N #1{\int_advance:w#1\c_one %<*check> \chk_local_or_pref_global:N #1 %</check> } -\def_new:Npn \int_decr:N #1{\tex_advance:D#1\c_minus_one +\def_new:Npn \int_decr:N #1{\int_advance:w#1\c_minus_one %<*check> \chk_local_or_pref_global:N #1 %</check> @@ -335,16 +493,22 @@ % % % \begin{macro}{\int_new:N} +% \begin{macro}{\int_new_l:N} % \begin{macro}{\int_new:c} % Allocation of a new internal counter is already done above. Here we define % the next likely variant. % \begin{macrocode} -\def_new:Npn \int_new:N {} % but since we don't distribute -\let:NN \int_new:N \newcount % allocation better nick the LaTeX one ... +%<*initex> +\alloc_setup_type:nnn {int} \c_eleven \c_max_register_num +\def_new:Npn \int_new:N #1 {\alloc_reg:NnNN g {int} \tex_countdef:D#1} +\def_new:Npn \int_new_l:N #1 {\alloc_reg:NnNN l {int} \tex_countdef:D#1} +%</initex> +%<package>\let:NN \int_new:N \newcount% allocation better nick the LaTeX one... \def_new:Npn \int_new:c {\exp_args:Nc \int_new:N} % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % % \begin{macro}{\int_set:Nn} @@ -354,7 +518,7 @@ % Setting counters is again something that I would like to make % uniform at the moment to get a better overview. % \begin{macrocode} -\def_new:Npn \int_set:Nn #1#2{#1#2\scan_stop: +\def_new:Npn \int_set:Nn #1#2{#1 \int_eval:w #2\scan_stop: %<*check> \chk_local_or_pref_global:N #1 %</check> @@ -373,6 +537,21 @@ % \end{macro} % \end{macro} % +% \begin{macro}{\int_zero:N} +% \begin{macro}{\int_zero:c} +% \begin{macro}{\int_gzero:N} +% \begin{macro}{\int_gzero:c} +% Functions that reset an \m{int} register to zero. +% \begin{macrocode} +\def_new:Npn \int_zero:N #1 {#1=\c_zero} +\def_new:Npn \int_zero:c #1 {\exp_args:Nc \int_zero:N} +\def_new:Npn \int_gzero:N #1 {\pref_global:D #1=\c_zero} +\def_new:Npn \int_gzero:c {\exp_args:Nc \int_gzero:N} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\int_add:Nn} % \begin{macro}{\int_add:cn} @@ -383,14 +562,19 @@ % We should think of using these functions % \begin{macrocode} \def_new:Npn \int_add:Nn #1#2{ - \tex_advance:D#1#2\scan_stop: +% \end{macrocode} +% We need to say |by| in case the first argument is a register +% accessed by its number, e.g., |\count23|. Not that it should +% ever happen but\dots +% \begin{macrocode} + \int_advance:w #1 by \int_eval:w #2\scan_stop: %<*check> \chk_local_or_pref_global:N #1 %</check> } \def_new:Npn\int_add:cn{\exp_args:Nc\int_add:Nn} \def_new:Npn \int_sub:Nn #1#2{ - \tex_advance:D#1-#2\scan_stop: + \int_advance:w #1-\int_eval:w #2\scan_stop: %<*check> \chk_local_or_pref_global:N #1 %</check> @@ -415,341 +599,649 @@ % \end{macro} % % -% \begin{macro}{\int_use:N} -% \begin{macro}{\int_use:c} +% \begin{macro}{\int_use:N} +% \begin{macro}{\int_use:c} % Here is how counters are accessed: % \begin{macrocode} \let_new:NN \int_use:N \tex_the:D \def_new:Npn \int_use:c #1{\int_use:N \cs:w#1\cs_end:} % \end{macrocode} -% \end{macro} -% \end{macro} - +% \end{macro} +% \end{macro} % -% \begin{macro}{\int_gincr:c} -% \begin{macro}{\int_gdecr:c} +% +% \begin{macro}{\int_gincr:c} +% \begin{macro}{\int_gdecr:c} % We also need \ldots % \begin{macrocode} \def_new:Npn \int_gincr:c {\exp_args:Nc \int_gincr:N} \def_new:Npn \int_gdecr:c {\exp_args:Nc \int_gdecr:N} % \end{macrocode} -% \end{macro} -% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\int_to_arabic:n} +% Nothing exciting here. +% \begin{macrocode} +\def_new:Npn \int_to_arabic:n #1{\int_to_number:w \int_eval:n{#1}} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\int_roman_lcuc_mapping:Nnn} +% Using \TeX's built-in feature for producing roman numerals has some +% surprising features. One is the the characters resulting from +% |\int_to_roman:w| have category code~12 so they may fail in +% certain comparison tests. Therefore we use a mapping from the +% character \TeX{} produces to the character we actually want which +% will give us letters with category code~11.% +% \begin{macrocode} +\def_new:Npn \int_roman_lcuc_mapping:Nnn #1#2#3{ + \def:cpn {int_to_lc_roman_#1:}{#2} + \def:cpn {int_to_uc_roman_#1:}{#3} +} +% \end{macrocode} +% \end{macro} +% Here are the default mappings. I haven't found any examples of say +% Turkish doing the mapping |i \i I| but at least there is a +% possibility for it if needed. Note: I have now asked a Turkish +% person and he tells me they do the |i I| mapping. +% \begin{macrocode} +\int_roman_lcuc_mapping:Nnn i i I +\int_roman_lcuc_mapping:Nnn v v V +\int_roman_lcuc_mapping:Nnn x x X +\int_roman_lcuc_mapping:Nnn l l L +\int_roman_lcuc_mapping:Nnn c c C +\int_roman_lcuc_mapping:Nnn d d D +\int_roman_lcuc_mapping:Nnn m m M +% \end{macrocode} +% For the delimiter we cheat and let it gobble its arguments instead. +% \begin{macrocode} +\int_roman_lcuc_mapping:Nnn Q \use_none:nn \use_none:nn +% \end{macrocode} +% +% \begin{macro}{\int_to_roman:n} +% \begin{macro}{\int_to_Roman:n} +% \begin{macro}{\int_to_roman_lcuc:NN} +% 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 +% |\int_eval:n| first which is safer and more flexible. +% \begin{macrocode} +\def_new:Npn \int_to_roman:n #1 { + \exp_after:NN \int_to_roman_lcuc:NN \exp_after:NN l + \int_to_roman:w \int_eval:n {#1} Q +} +\def_new:Npn \int_to_Roman:n #1 { + \exp_after:NN \int_to_roman_lcuc:NN \exp_after:NN u + \int_to_roman:w \int_eval:n {#1} Q +} +\def_new:Npn \int_to_roman_lcuc:NN #1#2{ + \cs_use:c {int_to_#1c_roman_#2:} + \int_to_roman_lcuc:NN #1 +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% \begin{macro}{\int_convert_number_with_rule:nnN} +% This is our major workhorse for conversions. |#1| is the number we +% want converted, |#2| is the base number, and |#3| is the function +% converting the number. This function expects to receive a +% non-negative integer and as such is ideal for something using +% |\if_case:w| internally. +% +% The basic example is this: We want to convert the number 50 (|#1|) +% into an alphabetic equivalent |ax|. For the English language our +% list contains 26 elements so this is our argument |#2| while the +% function |#3| just turns |1| into |a|, |2| into |b|, etc. Hence our +% goal is to turn 50 into the sequence |#3{1}#1{24}| so what we do is +% to first divide 50 by 26 and truncating the result returning 1. +% Then before we execute this we call the function again but this time +% on the result of the remainder of the division. This goes on until +% the remainder is less than or equal to the base number where we just +% call the function |#3| directly on the number. +% +% We do a little pre-expansion of the arguments below as they +% otherwise have a tendency to grow quite large. +% \begin{macrocode} +\def:Npn \int_convert_number_with_rule:nnN #1#2#3{ + \int_compare:nNnTF {#1}>{#2} + { + \exp_args:No \int_convert_number_with_rule:nnN + { \int_use:N\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:No #3 { \int_use:N\int_eval:n{1+\int_mod:nn {#1-1}{#2}} } + } + { \exp_args:No #3{ \int_use:N\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} +\def_new: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: +} +\def_new: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{macrocode} +\def_new:Npn \int_to_alph:n #1{ + \int_convert_number_with_rule:nnN {#1}{26} + \int_alph_default_conversion_rule:n +} +\def_new:Npn \int_to_Alph:n #1{ + \int_convert_number_with_rule:nnN {#1}{26} + \int_Alph_default_conversion_rule:n +} +% \end{macrocode} +% \end{macro} +% \end{macro} % +% \begin{macro}{\int_to_symbol:n} +% Turning a number into a symbol is also easy enough. +% \begin{macrocode} +\def_new:Npn \int_to_symbol:n #1{ + \mode_math:TF + { + \int_convert_number_with_rule:nnN {#1}{9} + \int_symbol_math_conversion_rule:n + } + { + \int_convert_number_with_rule:nnN {#1}{9} + \int_symbol_text_conversion_rule:n + } +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\int_symbol_math_conversion_rule:n} +% \begin{macro}{\int_symbol_text_conversion_rule:n} +% Nothing spectacular here. +% \begin{macrocode} +\def_new:Npn \int_symbol_math_conversion_rule:n #1 { + \if_case:w #1 + \or: * + \or: \dagger + \or: \ddagger + \or: \mathsection + \or: \mathparagraph + \or: \| + \or: ** + \or: \dagger\dagger + \or: \ddagger\ddagger + \fi: +} +\def_new:Npn \int_symbol_text_conversion_rule:n #1 { + \if_case:w #1 + \or: \textasteriskcentered + \or: \textdagger + \or: \textdaggerdbl + \or: \textsection + \or: \textparagraph + \or: \textbardbl + \or: \textasteriskcentered\textasteriskcentered + \or: \textdagger\textdagger + \or: \textdaggerdbl\textdaggerdbl + \fi: +} +% \end{macrocode} +% \end{macro} +% \end{macro} % % \begin{macro}{\l_tmpa_int} % \begin{macro}{\l_tmpb_int} % \begin{macro}{\l_tmpc_int} % \begin{macro}{\g_tmpa_int} % \begin{macro}{\g_tmpb_int} -% We provide two local and two global scratch counters, maybe we -% need more or less. Instead of using the allocation routines we -% partly allocate them by hand. -% \begin{macrocode} -\chk_new_cs:N \l_tmpa_int -% \end{macrocode} -% If it turns out that we don't need local counters then this -% register should be used for global counter. We might also think of -% using the |\l_last_alloc_fint| as a scratch register. +% \begin{macro}{\l_loop_int} +% We provide four local and two global scratch counters, maybe we +% need more or less. % \begin{macrocode} -\tex_countdef:D\l_tmpa_int 255 +\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 +\int_new:N \l_loop_int % a variable for use in loops (whilenum etc) % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \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_sixteen} -% \begin{macro}{\c_thirty_two} -% \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} -% \begin{macro}{\c_int_max} -% 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{macro}{\int_eval:n} +% \begin{macro}{\int_eval:w} +% Evaluating a calc expression using normal operators. Many of these +% are exactly the same as the ones in the \textsf{num} module so we +% just use them. % \begin{macrocode} -\tex_chardef:D \c_zero = 0 \scan_stop: -\tex_chardef:D \c_one = 1 \scan_stop: -\tex_chardef:D \c_two = 2 \scan_stop: -\tex_chardef:D \c_three = 3 \scan_stop: -\tex_chardef:D \c_four = 4 \scan_stop: -\tex_chardef:D \c_sixteen = 16 \scan_stop: -\tex_chardef:D \c_thirty_two = 32 \scan_stop: -\tex_chardef:D \c_twohundred_fifty_five = 255 \scan_stop: -\tex_mathchardef:D \c_twohundred_fifty_six = 256 \scan_stop: -\tex_mathchardef:D \c_thousand = 1000 \scan_stop: -\tex_mathchardef:D \c_ten_thousand = 10000 \scan_stop: -\tex_mathchardef:D \c_ten_thousand_one = 10001 \scan_stop: -\tex_mathchardef:D \c_ten_thousand_two = 10002 \scan_stop: -\tex_mathchardef:D \c_ten_thousand_three = 10003 \scan_stop: -\tex_mathchardef:D \c_ten_thousand_four = 10004 \scan_stop: -\tex_mathchardef:D \c_twenty_thousand = 20000 \scan_stop: -% already defined ... -%\int_new:N \c_minus_one -% \c_minus_one = -1 +\let_new:NN \int_eval:n \num_eval:n +\let_new:NN \int_eval:w \num_eval:w % \end{macrocode} -% The |\c_int_max| will be defined internally as the largest -% dimen. +% \end{macro} +% \end{macro} +% +% \begin{macro}{\c_max_int} +% The largest number allowed is $2^{31}-1$ % \begin{macrocode} -%\int_new:N \c_int_max -% \c_int_max = 2147483647 +\const_new:Nn \c_max_int {2147483647} % \end{macrocode} % \end{macro} +% +% \begin{macro}{\int_pre_eval_one_arg:Nn} +% \begin{macro}{\int_pre_eval_two_args:Nnn} +% These might be handy when handing down values to other +% functions. All they do is evaluate the number in advance. +% \begin{macrocode} +\def:Npn \int_pre_eval_one_arg:Nnn #1#2{\exp_args:No#1{\int_eval:w#2}} +\def:Npn \int_pre_eval_two_args:Nnn #1#2#3{ + \exp_args:Noo#1{\int_use:N\int_eval:w#2}{\int_use:N\int_eval:w#3} +} +% \end{macrocode} % \end{macro} % \end{macro} +% +% \begin{macro}{\int_div_truncate:nn} +% \begin{macro}{\int_div_round:nn} +% \begin{macro}{\int_mod:nn} +% \begin{macro}{\int_div_truncate_raw:nn} +% \begin{macro}{\int_div_round_raw:nn} +% \begin{macro}{\int_mod_raw:nn} +% As "\num_eval:w" rounds the result of a division we also +% provide a version that truncates the result. +% \begin{macrocode} +\def_new:Npn \int_div_truncate:nn { + \int_pre_eval_two_args:Nnn\int_div_truncate_raw:nn +} +\def_new:Npn \int_div_truncate_raw:nn #1#2 { + \int_eval:n{ (2*#1 - #2) / (2* #2) } +} +% \end{macrocode} +% For the sake of completeness: +% \begin{macrocode} +\def_new:Npn \int_div_round:nn { + \int_pre_eval_two_args:Nnn\int_div_round_raw:nn +} +\def_new:Npn \int_div_round_raw:nn #1#2 {\int_eval:n{#1/#2}} +% \end{macrocode} +% Finally there's the modulus operation. +% \begin{macrocode} +\def_new:Npn \int_mod:nn {\int_pre_eval_two_args:Nnn\int_mod_raw:nn} +\def_new:Npn \int_mod_raw:nn #1#2 { + \int_eval:n{ #1 - \int_div_truncate_raw:nn {#1}{#2} * #2 } +} +% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% +% +% \begin{macro}{\int_compare:nNnTF} +% \begin{macro}{\int_compare:nNnT} +% \begin{macro}{\int_compare:nNnF} +% Simple comparison tests. +% \begin{macrocode} +\let_new:NN \int_compare:nNnTF \num_compare:nNnTF +\let_new:NN \int_compare:nNnT \num_compare:nNnT +\let_new:NN \int_compare:nNnF \num_compare:nNnF +% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% +% \begin{macro}{\int_compare_p:nNn} +% A predicate function. +% \begin{macrocode} +\let_new:NN \int_compare_p:nNn \num_compare_p:nNn +% \end{macrocode} % \end{macro} +% +% \begin{macro}{\int_if_odd_p:n} +% \begin{macro}{\int_if_odd:nTF} +% \begin{macro}{\int_if_odd:nT} +% \begin{macro}{\int_if_odd:nF} +% A predicate function. +% \begin{macrocode} +\def_new:Npn \int_if_odd_p:n #1 { + \if_num_odd:w \int_eval:n{#1} + \c_true + \else: + \c_false + \fi: +} +\def_test_function_new:npn {int_if_odd:n}#1{\if_num_odd:w \int_eval:n{#1}} +% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% % -% Show token usage: +% \begin{macro}{\int_whiledo:nNnT} +% \begin{macro}{\int_whiledo:nNnF} +% \begin{macro}{\int_dowhile:nNnT} +% \begin{macro}{\int_dowhile:nNnF} +% These are quite easy given the above functions. The "while" versions +% test first and then execute the body. The "dowhile" does it the +% other way round. % \begin{macrocode} -%</package> -%<*showmemory> -\showMemUsage -%</showmemory> +\def_new:Npn \int_whiledo:nNnT #1#2#3#4{ + \int_compare:nNnT {#1}#2{#3}{#4 \int_whiledo:nNnT {#1}#2{#3}{#4}} +} +\def_new:Npn \int_whiledo:nNnF #1#2#3#4{ + \int_compare:nNnF {#1}#2{#3}{#4 \int_whiledo:nNnF {#1}#2{#3}{#4}} +} +\def_new:Npn \int_dowhile:nNnT #1#2#3#4{ + #4 \int_compare:nNnT {#1}#2{#3}{\int_dowhile:nNnT {#1}#2{#3}{#4}} +} +\def_new:Npn \int_dowhile:nNnF #1#2#3#4{ + #4 \int_compare:nNnF {#1}#2{#3}{\int_dowhile:nNnF {#1}#2{#3}{#4}} +} % \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % -% \section{Fake registers} -% -% Fake registers are registers which implement \m{counter}s, -% \m{dimen}s, etc.\ which aren't used often and therefore don't need -% to run efficiently. One possible way of using them is to prepare certain -% registers this way, but |\let:NN| the mutator functions to real -% \m{counter}s as long as we have a sufficient number available. Now -% if we are making real large formats (by adding Pic\TeX, for example) -% we can turn them easily into fake registers and everything will work -% as before (only a bit slower). -% -% -% I haven't implemented anything besides counters so far, but \m{dimen} -% and \m{skip} present no principal problem and should probably be -% added. +% \subsubsection{Scanning and conversion} % -% \subsection{Fake counters} % -% \begin{macro}{\fint_new:N} -% A fake counter is internally a \m{muskip} register. A count value -% \m{x} is saved as \m{x}|mu| (more exactly as \m{x}|.0mu|) in this -% register. This means that fake counter values are far more -% restricted then usual counters, the largest value is 16383, -% i.e.\ the |pt| part of \TeX{}'s largest \m{dimen}. This could be -% changed by using more complicated conversion routines, but it -% might be all right in usual applications. +% 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. % -% Of course, we should make sure that we don't reach the borders, -% otherwise the user will be faced by the surprising message that -% some dimension got to large. (Not done yet). +% \begin{macro}{\int_get_sign_and_digits:n} +% \begin{macro}{\int_get_sign:n} +% \begin{macro}{\int_get_digits:n} +% \begin{macro}{\int_get_sign_and_digits_aux:nNNN} +% \begin{macro}{\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{macrocode} -%<*package> -\let_new:NN \fint_new:N \newmuskip % nicked from LaTeX +\def_new:Npn \int_get_sign_and_digits:n #1{ + \int_get_sign_and_digits_aux:nNNN {#1} \c_true \c_true \c_true +} +\def_new:Npn \int_get_sign:n #1{ + \int_get_sign_and_digits_aux:nNNN {#1} \c_true \c_true \c_false +} +\def_new:Npn \int_get_digits:n #1{ + \int_get_sign_and_digits_aux:nNNN {#1} \c_true \c_false \c_true +} % \end{macrocode} -% \end{macro} -% -% -% \begin{macro}{\fint_use:N} -% \begin{macro}{\fint_use_aux:w} -% To use the value of a fake counter we have to get rid of |.0mu| in -% an expandable way, since we want to allow constructions like -% \begin{verbatim} -% \if_num:w\fint_use:N \l_test_fint > 55\scan_stop: ... -%\end{verbatim} -% The simplest way I came up with (not much thinking behind) was -% using parameter matching. +% 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} -\def_new:Npn \fint_use:N {\exp_after:NN\fint_use_aux:w\the_internal:D} +\def_new:Npn \int_get_sign_and_digits_aux:nNNN #1#2#3#4{ + \tlist_if_head_eq_charcode:fNTF {#1} - + { + \bool_if:NTF #2 + { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} \c_false #3#4 } + { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} \c_true #3#4 } + } % \end{macrocode} -% In the |\fint_use_aux:w| function we remove the |.0mu| and pass the -% the result back into the input stream. The only thing we -% have to think of, is that both |mu| have category code 12 when -% they are returned by |\the_internal:D|. +% The other cases are much simpler since we either just have to gobble +% the |+| or exit immediately and insert the correct sign. % \begin{macrocode} -\tex_lccode:D`\!=`\m \tex_lccode:D`\?=`\u -\tex_lowercase:D{\def_new:Npn \fint_use_aux:w #1.0!?{#1}} -\tex_lccode:D`\!=0\scan_stop: \tex_lccode:D`\?=0\scan_stop: + { + \tlist_if_head_eq_charcode:fNTF {#1} + + { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} #2#3#4} + { % \end{macrocode} -% \end{macro} -% \end{macro} -% -% -% \begin{macro}{\fint_set:Nn} -% \begin{macro}{\fint_gset:Nn} -% The way both routines are set up, the second argument might be -% either a \m{normal integer}, or an internal register. +% The boolean |#3| is for printing the sign while |#4| is for printing +% the digits. % \begin{macrocode} -\def_new:Npn \fint_set:Nn #1#2{#1#2~mu\scan_stop: -%<*check> - \chk_local_or_pref_global:N #1 -%</check> + \bool_double_if:NNnnnn #3#4 + { \bool_if:NF #2 - #1 } + { \bool_if:NF #2 - } + { #1 } { } + } + } +} +\def_new:Npn \int_get_sign_and_digits_aux:oNNN{ + \exp_args:No\int_get_sign_and_digits_aux:nNNN } -\def_new:Npn \fint_gset:Nn{ -%<*check> - \pref_global_chk: -%</check> -%<-check> \pref_global:D - \fint_set:Nn} % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % -% \begin{macro}{\fint_set_eq:NN} -% \begin{macro}{\fint_gset_eq:NN} -% We can easily set two fake counters equal to each other, but if -% fake counters and real counters are used, we have to use the -% slower |set| functions. +% \begin{macro}{\int_convert_from_base_ten:nn} +% \begin{macro}{\int_convert_from_base_ten_aux:nnn} +% \begin{macro}{\int_convert_from_base_ten_aux:non} +% \begin{macro}{\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} -\def_new:Npn \fint_set_eq:NN #1#2{#1#2 -%<*check> - \chk_local_or_pref_global:N #1\chk_var_or_const:N #2 -%</check> +\def:Npn \int_convert_from_base_ten:nn#1#2{ + \num_compare:nNnTF {#1}<\c_zero + { + - \int_convert_from_base_ten_aux:non {} + { \int_use:N \int_eval:n {-#1} } + } + { + \int_convert_from_base_ten_aux:non {} + { \int_use:N \int_eval:n {#1} } + } + {#2} } -\def_new:Npn \fint_gset_eq:NN { -%<*check> - \pref_global_chk: -%</check> -%<-check> \pref_global:D - \fint_set_eq:NN} % \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\fint_add:Nn} -% \begin{macro}{\fint_gadd:Nn} -% \begin{macro}{\fint_sub:Nn} -% \begin{macro}{\fint_gsub:Nn} -% Adding and substracting; we make use of the fact that internally -% \TeX{} always use the same primitives to advance a register. +% 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} -\def_new:Npn \fint_add:Nn #1#2{\int_add:Nn#1{#2mu}} -\def_new:Npn \fint_gadd:Nn { -%<*check> - \pref_global_chk: -%</check> -%<-check> \pref_global:D - \fint_add:Nn} -\def_new:Npn \fint_sub:Nn #1#2{\int_sub:Nn#1{#2mu}} -\def_new:Npn \fint_gsub:Nn { -%<*check> - \pref_global_chk: -%</check> -%<-check> \pref_global:D - \fint_sub:Nn} +\def_new:Npn \int_convert_from_base_ten_aux:nnn#1#2#3{ + \num_compare:nNnTF {#2}<{#3} + { \int_convert_number_to_letter:n{#2} #1 } + { + \int_convert_from_base_ten_aux:fon + { + \int_convert_number_to_letter:n {\int_use:N\int_mod_raw:nn {#2}{#3}} + #1 + } + {\int_use:N \int_div_truncate_raw:nn{#2}{#3}} + {#3} + } +} +\def:Npn \int_convert_from_base_ten_aux:non{ + \exp_args:Nno\int_convert_from_base_ten_aux:nnn +} +\def:Npn \int_convert_from_base_ten_aux:fon{ + \exp_args:Nfo\int_convert_from_base_ten_aux:nnn +} % \end{macrocode} % \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} +\def:Npn \int_convert_number_to_letter:n #1{ \if_case:w \int_eval:w + #1-10\scan_stop: \exp_after:NN A \or: \exp_after:NN B \or: + \exp_after:NN C \or: \exp_after:NN D \or: \exp_after:NN E \or: + \exp_after:NN F \or: \exp_after:NN G \or: \exp_after:NN H \or: + \exp_after:NN I \or: \exp_after:NN J \or: \exp_after:NN K \or: + \exp_after:NN L \or: \exp_after:NN M \or: \exp_after:NN N \or: + \exp_after:NN O \or: \exp_after:NN P \or: \exp_after:NN Q \or: + \exp_after:NN R \or: \exp_after:NN S \or: \exp_after:NN T \or: + \exp_after:NN U \or: \exp_after:NN V \or: \exp_after:NN W \or: + \exp_after:NN X \or: \exp_after:NN Y \or: \exp_after:NN Z \else: + \use_arg_i_after_fi:nw{ #1 }\fi: } +% \end{macrocode} +% \end{macro} % -% \begin{macro}{\fint_incr:N} -% \begin{macro}{\fint_gincr:N} -% \begin{macro}{\fint_decr:N} -% \begin{macro}{\fint_gdecr:N} -% Incrementing and decrementing the fake counters: +% \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} -\def_new:Npn \fint_incr:N #1{\advance:D#1\c_one mu\scan_stop: -%<*check> - \chk_local_or_pref_global:N #1 -%</check> +\def:Npn \int_convert_to_base_ten:nn #1#2 { + \int_use:N\int_eval:n{ + \int_get_sign:n{#1} + \exp_args:Nf\int_convert_to_base_ten_aux:nn {\int_get_digits:n{#1}}{#2} + } } -\def_new:Npn \fint_decr:N #1{\advance:D#1\c_minus_one mu\scan_stop: -%<*check> - \chk_local_or_pref_global:N #1 -%</check> +% \end{macrocode} +% This is an intermediate function to get things started. +% \begin{macrocode} +\def_new:Npn \int_convert_to_base_ten_aux:nn #1#2{ + \int_convert_to_base_ten_auxi:nnN {0}{#2} #1 \q_nil } -\def_new:Npn \fint_gincr:N { -%<*check> - \pref_global_chk: -%</check> -%<-check> \pref_global:D - \fint_incr:N} -\def_new:Npn \fint_gdecr:N { -%<*check> - \pref_global_chk: -%</check> -%<-check> \pref_global:D - \fint_decr:N} % \end{macrocode} -% This can be achieved with less tokens but extra expansions: +% 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} -\def:Npn \fint_incr:N #1{\fint_add:Nn#1\c_one} -\def:Npn \fint_decr:N #1{\fint_add:Nn#1\c_minus_one} +\def_new:Npn \int_convert_to_base_ten_auxi:nnN#1#2#3{ + \quark_if_nil:NTF #3 + {#1} + {\exp_args:No\int_convert_to_base_ten_auxi:nnN + {\int_use:N \int_eval:n{ #1*#2+\int_convert_letter_to_number:N #3} } + {#2} + } +} % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\c_fint_max} -% A constant, denoting the largest possible value for fake counters. +% 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|. % \begin{macrocode} -\tex_mathchardef:D\c_fint_max=16383 \scan_stop: +\def:Npn \int_convert_letter_to_number:N #1{ + \int_compare:nNnTF{`#1}<{58}{#1} + { + \int_eval:n{ `#1 - + \if:w\int_compare_p:nNn{`#1}<{91} + 55 + \else: + 87 + \fi: + } + } +} % \end{macrocode} % \end{macro} % % -% \subsection{Fake skip registers} % -% One has to convert simply from the \m{x}|pt| |plus| \m{y}|pt| |minus| -% \m{z}|pt| representation produced by |\the_internal:D|, to the -% corresponding |mu| representation. Complications arise from the -% possibility that |plus| and/or |minus| is not present,\footnote{This -% can be catched by adding a suitable constant and removing the -% corresponding constant in the other representation.} and by the -% possibility that the stretch or shrink component is a |fil| unit. % -% \subsection{Fake dimen registers} % -% I suppose this could be viewed as a subcase of the skip registers. -% See later section for a fake fake version for the moment. % % -% \subsection{Allocation routines} -% -% Counters are rare goods in \TeX{} and we are near the limit, if -% for example \LaTeX{} and Pic\TeX{} are merged. Therefore we should -% be careful not to throw away counter registers unnecessarily. One -% place for instance, where we can save some of them are the -% allocation routines. Instead of using counters we maintain the -% number of the last allocated register in a fake counter. -% -% +% Show token usage: % \begin{macrocode} -%</package> +%</initex|package> %<*showmemory> \showMemUsage %</showmemory> % \end{macrocode} - +% +% +% \endinput +% +% $Log$ +% Revision 1.26 2006/06/03 17:17:08 morten +% Functions for converting between number bases +% +% Revision 1.25 2006/03/20 18:26:35 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.24 2006/01/17 22:47:43 morten +% Changed \int_while:nNnT to \int_whiledo:nNnT to avoid confusion with +% the dowhile versions. +% +% Revision 1.23 2005/12/27 10:02:37 morten +% Minor changes plus changed RCS information retrieval +% +% Revision 1.22 2005/12/21 20:43:32 morten +% Fixed silly bugs! +% +% Revision 1.21 2005/12/06 17:31:23 morten +% fixed \int_convert_number_with_rule:nnN +% +% Revision 1.20 2005/12/06 14:49:36 morten +% Fixed primitive names plus a few minor touch-ups +% +% Revision 1.19 2005/04/25 15:02:47 morten +% Added ifodd functions +% +% Revision 1.18 2005/04/09 21:07:39 morten +% Added (extensible) implementations of \int_to_roman:n etc. +% +% Revision 1.17 2005/04/06 22:35:43 braams +% Now we have register allocation fitted +% +% Revision 1.16 2005/03/25 23:48:47 braams +% Added a missing \end{macro} +% +% Revision 1.15 2005/03/22 23:22:09 morten +% Moved definitions of constants to l3num +% +% Revision 1.14 2005/03/16 22:36:30 braams +% Added the tweaks necessary to be able to load with initex +% +% Revision 1.13 2005/03/11 21:38:31 braams +% Fixed the use of RCS information; added \StopEventually +% |