summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3intarray.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3intarray.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3intarray.dtx943
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