summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx271
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