diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx new file mode 100644 index 00000000000..0327082bf18 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx @@ -0,0 +1,271 @@ +% \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 "l3experimental 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|package> +% The version of expl3 required is tested as early as possible, as +% some really old versions do not define \ProvidesExplPackage. +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} +%<package> {} +%<package> {% +%<package> \PackageError{l3intarray}{Support package l3kernel too old} +%<package> {% +%<package> Please install an up to date version of l3kernel\MessageBreak +%<package> using your TeX package manager or from CTAN.\MessageBreak +%<package> \MessageBreak +%<package> Loading l3intarray will abort!% +%<package> }% +%<package> \endinput +%<package> } +%</driver|package> +%<*driver> +\documentclass[full]{l3doc} +\usepackage{amsmath} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \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/13} +% +% \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} +% +% \begin{macrocode} +\ProvidesExplPackage{l3intarray}{2017/05/13}{} + {L3 Experimental low-level arrays of small integers} +% \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 { intarray } { 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 { intarray } { 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 { intarray } { out-of-bounds } + { \token_to_str:N #1 } {#2} { \@@_count:N #1 } + 0 + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\__msg_kernel_new:nnnn { intarray } { overflow } + { Integers~larger~than~2^{30}-1~cannot~be~stored~in~arrays. } + { + An~attempt~was~made~to~store~#3~at~position~#2~in~the~array~'#1'.~ + The~largest~allowed~value~#4~will~be~used~instead. + } +\__msg_kernel_new:nnnn { intarray } { out-of-bounds } + { Access~to~an~entry~beyond~an~array's~bounds. } + { + An~attempt~was~made~to~access~or~store~data~at~position~#2~of~the~ + array~'#1',~but~this~array~has~entries~at~positions~from~1~to~#3. + } +% \end{macrocode} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex |