% \iffalse meta-comment % %% File: l3intarray.dtx Copyright (C) 2017 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this % license or (at your option) any later version. The latest version % of this license is in the file % % http://www.latex-project.org/lppl.txt % % This file is part of the "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]{l3doc} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % % \title{^^A % The \textsf{l3intarray} package: low-level arrays of small integers^^A % } % % \author{^^A % The \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % % \date{Released 2017/05/29} % % \maketitle % % \begin{documentation} % % \section{\pkg{l3intarray} documentation} % % This module provides no user function: at present it is meant for % kernel use only. % % 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} package % 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). % % \subsection{Internal functions} % % \begin{function}{\__intarray_new:Nn} % \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. % \end{function} % % \begin{function}[EXP]{\__intarray_count:N} % \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}{\__intarray_gset:Nnn, \__intarray_gset_fast:Nnn} % \begin{syntax} % \cs{__intarray_gset:Nnn} \meta{intarray~var} \Arg{position} \Arg{value} % \cs{__intarray_gset_fast: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}. While \cs{__intarray_gset:Nnn} checks that the % \meta{position} is between $1$ and the \cs{__intarray_count:N} and that % the \meta{value}'s absolute value is at most $2^{30}-1$, the % \enquote{fast} function performs no such bound check. % Assignments are always global. % \end{function} % % \begin{function}[EXP]{\__intarray_item:Nn, \__intarray_item_fast:Nn} % \begin{syntax} % \cs{__intarray_item:Nn} \meta{intarray~var} \Arg{position} % \cs{__intarray_item_fast: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}. While % \cs{__intarray_item:Nn} checks that the \meta{position} is between $1$ % and the \cs{__intarray_count:N}, the \enquote{fast} function performs % no such bound check. % \end{function} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3intarray} implementation} % % \begin{macrocode} %<*initex|package> % \end{macrocode} % % \begin{macrocode} %<@@=intarray> % \end{macrocode} % % \subsection{Allocating arrays} % % \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}[int]{\@@_new:Nn} % 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). % \begin{macrocode} \cs_new_protected:Npn \@@_new:Nn #1#2 { \__chk_if_free_cs:N #1 \int_gincr:N \g_@@_font_int \tex_global:D \tex_font:D #1 = cmr10~at~ \g_@@_font_int sp \scan_stop: \tex_hyphenchar:D #1 = \int_eval:n {#2} \scan_stop: \int_compare:nNnT { \tex_hyphenchar:D #1 } > 0 { \tex_fontdimen:D \tex_hyphenchar:D #1 #1 = 0 sp \scan_stop: } \int_step_inline:nnnn { 1 } { 1 } { 8 } { \tex_fontdimen:D ##1 #1 = 0 sp \scan_stop: } } % \end{macrocode} % \end{macro} % % \begin{macro}[int, EXP]{\@@_count:N} % Size of an array. % \begin{macrocode} \cs_new:Npn \@@_count:N #1 { \tex_the:D \tex_hyphenchar:D #1 } % \end{macrocode} % \end{macro} % % \subsection{Array items} % % \begin{macro}[int]{\@@_gset:Nnn, \@@_gset_fast:Nnn} % \begin{macro}[aux]{\@@_gset_aux:Nnn} % Set the appropriate \tn{fontdimen}. The slow version checks the % position and value are within bounds. % \begin{macrocode} \cs_new_protected:Npn \@@_gset_fast:Nnn #1#2#3 { \tex_fontdimen:D \int_eval:n {#2} #1 = \int_eval:n {#3} sp \scan_stop: } \cs_new_protected:Npn \@@_gset:Nnn #1#2#3 { \exp_args:Nff \@@_gset_aux:Nnn #1 { \int_eval:n {#2} } { \int_eval:n {#3} } } \cs_new_protected:Npn \@@_gset_aux:Nnn #1#2#3 { \int_compare:nTF { 1 <= #2 <= \@@_count:N #1 } { \int_compare:nTF { - \c_max_dim <= \int_abs:n {#3} <= \c_max_dim } { \@@_gset_fast:Nnn #1 {#2} {#3} } { \__msg_kernel_error:nnxxxx { kernel } { overflow } { \token_to_str:N #1 } {#2} {#3} { \int_compare:nNnT {#3} < 0 { - } \__int_value:w \c_max_dim } \@@_gset_fast:Nnn #1 {#2} { \int_compare:nNnT {#3} < 0 { - } \c_max_dim } } } { \__msg_kernel_error:nnxxx { kernel } { out-of-bounds } { \token_to_str:N #1 } {#2} { \@@_count:N #1 } } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[EXP]{\@@_item:Nn, \@@_item_fast:Nn} % \begin{macro}[aux]{\@@_item_aux:Nn} % Get the appropriate \tn{fontdimen} and perform bound checks if requested. % \begin{macrocode} \cs_new:Npn \@@_item_fast:Nn #1#2 { \__int_value:w \tex_fontdimen:D \int_eval:n {#2} #1 } \cs_new:Npn \@@_item:Nn #1#2 { \exp_args:Nf \@@_item_aux:Nn #1 { \int_eval:n {#2} } } \cs_new:Npn \@@_item_aux:Nn #1#2 { \int_compare:nTF { 1 <= #2 <= \@@_count:N #1 } { \@@_item_fast:Nn #1 {#2} } { \__msg_kernel_expandable_error:nnnnn { kernel } { out-of-bounds } { \token_to_str:N #1 } {#2} { \@@_count:N #1 } 0 } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \PrintIndex