diff options
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/doc/generic/tuple/README | 16 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/tuple/tuple-doc-en.pdf | bin | 147030 -> 149931 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/generic/tuple/tuple-doc-en.tex | 218 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.pdf | bin | 148764 -> 152074 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.tex | 178 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/tuple/tuple.tex | 569 |
6 files changed, 660 insertions, 321 deletions
diff --git a/Master/texmf-dist/doc/generic/tuple/README b/Master/texmf-dist/doc/generic/tuple/README index d445c863635..925b997fdde 100644 --- a/Master/texmf-dist/doc/generic/tuple/README +++ b/Master/texmf-dist/doc/generic/tuple/README @@ -2,9 +2,9 @@ ___________________________________ tuple - v0.1 + v0.2 - 2024/11/16 + 2024/12/20 ___________________________________ Maintainer: Christian Tellechea @@ -19,13 +19,13 @@ This package provides expandable operations for tuples of numbers: * len, sum, min, max, mean, med, quantile, standard deviation, get item, position of item - * sort, add or set(*) items, filter, operations, composition(*), - split(*), formatting and display + * sort, add or set items, filter, operations, composition, + split(*), formatting and display, store(*) All with a concise syntax that's easy and intuitive to use : "object.method1.method2..." -(*): no expandable method +(*): unexpandable method ----------------------------------------------------------------------- @@ -34,10 +34,10 @@ tuples de nombres : - len, sum, min, max, mean, med, quantile, écart type, get item, position d'un élément - - tri, ajout ou modification(*) d'éléments, filtre, opérations, - composition(*), coupure(*), formattage et affichage + - tri, ajout ou modification d'éléments, filtrage, opérations, + composition, coupure(*), formattage et affichage, stockage (*) Le tout avec une syntaxe concise et d'un usage facile et intuitif : - " object.methode1.methode2... " + "objet.methode1.methode2..." (*) : méthode non développable diff --git a/Master/texmf-dist/doc/generic/tuple/tuple-doc-en.pdf b/Master/texmf-dist/doc/generic/tuple/tuple-doc-en.pdf Binary files differindex 9b7d15cb011..a6aae3078dd 100644 --- a/Master/texmf-dist/doc/generic/tuple/tuple-doc-en.pdf +++ b/Master/texmf-dist/doc/generic/tuple/tuple-doc-en.pdf diff --git a/Master/texmf-dist/doc/generic/tuple/tuple-doc-en.tex b/Master/texmf-dist/doc/generic/tuple/tuple-doc-en.tex index e3fb9c76125..2b08c2f05b8 100644 --- a/Master/texmf-dist/doc/generic/tuple/tuple-doc-en.tex +++ b/Master/texmf-dist/doc/generic/tuple/tuple-doc-en.tex @@ -37,7 +37,8 @@ \begingroup \let\do\@makeother\dospecials \defactive\ {\space}% - \defactive\^^M{\par\leavevmode}% + \defactive\%{\noexpand\color{gray}\char`\% }% + \defactive\^^M{\par\leavevmode\noexpand\color{black}}% \defactive\^^I{\leavevmode\space\space\space\space}% \@makeother:\disable@lig,\disable@lig-% \exemple@@ @@ -87,6 +88,7 @@ \parskip=5ptplus0.5ptminus0.75pt\relax \parindent=0pt \thispagestyle{empty} +\tplsetmode{dec:long} \begin{titlepage} \renewcommand\thefootnote{\fnsymbol{footnote}} \begingroup @@ -141,13 +143,21 @@ This package does not rely on any other except the \LaTeX3 module "\texttt{l3fp} If we do not use \LaTeX{}, \tpl{} will load the file \texttt{expl3-generic.tex} in order to have the \texttt{l3fp} module. \section{Declaring a tuple object} -The macro \verb|\newtuple{<name>}{<list of numbers>}| allows to construct a tuple "object" that is then accessed by its \verb|<name>|: +The macro \verb|\newtuple{<name>}{<list of numbers>}| allows to construct a tuple "object" that is then accessed by its \verb|<name>|. + +The \verb|<name>| accepts all alphanumeric characters \texttt{[az][AZ][09]}, spaces and punctuation. Spaces preceding or following it are removed. A macro is also allowed\footnote{The macro will never be modified by the package \texttt{tuple}: internally, this macro is detokenized to build a more complex name of a macro.}. + +The \verb|<list of numbers>| is fully expanded and then detokenized before being used by the constructor of the tuple object. Empty elements are ignored. + +For the sake of simplicity or speed\footnote{The speed differences aren't huge, but they do exist, see page \pageref{benchmark}}, the user is given the choice of specifying the type of numbers that make up the tuple using the macro \verb|\tplsetmode| ; \begin{itemize} - \item the \verb|<name>| accepts all alphanumeric characters \texttt{[az][AZ][09]}, spaces and punctuation. Spaces preceding or following it are removed. A macro is also allowed\footnote{The macro will never be modified by the package \texttt{tuple}: internally, this macro is detokenized to build a more complex name of a macro.}. - \item the numbers composing the \verb|<list of numbers>| are understood in the sense of the \texttt{l3fp} module: they cover a much wider range and have a much higher precision than the decimal numbers (in the sense of dimensions) of \TeX{} (see the \href{http://mirrors.ctan.org/macros/latex/required/l3kernel/interface3.pdf}{documentation} of \LaTeX3{}, chapter \texttt{l3fp}); - \item the \verb|<list of numbers>| is fully expanded and then detokenized before being used by the constructor of the tuple object. Empty elements are ignored. + \item \verb|\tplsetmode{int}| to request that all numbers be signed integers between $-2^{31}+1$ and $2^{31}-1$. Comparisons during sorting are made with \verb|\ifnum|, operations on numbers with \verb|\numexpr|. + \item \verb|\tplsetmode{dec short}| specifies “short” decimals, i.e. 8-digit intpart and 8-digit decpart. In this case, comparisons are made with \verb|\ifdim| and operations on numbers by a rudimentary calculation engine embedded within \verb|tuple|. + \item \verb|\tplsetmode{dec long}|, which is the default mode, specifies “long” decimals in the sense of \verb|l3fp|. In this mode, comparisons and operations on numbers are performed by \verb|l3fp|. \end{itemize} +Whichever mode is selected, final calculations (standard deviation, mean, quartile, etc.) are performed by \verb|l3fp|.\medbreak + It is possible to define an empty tuple (i.e. one that does not contain any numbers), but many methods will return an error if they are executed on an empty list. On the other hand, it's impossible to redefine an existing tuple (this requires the \texttt{store} method). @@ -180,7 +190,7 @@ If no method is specified, an expandable, implicit and generic method of the gro \section{Methods of the group \texttt{tuple} $\longrightarrow$ \texttt{number}} \subsection{Methods \texttt{len}, \texttt{sum}, \texttt{min}, \texttt{max}, \texttt{mean}, \texttt{med} and \texttt{stdev}} -All these methods do not accept any argument and return respectively the number of elements, their sum, the minimum, the maximum, the mean, the median and the standard deviation. +All these expandable methods do not accept any argument and return respectively the number of elements, their sum, the minimum, the maximum, the mean, the median and the standard deviation. \exemple/%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% @@ -193,7 +203,7 @@ All these methods do not accept any argument and return respectively the number 6) stdev = \tplexe{nn.stdev}/ \subsection{Method \texttt{quantile}} -This method has the syntax +This expandable method has the syntax \code|quantile{<p>}| where \verb|<p>| must be a number between 0 and 1. The method returns the quantile according to the argument \verb|<p>|. The method used is the average method\footnote{If $p$ is the argument of the method, we define $h=(n-1)p+1$ where $n$ is the length of the tuple.\par The method returns the number equal to $x_{\lfloor h\rfloor}+(h-\lfloor h\rfloor)(x_{\lfloor h\rfloor}+x_{\lceil h\rceil})$, where $x_k$ is the $k^{\hbox{\tiny th}}$ number of the sorted tuple.}; this is interpolation scheme “R7” described in this \href{https://en.wikipedia.org/wiki/Quantile}{article}. @@ -208,32 +218,35 @@ Note that \verb|quantile{0.5}| is equivalent to \verb|med|. It's important to note that spaces before and after method arguments are ignored. It is therefore possible to write \verb*|.quantile {0.5} |. \subsection{Method \texttt{get}} -This method has the syntax +This expandable method has the syntax \code|get{<index>}| -The first index is 0 and the last is $n-1$ where $n$ is the number of elements in the tuple. Therefore, the argument of \texttt{get} must be between 0 and $n-1$ otherwise a compilation error will be returned. +The first index is 0 and the last is $n-1$ where $n$ is the number of elements in the tuple. Therefore, the argument of \texttt{get} must be between 0 and $n-1$. You can also use negative indexes, where $-1$ is the index of the last element, $-2$ that of the penultimate element and so on up to $-n$. \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% -1st number : \tplexe{nn.get{0}}\par -13th number : \tplexe{nn.get{12}}\par -last number : \tplexe{nn.get{\tplexe{nn.len}-1}}| +1st number : \tplexe{nn.get{0}}\par +13th number : \tplexe{nn.get{12}}\par +last number : \tplexe{nn.get{\tplexe{nn.len}-1}}\par +last number : \tplexe{nn.get{-1}}% better than above| The argument of \texttt{get} is evaluated before being used: it is therefore possible to put the expandable macro \verb|\tplexe| with a final method returning an integer. \subsection{Method \texttt{pos}} -This method has the syntax -\code|pos{<number>}| -and returns the index of the first occurrence of the \verb|<number>| in the tuple. If the tuple does not contain the \verb|<number>|, \verb|-1| is returned. +This expandable method has the syntax +\code|pos{<number>}[<n>]| +and returns the index of the \verb|<n>| occurrence of the \verb|<number>| in the tuple. If the tuple does not contain the \verb|<number>|, \verb|-1| is returned. If the optional argument is not present, \verb|<n>| is $-1$. \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% -index of 12.7: \tplexe{nn.pos{12.7}}\par -index of 2.9 : \tplexe{nn.pos{2.9}}\par -index of 31.8: \tplexe{nn.pos{31.8}}| +index of 12.7 : \tplexe{nn.pos{12.7}}\par +index of 2.9 : \tplexe{nn.pos{2.9}}\par +index of 2.9[2]: \tplexe{nn.pos{2.9}[2]}\par +index of 2.9[3]: \tplexe{nn.pos{2.9}[3]}\par +index of 31.8 : \tplexe{nn.pos{31.8}}| \subsection{Method \texttt{show}} -This method does not accept any arguments and is intended to convert a tuple object into a displayable result. To do this: +This expandable method does not accept any arguments and is intended to convert a tuple object into a displayable result. To do this: \begin{itemize} \item for each element, the macro \verb|\tplformat|, requiring 2 mandatory arguments, is executed. The first argument passed is the index of the element and the 2nd{} argument is the element itself; \item each result from the macro \verb|\tplformat| is separated from the next by the content of the macro \verb|\tplsep|. @@ -273,25 +286,25 @@ Below-average items highlighted in red: \section{Methods of the group \texttt{tuple} $\longrightarrow$ \texttt{tuple}} Each time a tuple is generated or modified, the \texttt{len}, \texttt{sum}, \texttt{min}, \texttt{max}, \texttt{mean}, \texttt{med}, \texttt{stdev} and \texttt{sorted} methods are updated. \subsection{Method \texttt{sorted}} -This method does not accept any arguments and returns a tuple object with its elements sorted in ascending order. +This expandable method does not accept any arguments and returns a tuple object with its elements sorted in ascending order. \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% \tplexe{nn.sorted}| \subsection{Method \texttt{set}} -The syntax of this method is +The syntax of this expandable method is \code|set{<index1>:<number1>,<index2>:<number2>,...}| In the tuple resulting from the previous methods, replaces the number at \verb|<index1>| with \verb|<number1>| and so on if several assignments are specified in a comma-separated list. -Each \verb|<index>| must be between 0 and $n-1$, where $n$ is the number of elements in the tuple passed as input to the method. +Each \verb|<index>| must be between 0 and $n-1$, where $n$ is the number of elements in the tuple passed as input to the method. Negative indexes from $-n$ to $-1$ are also permitted. \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% -\tplexe{nn.set{1:10,5:50}}| +\tplexe{nn.set{1:10,5:50,-1:-666}}| \subsection{Method \texttt{add}} -This method, which adds a \verb|<insertion>| at one or more specified indexes, has the syntax +This expandable method, which adds a \verb|<insertion>| at one or more specified indexes, has the syntax \code|add{<index1>:<insertion1>,<index2>:<insertion2>,...}| It should be noted that in this syntax, a \verb|<insertion>| can be @@ -301,27 +314,29 @@ It should be noted that in this syntax, a \verb|<insertion>| can be \item a tuple accessed by \verb|\tplexe|: "\verb|add{<index>:{\tplexe{<tuple name>}}}|". \end{itemize} -Concerning the \verb|<index>|: +As for \verb|<index>|, they can be between $0$ and $n$, where $n$ is the number of elements in the tuple. Negative indexes between $-n-1$ and $-1$ are also permitted: \begin{itemize} - \item if a \verb|<index>| is less than 0, it is taken as 0; - \item if a \verb|<index>| is "\verb|*|" or greater than $n-1$, the \verb|<insertion>| is placed at the end of the input tuple; - \item the \verb|<index>| \emph{are not} recalculated after each \verb|<insertion>|, but only after the last one. It is therefore not equivalent to write "\verb|.add{1:10,5:50}|" and "\verb|.add{1:10}.add{5:50}|". Indeed, 5 will be at index 6 in the first case while it will be at index 5 in the second. + \item a \verb|<index>| equal to 0 or $-n-1$ places the \verb|<insertion>| at the beginning of the tuple passed as input; + \item a \verb|<index>| equal to $n$ or $-1$ places the \verb|<insertion>| at the end of the tuple; + \item the \verb|<index>| \emph{are not} updated after each \verb|<insertion>|, but only after the last one. It is therefore not equivalent to write “\verb|.add{1:100,2:200}|” and “\verb|.add{1:100}.add{2:200}|”. Indeed, 200 will be at index 3 in the first case, whereas it will be at index 2 in the second. \end{itemize} \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% -1) add at first pos : \tplexe{nn.add{0:{666,667}}}\par -2) add index 16 : \tplexe{nn.add{16:{666,667}}}\par -3) add at last pos last: \tplexe{nn.add{*:{666,667}}}| +1) add at first pos: \tplexe{nn.add{0:{666,667}}}\par +2) add index 11 : \tplexe{nn.add{11:{666,667}}}\par +3) add at last pos : \tplexe{nn.add{-1:{666,667}}}| \exemple|\newtuple{X}{10,20,30,40,50,60}% \newtuple{Y}{1,2,3,4}% -1) \tplexe{X.add{-3:{\tplexe{Y}}}}\par -2) \tplexe{X.add{1:1000,3:{\tplexe{Y}}}}\par -3) \tplexe{X.add{1:1000}.add{3:{\tplexe{Y}}}}| +1) \tplexe{X.add{0:{\tplexe{Y}}}}\par +2) \tplexe{X.add{2:{\tplexe{Y}}}}\par +3) \tplexe{X.add{-1:{\tplexe{Y}}}}\par +4) \tplexe{X.add{1:100,2:200}}\par +5) \tplexe{X.add{1:100}.add{2:200}}| \subsection{Method \texttt{op}} -This method, which performs an \verb|<operation>| on all elements of the tuple, has the syntax +This expandable method, which performs an \verb|<operation>| on all elements of the tuple, has the syntax \code|op{<operation>}| The \verb|<operation>| is an expression not containing braces, evaluable by \verb|\fpeval| once all occurrences of "\texttt{val}" have been replaced by the value of each element, and all occurrences of "\texttt{idx}" by its index. @@ -333,7 +348,7 @@ The \verb|<operation>| is an expression not containing braces, evaluable by \ver 4) \tplexe{X.op{idx<4 ? val-1 : val+1 }}| \subsection{Method \texttt{filter}} -This method, which selects elements according to one or more criteria, has the syntax +Thi expandables method, which selects elements according to one or more criteria, has the syntax \code|filter{<test>}| and where \verb|<test>| is a boolean not containing braces, evaluable by \verb|\fpeval| once all occurrences of "\texttt{val}" have been replaced by the value of each element, and all occurrences of "\texttt{idx}" by its index. @@ -345,7 +360,7 @@ and where \verb|<test>| is a boolean not containing braces, evaluable by \verb|\ 4) \tplexe{nn.filter{val!=6.3 && val!=2.9 && val!=4.1}}/ \subsection{Method \texttt{comp}} -This method composes two tuples of the same length with an operation that the user specifies. Its syntax is +This expandable method composes two tuples of the same length with an operation that the user specifies. Its syntax is \code|comp{<operation>}{<tuple name>}| where the tuple whose name is passed as the second argument \emph{must} have the same length as the tuple passed as input to the method. @@ -370,7 +385,7 @@ This method cuts the tuple passed as input to the method after the specified ind \code|split{<index>}{<tuple1>}{<tuple2>}| The tuple passed as input to the method is split after the \verb|<index>|: the part before the split is assigned, via \verb||newtuple| to the tuple with name “\texttt{tuple1}” and the remaining part to the tuple with name “\texttt{tuple2}”. No check is made on the existence of the 2 tuples, so existing tuples can be silently replaced. -The \verb|<index>| must lie between 0 and $n-2$, where $n$ is the number of elements in the tuple passed as input. +The \verb|<index>| must lie between 0 and $n-2$ if positive, or between $-n$ and $-2$ if negative, $n$ being the number of elements in the tuple passed as input. \exemple/%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% @@ -429,9 +444,7 @@ Generation of the first 10 terms of $u_0=1$ ; $u_1=1$ ; $u_2=-1$ and $u_{n}=u_{n \exemple|\gentuple{1,1,-1,\genrule\1*\3-\2*\2; \until \i=10}| Generation of the Syracuse sequence (aka the “$3n+1$ sequence”) of 15: -\exemple|\edef\syr{% - \gentuple{15,\genrule \1/2=trunc(\1/2) ? \1/2 : 3*\1+1 ; \until val=1}% -}% +\exemple|\gentuple{15,\genrule \1/2=trunc(\1/2) ? \1/2 : 3*\1+1 ; \until val=1}% \meaning\syr| Maximum altitude and length of the Syracuse sequence of 27: @@ -442,8 +455,7 @@ max alt = \tplexe{syr27.max}| \section{Conclusion} \subsection{Motivation} -Somewhat surprisingly, very little exists to manipulate and operate on lists of numbers\footnote{There is one package, \texttt{commalists-tools}, but it's clearly too limited. Like all its author's packages that flood CTAN, it simply aligns, linearly and without any real programmation, the high-level macros of the packages \texttt{tikz}, \texttt{listofitems}, \texttt{xstring}, \texttt{xint} and \texttt{simplekv}.% What advice would you give this author? Quality over quantity? Progress in programming and not remain at this basic, distressing and uninteresting level forever? Think about what would happen (spoiler: CTAN would explode!) if all \LaTeX{} users started writing a package every time they managed to combine macros from other packages? -}. +Somewhat surprisingly, very little exists to manipulate and operate on lists of numbers\footnote{There is one package, \texttt{commalists-tools}, but it's clearly too limited. Like all its author's packages that flood CTAN, it simply aligns, linearly and without any real programmation, the high-level macros of the packages \texttt{tikz}, \texttt{listofitems}, \texttt{xstring}, \texttt{xint} and \texttt{simplekv}.}. The main challenge was to provide expandable macros and also an original syntax in the world of \TeX{} of the type \verb|<object>.<method 1>.<method 2>...<method n>|, where you can chain methods executed on an “object” which is a tuple of numbers. I don't know if any packages offer this kind of syntax, but it's actually quite intuitive. As I'm fairly unfamiliar with programming expandable macros, I almost gave up many times. But I've finally found a mouse-hole that makes it all work pretty much, except for the numerous bugs that are probably lurking everywhere. @@ -455,38 +467,73 @@ When you get into optimizing execution speed, especially for expandable macros, I hope I didn't fall into this trap, because I've barely entered it. In any case, \TeX{} is not made for massive calculations, since it is first and foremost a typesetting software. For calculations, powerful tools that beat \TeX{} hands down exist in abundance. In any case, "expandable macro" goes a bit against "execution speed". For information, I put below the compilation times, in seconds, of the creation of tuples containing $n$ random integers. It depends on the computer used, of course, but the orders of magnitude are quite revealing. We can clearly see that it is illusory to exceed a thousand numbers because the time to create a tuple then increases rapidly\footnote{Not to mention that, in addition to that, the tuple is immediately recreated and recalculated after being modified by the methods \texttt{set}, \texttt{add}, \texttt{op}, \texttt{filter}, \texttt{split} and \texttt{comp}}. That said, who would use \TeX{} for calculations on so many numbers? + +This table illustrates the creation speeds of a tuple of random signed integers between $-1000$ and $1000$. As a reminder, creating a tuple involves sorting its elements (by quick sort), calculating the sum of the numbers and the sum of squares. The 3 modes can thus be compared for larger or smaller tuples.\label{benchmark} + \begin{center} -\begin{tabular}{|c|c|}\hline - Number of elements $n$ & Execution time of \verb|\newtuple| in s\\\hline - 50 & 0.011\\\hline - 100 & 0.026\\\hline - 500 & 0.224\\\hline - 1000 & 0.703\\\hline - 1500 & 1.727\\\hline - 2000 & 2.876\\\hline - 5000 & 22.907\\\hline -\end{tabular} + \directlua{pdfelapsedtimer_basetime=0} + \protected\def\pdfresettimer{\directlua{pdfelapsedtimer_basetime = os.clock()}} + \protected\def\pdfelapsedtime{\numexpr\directlua{tex.print(math.floor((os.clock()-pdfelapsedtimer_basetime)*65536+0.5))}\relax} + \catcode`\_11 + \def\doten#1{#1#1#1#1#1#1#1#1#1#1} + \def\falsenewtuple#1{} + \def\printtime{\fpeval{round((\the\pdfelapsedtime-\tare)/655360,3)} s} + \def\dotest#1{% + \tplsetmode{#1}% + \pdfresettimer% + \doten{\edef\test{\expandafter\tpl_newtuple_b\expandafter{\mytuple}}\let\mytest\empty}% + \printtime + } + \def\testnewtuple#1{% #1=nb éléments dans le tuple + \xdef\mytuple{\gentuple{\genrule randint(-1000,1000) ; \until \i==#1 }}% + \pdfresettimer + \doten{\edef\mytest{\expandafter\falsenewtuple\expandafter{\mytuple}}\let\mytest\empty}% + \xdef\tare{\the\pdfelapsedtime}% + #1% + &% + \dotest{int} + &% + \dotest{dec:short} + &% + \dotest{dec:long} + } + \def\gentab{% + \begin{center} + \begin{tabular}{|r|c|c|c|}\hline + Nb items&\texttt{int} & \texttt{dec:short} & \texttt{dec:long}\\\hline + \testnewtuple{25} \\\hline + \testnewtuple{50} \\\hline + \testnewtuple{100} \\\hline + \testnewtuple{200} \\\hline + \testnewtuple{400} \\\hline + \testnewtuple{800} \\\hline + \testnewtuple{1600}\\\hline + \end{tabular} + \end{center} + } + \catcode`\_8 + \gentab \end{center} \subsection{Example: state population} The tuple \verb|\Wpop| contains the population of each state in the world, in millions of inhabitants\footnote{The data comes from \href{https://www.unfpa.org/data/world-population-dashboard}{https://www.unfpa.org/data/world-population-dashboard}} : \exemple/\newtuple\Wpop{% -43.4, 2.8, 46.3, 37.8, 0.1, 46.1, 2.8, 0.1, 26.7, 9.0, 10.5, 0.4, 1.5,% -174.7, 0.3, 9.5, 11.7, 0.4, 14.1, 0.8, 12.6, 3.2, 2.7, 217.6, 0.5, 6.6,% -23.8, 13.6, 0.6, 17.1, 29.4, 39.1, 5.9, 18.8, 19.7, 1425.2, 7.5, 0.7,% -52.3, 0.9, 6.2, 5.2, 29.6, 4.0, 11.2, 0.2, 1.3, 10.5, 26.2, 105.6, 5.9,% -1.2, 0.1, 11.4, 18.4, 114.5, 6.4, 1.8, 3.8, 1.3, 1.2, 129.7, 0.9, 5.5,% -64.9, 0.3, 0.3, 2.5, 2.8, 3.7, 83.3, 34.8, 10.3, 0.1, 0.4, 0.2, 18.4,% -14.5, 2.2, 0.8, 11.9, 10.8, 10.0, 0.4, 1441.7, 279.8, 89.8, 46.5, 5.1,% -9.3, 58.7, 2.8, 122.6, 11.4, 19.8, 56.2, 0.1, 4.3, 6.8, 7.7, 1.8, 5.2,% -2.4, 5.5, 7.0, 2.7, 0.7, 31.1, 21.5, 34.7, 0.5, 24.0, 0.5, 0.4, 5.0,% -1.3,129.4, 0.1, 3.5, 0.6, 38.2, 34.9, 55.0, 2.6, 31.2, 17.7, 0.3, 5.3,% -7.1,28.2, 229.2, 2.1, 5.5, 4.7, 245.2, 4.5, 10.5, 6.9, 34.7, 119.1,% -40.2,10.2, 3.3, 2.7, 51.7, 3.3, 1.0, 19.6, 144.0, 14.4, 0.0, 0.2, 0.1,% -0.2,0.03, 0.2, 37.5, 18.2, 7.1, 0.1, 9.0, 6.1, 0.0, 5.7, 2.1, 0.8, 18.7,% -61.0,11.3, 47.5, 21.9, 5.5, 49.4, 0.6, 10.7, 8.9, 24.3, 10.3, 71.9, 1.4,% -9.3,0.1, 1.5, 12.6, 86.3, 6.6, 0.0, 0.0, 49.9, 37.9, 9.6, 68.0, 69.4,% -341.8,0.1, 3.4, 35.7, 0.3, 29.4, 99.5, 0.6, 35.2, 21.1, 17.0}% +43.4, 2.8, 46.3, 37.8, 0.1, 46.1, 2.8, 0.1, 26.7, 9.0, 10.5, 0.4, 1.5, +174.7, 0.3, 9.5, 11.7, 0.4, 14.1, 0.8, 12.6, 3.2, 2.7, 217.6, 0.5, 6.6, +23.8, 13.6, 0.6, 17.1, 29.4, 39.1, 5.9, 18.8, 19.7, 1425.2, 7.5, 0.7, +52.3, 0.9, 6.2, 5.2, 29.6, 4.0, 11.2, 0.2, 1.3, 10.5, 26.2, 105.6, 5.9, +1.2, 0.1, 11.4, 18.4, 114.5, 6.4, 1.8, 3.8, 1.3, 1.2, 129.7, 0.9, 5.5, +64.9, 0.3, 0.3, 2.5, 2.8, 3.7, 83.3, 34.8, 10.3, 0.1, 0.4, 0.2, 18.4, +14.5, 2.2, 0.8, 11.9, 10.8, 10.0, 0.4, 1441.7, 279.8, 89.8, 46.5, 5.1, +9.3, 58.7, 2.8, 122.6, 11.4, 19.8, 56.2, 0.1, 4.3, 6.8, 7.7, 1.8, 5.2, +2.4, 5.5, 7.0, 2.7, 0.7, 31.1, 21.5, 34.7, 0.5, 24.0, 0.5, 0.4, 5.0, +1.3 ,129.4, 0.1, 3.5, 0.6, 38.2, 34.9, 55.0, 2.6, 31.2, 17.7, 0.3, 5.3, +7.1 ,28.2, 229.2, 2.1, 5.5, 4.7, 245.2, 4.5, 10.5, 6.9, 34.7, 119.1, +40.2 ,10.2, 3.3, 2.7, 51.7, 3.3, 1.0, 19.6, 144.0, 14.4, 0.0, 0.2, 0.1, +0.2 ,0.03, 0.2, 37.5, 18.2, 7.1, 0.1, 9.0, 6.1, 0.0, 5.7, 2.1, 0.8, 18.7, +61.0 ,11.3, 47.5, 21.9, 5.5, 49.4, 0.6, 10.7, 8.9, 24.3, 10.3, 71.9, 1.4, +9.3 ,0.1, 1.5, 12.6, 86.3, 6.6, 0.0, 0.0, 49.9, 37.9, 9.6, 68.0, 69.4, +341.8 ,0.1, 3.4, 35.7, 0.3, 29.4, 99.5, 0.6, 35.2, 21.1, 17.0} Number of state: \tplexe{\Wpop.len}\par Mean: \tplexe{\Wpop.mean}\par Median: \tplexe{\Wpop.med}\par @@ -494,22 +541,22 @@ Standard deviation: \tplexe{\Wpop.stdev}\par Quintile \#1 : \tplexe{\Wpop.quantile{0.2}}\par Quintile \#4 : \tplexe{\Wpop.quantile{0.8}}/ \newtuple\Wpop{% -43.4, 2.8, 46.3, 37.8, 0.1, 46.1, 2.8, 0.1, 26.7, 9.0, 10.5, 0.4, 1.5,% -174.7, 0.3, 9.5, 11.7, 0.4, 14.1, 0.8, 12.6, 3.2, 2.7, 217.6, 0.5, 6.6,% -23.8, 13.6, 0.6, 17.1, 29.4, 39.1, 5.9, 18.8, 19.7, 1425.2, 7.5, 0.7,% -52.3, 0.9, 6.2, 5.2, 29.6, 4.0, 11.2, 0.2, 1.3, 10.5, 26.2, 105.6, 5.9,% -1.2, 0.1, 11.4, 18.4, 114.5, 6.4, 1.8, 3.8, 1.3, 1.2, 129.7, 0.9, 5.5,% -64.9, 0.3, 0.3, 2.5, 2.8, 3.7, 83.3, 34.8, 10.3, 0.1, 0.4, 0.2, 18.4,% -14.5, 2.2, 0.8, 11.9, 10.8, 10.0, 0.4, 1441.7, 279.8, 89.8, 46.5, 5.1,% -9.3, 58.7, 2.8, 122.6, 11.4, 19.8, 56.2, 0.1, 4.3, 6.8, 7.7, 1.8, 5.2,% -2.4, 5.5, 7.0, 2.7, 0.7, 31.1, 21.5, 34.7, 0.5, 24.0, 0.5, 0.4, 5.0,% -1.3,129.4, 0.1, 3.5, 0.6, 38.2, 34.9, 55.0, 2.6, 31.2, 17.7, 0.3, 5.3,% -7.1,28.2, 229.2, 2.1, 5.5, 4.7, 245.2, 4.5, 10.5, 6.9, 34.7, 119.1,% -40.2,10.2, 3.3, 2.7, 51.7, 3.3, 1.0, 19.6, 144.0, 14.4, 0.0, 0.2, 0.1,% -0.2,0.03, 0.2, 37.5, 18.2, 7.1, 0.1, 9.0, 6.1, 0.0, 5.7, 2.1, 0.8, 18.7,% -61.0,11.3, 47.5, 21.9, 5.5, 49.4, 0.6, 10.7, 8.9, 24.3, 10.3, 71.9, 1.4,% -9.3,0.1, 1.5, 12.6, 86.3, 6.6, 0.0, 0.0, 49.9, 37.9, 9.6, 68.0, 69.4,% -341.8,0.1, 3.4, 35.7, 0.3, 29.4, 99.5, 0.6, 35.2, 21.1, 17.0}% +43.4, 2.8, 46.3, 37.8, 0.1, 46.1, 2.8, 0.1, 26.7, 9.0, 10.5, 0.4, 1.5, +174.7, 0.3, 9.5, 11.7, 0.4, 14.1, 0.8, 12.6, 3.2, 2.7, 217.6, 0.5, 6.6, +23.8, 13.6, 0.6, 17.1, 29.4, 39.1, 5.9, 18.8, 19.7, 1425.2, 7.5, 0.7, +52.3, 0.9, 6.2, 5.2, 29.6, 4.0, 11.2, 0.2, 1.3, 10.5, 26.2, 105.6, 5.9, +1.2, 0.1, 11.4, 18.4, 114.5, 6.4, 1.8, 3.8, 1.3, 1.2, 129.7, 0.9, 5.5, +64.9, 0.3, 0.3, 2.5, 2.8, 3.7, 83.3, 34.8, 10.3, 0.1, 0.4, 0.2, 18.4, +14.5, 2.2, 0.8, 11.9, 10.8, 10.0, 0.4, 1441.7, 279.8, 89.8, 46.5, 5.1, +9.3, 58.7, 2.8, 122.6, 11.4, 19.8, 56.2, 0.1, 4.3, 6.8, 7.7, 1.8, 5.2, +2.4, 5.5, 7.0, 2.7, 0.7, 31.1, 21.5, 34.7, 0.5, 24.0, 0.5, 0.4, 5.0, +1.3 ,129.4, 0.1, 3.5, 0.6, 38.2, 34.9, 55.0, 2.6, 31.2, 17.7, 0.3, 5.3, +7.1 ,28.2, 229.2, 2.1, 5.5, 4.7, 245.2, 4.5, 10.5, 6.9, 34.7, 119.1, +40.2 ,10.2, 3.3, 2.7, 51.7, 3.3, 1.0, 19.6, 144.0, 14.4, 0.0, 0.2, 0.1, +0.2 ,0.03, 0.2, 37.5, 18.2, 7.1, 0.1, 9.0, 6.1, 0.0, 5.7, 2.1, 0.8, 18.7, +61.0 ,11.3, 47.5, 21.9, 5.5, 49.4, 0.6, 10.7, 8.9, 24.3, 10.3, 71.9, 1.4, +9.3 ,0.1, 1.5, 12.6, 86.3, 6.6, 0.0, 0.0, 49.9, 37.9, 9.6, 68.0, 69.4, +341.8 ,0.1, 3.4, 35.7, 0.3, 29.4, 99.5, 0.6, 35.2, 21.1, 17.0} We modify the tuple \verb|\Wpop|, retaining only “moderately” populated states. We arbitrarily consider their population between 10 and 100 millions: \exemple/\tplexe{\Wpop.filter{val>=10 && val<=100}.store\Wpop}% @@ -533,7 +580,6 @@ Distribution over 6 equal intervals:\par \subsection{TODO list} To be implemented more or less quickly: \begin{enumerate} - \item allow the user to choose \texttt{l3fp} or \texttt{xint} as the calculation engine; \item insertion sorting to sort almost-sorted tuples obtained using the \texttt{add}, \texttt{set}, \texttt{op} methods (risky as it depends on the operation!). \item merge sorting to add one tuple to another; \item other speed optimization? diff --git a/Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.pdf b/Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.pdf Binary files differindex 6ea0d990967..9723642ee49 100644 --- a/Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.pdf +++ b/Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.pdf diff --git a/Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.tex b/Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.tex index 76ec899178b..90b2bce41bd 100644 --- a/Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.tex +++ b/Master/texmf-dist/doc/generic/tuple/tuple-doc-fr.tex @@ -37,7 +37,8 @@ \begingroup \let\do\@makeother\dospecials \defactive\ {\space}% - \defactive\^^M{\par\leavevmode}% + \defactive\%{\noexpand\color{gray}\char`\% }% + \defactive\^^M{\par\leavevmode\noexpand\color{black}}% \defactive\^^I{\leavevmode\space\space\space\space}% \@makeother:\disable@lig,\disable@lig-% \exemple@@ @@ -87,6 +88,7 @@ \parskip=5ptplus0.5ptminus0.75pt\relax \parindent=0pt \thispagestyle{empty} +\tplsetmode{dec:long} \begin{titlepage} \renewcommand\thefootnote{\fnsymbol{footnote}} \begingroup @@ -141,13 +143,21 @@ Ce package ne s'appuie sur aucun autre si ce n'est le module de \LaTeX3 «\textt Si l'on n'utilise pas \LaTeX{}, \tpl{} va charger le fichier \texttt{expl3-generic.tex} afin de disposer du module \texttt{l3fp}. \section{Déclarer un objet tuple} -La macro \verb|\newtuple{<nom>}{<liste de nombres>}| permet de construire un «objet» tuple auquel on accède ensuite par son \verb|<nom>|: +La macro \verb|\newtuple{<nom>}{<liste de nombres>}| permet de construire un «objet» tuple auquel on accède ensuite par son \verb|<nom>|. + +Ce \verb|<nom>| admet tous les caractères alphanumériques \texttt{[az][AZ][09]}, espaces et ponctuations. Les espaces qui le précèdent ou le suivent sont supprimés. Il est également possible de mettre une macro\footnote{La macro ne sera jamais modifiée par le package \texttt{tuple} : en interne cette macro est détokenisée pour construire le nom plus complexe d'une macro.}. + +La \verb|<liste de nombres>| est développée au maximum puis détokénisée avant d'être exploitée par le constructeur de l'objet tuple. Les éléments vides sont ignorés. + +Par souci de simplification ou de vitesse\footnote{Les différences de vitesse ne sont pas énormes, mais elles existent, voir page \pageref{benchmark}}, le choix est donné à l'utilisateur de spécifier le type de nombre qui composent le tuple à l'aide la macro \verb|\tplsetmode| ; \begin{itemize} - \item le \verb|<nom>| admet tous les caractères alphanumériques \texttt{[az][AZ][09]}, espaces et ponctuations. Les espaces qui le précèdent ou le suivent sont supprimés. Il est également possible de mettre une macro\footnote{La macro ne sera jamais modifiée par le package \texttt{tuple} : en interne cette macro est détokenisée pour construire le nom plus complexe d'une macro.}. - \item les nombres composant la \verb|<liste de nombres>| s'entendent au sens du module \texttt{l3fp}, c'est-à-dire qu'ils couvrent une plage beaucoup plus étendue et disposent d'une précision très supérieure aux nombres décimaux (pris au sens de dimensions) de \TeX{} (voir la \href{http://mirrors.ctan.org/macros/latex/required/l3kernel/interface3.pdf}{documentation} de \LaTeX3{}, chapitre \texttt{l3fp}) ; - \item la \verb|<liste de nombres>| est développée au maximum puis détokénisée avant d'être exploitée par le constructeur de l'objet tuple. Les éléments vides sont ignorés. + \item \verb|\tplsetmode{int}| pour indiquer que tous les nombres sont des entiers signés entre $-2^{31}+1$ et $2^{31}-1$. Les comparaisons lors du tri sont faites avec \verb|\ifnum|, les opérations sur les nombres avec \verb|\numexpr|. + \item \verb|\tplsetmode{dec short}| pour indiquer des décimaux «courts», c'est-à-dire comprenant 8 chiffres en partie entière et 8 chiffres en partie décimale. Dans ce cas, les comparaison sont faites avec \verb|\ifdim| et les opérations sur les nombres par un moteur de calcul rudimentaire embarqué au sein de \verb|tuple|. + \item \verb|\tplsetmode{dec long}|, qui est le mode par défaut, spécifie des décimaux «longs» qui s'entendent au sens de \verb|l3fp|. Dans ce mode, les comparaisons et les opérations sont faites par \verb|l3fp|. \end{itemize} +Quel que soit le mode sélectionné, les calculs finaux à destination de l'utilisateur (écart-type, moyenne, quartile, etc) sont effectués par \verb|l3fp|.\medbreak + Il est possible de définir un tuple vide (c'est-à-dire ne contenant donc aucun nombre), mais beaucoup de méthodes renverront une erreur si elles sont exécutées sur une liste vide. Il est en revanche impossible de redéfinir un tuple déjà existant (il faut pour cela passer par la méthode \texttt{store}). @@ -180,7 +190,7 @@ Si aucune méthode n'est spécifiée, une méthode générique implicite du grou \section{Les méthodes du groupe \texttt{tuple} $\longrightarrow$ \texttt{nombre}} \subsection{Les méthodes \texttt{len}, \texttt{sum}, \texttt{min}, \texttt{max}, \texttt{mean}, \texttt{med} et \texttt{stdev}} -Toutes ces méthodes n'admettent pas d'argument et renvoient respectivement le nombre d'éléments, leur somme, le minimum, le maximum, la moyenne, la médiane et l'écart-type. +Toutes ces méthodes développables n'admettent pas d'argument et renvoient respectivement le nombre d'éléments, leur somme, le minimum, le maximum, la moyenne, la médiane et l'écart-type. \exemple/%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% @@ -193,7 +203,7 @@ Toutes ces méthodes n'admettent pas d'argument et renvoient respectivement le n 6) stdev = \tplexe{nn.stdev}/ \subsection{La méthode \texttt{quantile}} -Cette méthode a pour syntaxe +Cette méthode développable a pour syntaxe \code|quantile{<p>}| où \verb|<p>| doit être un nombre compris entre 0 et 1. La méthode renvoie le quantile correspondant à l'argument \verb|<p>|. La méthode utilisée est celle de la moyenne pondérée\footnote{Si $p$ est l'argument de la méthode, on définit $h=(n-1)p+1$ où $n$ est la longueur du tuple.\par La méthode renvoie le nombre égal à $x_{\lfloor h\rfloor}+(h-\lfloor h\rfloor)(x_{\lfloor h\rfloor}+x_{\lceil h\rceil})$, où $x_k$ est le $k$\ieme{} nombre du tuple ordonné.} ; il s'agit de l'interpolation linéaire du type «R7» décrite dans l'article de \href{https://en.wikipedia.org/wiki/Quantile}{wikipedia}. @@ -208,29 +218,32 @@ La méthode \verb|quantile{0.5}| est équivalente à la méthode \verb|med|. Il est important de noter que les espaces avant/après les arguments d'une méthode sont ignorés. Il est donc licite d'écrire \verb*|.quantile {0.5} |. \subsection{La méthode \texttt{get}} -Cette méthode a pour syntaxe +Cette méthode développable a pour syntaxe \code|get{<index>}| -Le premier index est 0 et le dernier est $n-1$ où $n$ est le nombre d'éléments du tuple. Par conséquent, l'argument de \texttt{get} doit être entre 0 et $n-1$ sans quoi une erreur de compilation sera renvoyée. +Le premier index est 0 et le dernier est $n-1$ où $n$ est le nombre d'éléments du tuple. Par conséquent, l'argument de \texttt{get} doit être entre 0 et $n-1$. On peut également utiliser des index négatifs où $-1$ représente l'index du dernier élément, $-2$ celui de l'avant dernier et ainsi de suite jusqu'à $-n$. \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% 1er élément : \tplexe{nn.get{0}}\par 13e élément : \tplexe{nn.get{12}}\par -dernier élément : \tplexe{nn.get{\tplexe{nn.len}-1}}| +dernier élément : \tplexe{nn.get{\tplexe{nn.len}-1}}\par +dernier élément : \tplexe{nn.get{-1}}% mieux que ci-dessus| L'argument de \texttt{get} est évalué avant d'être exploité : il est donc possible d'y mettre la macro purement développable \verb|\tplexe| avec une méthode finale renvoyant un nombre entier. \subsection{La méthode \texttt{pos}} -Cette méthode a pour syntaxe -\code|pos{<nombre>}| -et renvoie l'index de la première occurrence du \verb|<nombre>| dans le tuple. Si le tuple ne contient pas le \verb|<nombre>|, \verb|-1| est renvoyé. +Cette méthode développable a pour syntaxe +\code|pos{<nombre>}[<n>]| +et renvoie l'index de l'occurrence \no\verb|<n>| du \verb|<nombre>| dans le tuple. Si le tuple ne contient pas cette occurrence, \verb|-1| est renvoyé. Si l'argument optionnel est omis, \verb|<n>| vaut 1. \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% -index de 12.7 : \tplexe{nn.pos{12.7}}\par -index de 2.9 : \tplexe{nn.pos{2.9}}\par -index de 31.8 : \tplexe{nn.pos{31.8}}| +index de 12.7 : \tplexe{nn.pos{12.7}}\par +index de 2.9 : \tplexe{nn.pos{2.9}}\par +index de 2.9[2] : \tplexe{nn.pos{2.9}[2]}\par +index de 2.9[3] : \tplexe{nn.pos{2.9}[3]}\par +index de 31.8 : \tplexe{nn.pos{31.8}}| \subsection{La méthode \texttt{show}} Cette méthode n'admet pas d'argument et a pour but de convertir un objet tuple en résultat affichable. Pour ce faire : @@ -273,25 +286,25 @@ Mise en rouge des éléments inférieurs à la moyenne : \section{Les méthodes du groupe \texttt{tuple} $\longrightarrow$ \texttt{tuple}} Chaque fois qu'un tuple est généré ou modifié, ses méthodes \texttt{len}, \texttt{sum}, \texttt{min}, \texttt{max}, \texttt{mean}, \texttt{med}, \texttt{stdev} et \texttt{sorted} sont mises à jour. \subsection{La méthode \texttt{sorted}} -Cette méthode n'admet pas d'argument et retourne un objet tuple avec ses éléments rangés dans l'ordre croissant. +Cette méthode développable n'admet pas d'argument et retourne un objet tuple avec ses éléments rangés dans l'ordre croissant. \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% \tplexe{nn.sorted}| \subsection{La méthode \texttt{set}} -Cette méthode a pour syntaxe +Cette méthode développable a pour syntaxe \code|set{<index1>:<nombre1>,<index2>:<nombre2>,...}| Dans le tuple issu des méthodes précédentes, remplace le nombre à l'\verb|<index1>| par \verb|<nombre1>| et ainsi de suite si plusieurs assignations sont spécifiées dans une liste séparée par des virgules. -Chaque \verb|<index>| doit être compris entre 0 et $n-1$, où $n$ est le nombre d'élément du tuple passé en entrée de la méthode. +Chaque \verb|<index>| doit être compris entre 0 et $n-1$, où $n$ est le nombre d'élément du tuple passé en entrée de la méthode. Les index négatifs de $-n$ à $-1$ sont également autorisés. \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% -\tplexe{nn.set{1:10,5:50}}| +\tplexe{nn.set{1:10,5:50,-1:-666}}| \subsection{La méthode \texttt{add}} -Cette méthode, qui ajoute une \verb|<insertion>| à un ou plusieurs index spécifiés, a pour syntaxe +Cette méthode développable, qui ajoute une \verb|<insertion>| à un ou plusieurs index spécifiés, a pour syntaxe \code|add{<index1>:<insertion1>,<index2>:<insertion2>,...}| Il faut noter que dans cette syntaxe, une \verb|<insertion>| peut être @@ -301,27 +314,29 @@ Il faut noter que dans cette syntaxe, une \verb|<insertion>| peut être \item un tuple auquel on accède par \verb|\tplexe| : «\verb|add{<index>:{\tplexe{<nom tuple>}}}|». \end{itemize} -En ce qui concerne les \verb|<index>| : +En ce qui concerne les \verb|<index>|, ils peuvent être compris entre $0$ et $n$ où $n$ est le nombre d'éléments du tuple. Les index négatifs entre $-n-1$ et $-1$ sont également permis : \begin{itemize} - \item si un \verb|<index>| est inférieur à 0, il est compris comme étant 0 ; - \item si un \verb|<index>| est «\verb|*|» ou supérieur à $n-1$, l'\verb|<insertion>| est placée à la fin du tuple passé en entrée ; - \item les \verb|<index>| \emph{ne sont pas} recalculés après chaque \verb|<insertion>|, mais seulement après la dernière. Il n'est donc pas équivalent d'écrire «\verb|.add{1:10,5:50}|» et «\verb|.add{1:10}.add{5:50}|. En effet, 5 sera à l'index 6 dans le premier cas alors qu'il sera à l'index 5 dans le second. + \item un \verb|<index>| égal à 0 ou à $-n-1$ place l'\verb|<insertion>| au début du tuple passé en entrée ; + \item un \verb|<index>| égal à $n$ ou $-1$ place l'\verb|<insertion>| à la fin du tuple ; + \item les \verb|<index>| \emph{ne sont pas} recalculés après chaque \verb|<insertion>|, mais seulement après la dernière. Il n'est donc pas équivalent d'écrire «\verb|.add{1:100,2:200}|» et «\verb|.add{1:100}.add{2:200}|». En effet, 200 sera à l'index 3 dans le premier cas alors qu'il sera à l'index 2 dans le second cas. \end{itemize} \exemple|%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% 1) ajout en 1er : \tplexe{nn.add{0:{666,667}}}\par -2) ajout index 16 : \tplexe{nn.add{16:{666,667}}}\par -3) ajout en dernier : \tplexe{nn.add{*:{666,667}}}| +2) ajout index 11 : \tplexe{nn.add{11:{666,667}}}\par +3) ajout en dernier : \tplexe{nn.add{-1:{666,667}}}| \exemple|\newtuple{X}{10,20,30,40,50,60}% \newtuple{Y}{1,2,3,4}% -1) \tplexe{X.add{-3:{\tplexe{Y}}}}\par -2) \tplexe{X.add{1:1000,3:{\tplexe{Y}}}}\par -3) \tplexe{X.add{1:1000}.add{3:{\tplexe{Y}}}}| +1) \tplexe{X.add{0:{\tplexe{Y}}}}\par +2) \tplexe{X.add{2:{\tplexe{Y}}}}\par +3) \tplexe{X.add{-1:{\tplexe{Y}}}}\par +4) \tplexe{X.add{1:100,2:200}}\par +5) \tplexe{X.add{1:100}.add{2:200}}| \subsection{La méthode \texttt{op}} -Cette méthode, qui effectue une \verb|<opération>| sur tous les éléments du tuple, a pour syntaxe +Cette méthode développable, qui effectue une \verb|<opération>| sur tous les éléments du tuple, a pour syntaxe \code|op{<opération>}| L'\verb|<opération>| est une expression ne contenant pas d'accolades, évaluable par \verb|\fpeval| une fois que toutes les occurrences de «\texttt{val}» aient été remplacées par la valeur de chaque élément, et toutes les occurrences de «\texttt{idx}» par son index. @@ -333,7 +348,7 @@ L'\verb|<opération>| est une expression ne contenant pas d'accolades, évaluabl 4) \tplexe{X.op{idx<4 ? val-1 : val+1 }}| \subsection{La méthode \texttt{filter}} -Cette méthode, qui sélectionne certains éléments selon un ou plusieurs critères, a pour syntaxe +Cette méthode développable, qui sélectionne certains éléments selon un ou plusieurs critères, a pour syntaxe \code|filter{<test>}| et où \verb|<test>| est un booléen ne contenant pas d'accolades, évaluable par \verb|\fpeval| une fois que toutes les occurrences de «\texttt{val}» aient été remplacées par la valeur de chaque élément, et toutes les occurrences de «\texttt{idx}» par son index. @@ -345,7 +360,7 @@ et où \verb|<test>| est un booléen ne contenant pas d'accolades, évaluable pa 4) \tplexe{nn.filter{val!=6.3 && val!=2.9 && val!=4.1}}/ \subsection{La méthode \texttt{comp}} -Cette méthode compose deux tuples de même longueur avec une opération que l'utilisateur spécifie. Sa syntaxe est +Cette méthode développable compose deux tuples de même longueur avec une opération que l'utilisateur spécifie. Sa syntaxe est \code|comp{<opération>}{<nom tuple>}| où le tuple dont le nom est passé en deuxième argument \emph{doit} avoir la même longueur que le tuple passé en entrée de la méthode. @@ -370,7 +385,7 @@ Cette méthode coupe le tuple passé en entré à la méthode après l'index sp \code|split{<index>}{<tuple1>}{<tuple2>}| Le tuple passé en entrée de la méthode est coupé après l'\verb|<index>| : la partie avant la coupure est assignée, via \verb|\newtuple| au tuple de nom «\texttt{tuple1}» et la partie restant au tuple de nom «\texttt{tuple2}». Aucune vérification n'est faite sur l'existence des 2 tuples ; il est donc possible de remplacer silencieusement des tuples existants. -L'\verb|<index>| doit se trouver entre 0 et $n-2$ où $n$ est le nombre d'éléments du tuple passé en entré. +L'\verb|<index>| doit se trouver entre 0 et $n-2$ s'il est positif ou entre $-n$ et $-2$ s'il est négatif, $n$ étant le nombre d'éléments du tuple passé en entré. \exemple/%\newtuple{nn}{12.7, 6.3, 11.7, 2.9, 5.5, 8.1, 4.3, 9.4, % 13.6, 2.9, 6.9, 11.2, 5.1, 7.7, 10.1, 3, 4.1}% @@ -417,7 +432,7 @@ ou\par \gentuple{\genrule (\i+1)*2 ; \while \i<10 }| Génération de 15 entiers aléatoires entre 1 et 10 : -\exemple|\gentuple{\genrule randint(1,10) ; \until \i=14 }| +\exemple|\gentuple{\genrule randint(1,10) ; \until \i=14}| Génération des carrés d'entiers jusqu'à 500 : \exemple|\gentuple{\genrule\i*\i; \while val<500 }| @@ -429,9 +444,7 @@ Génération des 10 premiers termes de $u_0=1$ ; $u_1=1$ ; $u_2=-1$ et $u_{n}=u_ \exemple|\gentuple{1,1,-1,\genrule\1*\3-\2*\2; \until \i=10}| Génération de la suite de Syracuse (connue aussi comme «suite $3n+1$») de 15 : -\exemple|\edef\syr{% - \gentuple{15,\genrule \1/2=trunc(\1/2) ? \1/2 : 3*\1+1 ; \until val=1}% -}% +\exemple|\gentuple{15,\genrule \1/2=trunc(\1/2) ? \1/2 : 3*\1+1 ; \until val=1}% \meaning\syr| Altitude maximale et longueur de la suite de Syracuse de 27 : @@ -442,8 +455,7 @@ alt max = \tplexe{syr27.max}| \section{Conclusion} \subsection{Motivation} -D'une façon un peu étonnante, assez peu de choses existent pour manipuler et opérer sur des listes de nombres\footnote{Il y a bien un package \texttt{commalists-tools}, mais il est clairement trop limité. Comme tous les packages de son auteur qui floode le CTAN, il ne fait qu'aligner \emph{ad nauseam}, linéairement et sans véritable programmation, les macros de haut niveau des packages \texttt{tikz}, \texttt{listofitems}, \texttt{xstring}, \texttt{xint} et \texttt{simplekv}.% Que pourrait-on conseiller à cet auteur ? De privilégier la qualité à la quantité ? Progresser en programmation et ne pas rester at vitam eternam à ce niveau basique affligeant et sans grand intérêt ? De penser à ce qu'il adviendrait (spoiler : le CTAN exploserait !) si tous les utilisteurs de \LaTeX{} se mettaient à pondre un package compulsivement chaque fois qu'ils ont réussi à combiner entre-elles des macros d'autres packages ? -}. +D'une façon un peu étonnante, assez peu de choses existent pour manipuler et opérer sur des listes de nombres\footnote{Il y a bien un package \texttt{commalists-tools}, mais il est clairement trop limité. Comme tous les packages de son auteur qui floode le CTAN, il ne fait qu'aligner \emph{ad nauseam}, linéairement et sans véritable programmation, les macros de haut niveau des packages \texttt{tikz}, \texttt{listofitems}, \texttt{xstring}, \texttt{xint} et \texttt{simplekv}.}. Le principal défi a surtout été d'offrir des macros développables et aussi une syntaxe originale dans le monde de \TeX{} du type \verb|<objet>.<méthode 1>.<méthode 2>...<méthode n>|, où l'on peut enchainer les méthodes exécutées sur un «objet» qui est un tuple de nombres. J'ignore si des packages proposent ce genre de syntaxe, mais elle est finalement assez intuitive. Comme je suis assez peu familier avec la programmation de macros purement développables, j'ai voulu de nombreuses fois renoncer. Mais j'ai fini par trouver un trou de souris qui permet que le tout fonctionne à peu près, à l'exception des nombreux bugs qui doivent encore se cacher un peu partout. @@ -455,17 +467,52 @@ Lorsqu'on met un pied dans l'optimisation de la vitesse d'exécution, surtout de J'espère ne pas être tombé dans ce piège, car j'y suis à peine entré. De toutes façons, \TeX{} n'est pas fait pour du calcul massif, car c'est avant tout un logiciel de composition. Pour le calcul, des outils performants qui battent \TeX{} à plate couture existent à foison. Quoiqu'il en soit, «macro développable» va un peu à l'encontre de «vitesse d'exécution». À titre d'information, je mets ci-dessous les temps de compilation, en secondes, de la création de tuples contenant $n$ entiers aléatoires. Cela dépend de l'ordinateur utilisé, bien sûr, mais les ordres de grandeur sont bien révélateurs. On voit clairement qu'il est illusoire de dépasser le millier de nombres car le temps de création d'un tuple croit ensuite rapidement\footnote{Sans compter que le tuple est immédiatement recréé et recalculé après avoir été modifié par les méthodes \texttt{set}, \texttt{add}, \texttt{op}, \texttt{filter}, \texttt{split} et \texttt{comp}}. Ceci dit, qui utiliserait \TeX{} pour des calculs sur autant de nombres ? + +Ce tableau illustre les vitesses de création d'un tuple d'entiers signés aléatoires compris entre $-1000$ et $1000$. Pour rappel la création d'un tuple suppose le tri de ses éléments (par tri rapide), le calcul de la somme des nombres et celui de la somme des carrés. Les 3 modes peuvent ainsi être comparés pour des tuples plus ou moins grands.\label{benchmark} + \begin{center} -\begin{tabular}{|c|c|}\hline - Nombre d'éléments $n$ & Durée de \verb|\newtuple| en s\\\hline - 50 & 0,011\\\hline - 100 & 0,026\\\hline - 500 & 0,224\\\hline - 1000 & 0,703\\\hline - 1500 & 1,727\\\hline - 2000 & 2,876\\\hline - 5000 & 22,907\\\hline -\end{tabular} + \directlua{pdfelapsedtimer_basetime=0} + \protected\def\pdfresettimer{\directlua{pdfelapsedtimer_basetime = os.clock()}} + \protected\def\pdfelapsedtime{\numexpr\directlua{tex.print(math.floor((os.clock()-pdfelapsedtimer_basetime)*65536+0.5))}\relax} + \catcode`\_11 + \def\doten#1{#1#1#1#1#1#1#1#1#1#1} + \def\falsenewtuple#1{} + \def\printtime{\fpeval{round((\the\pdfelapsedtime-\tare)/655360,3)} s} + \def\dotest#1{% + \tplsetmode{#1}% + \pdfresettimer% + \doten{\edef\test{\expandafter\tpl_newtuple_b\expandafter{\mytuple}}\let\mytest\empty}% + \printtime + } + \def\testnewtuple#1{% #1=nb éléments dans le tuple + \xdef\mytuple{\gentuple{\genrule randint(-1000,1000) ; \until \i==#1 }}% + \pdfresettimer + \doten{\edef\mytest{\expandafter\falsenewtuple\expandafter{\mytuple}}\let\mytest\empty}% + \xdef\tare{\the\pdfelapsedtime}% + #1% + &% + \dotest{int} + &% + \dotest{dec:short} + &% + \dotest{dec:long} + } + \def\gentab{% + \begin{center} + \begin{tabular}{|r|c|c|c|}\hline + Nb items&\texttt{int} & \texttt{dec:short} & \texttt{dec:long}\\\hline + \testnewtuple{25} \\\hline + \testnewtuple{50} \\\hline + \testnewtuple{100} \\\hline + \testnewtuple{200} \\\hline + \testnewtuple{400} \\\hline + \testnewtuple{800} \\\hline + \testnewtuple{1600}\\\hline + \end{tabular} + \end{center} + } + \catcode`\_8 + \gentab \end{center} \subsection{Exemple : population des états} @@ -480,13 +527,13 @@ Le tuple \verb|\Wpop| contient la population de chaque état dans le monde, en m 14.5, 2.2, 0.8, 11.9, 10.8, 10.0, 0.4, 1441.7, 279.8, 89.8, 46.5, 5.1, 9.3, 58.7, 2.8, 122.6, 11.4, 19.8, 56.2, 0.1, 4.3, 6.8, 7.7, 1.8, 5.2, 2.4, 5.5, 7.0, 2.7, 0.7, 31.1, 21.5, 34.7, 0.5, 24.0, 0.5, 0.4, 5.0, -1.3,129.4, 0.1, 3.5, 0.6, 38.2, 34.9, 55.0, 2.6, 31.2, 17.7, 0.3, 5.3, -7.1,28.2, 229.2, 2.1, 5.5, 4.7, 245.2, 4.5, 10.5, 6.9, 34.7, 119.1, -40.2,10.2, 3.3, 2.7, 51.7, 3.3, 1.0, 19.6, 144.0, 14.4, 0.0, 0.2, 0.1, -0.2,0.03, 0.2, 37.5, 18.2, 7.1, 0.1, 9.0, 6.1, 0.0, 5.7, 2.1, 0.8, 18.7, -61.0,11.3, 47.5, 21.9, 5.5, 49.4, 0.6, 10.7, 8.9, 24.3, 10.3, 71.9, 1.4, -9.3,0.1, 1.5, 12.6, 86.3, 6.6, 0.0, 0.0, 49.9, 37.9, 9.6, 68.0, 69.4, -341.8,0.1, 3.4, 35.7, 0.3, 29.4, 99.5, 0.6, 35.2, 21.1, 17.0} +1.3 ,129.4, 0.1, 3.5, 0.6, 38.2, 34.9, 55.0, 2.6, 31.2, 17.7, 0.3, 5.3, +7.1 ,28.2, 229.2, 2.1, 5.5, 4.7, 245.2, 4.5, 10.5, 6.9, 34.7, 119.1, +40.2 ,10.2, 3.3, 2.7, 51.7, 3.3, 1.0, 19.6, 144.0, 14.4, 0.0, 0.2, 0.1, +0.2 ,0.03, 0.2, 37.5, 18.2, 7.1, 0.1, 9.0, 6.1, 0.0, 5.7, 2.1, 0.8, 18.7, +61.0 ,11.3, 47.5, 21.9, 5.5, 49.4, 0.6, 10.7, 8.9, 24.3, 10.3, 71.9, 1.4, +9.3 ,0.1, 1.5, 12.6, 86.3, 6.6, 0.0, 0.0, 49.9, 37.9, 9.6, 68.0, 69.4, +341.8 ,0.1, 3.4, 35.7, 0.3, 29.4, 99.5, 0.6, 35.2, 21.1, 17.0} Nombre : \tplexe{\Wpop.len}\par Moyenne : \tplexe{\Wpop.mean}\par Médiane : \tplexe{\Wpop.med}\par @@ -503,13 +550,13 @@ Quintile \#4 : \tplexe{\Wpop.quantile{0.8}}/ 14.5, 2.2, 0.8, 11.9, 10.8, 10.0, 0.4, 1441.7, 279.8, 89.8, 46.5, 5.1, 9.3, 58.7, 2.8, 122.6, 11.4, 19.8, 56.2, 0.1, 4.3, 6.8, 7.7, 1.8, 5.2, 2.4, 5.5, 7.0, 2.7, 0.7, 31.1, 21.5, 34.7, 0.5, 24.0, 0.5, 0.4, 5.0, -1.3,129.4, 0.1, 3.5, 0.6, 38.2, 34.9, 55.0, 2.6, 31.2, 17.7, 0.3, 5.3, -7.1,28.2, 229.2, 2.1, 5.5, 4.7, 245.2, 4.5, 10.5, 6.9, 34.7, 119.1, -40.2,10.2, 3.3, 2.7, 51.7, 3.3, 1.0, 19.6, 144.0, 14.4, 0.0, 0.2, 0.1, -0.2,0.03, 0.2, 37.5, 18.2, 7.1, 0.1, 9.0, 6.1, 0.0, 5.7, 2.1, 0.8, 18.7, -61.0,11.3, 47.5, 21.9, 5.5, 49.4, 0.6, 10.7, 8.9, 24.3, 10.3, 71.9, 1.4, -9.3,0.1, 1.5, 12.6, 86.3, 6.6, 0.0, 0.0, 49.9, 37.9, 9.6, 68.0, 69.4, -341.8,0.1, 3.4, 35.7, 0.3, 29.4, 99.5, 0.6, 35.2, 21.1, 17.0} +1.3 ,129.4, 0.1, 3.5, 0.6, 38.2, 34.9, 55.0, 2.6, 31.2, 17.7, 0.3, 5.3, +7.1 ,28.2, 229.2, 2.1, 5.5, 4.7, 245.2, 4.5, 10.5, 6.9, 34.7, 119.1, +40.2 ,10.2, 3.3, 2.7, 51.7, 3.3, 1.0, 19.6, 144.0, 14.4, 0.0, 0.2, 0.1, +0.2 ,0.03, 0.2, 37.5, 18.2, 7.1, 0.1, 9.0, 6.1, 0.0, 5.7, 2.1, 0.8, 18.7, +61.0 ,11.3, 47.5, 21.9, 5.5, 49.4, 0.6, 10.7, 8.9, 24.3, 10.3, 71.9, 1.4, +9.3 ,0.1, 1.5, 12.6, 86.3, 6.6, 0.0, 0.0, 49.9, 37.9, 9.6, 68.0, 69.4, +341.8 ,0.1, 3.4, 35.7, 0.3, 29.4, 99.5, 0.6, 35.2, 21.1, 17.0} On modifie \verb|\Wpop|, en ne retenant que les états «moyennement» peuplés. On considère arbitrairement leur population entre 10 et 100 millions d'habitants : \exemple/\tplexe{\Wpop.filter{val>=10 && val<=100}.store\Wpop}% @@ -533,9 +580,8 @@ Répartition sur 6 intervalles égaux :\par \subsection{TODO list} À implémenter plus ou moins rapidement : \begin{enumerate} - \item permettre à l'utilisateur de choisir \texttt{l3fp} ou \texttt{xint} comme moteur de calcul ; \item utiliser le tri par insertion pour trier les tuples presque triés obtenus suite aux méthodes \texttt{add}, \texttt{set}, \texttt{op} (risqué car dépend de l'opération !) - \item utiliser le tri fusion pour ajouter un tuple à un autre ; + \item utiliser le tri fusion pour ajouter un tuple ou des nombres à un tuple ; \item autres optimisation de la rapidité ? \end{enumerate} \end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/tuple/tuple.tex b/Master/texmf-dist/tex/generic/tuple/tuple.tex index 7b182568239..ed8b345a140 100644 --- a/Master/texmf-dist/tex/generic/tuple/tuple.tex +++ b/Master/texmf-dist/tex/generic/tuple/tuple.tex @@ -4,9 +4,9 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \def\tplname {tuple} % -\def\tplversion {0.1} % +\def\tplversion {0.2} % % % -\def\tpldate {2024/11/16} % +\def\tpldate {2024/12/20} % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -82,9 +82,10 @@ }% \expandafter\tpl_foreach_a#2,\tpl_foreach_a,% 1-développer #2 au cas où... } -\tpl_e_after{\let\tplfpcompare}{\csname fp_compare:nNnTF\endcsname} -%%% indexage développable d'un tuple +%--------------- +% indexage développable d'un tuple +%--------------- \def\tpl_index_tuple#1{\tpl_index_tuple_a0#1,\relax,}% \def\tpl_index_tuple_a#1#2,{% TODO : le faire 8 par 8 ? \ifx\relax#2\else @@ -92,10 +93,214 @@ #1:#2,\tpl_e_second\tpl_index_tuple_a{\the\numexpr#1+1}% \fi% } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Choix options %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\tpl_testifstreq#1#2{% teste si #1=#2 + \tpl_stripsp{\def\tpl__tmpa}{#1}% + \tpl_stripsp{\def\tpl__tmpb}{#2}% + \tpl_testifx{\tpl__tmpa\tpl__tmpb} +} +\def\tplsetmode#1{% + \tpl_testifstreq{#1}{int} + {% + \tpl_set_mode_a#1:\_nil + } + {% + \tpl_ifddot{#1} + {\tpl_set_mode_a#1\_nil} + {\tpl_error{":" expected in "\detokenize{#1}"}}% + }% +} +\def\tpl_set_mode_a#1:#2\_nil{% + \let\tpl_expr_eval\fpeval + \tpl_testifstreq{#1}{int} + {% + \def\tplfpcompare##1##2##3{\ifnum##1##2##3 \tpl_exec_first\fi\tpl_exec_second}% + \def\tpl_item_add##1##2{\the\numexpr##1+##2\relax}% + \def\tpl_item_addsq##1##2{\the\numexpr##1+##2*##2\relax}% + } + {% + \tpl_testifstreq{#1}{dec} + {% + \tpl_testifstreq{#2}{long} + {% + \tpl_e_after{\let\tplfpcompare}{\csname fp_compare:nNnTF\endcsname}% + \def\tpl_item_add##1##2{\fpeval{##1+##2}}% + \def\tpl_item_addsq##1##2{\fpeval{##1+##2*##2}}% + } + {% + \tpl_testifstreq{#2}{short} + {% + \def\tplfpcompare##1##2##3{\ifdim##1pt##2##3pt \tpl_exec_first\fi\tpl_exec_second}% + \let\tpl_item_add\tpl_short_short_add + \def\tpl_item_addsq##1##2{\tpl_x_second\tpl_short_short_add{\tpl_short_mult{##2}{##2}}{##1}}% + }% + {% + \tpl_error{number 'short' or 'long' expected in '\detokenize{#1:#2}'}% + }% + }% + } + {% + \tpl_error{number "long" or "dec" expected in "\detokenize{#1:#2}"}% + }% + }% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Moteur rudimentaire de calcul %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Macros développables sur les +% décimaux courts "#8.#8" +\def\tpl_gob_zeros#1{% + \tpl_testifx{0#1} + \tpl_gob_zeros + {\tpl_testifx{\empty#1}0{#1}}% +} +\def\tpl_split_iv_iv#1{\tpl_split_iv_iv_a#1{}{}{}{}{}{}{}{}{}\_nil}% coupe le nombre #1 en 2 nombres de 4 chiffres +\def\tpl_esplit_iv_iv#1{\expandafter\tpl_split_iv_iv_a#1{}{}{}{}{}{}{}{}{}\_nil}% coupe le nombre #1 en 2 nombres de 4 chiffres +\def\tpl_split_iv_iv_a#1#2#3#4#5#6#7#8#9{\tpl_split_iv_iv_b#9#8#7#6#5#4#3#2#1000000000} +\def\tpl_split_iv_iv_b#1#2#3#4#5#6#7#8#9{{#9#8#7#6#5}{#4#3#2#1}\tpl_gobtonil} + +\def\tpl_pack_iv_iv#1{\tpl_pack_iv_iv_a#100000000\_nil} +\def\tpl_pack_iv_iv_a#1#2#3#4#5#6#7#8{{#1#2#3#4}{#5#6#7#8}\tpl_gobtonil} +%--------------- +% multiplication #8.#8 * #8*#8 -> #16.#8 +%--------------- +\def\tpl_ifdot#1#2#3{\tpl_ifdot_a#1\_YN{#2}\mark_dot.\_YN{#3}\mark_dot\_nil}% #1 contient-il "." ? #2=T #3=F +\def\tpl_ifdot_a#1.#2\_YN#3\mark_dot#4\_nil{#3}% + +\def\tpl_hi#1{\expandafter\tpl_hi_a\the\numexpr#1\relax{}{}{}{}{}{}{}{}{}\_nil} +\def\tpl_hi_a#1#2#3#4#5#6#7#8#9{\tpl_hi_b#9#8#7#6#5#4#3#2#1000000000} +\def\tpl_hi_b#1#2#3#4#5#6#7#8#9{#9#8#7#6#5\tpl_gobtonil} + +\def\tpl_pack_hi_unpack_lo#1#2{\expandafter\tpl_pack_hi_unpack_lo_a\the\numexpr#2\relax{}{}{}{}{}{}{}{}{}\_nil{#1}} +\def\tpl_pack_hi_unpack_lo_a#1#2#3#4#5#6#7#8#9{\tpl_pack_hi_unpack_lo_b#9#8#7#6#5#4#3#2#1000000000} +\def\tpl_pack_hi_unpack_lo_b#1#2#3#4#5#6#7#8#9{\tpl_pack_hi_unpack_lo_c{#9#8#7#6#5}{#4#3#2#1}} +\def\tpl_pack_hi_unpack_lo_c#1#2#3\_nil#4{#4{#1}#2} + +\def\tpl_short_mult#1#2{% #1=a,b #2=c,d (a,b,c,d 8 chiffres max chacun) + \tpl_short_mult_a#1\relax#2\relax +} +\def\tpl_short_mult_a#1#2\relax#3#4\relax{% + \tpl_x_after\tpl_short_mult_b{\unless\ifx-#1+\fi#1#2\relax\unless\ifx-#3+\fi#3#4\relax}% +} +\def\tpl_short_mult_b#1#2\relax#3#4\relax{% + \unless\ifx#1#3-\fi + \tpl_x_after\tpl_short_mult_c{0#2\tpl_ifdot{#2}{}{.0}\relax0#4\tpl_ifdot{#4}{}{.0}\relax}% +} +\def\tpl_short_mult_c#1.#2\relax#3.#4\relax{% #1=hi(a) + \tpl_x_after\tpl_short_mult_d{\tpl_split_iv_iv{#1}\tpl_pack_iv_iv{#2}\tpl_split_iv_iv{#3}\tpl_pack_iv_iv{#4}}% +} +\def\tpl_short_mult_d#1#2#3#4#5#6#7#8{% #1=a1 #2=a0 . #3=b1 #4=b0 +% * #5=c1 #6=c0 . #7=d1 #8=d0 + \tpl_pack_hi_unpack_lo{\tpl_short_mult_e{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}{% + #8*#2+#3*#7+#6*#4+\tpl_hi{#8*#3+#7*#4+\tpl_hi{#4*#8}}% d0a0 + d1b1 +c0b0 + hi(d0b1 + d1b0 + hi(b0d0)) + }% +} +\def\tpl_short_mult_e#1#2#3#4#5#6#7#8#9{% #1=a1 #2=a0 . #3=b1 #4=b0 * #5=c1 #6=c0 . #7=d1 #8=d0 #9=retenue pour rang suivan + \tpl_pack_hi_unpack_lo{\tpl_short_mult_f{#1}{#2}{#3}{#5}{#6}{#7}}{#9+#8*#1+#7*#2+#6*#3+#5*#4}% d0a1+d1a0+c0b1+c1b0 +} +\def\tpl_short_mult_f#1#2#3#4#5#6#7{% #1=a1 #2=a0 #3=b1 #4=c1 #5=c0 #6=d1 #7=retenue + \tpl_pack_hi_unpack_lo{\tpl_short_mult_g{#1}{#2}{#4}{#5}}{#7+#1*#6+#2*#5+#3*#4}.% d1a1+c0a0+c1b1% +} +\def\tpl_short_mult_g#1#2#3#4#5{% #1=a1 #2=a0 #3=c1 #4=c0 #5=retenue + \tpl_pack_hi_unpack_lo{\tpl_short_mult_h{#1}{#3}}{#5+#1*#4+#2*#3}% +} +\def\tpl_short_mult_h#1#2#3{\expandafter\tpl_gob_zeros\the\numexpr#1*#2+#3\relax} +%--------------- +% addition #16.#8 + #16.#8 -> #16.#8 (décimaux non signés) +%--------------- +\def\tpl_split_viii_viii#1{\tpl_split_viii_viii_a#1{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}\_nil} +\def\tpl_split_viii_viii_a#1#2#3#4#5#6#7#8{\tpl_split_viii_viii_b{#8#7#6#5#4#3#2#1}} +\def\tpl_split_viii_viii_b#1#2#3#4#5#6#7#8#9{\tpl_split_viii_viii_c#9#8#7#6#5#4#3#2#100000000000000000} +\def\tpl_split_viii_viii_c#1#2#3#4#5#6#7#8{\tpl_split_viii_viii_d{#8#7#6#5#4#3#2#1}} +\def\tpl_split_viii_viii_d#1#2#3#4#5#6#7#8#9{{#9#8#7#6#5#4#3#2}{#1}\tpl_gobtonil} + +\def\tpl_decpart_format_viii#1{\tpl_decpart_format_viii_a#100000000\_nil} +\def\tpl_decpart_format_viii_a#1#2#3#4#5#6#7#8{#1#2#3#4#5#6#7#8\tpl_gobtonil} +\def\tpl_shortadd#1#2{% #1=décimal ou entier ; #2 de la forme 'x.y' + \tpl_x_after{\tpl_shortadd_a#1}{\tpl_ifdot{#1}{}{.0}}\relax#2\relax +} +\def\tpl_shortadd_a#1.#2\relax#3.#4\relax{% a.b + c.d + \tpl_x_after\tpl_shortadd_b{\tpl_split_viii_viii{#1}\tpl_split_viii_viii{#3}{\the\numexpr\tpl_decpart_format_viii{#2}+\tpl_decpart_format_viii{#4}\relax}}% +} +\def\tpl_shortadd_b#1#2#3#4#5{% #1=hi8(a) #2=lo8(a) #3=hi8(c) #4=lo8(c) #5=b+c + \tpl_x_after{\tpl_shortadd_c{#1}{#3}}{\the\numexpr#2+#4\tpl_testifnum{#5>99999999 }{+1\relax!.\tpl_gobone}{\relax!.}#5}% +} +\def\tpl_shortadd_c#1#2#3!{% #1=hi8(a) #2=hi8(c) #3=lo8(a)+lo8(c)+retenue + \the\numexpr#1+#2\tpl_testifnum{#3>99999999 }{+1\relax\tpl_gobone}{\relax}#3% +} +%--------------- +% addition entiers signés <signe>#8.#8 +%--------------- +\def\tpl_intpart_format#1{% + \tpl_ifempty{#1}{+0}{\tpl_intpart_format_a#1\_nil}% +} +\def\tpl_intpart_format_a#1#2\_nil{% + \ifx#1--\tpl_ifempty{#2}0{}% + \else + \ifx#1++\tpl_ifempty{#2}0{}% + \else+#1% + \fi + \fi#2% +} +\def\tpl_short_short_add#1#2{% a.b + c.d + \tpl_x_after\tpl_short_short_add_a{#1\tpl_ifdot{#1}{}{.0}\relax#2\tpl_ifdot{#2}{}{.0}\relax}% +} +\def\tpl_short_short_add_a#1.#2\relax#3.#4\relax{% + \tpl_x_after\tpl_short_short_add_b{% + \tpl_intpart_format{#1}.\tpl_decpart_format_viii{#2}\relax + \tpl_intpart_format{#3}.\tpl_decpart_format_viii{#4}\relax% + }% +} +\def\tpl_short_short_add_b#1#2.#3\relax#4#5.#6\relax{% #1=+/- #2.#3 "+" #4=+/- #5.#6 + \tpl_testifx{#1#4}% mêmes signes ? + {% + \ifx-#1-\fi% afficher le signe - + \tpl_e_second\tpl_short_short_add_c{\the\numexpr#3+#6}{#2}{#5}% + } + {% signes différents + \tpl_x_after\tpl_short_short_add_d{\the\numexpr#1#2#4#5\relax.\the\numexpr#1#3#4#6\relax}\_nil + }% +} +\def\tpl_short_short_add_c#1#2#3{% relatifs de mêmes signes : #1=somme (dec part) #2=intpart(a) #3=intpart(b) + \the\numexpr#2+#3\ifnum#1>99999999 +1\fi.\tpl_decpart_format{#1}% +} +\def\tpl_short_short_add_d#1.#2\_nil{% + \tpl_x_after\tpl_short_short_add_e{\unless\ifnum#1<0 +\fi#1.\unless\ifnum#2<0 +\fi}#2\_nil +} +\def\tpl_short_short_add_e#1#2.#3#4\_nil{%résultat : #1=signe #2=intpart #3=signe #4=decpart + \ifx#1#3% memes signes + \the\numexpr#1#2\relax.\expandafter\tpl_gobone\the\numexpr#4+100000000\relax% + \else + \ifnum#2=0 + #30.\tpl_decpart_format{#4}% prendre le signe de decpart + \else + \ifnum#4=0 + #1#2% + \else + \tpl_x_after\tpl_short_short_add_f{\the\numexpr#1#2#31\relax.\expandafter\tpl_abs\the\numexpr#3#4#1100000000\relax}\_nil{#1}% + \fi + \fi + \fi +} +\def\tpl_short_short_add_f#1.#2\_nil#3{% #1=intpart final #2=decpart final #3=signe intpart + \ifnum#1=0 #3\fi#1.\tpl_decpart_format{#2}% +} +\def\tpl_abs#1{\unless\ifx-#1#1\fi} +\def\tpl_decpart_format#1{\expandafter\tpl_decpart_format_a\the\numexpr100000000+#1\relax\_nil} +\def\tpl_decpart_format_a#1#2#3#4#5#6#7#8#9{\expandafter\tpl_decpart_format_b\the\numexpr#9#8#7#6#5#4#3#2\relax{}{}{}{}{}{}{}{}{}} +\def\tpl_decpart_format_b#1#2#3#4#5#6#7#8{#8#7#6#5#4#3#2#1\tpl_gobtonil} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Quicksort développable %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Effectue un quicksort en indexant en même temps les éléments sos la forme "idx:val" +%--------------- +% Effectue un quicksort en indexant en +% même temps les éléments sous la forme "idx:val" +%--------------- \def\tpl_quicksort_and_index#1{\tpl_quicksort_and_index_a0;{#1}?}% #1= tuple finissant par "," \def\tpl_quicksort_and_index_a#1;#2{\tpl_quicksort_and_index_b{#1}#2!,}% #1=index de départ #2= tuple finissant par "," \def\tpl_quicksort_and_index_b#1#2,{% @@ -155,8 +360,9 @@ \def\tpl_reverse#1{\tpl_reverse_a#1{}{}{}{}{}{}{}{}{}\_nil} \def\tpl_reverse_a#1#2#3#4#5#6#7#8#9{#9#8#7#6#5#4#3#2#1\tpl_gobtonil} - -% getitem +%--------------- +% getitem (développable) +%--------------- \def\tpl_getitem#1#2{% #1=index #2=tuple \tpl_x_after\tpl_getitem_a{\tpl_reverse{#1}}\relax#2\_nil% #2=tuple (finissant par ",") } @@ -173,8 +379,9 @@ {} {\expanded{\unexpanded{\tpl_getitem_c#2\_nil}\expandafter\expandafter\expandafter}}#1% } - -%%% set item +%--------------- +% set item (développable) +%-------------- \def\tpl_setitem#1#2#3{% #1=index #2=valeur #3=tuple \tpl_x_after\tpl_setitem_a{{#2}\tpl_reverse{#1}}\relax#3% #3=tuple (finissant par ",") } @@ -186,8 +393,9 @@ {#1\_nil} {\tpl_e_second\tpl_setitem_b{\csname passto_#3#2\endcsname#1}{#20}}% } - -%%% split at index +%--------------- +% split at index (développable) +%-------------- \def\tpl_split#1#2{% #1=index #2=tuple -> coupe avec "?" le tuple après l'index #1 et renvoie 'tuple1?tuple2' \tpl_x_after\tpl_split_a{\tpl_reverse{#1}}\relax#2% #2=tuple (finissant par ",") } @@ -212,41 +420,41 @@ {\tpl_csedef{tpl_tuple(#1)}{\tpl_e_second\tpl_newtuple_b{\detokenize\expandafter{\expanded{#2}}}}}% }% } -% Développable, renvoie : (len,sum,sum:x^2,min,max){tuple indexé}{tuple ordonné indexé} +%--------------- +% \tpl_newtuple_b est développable et renvoie : +% (len,sum,sumsq){tuple indexé}{tuple ordonné indexé} +%-------------- \def\tpl_newtuple_b#1{% \tpl_ifempty{#1} - {(0,0,0,nan,nan){}{}}% TODO : mettre un warning ? + {(0,0,0,nan,nan){}{}} {\tpl_newtuple_c(0,0,0){}{}#1,\relax,}% } \def\tpl_newtuple_c(#1,#2,#3)#4#5#6,{% #1=index courant #2=sum #3=sumsq #4=éléments lus indexés #5=éléments lus désindexés #6=élément courant \tpl_testifx{\relax#6}% fin atteinte -> trouver min, max et renvoyer le tout "(len,sum,sum:x^2,min,max){tuple indexé}{tuple ordonné indexé}" - {\tpl_x_after{\tpl_newtuple_ca(#1,#2,#3){#4}}{\tpl_e_second\tpl_quicksort_and_index{\tpl_gobone#5,}}\relax}% manger ',' qui commence #5 + {\tpl_x_second{(#1,#2,#3){#4}}{\tpl_e_second\tpl_quicksort_and_index{\tpl_gobone#5,}}}% manger ',' qui commence #5 {\tpl_stripsp\tpl_newtuple_d{#6}(#1,#2,#3){#4}{#5}}% } -\def\tpl_newtuple_ca(#1,#2,#3)#40:#5,#6\relax{% - (#1,#2,#3,#5,\tpl_e_second\tpl_getitem{\the\numexpr#1-1}{0:#5,#6}){#4}{0:#5,#6}% -} \def\tpl_newtuple_d#1{% #1=item en cours \tpl_ifempty{#1} {% \tpl_newtuple_c } {% - \tpl_ifdot{#1}% si ":" est contenu dans #1, c'est indexé + \tpl_ifddot{#1}% si ":" est contenu dans #1, c'est indexé {\tpl_newtuple_f#1\_nil}% traiter ce qui est après ":" {\tpl_newtuple_e{#1}}% }% } \def\tpl_newtuple_e#1(#2,#3,#4)#5#6{% #1=item en cours #2=index courant #3=sum #4=sumsq #5=éléments déjà triés #6=elements non indexés - \tpl_x_after\tpl_newtuple_c{(\the\numexpr#2+1,\fpeval{#3+#1},\fpeval{#4+#1*#1})}{#5#2:#1,}{#6,#1}% + \tpl_x_after\tpl_newtuple_c{(\the\numexpr#2+1,\tpl_item_add{#3}{#1},\tpl_item_addsq{#4}{#1})}{#5#2:#1,}{#6,#1}% } \def\tpl_newtuple_f#1:#2\_nil{% \tpl_ifempty{#2} {\tpl_newtuple_c} {\tpl_newtuple_e{#2}}% } -\def\tpl_ifdot#1#2#3{\tpl_ifdot_a#1\_YN{#2}\mark_ddot:\_YN{#3}\mark_ddot\_nil}% #1 contient-il ":" ? #2=T #3=F -\def\tpl_ifdot_a#1:#2\_YN#3\mark_ddot#4\_nil{#3}% +\def\tpl_ifddot#1#2#3{\tpl_ifddot_a#1\_YN{#2}\mark_ddot:\_YN{#3}\mark_ddot\_nil}% #1 contient-il ":" ? #2=T #3=F +\def\tpl_ifddot_a#1:#2\_YN#3\mark_ddot#4\_nil{#3}% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Les méthodes %%% @@ -254,9 +462,10 @@ \def\tpl_error_only_for_tuples #1{\tpl_error_inmethod{Method '#1' only available for tuples}} \def\tpl_error_no_argument #1#2{\tpl_error_inmethod{Method '#1' does not accept argument '\detokenize{#2}'}} \def\tpl_error_argument_required#1{\tpl_error_inmethod{Method '#1' requires an argument}} -%------------------- -% Méthode len -%------------------- +\def\tpl_error_empty_tuple#1{\tpl_error_inmethod{Method '#1' not compatible with an empty tuple}} +%--------------- +% Méthode len (développable) +%-------------- \def\tpl_method_len#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -269,10 +478,9 @@ }% } \def\tpl_method_len_a(#1,#2\_nil{{#1}{0}}% renvoie un nombre - -%------------------- -% Méthode sum -%------------------- +%--------------- +% Méthode sum (développable) +%-------------- \def\tpl_method_sum#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -285,10 +493,9 @@ }% } \def\tpl_method_sum_a(#1,#2,#3\_nil{{#2}{0}}% renvoie un nombre - -%------------------- -% Méthode min -%------------------- +%--------------- +% Méthode min (développable) +%--------------- \def\tpl_method_min#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -300,11 +507,15 @@ \tpl_error_no_argument{min}{#1}%% }% } -\def\tpl_method_min_a(#1,#2,#3,#4,#5\_nil{{#4}{0}}% renvoie un nombre - -%------------------- -% Méthode max -%------------------- +\def\tpl_method_min_a#1)#2#3\_nil{% + \tpl_ifempty{#3} + {\tpl_error_empty_tuple{min}} + {\tpl_method_min_b#3\_nil}% +} +\def\tpl_method_min_b0:#1,#2\_nil{{#1}{0}}% renvoie un nombre +%--------------- +% Méthode max (développable) +%--------------- \def\tpl_method_max#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -313,14 +524,17 @@ {\tpl_method_max_a#2\_nil}% } {% - \tpl_error_no_argument{max}{#1}%% + \tpl_error_no_argument{max}{#1}% }% } -\def\tpl_method_max_a(#1,#2,#3,#4,#5)#6\_nil{{#5}{0}}% renvoie un nombre - -%------------------- -% Méthode mean -%------------------- +\def\tpl_method_max_a(#1,#2)#3#4\_nil{% + \tpl_ifempty{#4} + {\tpl_error_empty_tuple{max}} + {{\tpl_e_second\tpl_getitem{\the\numexpr#1-1}{#4}}{0}}% renvoie un nombre +} +%--------------- +% Méthode mean (développable) +%--------------- \def\tpl_method_mean#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -332,15 +546,14 @@ \tpl_error_no_argument{mean}{#1}%% }% } -\def\tpl_method_mean_a(#1,#2,#3\_nil{ +\def\tpl_method_mean_a(#1,#2,#3\_nil{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_testifnum{#1=0 } - {\tpl_error_inmethod{Method 'mean' invalid for an empty tuple}} - {{\fpeval{#2/#1}}{0}}% renvoie un nombre + {\tpl_error_empty_tuple{mean}} + {{\tpl_expr_eval{#2/#1}}{0}}% renvoie un nombre }% - -%------------------- -% Méthode med -%------------------- +%--------------- +% Méthode med (développable) +%--------------- \def\tpl_method_med#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -354,13 +567,12 @@ } \def\tpl_method_med_a(#1,#2)#3#4\_nil{% \tpl_testifnum{#1=0 } - {\tpl_error_inmethod{Method 'med' invalid for an empty tuple}} + {\tpl_error_empty_tuple{med}} {\tpl_method_quantile_a0.5\_nil(#1,#2){#3}{#4}\_nil}% renvoie un nombre } - -%------------------- -% Méthode quantile -%------------------- +%--------------- +% Méthode quantile (développable) +%--------------- \def\tpl_method_quantile#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -380,12 +592,12 @@ } \def\tpl_method_quantile_a#1\_nil(#2,#3)#4#5\_nil{% \tpl_testifnum{#2=0 } - {\tpl_error_inmethod{Method 'quantile' invalid for an empty tuple}} - {\tpl_x_after\tpl_method_quantile_b{{\fpeval{(#2-1)*#1+1}}{\fpeval{trunc((#2-1)*#1+1)}}}{#5}}% renvoie un nombre + {\tpl_error_empty_tuple{quantile}} + {\tpl_x_after\tpl_method_quantile_b{{\tpl_expr_eval{(#2-1)*#1+1}}{\tpl_expr_eval{trunc((#2-1)*#1+1)}}}{#5}}% renvoie un nombre } \def\tpl_method_quantile_b#1#2#3{% #1=(len-1)*p+1 #2=E(#1) #3=tuple trié {% - \fpeval{% interpolation linéaire + \tpl_expr_eval{% interpolation linéaire (1-#1+#2)*\tpl_e_second\tpl_getitem{\the\numexpr#2-1\relax}{#3}% +% (#1-#2)*\tpl_getitem{#2}{#3}% @@ -393,10 +605,9 @@ }% {0}% } - -%------------------- -% Méthode stdev -%------------------- +%--------------- +% Méthode stdev (développable) +%--------------- \def\tpl_method_stdev#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -408,15 +619,14 @@ \tpl_error_no_argument{stdev}{#1}%% }% } -\def\tpl_method_stdev_a(#1,#2,#3,#4\_nil{% +\def\tpl_method_stdev_a(#1,#2,#3)#4\_nil{% \tpl_testifnum{#1=0 } - {\tpl_error_inmethod{Method 'stdev' invalid for an empty tuple}} - {{\fpeval{sqrt(#3/#1-(#2/#1)**2)}}{0}}% renvoie un nombre + {\tpl_error_empty_tuple{stdev}} + {{\tpl_expr_eval{sqrt(#3/#1-(#2/#1)**2)}}{0}}% renvoie un nombre } - -%------------------- -% Méthode get -%------------------- +%--------------- +% Méthode get (développable) +%--------------- \def\tpl_method_get#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -431,18 +641,23 @@ \def\tpl_method_get_a#1(#2,#3)#4#5\_nil{% \tpl_testifnum{#2=0 } {% - \tpl_error_inmethod{Method 'get' invalid for an empty tuple}% + \tpl_error_empty_tuple{get}% } {% \tpl_testifnum{0\ifnum#1>-1 1\fi\ifnum#1<#2 1\fi=11 }% si index dans [0 ; len -1] - {{\tpl_getitem{#1}{#4}}{0}} - {\tpl_error_inmethod{Method 'get': invalid index '\detokenize{#1}'}}% + {% + {\tpl_getitem{#1}{#4}}{0}% + } + {% + \tpl_testifnum{0\ifnum#1<0 1\fi\ifnum\numexpr#1+#2+1>0 1\fi=11 }% si index dans [-len ; -1] + {{\tpl_e_second\tpl_getitem{\the\numexpr#1+#2\relax}{#4}}{0}} + {\tpl_error_inmethod{Method 'get': invalid index '\detokenize{#1}'}}% + }% }% } - -%------------------- -% Méthode set -%------------------- +%--------------- +% Méthode set (développable) +%--------------- \def\tpl_method_set#1#2#3{% #1=arg méthode ("index1:val1,index2:val2, etc") #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -465,15 +680,20 @@ } {% \tpl_testifnum{0\ifnum#3>-1 1\fi\ifnum#3<#2 1\fi=11 }% si index dans [0 ; len-1] - {\tpl_x_second\tpl_method_set_b{\tpl_setitem{#3}{#4}{#1}}{#2}}% - {\tpl_error_inmethod{Method 'set': invalid index '#3'}\tpl_gobtonil}% + {% + \tpl_x_second\tpl_method_set_b{\tpl_setitem{#3}{#4}{#1}}{#2}% + }% + {% + \tpl_testifnum{0\ifnum#3<0 1\fi\ifnum\numexpr#3+#2+1>0 1\fi=11 }% si index dans [-len ; -1] + {\tpl_x_second\tpl_method_set_b{\tpl_e_second\tpl_setitem{\the\numexpr#3+#2}{#4}{#1}}{#2}} + {\tpl_error_inmethod{Method 'set': invalid index '#3'}\tpl_gobtonil}% + }% }% } - -%------------------- -% Méthode sorted -%------------------- -\def\tpl_method_sorted#1#2#3{% #1=tuple #2=len #3=index courant #4=valeur courante +%--------------- +% Méthode sorted (développable) +%--------------- +\def\tpl_method_sorted#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% \tpl_testifnum{#3<1 } @@ -487,10 +707,9 @@ \def\tpl_method_sorted_a(#1)#2#3\_nil{% {(#1){\tpl_ifempty{#3}{#2}{#3}}{}}{1}% } - -%------------------- -% Méthode store -%------------------- +%--------------- +% Méthode store (_NON_ développable) +%--------------- \def\tpl_ifcs#1{% #1 est-il constitué d'une seule séquence de contrôle ? \tpl_testifnum{\tpl_ifempty{#1}0{\tpl_e_second\tpl_ifempty{\tpl_gobone#1}10}\ifnum\expandafter\expandafter\expandafter`\expandafter\tpl_firsttonil\string#1.\_nil=\escapechar1\fi=11 }% } @@ -516,10 +735,9 @@ {\tpl_error_inmethod{Method 'store': impossible to define a tuple with an empty name}} {{\noexpand\tpl_csedef{tpl_tuple(\tpl_stripsp\detokenize{#1})}{\tpl_e_second\tpl_newtuple_b{\detokenize\expandafter{\expanded{#4}}}}}{-1}}% bypass \newtuple pour permettre de modifier le tuple initial } - -%------------------- -% Méthode split -%------------------- +%--------------- +% Méthode split (_NON_ développable) +%--------------- \def\tpl_method_split#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes \tpl_ifempty{#1} {% @@ -535,23 +753,23 @@ \def\tpl_method_split_a#1#2#3\_nil(#4,#5)#6#7\_nil{% #1=index de coupure #2=nom tuple 1 #3=nom tuple2 \tpl_testifnum{#4=0 } {% - \tpl_error_inmethod{Method 'split' invalid for an empty tuple}% + \tpl_error_empty_tuple{split}% } {% - \tpl_testifnum{0\ifnum#1>-1 1\fi\ifnum#1<\numexpr#4-1\relax1\fi=11 }% si #1 dans [0;len-2] + \tpl_testifnum{\tpl_ifempty{#2}01\tpl_ifempty{#3}01=11 }% si les deux noms ne sont pas vide {% - \tpl_testifnum{\tpl_ifempty{#2}01\tpl_ifempty{#3}01=11 }% si les deux noms ne sont pas vide + \tpl_testifnum{0\ifnum#1>-1 1\fi\ifnum#1<\numexpr#4-1\relax1\fi=11 }% si #1 dans [0;len-2] {% - \tpl_testifnum{#4=0 } - {\tpl_error_inmethod{Method 'split' invalid for an empty tuple}} - {\tpl_x_after\tpl_method_split_b{\tpl_split{#1}{#6}}?{#2}{#3}}% + \tpl_x_after\tpl_method_split_b{\tpl_split{#1}{#6}}?{#2}{#3}% } {% - \tpl_error_inmethod{Method 'split': empty name not allowed}% + \tpl_testifnum{0\ifnum#1<-1 1\fi\ifnum\numexpr#1+#4+1>0 1\fi=11 }% si #1 dans [-len ; -2] + {\tpl_x_after\tpl_method_split_b{\tpl_e_second\tpl_split{\the\numexpr#1+#4}{#6}}?{#2}{#3}} + {\tpl_error_inmethod{Method 'split': invalid index '#1"}}% }% } {% - \tpl_error_inmethod{Method 'split': invalid index '#1"}% + \tpl_error_inmethod{Method 'split': empty name not allowed}% }% }% } @@ -562,14 +780,9 @@ }% {-1}% } - -%------------------- -% Méthode add -%------------------- -%Les index peuvent être : -% "*" ou un entier >=len -> ajouter en dernier -% 0 ou moins -> ajouter en premier -% sinon, ajouter pour le que le 1er item ajouté ait l'index spécifié +%--------------- +% Méthode add (développable) +%--------------- \def\tpl_method_add#1#2#3{% #1=arg méthode (index1:items,index2:items,...) #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -582,36 +795,55 @@ }% } \def\tpl_method_add_a#1\_nil(#2,#3)#4#5\_nil{% #2=len - \tpl_method_add_b{#4}{#2}#1,\relax:\relax,% + \tpl_method_add_b{#4}{#2}#1,\relax:\relax,\_nil } + \def\tpl_method_add_b#1#2#3:#4,{% #1=tuple #2=len #3=index courant #4=item(s) \tpl_testifx{\relax#3} {% {\tpl_newtuple_b{#1}}{1}% + \tpl_gobtonil } {% - \tpl_testifnum{0\if*\tpl_firsttonil#3*\_nil1\else\ifnum#3<#2 \else1\fi\fi>0 }% TODO "#3*" est gentil. Mieux : "#30" ? + \tpl_testifnum{#3<0 } + {% + \tpl_testifnum{\numexpr#3+#2+2>0 }% si index dans [-n-1 ; -1] + {\tpl_x_second{\tpl_method_add_c{#1}{#2}}{\the\numexpr#3+#2+1}{#4}}% + {\tpl_error_inmethod{Method 'add': invalid index '\detokenize{#3:#4}'}\tpl_gobtonil}% + } {% - \tpl_method_add_b{#1#4,}{#2}% si #1='*' ou #1>=len : ajouter #4 à la fin + \tpl_method_add_c{#1}{#2}{#3}{#4}% }% + }% +} +\def\tpl_method_add_c#1#2#3#4{% #1=tuple #2=len #3=index courant #4=item(s) + \tpl_testifnum{#3=0 } + {% + \tpl_method_add_b{#4,#1}{#2}% si index=0 : ajouter au début + } + {% + \tpl_testifnum{#3=#2 } + {% + \tpl_method_add_b{#1#4,}{#2}% si index=len : ajouter #4 à la fin + } {% - \tpl_testifnum{#3<1 }% TODO "#3<1 " est gentil. Mieux : "#3=0 " ? - {\tpl_method_add_b{#4,#1}{#2}} - {\tpl_x_after\tpl_method_add_c{\expandafter\tpl_split\expandafter{\the\numexpr#3-1}{#1}}?{#4}{#2}}% + \tpl_testifnum{0\ifnum#3>0 1\fi\ifnum#3<#2 1\fi=11 }% si index dans [1 ; len-1] + {\tpl_x_after\tpl_method_add_d{\expandafter\tpl_split\expandafter{\the\numexpr#3-1}{#1}}?{#4}{#2}} + {\tpl_error_inmethod{Method 'add': invalid index '\detokenize{#3:#4}'}\tpl_gobtonil}% }% }% } -\def\tpl_method_add_c#1?#2?#3#4{%#1=tuple 1 #2=tuple 2 #3=items à insérer #4=len + +\def\tpl_method_add_d#1?#2?#3#4{%#1=tuple 1 #2=tuple 2 #3=items à insérer #4=len \tpl_method_add_b{#1#3,#2}{#4}% } - -%------------------- -% Méthode op -%------------------- -\def\tpl_fpeval_op#1#2{\tpl_subst_idx_a#1\?{\tpl_subst_idx_b#1\_nil{#2}}\_markit idx\?{\tpl_subst_val{#1}}\_markit\_nil} +%--------------- +% Méthode op (développable) +%--------------- +\def\tpl_eval_op#1#2{\tpl_subst_idx_a#1\?{\tpl_subst_idx_b#1\_nil{#2}}\_markit idx\?{\tpl_subst_val{#1}}\_markit\_nil} \def\tpl_subst_idx_a#1idx#2\?#3\_markit#4\_nil{#3}% -\def\tpl_subst_idx_b#1idx#2\_nil#3{\tpl_fpeval_op{#1#3#2}{#3}} -\def\tpl_subst_val#1#2{\tpl_subst_val_a#1\?{\tpl_subst_val_b#1\_nil{#2}}\_markit val\?{\fpeval{#1}}\_markit\_nil} +\def\tpl_subst_idx_b#1idx#2\_nil#3{\tpl_eval_op{#1#3#2}{#3}} +\def\tpl_subst_val#1#2{\tpl_subst_val_a#1\?{\tpl_subst_val_b#1\_nil{#2}}\_markit val\?{\tpl_expr_eval{#1}}\_markit\_nil} \def\tpl_subst_val_a#1val#2\?#3\_markit#4\_nil{#3}% \def\tpl_subst_val_b#1val#2\_nil#3{\tpl_subst_val{#1#3#2}{#3}} \def\tpl_method_op#1#2#3{% #1=arg méthode f(idx, val) #2=résultat méthodes précédentes #3=flag @@ -631,12 +863,11 @@ \def\tpl_method_op_b#1#2:#3,{% \tpl_testifx{\relax#2} {} - {#2:\tpl_fpeval_op{#1}{#2}{#3},\tpl_method_op_b{#1}}% + {#2:\tpl_eval_op{#1}{#2}{#3},\tpl_method_op_b{#1}}% } - -%------------------- -% Méthode filter -%------------------- +%--------------- +% Méthode filter (développable) +%--------------- \def\tpl_method_filter#1#2#3{% #1=arg méthode f(idx, val) #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -655,16 +886,15 @@ \tpl_testifx{\relax#2} {} {% - \tpl_testifnum{\tpl_fpeval_op{#1}{#2}{#3}=1 } + \tpl_testifnum{\tpl_eval_op{#1}{#2}{#3}=1 } {#2:#3,} {}% \tpl_method_filter_b{#1}% }% } - -%------------------- -% Méthode pos -%------------------- +%--------------- +% Méthode pos (développable) +%--------------- \def\tpl_method_pos#1#2#3{% #1=arg méthode {valeur} #2=résultat méthodes précédentes #3=flag \tpl_ifempty{#1} {% @@ -673,31 +903,36 @@ {% \tpl_testifnum{#3<1 } {\tpl_error_only_for_tuples{pos}} - {\tpl_method_pos_a#1\_nil#2\_nil}% + {\tpl_method_pos_a#1[1]\_nil#2\_nil}% }% } -\def\tpl_method_pos_a#1\_nil#2)#3#4\_nil{% - {\tpl_method_pos_b{#1}#3\relax:\relax,\_nil}{0}% +\def\tpl_method_pos_a#1[#2]#3\_nil#4)#5#6\_nil{% + {\tpl_method_pos_b{1}{#2}{#1}#5\relax:\relax,\_nil}{0}% } -\def\tpl_method_pos_b#1#2:#3,{% - \tpl_testifx{\relax#2} +\def\tpl_method_pos_b#1#2#3#4:#5,{% #1=occurrence en cours #2=occurrence souhaitée #3=nombre cherché + \tpl_testifx{\relax#4} {% - -1\tpl_gobtonil% si valeur absente, renvoyer -1 + -1\tpl_gobtonil% si occurrence non trouvée, renvoyer -1 } {% - \tplfpcompare{#1}={#3}% - {#2\tpl_gobtonil}% à la première occurrence, renvoyer #2 - {\tpl_method_pos_b{#1}}% + \tplfpcompare{#3}={#5}% nombres correspondent ? + {% + \tpl_testifnum{#1=#2 }% occurrence souhaitée ? + {#4\tpl_gobtonil} + {\tpl_e_second\tpl_method_pos_b{\the\numexpr#1+1}{#2}{#3}}% + }% à la première occurrence, renvoyer #2 + {% + \tpl_method_pos_b{#1}{#2}{#3}% + }% }% } - -%------------------- -% Méthode comp -%------------------- -\def\tpl_fpeval_comp#1#2{\tpl_subst_xa_a#1\?{\tpl_subst_xa_b#1\_nil{#2}}\_markit xa\?{\tpl_subst_xb{#1}}\_markit\_nil} +%--------------- +% Méthode comp (développable) +%--------------- +\def\tpl_eval_comp#1#2{\tpl_subst_xa_a#1\?{\tpl_subst_xa_b#1\_nil{#2}}\_markit xa\?{\tpl_subst_xb{#1}}\_markit\_nil} \def\tpl_subst_xa_a#1xa#2\?#3\_markit#4\_nil{#3}% -\def\tpl_subst_xa_b#1xa#2\_nil#3{\tpl_fpeval_comp{#1#3#2}{#3}} -\def\tpl_subst_xb#1#2{\tpl_subst_xb_a#1\?{\tpl_subst_xb_b#1\_nil{#2}}\_markit xb\?{\fpeval{#1}}\_markit\_nil} +\def\tpl_subst_xa_b#1xa#2\_nil#3{\tpl_eval_comp{#1#3#2}{#3}} +\def\tpl_subst_xb#1#2{\tpl_subst_xb_a#1\?{\tpl_subst_xb_b#1\_nil{#2}}\_markit xb\?{\tpl_expr_eval{#1}}\_markit\_nil} \def\tpl_subst_xb_a#1xb#2\?#3\_markit#4\_nil{#3}% \def\tpl_subst_xb_b#1xb#2\_nil#3{\tpl_subst_xb{#1#3#2}{#3}} \def\tpl_method_comp#1#2#3{% #1=arg méthode "{op}{nom tuple B}" #2=résultat méthodes précédentes #3=flag @@ -724,12 +959,11 @@ \def\tpl_method_comp_c#1#2:#3,#4\_nil#5:#6,#7\_nil{% \tpl_testifx{\relax#3} {} - {#2:\tpl_fpeval_comp{#1}{#6}{#3},\tpl_method_comp_c{#1}#4\_nil#7\_nil}% + {#2:\tpl_eval_comp{#1}{#6}{#3},\tpl_method_comp_c{#1}#4\_nil#7\_nil}% } - -%------------------- -% Méthode show -%------------------- +%--------------- +% Méthode show (développable ou _NON_ développable, dépend des macros \tplformat et \tplsep) +%--------------- \def\tpl_method_show#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag \tpl_testifnum{#3=1 } {{\tpl_method_show_a#2}{0}} @@ -738,10 +972,9 @@ \def\tpl_method_show_a#1)#2#3{\tpl_unindex\tplformat\tplsep{#2}} \def\tplformat#1#2{#2}% #1=index en cours #2=item en cours \def\tplsep{, } - -%------------------- -% Méthode end_exe (privée) -%------------------- +%--------------- +% Méthode end_exe (privée et développable) +%--------------- \def\tpl_method_end_exe#1#2#3{% #1=arg méthode #2=résultat méthodes précédentes #3=flag {% \tpl_testifnum{#3=1 } @@ -753,8 +986,9 @@ \def\tpl_method_end_exe_a#1)#2#3{\tpl_unindex\tpl_method_end_exe_format\tpl_method_end_exe_sep{#2}} \def\tpl_method_end_exe_format#1#2{#2} \def\tpl_method_end_exe_sep{, } - +%--------------- % macro \tpl_unindex +%--------------- \def\tpl_unindex#1#2#3{% #1=macro pour formater un item #2=macro séparateur #3=tuple indexé \tpl_ifempty{#3} {}% @@ -785,9 +1019,9 @@ {\tpl_error{Tuple '\detokenize{#1}' not defined}\tpl_gobtonil}% } % Flag -% -1 : c'est la dernière méthode appelée, les autres sont ignorées -% 0 : résultat est un nombre ou est affichable -% 1 : résultat est un tuple +% -1 : c'est la dernière méthode appelée, les autres sont ignorées +% 0 : résultat est un nombre ou est affichable +% 1 : résultat est un tuple \def\tpl_exeb(#1)#2#3#4{% #1=flag #2=données du tuple #3=tuple non indexé #4=tuple indexé \tpl_exec{(#1){#2}{#3}}{#4}%{#5}% grouper les argument du tuple } @@ -867,7 +1101,7 @@ {\tpl_e_second\tpl_gentuple_c{\the\numexpr#1+1}{#2#4,}{#3{#4}}}% } \def\tpl_gentuple_e#1#2#3#4#5#6{% #1=index en cours #2=nb de variables #3=dernières valeurs #4=expression de génération #5=condition arret #6=\tpl_gentuple_g(while) ou \tpl_gentuple_f(until) - \tpl_x_second{#6}{\fpeval{\tpl_subst_allvalues{#2}{#4}{#3}{#1}}}% <- #1=valeur pour \i (index courant) + \tpl_x_second{#6}{\tpl_expr_eval{\tpl_subst_allvalues{#2}{#4}{#3}{#1}}}% <- #1=valeur pour \i (index courant) {#1}{#2}{#3}{#4}{#5}% } \def\tpl_gentuple_f#1#2#3#4#5#6{% #1=item en cours #2=index en cours #3=nb de variables #4=dernières valeurs #5=expression de génération #6=condition arret (until) @@ -885,7 +1119,9 @@ \expandafter\tpl_gentuple_e\expanded{{\the\numexpr#2+1}{#3}{\tpl_gobone#4{#1}}}{#5}{#6}\tpl_gentuple_g% puis recommencer \fi } +%--------------- % macros auxiliaires pour \gentuple +%--------------- \tpl_foreach\__temp\in{i,1,2,3,4,5,6,7,8,9}\do{% définition des macros de remplacement \1, \2, etc \tpl_csedef{tpl_subst_\__temp}##1##2{\tpl_cs_enxp{tpl_subst_\__temp _a}##1\noexpand\?{\tpl_cs_enxp{tpl_subst_\__temp _b}##1\noexpand\_nil{##2}}\noexpand\_markit\tpl_cs_enxp{\__temp}\noexpand\?{\noexpand\unexpanded{##1}}\noexpand\_markit\noexpand\_nil}% \tpl_csdef {tpl_subst_\__temp _a\expandafter}\expandafter##\expandafter1\csname\__temp\endcsname##2\?##3\_markit##4\_nil{##3}% @@ -901,10 +1137,21 @@ } \tpl_restorecatcode +\tplsetmode{dec : long} \endinput + Versions : _____________________________________________________________________________ | Version | Date | Changements | |-----------------------------------------------------------------------------| | 0.1 | 16/11/2024 | Première version | +|-----------------------------------------------------------------------------| +| 0.2 | 20/12/2024 | * choix du type de nombres dans le tuple : "int", | +| | | "dec:short" ou bien "dec:long" (défaut) | +| | | * index négatifs possibles pour les méthodes get, | +| | | set, add et split | +| | | * ajout d'un moteur de calcul rudimentaire pour les | +| | | décimaux #8.#8 avec produit de type #16.#8 | +| | | * la méthode 'pos' admet un argument optionnel pour | +| | | indiquer l'occurrence cherchée | |-----------------------------------------------------------------------------|
\ No newline at end of file |