diff options
author | Norbert Preining <norbert@preining.info> | 2024-05-01 03:00:54 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2024-05-01 03:00:54 +0000 |
commit | 6ac3dbed4b71022bd6bb0cc25e8fc3df81198498 (patch) | |
tree | 74689e5368262d351f68fb5d1f0fbea88a3af701 /macros/latex/contrib/l3kernel/l3intarray.dtx | |
parent | 3bb814fe836cd59db56f2f5d07f69cb531ed25e0 (diff) |
CTAN sync 202405010300
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3intarray.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3intarray.dtx | 943 |
1 files changed, 0 insertions, 943 deletions
diff --git a/macros/latex/contrib/l3kernel/l3intarray.dtx b/macros/latex/contrib/l3kernel/l3intarray.dtx deleted file mode 100644 index 5704a2ab75..0000000000 --- a/macros/latex/contrib/l3kernel/l3intarray.dtx +++ /dev/null @@ -1,943 +0,0 @@ -% \iffalse meta-comment -% -%% File: l3intarray.dtx -% -% Copyright (C) 2017-2024 The LaTeX 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 -% -% https://www.latex-project.org/lppl.txt -% -% This file is part of the "l3kernel bundle" (The Work in LPPL) -% and all files in that bundle must be distributed together. -% -% ----------------------------------------------------------------------- -% -% The development version of the bundle can be found at -% -% https://github.com/latex3/latex3 -% -% for those people who are interested. -% -%<*driver> -\documentclass[full,kernel]{l3doc} -\begin{document} - \DocInput{\jobname.dtx} -\end{document} -%</driver> -% \fi -% -% -% \title{^^A -% The \pkg{l3intarray} module\\ Fast global integer arrays^^A -% } -% -% \author{^^A -% The \LaTeX{} Project\thanks -% {^^A -% E-mail: -% \href{mailto:latex-team@latex-project.org} -% {latex-team@latex-project.org}^^A -% }^^A -% } -% -% \date{Released 2024-03-14} -% -% \maketitle -% -% \begin{documentation} -% -% \section{\pkg{l3intarray} documentation} -% -% For applications requiring heavy use of integers, this module provides -% arrays which can be accessed in constant time (contrast \pkg{l3seq}, -% where access time is linear). These arrays have several important -% features -% \begin{itemize} -% \item The size of the array is fixed and must be given at -% point of initialisation -% \item The absolute value of each entry has maximum $2^{30}-1$ -% (\emph{i.e.}~one power lower than the usual \cs{c_max_int} -% ceiling of $2^{31}-1$) -% \end{itemize} -% The use of \texttt{intarray} data is therefore recommended for cases where -% the need for fast access is of paramount importance. -% -% \begin{function}[added = 2018-03-29]{\intarray_new:Nn, \intarray_new:cn} -% \begin{syntax} -% \cs{intarray_new:Nn} \meta{intarray~var} \Arg{size} -% \end{syntax} -% Evaluates the integer expression \meta{size} and allocates an -% \meta{integer array variable} with that number of (zero) entries. -% The variable name should start with |\g_| because assignments are -% always global. -% \end{function} -% -% \begin{function}[EXP, added = 2018-03-29]{\intarray_count:N, \intarray_count:c} -% \begin{syntax} -% \cs{intarray_count:N} \meta{intarray~var} -% \end{syntax} -% Expands to the number of entries in the \meta{integer array variable}. -% Contrarily to \cs{seq_count:N} this is performed in constant time. -% \end{function} -% -% \begin{function}[added = 2018-03-29]{\intarray_gset:Nnn, \intarray_gset:cnn} -% \begin{syntax} -% \cs{intarray_gset:Nnn} \meta{intarray~var} \Arg{position} \Arg{value} -% \end{syntax} -% Stores the result of evaluating the integer expression \meta{value} -% into the \meta{integer array variable} at the (integer expression) -% \meta{position}. If the \meta{position} is not between $1$ and the -% \cs{intarray_count:N}, or the \meta{value}'s absolute value is -% bigger than $2^{30}-1$, an error occurs. Assignments are always -% global. -% \end{function} -% -% \begin{function}[added = 2018-05-04] -% {\intarray_const_from_clist:Nn, \intarray_const_from_clist:cn} -% \begin{syntax} -% \cs{intarray_const_from_clist:Nn} \meta{intarray~var} \meta{int expr clist} -% \end{syntax} -% Creates a new constant \meta{integer array variable} or raises an -% error if the name is already taken. The \meta{integer array -% variable} is set (globally) to contain as its items the results of -% evaluating each \meta{integer expression} in the \meta{comma list}. -% \end{function} -% -% \begin{function}[added = 2018-05-04]{\intarray_gzero:N, \intarray_gzero:c} -% \begin{syntax} -% \cs{intarray_gzero:N} \meta{intarray~var} -% \end{syntax} -% Sets all entries of the \meta{integer array variable} to zero. -% Assignments are always global. -% \end{function} -% -% \begin{function}[EXP, added = 2018-03-29]{\intarray_item:Nn, \intarray_item:cn} -% \begin{syntax} -% \cs{intarray_item:Nn} \meta{intarray~var} \Arg{position} -% \end{syntax} -% Expands to the integer entry stored at the (integer expression) -% \meta{position} in the \meta{integer array variable}. If the -% \meta{position} is not between $1$ and the \cs{intarray_count:N}, an -% error occurs. -% \end{function} -% -% \begin{function}[EXP, added = 2018-05-05] -% {\intarray_rand_item:N, \intarray_rand_item:c} -% \begin{syntax} -% \cs{intarray_rand_item:N} \meta{intarray~var} -% \end{syntax} -% Selects a pseudo-random item of the \meta{integer array}. If the -% \meta{integer array} is empty, produce an error. -% \end{function} -% -% \begin{function}[added = 2018-05-04] -% {\intarray_show:N, \intarray_show:c, \intarray_log:N, \intarray_log:c} -% \begin{syntax} -% \cs{intarray_show:N} \meta{intarray~var} -% \cs{intarray_log:N} \meta{intarray~var} -% \end{syntax} -% Displays the items in the \meta{integer array variable} in the -% terminal or writes them in the log file. -% \end{function} -% -% \subsection{Implementation notes} -% -% It is a wrapper around the \tn{fontdimen} primitive, used to store -% arrays of integers (with a restricted range: absolute value at most -% $2^{30}-1$). In contrast to \pkg{l3seq} sequences the access to -% individual entries is done in constant time rather than linear time, -% but only integers can be stored. More precisely, the primitive -% \tn{fontdimen} stores dimensions but the \pkg{l3intarray} module -% transparently converts these from/to integers. Assignments are always -% global. -% -% While \LuaTeX{}'s memory is extensible, other engines can -% \enquote{only} deal with a bit less than $4\times 10^6$ entries in all -% \tn{fontdimen} arrays combined (with default \TeX{} Live settings). -% -% \end{documentation} -% -% \begin{implementation} -% -% \section{\pkg{l3intarray} implementation} -% -% \begin{macrocode} -%<*package> -% \end{macrocode} -% -% \begin{macrocode} -%<@@=intarray> -% \end{macrocode} -% -% There are two implementations for this module: One \cs{fontdimen} based one -% for more traditional \TeX\ engines and a Lua based one for engines with Lua support. -% -% Both versions do not allow negative array sizes. -% \begin{macrocode} -%<*tex> -\msg_new:nnn { kernel } { negative-array-size } - { Size~of~array~may~not~be~negative:~#1 } -% \end{macrocode} -% -% \begin{variable}{\l_@@_loop_int} -% A loop index. -% \begin{macrocode} -\int_new:N \l_@@_loop_int -% \end{macrocode} -% \end{variable} -% -% \subsection{Lua implementation} -% First, let's look at the Lua variant: -% -% We select the Lua version if the Lua helpers were defined. This can be detected by -% the presence of \cs{@@_gset_count:Nw}. -% -% \begin{macrocode} -\cs_if_exist:NTF \@@_gset_count:Nw - { -% \end{macrocode} -% -% \subsubsection{Allocating arrays} -% -% \begin{variable}{\g_@@_table_int, \l_@@_bad_index_int} -% Used to differentiate intarrays in Lua and to record an invalid index. -% \begin{macrocode} - \int_new:N \g_@@_table_int - \int_new:N \l_@@_bad_index_int -%</tex> -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\@@:w} -% Used as marker for intarrays in Lua. Followed by an unbraced number -% identifying the array and a single space. This format is used to make it -% easy to scan from Lua. -% \begin{macrocode} -%<*lua> -luacmd('@@:w', function() - scan_int() - tex.error'LaTeX Error: Isolated intarray ignored' -end, 'protected', 'global') -%</lua> -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\intarray_new:Nn, \intarray_new:cn} -% \begin{macro}{\@@_new:N} -% Declare |#1| as a tokenlist with the scanmark and a unique number. -% Pass the array's size to the Lua helper. -% Every \texttt{intarray} must be global; it's enough to run this -% check in \cs{intarray_new:Nn}. -% \begin{macrocode} -%<*tex> - \cs_new_protected:Npn \@@_new:N #1 - { - \__kernel_chk_if_free_cs:N #1 - \int_gincr:N \g_@@_table_int - \cs_gset_nopar:Npe #1 { \@@:w \int_use:N \g_@@_table_int \c_space_tl } - } - \cs_new_protected:Npn \intarray_new:Nn #1#2 - { - \@@_new:N #1 - \@@_gset_count:Nw #1 \int_eval:n {#2} \scan_stop: - \int_compare:nNnT { \intarray_count:N #1 } < 0 - { - \msg_error:nne { kernel } { negative-array-size } - { \intarray_count:N #1 } - } - } - \cs_generate_variant:Nn \intarray_new:Nn { c } -%</tex> -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% Before we get to the first command implmented in Lua, we first need some -% definitions. Since \texttt{token.create} only works correctly if \TeX{} -% has seen the tokens before, we first run a short \TeX{} sequence to ensure -% that all relevant control sequences are known. -% \begin{macrocode} -%<*lua> - -local scan_token = token.scan_token -local put_next = token.put_next -local intarray_marker = token_create_safe'@@:w' -local use_none = token_create_safe'use_none:n' -local use_i = token_create_safe'use:n' -local expand_after_scan_stop = {token_create_safe'exp_after:wN', - token_create_safe'scan_stop:'} -local comma = token_create(string.byte',') -% \end{macrocode} -% -% \begin{macro}{@@_table} -% Internal helper to scan an intarray token, extract the associated -% Lua table and return an error if the input is invalid. -% -% \begin{macrocode} -local @@_table do - local tables = get_luadata and get_luadata'@@' or {[0] = {}} - function @@_table() - local t = scan_token() - if t ~= intarray_marker then - put_next(t) - tex.error'LaTeX Error: intarray expected' - return tables[0] - end - local i = scan_int() - local current_table = tables[i] - if current_table then return current_table end - current_table = {} - tables[i] = current_table - return current_table - end -% \end{macrocode} -% Since in \LaTeX{} this is loaded in the format, we want to preserve any intarrays -% which are created while format building for the actual run. -% -% To do this, we use the \texttt{register_luadata} mechanism from \pkg{l3luatex}: -% Directly before the format get dumped, the following function gets invoked and serializes -% all existing tables into a string. This string gets compiled and dumped into the format and -% is made available at the beginning of regular runs as \texttt{get_luadata'@@'}. -% \begin{macrocode} - if register_luadata then - register_luadata('@@', function() - local t = "{[0]={}," - for i=1, #tables do - t = string.format("%s{%s},", t, table.concat(tables[i], ',')) - end - return t .. "}" - end) - end -end -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\intarray_count:N, \intarray_count:c} -% \begin{macro}[EXP]{\@@_gset_count:Nw} -% Set and get the size of an array. ``Setting the size'' means in this context that -% we add zeros until we reach the desired size. -% \begin{macrocode} - -local sprint = tex.sprint - -luacmd('@@_gset_count:Nw', function() - local t = @@_table() - local n = scan_int() - for i=#t+1, n do t[i] = 0 end -end, 'protected', 'global') - -luacmd('intarray_count:N', function() - sprint(-2, #@@_table()) -end, 'global') -%</lua> -% \end{macrocode} -% -% \begin{macrocode} -%<*tex> - \cs_generate_variant:Nn \intarray_count:N { c } -%</tex> -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsubsection{Array items} -% -% \begin{macro}{\@@_gset:wF, \@@_gset:w} -% The setter provided by Lua. The argument order somewhat emulates the |\fontdimen|: -% First the array index, followed by the intarray and then the new value. -% This has been chosen over a more conventional order to provide a delimiter for the numbers. -% \begin{macrocode} -%<*lua> -luacmd('@@_gset:wF', function() - local i = scan_int() - local t = @@_table() - if t[i] then - t[i] = scan_int() - put_next(use_none) - else - tex.count.l_@@_bad_index_int = i - scan_int() - put_next(use_i) - end -end, 'protected', 'global') - -luacmd('@@_gset:w', function() - local i = scan_int() - local t = @@_table() - t[i] = scan_int() -end, 'protected', 'global') -%</lua> -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\intarray_gset:Nnn, \intarray_gset:cnn, \__kernel_intarray_gset:Nnn} -% The \cs{__kernel_intarray_gset:Nnn} function does not use -% \cs{int_eval:n}, namely its arguments must be suitable for -% \cs{int_value:w}. The user version checks the position and value -% are within bounds. -% \begin{macrocode} -%<*tex> - \cs_new_protected:Npn \__kernel_intarray_gset:Nnn #1#2#3 - { \@@_gset:w #2 #1 #3 \scan_stop: } - \cs_new_protected:Npn \intarray_gset:Nnn #1#2#3 - { - \@@_gset:wF \int_eval:n {#2} #1 \int_eval:n{#3} - { - \msg_error:nneee { kernel } { out-of-bounds } - { \token_to_str:N #1 } { \int_use:N \l_@@_bad_index_int } { \intarray_count:N #1 } - } - } - \cs_generate_variant:Nn \intarray_gset:Nnn { c } -%</tex> -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\intarray_gzero:N, \intarray_gzero:c} -% Set the appropriate array entry to zero. No bound checking -% needed. -% \begin{macrocode} -%<*lua> -luacmd('intarray_gzero:N', function() - local t = @@_table() - for i=1, #t do - t[i] = 0 - end -end, 'global', 'protected') -%</lua> -%<*tex> - \cs_generate_variant:Nn \intarray_gzero:N { c } -%</tex> -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\intarray_item:Nn, \intarray_item:cn, \__kernel_intarray_item:Nn} -% \begin{macro}{\@@_item:wF,\@@_item:w} -% Get the appropriate entry and perform bound checks. The -% \cs{__kernel_intarray_item:Nn} function omits bound checks and omits -% \cs{int_eval:n}, namely its argument must be a \TeX{} integer -% suitable for \cs{int_value:w}. -% \begin{macrocode} -%<*lua> -luacmd('@@_item:wF', function() - local i = scan_int() - local t = @@_table() - local item = t[i] - if item then - put_next(use_none) - else - tex.l_@@_bad_index_int = i - put_next(use_i) - end - put_next(expand_after_scan_stop) - scan_token() - if item then - sprint(-2, item) - end -end, 'global') - -luacmd('@@_item:w', function() - local i = scan_int() - local t = @@_table() - sprint(-2, t[i]) -end, 'global') -%</lua> -% \end{macrocode} -% -% \begin{macrocode} -%<*tex> - \cs_new:Npn \__kernel_intarray_item:Nn #1#2 - { \@@_item:w #2 #1 } - \cs_new:Npn \intarray_item:Nn #1#2 - { - \@@_item:wF \int_eval:n {#2} #1 - { - \msg_expandable_error:nnfff { kernel } { out-of-bounds } - { \token_to_str:N #1 } { \int_use:N \l_@@_bad_index_int } { \intarray_count:N #1 } - 0 - } - } - \cs_generate_variant:Nn \intarray_item:Nn { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\intarray_rand_item:N, \intarray_rand_item:c} -% Importantly, \cs{intarray_item:Nn} only evaluates its argument once. -% \begin{macrocode} - \cs_new:Npn \intarray_rand_item:N #1 - { \intarray_item:Nn #1 { \int_rand:n { \intarray_count:N #1 } } } - \cs_generate_variant:Nn \intarray_rand_item:N { c } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Working with contents of integer arrays} -% -% \begin{macro}{\intarray_const_from_clist:Nn, \intarray_const_from_clist:cn} -% We use the \cs{__kernel_intarray_gset:Nnn} which does not do bounds checking -% and instead automatically resizes the array. -% This is not implemented in Lua to ensure that the clist parsing is consistent -% with the clist module. -% \begin{macrocode} - \cs_new_protected:Npn \intarray_const_from_clist:Nn #1#2 - { - \@@_new:N #1 - \int_zero:N \l_@@_loop_int - \clist_map_inline:nn {#2} - { - \int_incr:N \l_@@_loop_int - \__kernel_intarray_gset:Nnn #1 \l_@@_loop_int { \int_eval:n {##1} } } - } - \cs_generate_variant:Nn \intarray_const_from_clist:Nn { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[rEXP]{\@@_to_clist:Nn, \@@_to_clist:w} -% The \cs{@@_to_clist:Nn} auxiliary allows to choose the delimiter and -% is also used in \cs{intarray_show:N}. Here we just pass the information -% to Lua and let \texttt{table.concat} do the actual work. -% We discard the category codes of the passed delimiter but this is not -% an issue since the delimiter is always just a comma or a comma and a space. -% In both cases \texttt{sprint(2, ...)} provides the right catcodes. -% \begin{macrocode} -%</tex> -%<*lua> -local concat = table.concat -luacmd('@@_to_clist:Nn', function() - local t = @@_table() - local sep = token.scan_string() - sprint(-2, concat(t, sep)) -end, 'global') -%</lua> -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[rEXP]{\__kernel_intarray_range_to_clist:Nnn, \@@_range_to_clist:w} -% Loop through part of the array. -% \begin{macrocode} -%<*tex> - \cs_new:Npn \__kernel_intarray_range_to_clist:Nnn #1#2#3 - { - \@@_range_to_clist:w #1 - \int_eval:n {#2} ~ \int_eval:n {#3} ~ - } -%</tex> -%<*lua> -luacmd('@@_range_to_clist:w', function() - local t = @@_table() - local from = scan_int() - local to = scan_int() - sprint(-2, concat(t, ',', from, to)) -end, 'global') -%</lua> -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\__kernel_intarray_gset_range_from_clist:Nnn, \@@_gset_range:nNw} -% Loop through part of the array. We allow additional commas at the end. -% \begin{macrocode} -%<*tex> - \cs_new_protected:Npn \__kernel_intarray_gset_range_from_clist:Nnn #1#2#3 - { - \@@_gset_range:w \int_eval:w #2 #1 #3 , , \scan_stop: - } -%</tex> -%<*lua> -luacmd('@@_gset_range:w', function() - local from = scan_int() - local t = @@_table() - while true do - local tok = scan_token() - if tok == comma then - repeat - tok = scan_token() - until tok ~= comma - break - else - put_next(tok) - end - t[from] = scan_int() - scan_token() - from = from + 1 - end - end, 'global', 'protected') -%</lua> -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_gset_overflow_test:nw} -% In order to allow some code sharing later we provide the -% \cs{@@_gset_overflow_test:nw} name here. It doesn't actually test anything -% since the Lua implementation accepts all integers which could be tested with -% \cs{tex_ifabsnum:D}. -% \begin{macrocode} -%<*tex> - \cs_new_protected:Npn \@@_gset_overflow_test:nw #1 - { - } -% \end{macrocode} -% \end{macro} -% -% \subsection{Font dimension based implementation} -% -% Go to the false branch of the conditional above. -% \begin{macrocode} - } - { -% \end{macrocode} -% -% \subsubsection{Allocating arrays} -% -% \begin{macro}{\@@_entry:w, \@@_count:w} -% We use these primitives quite a lot in this module. -% \begin{macrocode} - \cs_new_eq:NN \@@_entry:w \tex_fontdimen:D - \cs_new_eq:NN \@@_count:w \tex_hyphenchar:D -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\c_@@_sp_dim} -% Used to convert integers to dimensions fast. -% \begin{macrocode} - \dim_const:Nn \c_@@_sp_dim { 1 sp } -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\g_@@_font_int} -% Used to assign one font per array. -% \begin{macrocode} - \int_new:N \g_@@_font_int -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\intarray_new:Nn, \intarray_new:cn} -% \begin{macro}{\@@_new:N} -% Declare |#1| to be a font (arbitrarily |cmr10| at a never-used -% size). Store the array's size as the \tn{hyphenchar} of that font -% and make sure enough \tn{fontdimen} are allocated, by setting the -% last one. Then clear any \tn{fontdimen} that |cmr10| starts with. -% It seems \LuaTeX{}'s |cmr10| has an extra \tn{fontdimen} parameter -% number $8$ compared to other engines (for a math font we would -% replace $8$ by $22$ or some such). -% Every \texttt{intarray} must be global; it's enough to run this -% check in \cs{intarray_new:Nn}. -% \begin{macrocode} - \cs_new_protected:Npn \@@_new:N #1 - { - \__kernel_chk_if_free_cs:N #1 - \int_gincr:N \g_@@_font_int - \tex_global:D \tex_font:D #1 - = cmr10~at~ \g_@@_font_int \c_@@_sp_dim \scan_stop: - \int_step_inline:nn { 8 } - { \__kernel_intarray_gset:Nnn #1 {##1} \c_zero_int } - } - \cs_new_protected:Npn \intarray_new:Nn #1#2 - { - \@@_new:N #1 - \@@_count:w #1 = \int_eval:n {#2} \scan_stop: - \int_compare:nNnT { \intarray_count:N #1 } < 0 - { - \msg_error:nne { kernel } { negative-array-size } - { \intarray_count:N #1 } - } - \int_compare:nNnT { \intarray_count:N #1 } > 0 - { \__kernel_intarray_gset:Nnn #1 { \intarray_count:N #1 } { 0 } } - } - \cs_generate_variant:Nn \intarray_new:Nn { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\intarray_count:N, \intarray_count:c} -% Size of an array. -% \begin{macrocode} - \cs_new:Npn \intarray_count:N #1 { \int_value:w \@@_count:w #1 } - \cs_generate_variant:Nn \intarray_count:N { c } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Array items} -% -% \begin{macro}[EXP]{\@@_signed_max_dim:n} -% Used when an item to be stored is larger than \cs{c_max_dim} in -% absolute value; it is replaced by $\pm\cs{c_max_dim}$. -% \begin{macrocode} - \cs_new:Npn \@@_signed_max_dim:n #1 - { \int_value:w \int_compare:nNnT {#1} < 0 { - } \c_max_dim } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_bounds:NNnTF, \@@_bounds_error:NNnw} -% The functions \cs{intarray_gset:Nnn} and \cs{intarray_item:Nn} share -% bounds checking. The |T| branch is used if |#3| is within bounds of -% the array |#2|. -% \begin{macrocode} - \cs_new:Npn \@@_bounds:NNnTF #1#2#3 - { - \if_int_compare:w 1 > #3 \exp_stop_f: - \@@_bounds_error:NNnw #1 #2 {#3} - \else: - \if_int_compare:w #3 > \intarray_count:N #2 \exp_stop_f: - \@@_bounds_error:NNnw #1 #2 {#3} - \fi: - \fi: - \use_i:nn - } - \cs_new:Npn \@@_bounds_error:NNnw #1#2#3#4 \use_i:nn #5#6 - { - #4 - #1 { kernel } { out-of-bounds } - { \token_to_str:N #2 } {#3} { \intarray_count:N #2 } - #6 - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\intarray_gset:Nnn, \intarray_gset:cnn, \__kernel_intarray_gset:Nnn} -% \begin{macro}{\@@_gset:Nnn, \@@_gset_overflow:Nnn} -% Set the appropriate \tn{fontdimen}. The -% \cs{__kernel_intarray_gset:Nnn} function does not use -% \cs{int_eval:n}, namely its arguments must be suitable for -% \cs{int_value:w}. The user version checks the position and value -% are within bounds. -% \begin{macrocode} - \cs_new_protected:Npn \__kernel_intarray_gset:Nnn #1#2#3 - { \@@_entry:w #2 #1 #3 \c_@@_sp_dim } - \cs_new_protected:Npn \intarray_gset:Nnn #1#2#3 - { - \exp_after:wN \@@_gset:Nww - \exp_after:wN #1 - \int_value:w \int_eval:n {#2} \exp_after:wN ; - \int_value:w \int_eval:n {#3} ; - } - \cs_generate_variant:Nn \intarray_gset:Nnn { c } - \cs_new_protected:Npn \@@_gset:Nww #1#2 ; #3 ; - { - \@@_bounds:NNnTF \msg_error:nneee #1 {#2} - { - \@@_gset_overflow_test:nw {#3} - \__kernel_intarray_gset:Nnn #1 {#2} {#3} - } - { } - } - \cs_if_exist:NTF \tex_ifabsnum:D - { - \cs_new_protected:Npn \@@_gset_overflow_test:nw #1 - { - \tex_ifabsnum:D #1 > \c_max_dim - \exp_after:wN \@@_gset_overflow:NNnn - \fi: - } - } - { - \cs_new_protected:Npn \@@_gset_overflow_test:nw #1 - { - \if_int_compare:w \int_abs:n {#1} > \c_max_dim - \exp_after:wN \@@_gset_overflow:NNnn - \fi: - } - } - \cs_new_protected:Npn \@@_gset_overflow:NNnn #1#2#3#4 - { - \msg_error:nneeee { kernel } { overflow } - { \token_to_str:N #2 } {#3} {#4} { \@@_signed_max_dim:n {#4} } - #1 #2 {#3} { \@@_signed_max_dim:n {#4} } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\intarray_gzero:N, \intarray_gzero:c} -% Set the appropriate \tn{fontdimen} to zero. No bound checking -% needed. The \cs{prg_replicate:nn} possibly uses quite a lot of -% memory, but this is somewhat comparable to the size of the array, -% and it is much faster than an \cs{int_step_inline:nn} loop. -% \begin{macrocode} - \cs_new_protected:Npn \intarray_gzero:N #1 - { - \int_zero:N \l_@@_loop_int - \prg_replicate:nn { \intarray_count:N #1 } - { - \int_incr:N \l_@@_loop_int - \@@_entry:w \l_@@_loop_int #1 \c_zero_dim - } - } - \cs_generate_variant:Nn \intarray_gzero:N { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\intarray_item:Nn, \intarray_item:cn, \__kernel_intarray_item:Nn} -% \begin{macro}{\@@_item:Nw} -% Get the appropriate \tn{fontdimen} and perform bound checks. The -% \cs{__kernel_intarray_item:Nn} function omits bound checks and omits -% \cs{int_eval:n}, namely its argument must be a \TeX{} integer -% suitable for \cs{int_value:w}. -% \begin{macrocode} - \cs_new:Npn \__kernel_intarray_item:Nn #1#2 - { \int_value:w \@@_entry:w #2 #1 } - \cs_new:Npn \intarray_item:Nn #1#2 - { - \exp_after:wN \@@_item:Nw - \exp_after:wN #1 - \int_value:w \int_eval:n {#2} ; - } - \cs_generate_variant:Nn \intarray_item:Nn { c } - \cs_new:Npn \@@_item:Nw #1#2 ; - { - \@@_bounds:NNnTF \msg_expandable_error:nnfff #1 {#2} - { \__kernel_intarray_item:Nn #1 {#2} } - { 0 } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\intarray_rand_item:N, \intarray_rand_item:c} -% Importantly, \cs{intarray_item:Nn} only evaluates its argument once. -% \begin{macrocode} - \cs_new:Npn \intarray_rand_item:N #1 - { \intarray_item:Nn #1 { \int_rand:n { \intarray_count:N #1 } } } - \cs_generate_variant:Nn \intarray_rand_item:N { c } -% \end{macrocode} -% \end{macro} -% -% \subsubsection{Working with contents of integer arrays} -% -% \begin{macro}{\intarray_const_from_clist:Nn, \intarray_const_from_clist:cn} -% \begin{macro}{\@@_const_from_clist:nN} -% Similar to \cs{intarray_new:Nn} (which we don't use because when -% debugging is enabled that function checks the variable name starts -% with |g_|). We make use of the fact that \TeX{} allows allocation -% of successive \tn{fontdimen} as long as no other font has been -% declared: no need to count the comma list items first. We need the -% code in \cs{intarray_gset:Nnn} that checks the item value is not too -% big, namely \cs{@@_gset_overflow_test:nw}, but not the code that -% checks bounds. At the end, set the size of the intarray. -% \begin{macrocode} - \cs_new_protected:Npn \intarray_const_from_clist:Nn #1#2 - { - \@@_new:N #1 - \int_zero:N \l_@@_loop_int - \clist_map_inline:nn {#2} - { \exp_args:Nf \@@_const_from_clist:nN { \int_eval:n {##1} } #1 } - \@@_count:w #1 \l_@@_loop_int - } - \cs_generate_variant:Nn \intarray_const_from_clist:Nn { c } - \cs_new_protected:Npn \@@_const_from_clist:nN #1#2 - { - \int_incr:N \l_@@_loop_int - \@@_gset_overflow_test:nw {#1} - \__kernel_intarray_gset:Nnn #2 \l_@@_loop_int {#1} - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[rEXP]{\@@_to_clist:Nn, \@@_to_clist:w} -% Loop through the array, putting a comma before each item. Remove -% the leading comma with |f|-expansion. We also use the auxiliary in -% \cs{intarray_show:N} with argument comma, space. -% \begin{macrocode} - \cs_new:Npn \@@_to_clist:Nn #1#2 - { - \int_compare:nNnF { \intarray_count:N #1 } = \c_zero_int - { - \exp_last_unbraced:Nf \use_none:n - { \@@_to_clist:w 1 ; #1 {#2} \prg_break_point: } - } - } - \cs_new:Npn \@@_to_clist:w #1 ; #2#3 - { - \if_int_compare:w #1 > \@@_count:w #2 - \prg_break:n - \fi: - #3 \__kernel_intarray_item:Nn #2 {#1} - \exp_after:wN \@@_to_clist:w - \int_value:w \int_eval:w #1 + \c_one_int ; #2 {#3} - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[rEXP]{\__kernel_intarray_range_to_clist:Nnn, \@@_range_to_clist:ww} -% Loop through part of the array. -% \begin{macrocode} - \cs_new:Npn \__kernel_intarray_range_to_clist:Nnn #1#2#3 - { - \exp_last_unbraced:Nf \use_none:n - { - \exp_after:wN \@@_range_to_clist:ww - \int_value:w \int_eval:w #2 \exp_after:wN ; - \int_value:w \int_eval:w #3 ; - #1 \prg_break_point: - } - } - \cs_new:Npn \@@_range_to_clist:ww #1 ; #2 ; #3 - { - \if_int_compare:w #1 > #2 \exp_stop_f: - \prg_break:n - \fi: - , \__kernel_intarray_item:Nn #3 {#1} - \exp_after:wN \@@_range_to_clist:ww - \int_value:w \int_eval:w #1 + \c_one_int ; #2 ; #3 - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\__kernel_intarray_gset_range_from_clist:Nnn, \@@_gset_range:Nw} -% Loop through part of the array. -% \begin{macrocode} - \cs_new_protected:Npn \__kernel_intarray_gset_range_from_clist:Nnn #1#2#3 - { - \int_set:Nn \l_@@_loop_int {#2} - \@@_gset_range:Nw #1 #3 , , \prg_break_point: - } - \cs_new_protected:Npn \@@_gset_range:Nw #1 #2 , - { - \if_catcode:w \scan_stop: \tl_to_str:n {#2} \scan_stop: - \prg_break:n - \fi: - \__kernel_intarray_gset:Nnn #1 \l_@@_loop_int {#2} - \int_incr:N \l_@@_loop_int - \@@_gset_range:Nw #1 - } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} - } -% \end{macrocode} -% -% \subsection{Common parts} -% -% \begin{macro}{\intarray_show:N, \intarray_show:c, \intarray_log:N, \intarray_log:c} -% Convert the list to a comma list (with spaces after each comma) -% \begin{macrocode} -\cs_new_protected:Npn \intarray_show:N { \@@_show:NN \msg_show:nneeee } -\cs_generate_variant:Nn \intarray_show:N { c } -\cs_new_protected:Npn \intarray_log:N { \@@_show:NN \msg_log:nneeee } -\cs_generate_variant:Nn \intarray_log:N { c } -\cs_new_protected:Npn \@@_show:NN #1#2 - { - \__kernel_chk_defined:NT #2 - { - #1 { intarray } { show } - { \token_to_str:N #2 } - { \intarray_count:N #2 } - { >~ \@@_to_clist:Nn #2 { , ~ } } - { } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</tex> -%</package> -% \end{macrocode} -% -% \end{implementation} -% -% \PrintIndex |