summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/tuple/tuple.tex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/generic/tuple/tuple.tex')
-rw-r--r--Master/texmf-dist/tex/generic/tuple/tuple.tex1157
1 files changed, 1157 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/tuple/tuple.tex b/Master/texmf-dist/tex/generic/tuple/tuple.tex
new file mode 100644
index 00000000000..ed8b345a140
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/tuple/tuple.tex
@@ -0,0 +1,1157 @@
+% !TeX encoding = UTF-8
+% Ce fichier contient le code de l'extension "tuple"
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+\def\tplname {tuple} %
+\def\tplversion {0.2} %
+% %
+\def\tpldate {2024/12/20} %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%____________________________________________________________________
+% Author : Christian Tellechea |
+% Status : Maintained |
+% Email : unbonpetit@netc.fr |
+% Package URL: https://www.ctan.org/pkg/tuple |
+% Copyright : Christian Tellechea 2024 |
+% Licence : Released under the LaTeX Project Public License v1.3c |
+% or later, see http://www.latex-project.org/lppl.txt |
+% Files : 1) tuple.tex |
+% 2) tuple.sty |
+% 3) README |
+% 4) tuple-doc-fr.tex |
+% 5) tuple-doc-fr.pdf |
+% 6) tuple-doc-en.tex |
+% 7) tuple-doc-en.pdf |
+%--------------------------------------------------------------------
+
+\csname tpl_load_once\endcsname
+\expandafter\let\csname tpl_load_once\endcsname\endinput
+
+\expandafter\edef\csname tpl_restorecatcode\endcsname{\catcode\number`\_=\the\catcode`\_\relax }
+\catcode`\_11
+
+\def\tpl_exec_first\fi\tpl_exec_second#1#2{\fi#1}
+\def\tpl_exec_second#1#2{#2}
+\ifdefined\tpl_fromsty\tpl_exec_first\fi\tpl_exec_second
+ {%
+ \def\tpl_error#1{\PackageError\tplname{#1}{Read the \tplname\space manual}}% pour LaTeX
+ }
+ {%
+ \def\tpl_error#1{\errmessage{Package \tplname\space Error: #1^^J}}% pour TeX
+ \immediate\write -1 {Package: \tpldate\space v\tplversion\space Expandable operations for tuples of numbers (CT)}%
+ \input expl3-generic.tex % pour fp
+ }%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Macros diverses %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\tpl_stripsp#1{%
+ \def\tpl_stripsp##1##2{\expanded{\tpl_stripsp_i\_marksp##2\__nil\_marksp#1\_marksp\_nil{##1}}}%
+ \def\tpl_stripsp_i##1\_marksp#1##2\_marksp##3\_nil{\tpl_stripsp_ii##3##1##2\__nil#1\__nil\_nil}%
+ \def\tpl_stripsp_ii##1#1\__nil##2\_nil{\tpl_stripsp_iii##1##2\_nil}%
+ \def\tpl_stripsp_iii##1##2\__nil##3\_nil##4{\unexpanded{##4{##2}}}%
+}
+\tpl_stripsp{ }
+\def\tpl_swaparg#1#2{#2{#1}}
+\def\tpl_e_second#1#2{\expandafter\tpl_swaparg\expandafter{#2}{#1}}
+\def\tpl_x_second#1#2{\expandafter\tpl_swaparg\expandafter{\expanded{#2}}{#1}}
+\def\tpl_swaptwo#1#2{#2#1}
+\def\tpl_e_after#1#2{\expandafter\tpl_swaptwo\expandafter{#2}{#1}}
+\def\tpl_x_after#1#2{\expandafter\tpl_swaptwo\expandafter{\expanded{#2}}{#1}}
+\def\tpl_error_inmethod#1{{\tpl_error{#1}}{-1}}
+\def\tpl_gobone#1{}
+\def\tpl_gobtonil#1\_nil{}
+\def\tpl_firsttonil#1#2\_nil{#1}
+\def\tpl_antefi#1\fi{\fi#1}
+\def\tpl_testifx#1{\ifx#1\tpl_exec_first\fi\tpl_exec_second}
+\def\tpl_testifnum#1{\ifnum#1\tpl_exec_first\fi\tpl_exec_second}
+\def\tpl_testifcsname#1{\ifcsname#1\endcsname\tpl_exec_first\fi\tpl_exec_second}
+\def\tpl_cs_enxp#1{\expandafter\noexpand\csname#1\endcsname}
+\def\tpl_ifempty#1#2#3{\tpl_ifempty_a#1\_YN{#3}\_YN{#2}\_nil}
+\def\tpl_ifempty_a#1#2\_YN#3#4\_nil{#3}
+\def\tpl_foreach#1\in#2\do#3{% #1=macro recevant chaque élément #2=liste d'éléments #3=code
+ \def\tpl_foreach_a##1,{%
+ \ifx\tpl_foreach_a##1\else
+ \def#1{##1}%
+ #3%
+ \expandafter\tpl_foreach_a
+ \fi
+ }%
+ \expandafter\tpl_foreach_a#2,\tpl_foreach_a,% 1-développer #2 au cas où...
+}
+
+%---------------
+% 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
+ \tpl_antefi
+ #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 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,{%
+ \tpl_testifx{!#2}
+ {\tpl_quicksort_and_index_d{#1}}
+ {\tpl_quicksort_and_index_c{#1}{}{}{#2}}%
+}
+\def\tpl_quicksort_and_index_c#1#2#3#4#5,{% #1=index courant #2=part lt #3=part gt #4=pivot #5=élément courant
+ \tpl_testifx{!#5}% partition achevée -> partitionner "part lt" et passer les arguments <pivot><part gt> pour la macro
+ {% \tpl_quicksort_and_index_d lancée à la fin du partitionnement de "part lt"
+ \tpl_quicksort_and_index_a#1;{#2}{#4}{#3}% arg {#4}{#3} lus à la fin par \tpl_quicksort_and_index_d
+ }
+ {%
+ \tplfpcompare{#5}<{#4}
+ {\tpl_quicksort_and_index_c{#1}{#2#5,}{#3}}
+ {\tpl_quicksort_and_index_c{#1}{#2}{#3#5,}}%
+ {#4}%
+ }%
+}
+\def\tpl_quicksort_and_index_d#1#2{% #1=index ancien #2=pivot #3=part gt (à suivre, non lu par cette macro)
+ \ifx?#2\else\tpl_antefi#1:#2,\expandafter\tpl_quicksort_and_index_a\the\numexpr#1+1;\fi
+}
+
+%TODO : insertion sort && fusion sort
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% Macros pour set, get, split %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\tpl_csdef#1{\expandafter\def\csname#1\endcsname}
+\def\tpl_csedef#1{\expandafter\edef\csname#1\endcsname}
+\tpl_foreach\__temp\in{1,2,3,4,5,6,7,8,9}\do{% définition des macros qui parcourent le tuple indexé
+ \tpl_csdef {get_\__temp\expandafter}\expandafter##\expandafter1\__temp:##2,{##2\tpl_gobtonil}%
+ \tpl_csedef{split_\__temp\expandafter}\expandafter\_nil\expandafter##\expandafter1\__temp:##2,{##1\__temp:##2,?}%
+ \tpl_csedef{set_\__temp\expandafter}\expandafter##\expandafter1\expandafter\_nil\expandafter##\expandafter2\__temp:##3,{##2\__temp:##1,}%
+ \tpl_csdef {gobto_\the\numexpr\__temp+1\relax 0\expandafter}\expandafter##\expandafter1\__temp 9:##2,{}%
+ \tpl_csdef {gobto_\the\numexpr\__temp+1\relax 00\expandafter}\expandafter##\expandafter1\__temp 99:##2,{}%
+ \tpl_csdef {gobto_\the\numexpr\__temp+1\relax 000\expandafter}\expandafter##\expandafter1\__temp 999:##2,{}%
+ \tpl_csdef {gobto_\the\numexpr\__temp+1\relax0000\expandafter}\expandafter##\expandafter1\__temp9999:##2,{}%
+ \tpl_csedef{passto_\__temp 0\expandafter}\expandafter##\expandafter1\expandafter\_nil\expandafter##\expandafter2\the\numexpr\__temp 0-1:##3,{##2\the\numexpr\__temp 0-1:##3,##1\noexpand\_nil}%
+ \tpl_csedef{passto_\__temp 00\expandafter}\expandafter##\expandafter1\expandafter\_nil\expandafter##\expandafter2\the\numexpr\__temp 00-1:##3,{##2\the\numexpr\__temp 00-1:##3,##1\noexpand\_nil}%
+ \tpl_csedef{passto_\__temp 000\expandafter}\expandafter##\expandafter1\expandafter\_nil\expandafter##\expandafter2\the\numexpr\__temp 000-1:##3,{##2\the\numexpr\__temp 000-1:##3,##1\noexpand\_nil}%
+ \tpl_csedef{passto_\__temp0000\expandafter}\expandafter##\expandafter1\expandafter\_nil\expandafter##\expandafter2\the\numexpr\__temp0000-1:##3,{##2\the\numexpr\__temp0000-1:##3,##1\noexpand\_nil}%
+}
+\tpl_csdef{get_0}#10:#2,{#2\tpl_gobtonil}%
+\tpl_csdef{split_0}\_nil#10:#2,{#10:#2,?}%
+\tpl_csdef{set_0}#1\_nil#20:#3,{#20:#1,}%
+\tpl_csdef{gobto_10}#19:#2,{}
+\tpl_csdef{gobto_100}#199:#2,{}
+\tpl_csdef{gobto_1000}#1999:#2,{}
+\tpl_csdef{gobto_10000}#19999:#2,{}
+\tpl_csdef{gobto_00}{}
+\tpl_csdef{gobto_000}{}
+\tpl_csdef{gobto_0000}{}
+\tpl_csdef{passto_00}{}
+\tpl_csdef{passto_000}{}
+\tpl_csdef{passto_0000}{}
+
+\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 (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 ",")
+}
+\def\tpl_getitem_a#1{% #1=chiffre unités
+ \expandafter\tpl_getitem_b\csname get_#1\endcsname{0}%
+}
+\def\tpl_getitem_b#1#2#3{% #1=commandes à exécuter #2=nb de 0 #3=chiffre courant
+ \tpl_testifx{\relax#3}
+ {\tpl_getitem_c#1\_nil}
+ {\tpl_e_second\tpl_getitem_b{\csname gobto_#3#2\endcsname#1}{#20}}%
+}
+\def\tpl_getitem_c#1#2\_nil{%
+ \tpl_ifempty{#2}
+ {}
+ {\expanded{\unexpanded{\tpl_getitem_c#2\_nil}\expandafter\expandafter\expandafter}}#1%
+}
+%---------------
+% 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 ",")
+}
+\def\tpl_setitem_a#1#2{% #1= valeur #2=chiffre unités
+ \tpl_e_second\tpl_setitem_b{\csname set_#2\endcsname#1}{0}%
+}
+\def\tpl_setitem_b#1#2#3{% #1=commandes à exécuter #2=nb de 0 #3=chiffre courant
+ \tpl_testifx{\relax#3}
+ {#1\_nil}
+ {\tpl_e_second\tpl_setitem_b{\csname passto_#3#2\endcsname#1}{#20}}%
+}
+%---------------
+% 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 ",")
+}
+\def\tpl_split_a#1{% #1=chiffre unités
+ \tpl_e_second\tpl_setitem_b{\csname split_#1\endcsname}{0}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% Constructeur de tuple %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\newtuple#1{%
+ \tpl_x_after\tpl_newtuple_a{\tpl_stripsp\detokenize{#1}}\_nil
+}
+\def\tpl_newtuple_a#1\_nil#2{%
+ \tpl_ifempty{#1}
+ {%
+ \tpl_error{Impossible to define a tuple with an empty name}%
+ }
+ {%
+ \tpl_testifcsname{tpl_tuple(#1)}
+ {\tpl_error{Tuple '#1' already defined}}%
+ {\tpl_csedef{tpl_tuple(#1)}{\tpl_e_second\tpl_newtuple_b{\detokenize\expandafter{\expanded{#2}}}}}%
+ }%
+}
+%---------------
+% \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){}{}}
+ {\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_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_d#1{% #1=item en cours
+ \tpl_ifempty{#1}
+ {%
+ \tpl_newtuple_c
+ }
+ {%
+ \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,\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_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 %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\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}}
+\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}
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{len}}
+ {\tpl_method_len_a#2\_nil}%
+ }
+ {%
+ \tpl_error_no_argument{len}{#1}%
+ }%
+}
+\def\tpl_method_len_a(#1,#2\_nil{{#1}{0}}% renvoie un nombre
+%---------------
+% 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}
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{sum}}
+ {\tpl_method_sum_a#2\_nil}%
+ }
+ {%
+ \tpl_error_no_argument{sum}{#1}%%
+ }%
+}
+\def\tpl_method_sum_a(#1,#2,#3\_nil{{#2}{0}}% renvoie un nombre
+%---------------
+% 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}
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{min}}
+ {\tpl_method_min_a#2\_nil}%
+ }
+ {%
+ \tpl_error_no_argument{min}{#1}%%
+ }%
+}
+\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}
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{max}}
+ {\tpl_method_max_a#2\_nil}%
+ }
+ {%
+ \tpl_error_no_argument{max}{#1}%
+ }%
+}
+\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}
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{mean}}
+ {\tpl_method_mean_a#2\_nil}%
+ }
+ {%
+ \tpl_error_no_argument{mean}{#1}%%
+ }%
+}
+\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_empty_tuple{mean}}
+ {{\tpl_expr_eval{#2/#1}}{0}}% renvoie un nombre
+}%
+%---------------
+% 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}
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{med}}
+ {\tpl_method_med_a#2\_nil}%
+ }
+ {%
+ \tpl_error_no_argument{med}{#1}%%
+ }%
+}
+\def\tpl_method_med_a(#1,#2)#3#4\_nil{%
+ \tpl_testifnum{#1=0 }
+ {\tpl_error_empty_tuple{med}}
+ {\tpl_method_quantile_a0.5\_nil(#1,#2){#3}{#4}\_nil}% renvoie un nombre
+}
+%---------------
+% 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}
+ {%
+ \tpl_error_argument_required{quantile}%
+ }%
+ {%
+ \tpl_testifnum{#3<1 }
+ {%
+ \tpl_error_only_for_tuples{quantile}%
+ }
+ {%
+ \tpl_testifnum{0\ifdim #1pt<0pt \else1\fi\ifdim#1pt<1pt 1\fi=11 }% si #1 dans [0 ; 1[
+ {\tpl_method_quantile_a#1\_nil#2\_nil}%
+ {\tpl_error_inmethod{Method 'quantile': argument '#1' not in [0;1-]}}%
+ }%
+ }%
+}
+\def\tpl_method_quantile_a#1\_nil(#2,#3)#4#5\_nil{%
+ \tpl_testifnum{#2=0 }
+ {\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é
+ {%
+ \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}%
+ }%
+ }%
+ {0}%
+}
+%---------------
+% 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}
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{stdev}}
+ {\tpl_method_stdev_a#2\_nil}%
+ }
+ {%
+ \tpl_error_no_argument{stdev}{#1}%%
+ }%
+}
+\def\tpl_method_stdev_a(#1,#2,#3)#4\_nil{%
+ \tpl_testifnum{#1=0 }
+ {\tpl_error_empty_tuple{stdev}}
+ {{\tpl_expr_eval{sqrt(#3/#1-(#2/#1)**2)}}{0}}% renvoie un nombre
+}
+%---------------
+% 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}
+ {%
+ \tpl_error_inmethod{Method 'get': argument required}%
+ }
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{get}}%
+ {\tpl_e_second\tpl_method_get_a{\the\numexpr#1\relax}#2\_nil}%
+ }%
+}
+\def\tpl_method_get_a#1(#2,#3)#4#5\_nil{%
+ \tpl_testifnum{#2=0 }
+ {%
+ \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_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 (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}
+ {%
+ \tpl_error_inmethod{Method 'set': argument required}%
+ }
+ {\tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{set}}%
+ {\tpl_x_after\tpl_method_set_a{#1}\_nil#2\_nil}% xdévelopper #1 et dégrouper #1 et #3
+ }%
+}
+\def\tpl_method_set_a#1\_nil(#2,#3)#4#5\_nil{% #2=len
+ \tpl_testifnum{#2=0 }% si tuple vide, on envoie '0:0,' avec len=1
+ {\tpl_method_set_b{0:0,}{1}#1,\relax:\relax,\_nil}
+ {\tpl_method_set_b{#4}{#2}#1,\relax:\relax,\_nil}%
+}
+\def\tpl_method_set_b#1#2#3:#4,{% #1=tuple #2=len #3=index courant #4=valeur courante
+ \tpl_testifx{\relax#3}
+ {%
+ {\tpl_newtuple_b{#1}}{1}\tpl_gobtonil
+ }
+ {%
+ \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_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 (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 }
+ {\tpl_error_only_for_tuples{sorted}}%
+ {\tpl_method_sorted_a#2\_nil}%
+ }
+ {%
+ \tpl_error_no_argument{sorted}{#1}%%
+ }%
+}
+\def\tpl_method_sorted_a(#1)#2#3\_nil{%
+ {(#1){\tpl_ifempty{#3}{#2}{#3}}{}}{1}%
+}
+%---------------
+% 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 }%
+}
+\def\tpl_method_store#1#2#3{% #1=arg méthode #2=len #3=index courant #4=valeur courante
+ \tpl_ifempty{#1}
+ {%
+ \tpl_error_argument_required{store}%
+ }
+ {%
+ \tpl_testifnum{#3<1 }
+ \tpl_method_store_a
+ \tpl_method_store_b
+ #1\_nil#2\_nil
+ }%
+}
+\def\tpl_method_store_a#1\_nil#2\_nil{% #1=arg méthode #2=résultat méthodes précédentes
+ \tpl_ifcs{#1}
+ {\unexpanded{{\def#1{#2}}}{-1}}% bloquer le développement
+ {\tpl_error_inmethod{Method 'store': unexpected argument '\detokenize{#1}'}}%
+}
+\def\tpl_method_store_b#1\_nil(#2,#3)#4#5\_nil{% #1=arg méthode #2=arg méthode #3=flag #4=résultat méthodes précédentes
+ \tpl_ifempty{#1}
+ {\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 (_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}
+ {%
+ \tpl_error_inmethod{Method 'split': argument required}%
+ }
+ {%
+ \tpl_testifnum{#3>0 }
+ {\tpl_method_split_a#1\_nil#2\_nil}% dégrouper #1 et #3
+ {\tpl_error_only_for_tuples{split}}%
+ }%
+}
+
+\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_empty_tuple{split}%
+ }
+ {%
+ \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_x_after\tpl_method_split_b{\tpl_split{#1}{#6}}?{#2}{#3}%
+ }
+ {%
+ \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': empty name not allowed}%
+ }%
+ }%
+}
+\def\tpl_method_split_b#1?#2?#3#4{%
+ {%
+ \noexpand\tpl_csedef{tpl_tuple(\tpl_stripsp\detokenize{#3})}{\tpl_e_second\tpl_newtuple_b{\detokenize\expandafter{\expanded{#1}}}}%
+ \noexpand\tpl_csedef{tpl_tuple(\tpl_stripsp\detokenize{#4})}{\tpl_e_second\tpl_newtuple_b{\detokenize\expandafter{\expanded{#2}}}}%
+ }%
+ {-1}%
+}
+%---------------
+% 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}
+ {%
+ \tpl_error_inmethod{Method 'add': argument required}%
+ }
+ {%
+ \tpl_testifnum{#3>0 }
+ {\tpl_x_after\tpl_method_add_a{#1}\_nil#2\_nil}% xdévelopper # et dégrouper #1 et #3
+ {\tpl_error_only_for_tuples{add}}%
+ }%
+}
+\def\tpl_method_add_a#1\_nil(#2,#3)#4#5\_nil{% #2=len
+ \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{#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_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{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_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 (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_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
+ \tpl_ifempty{#1}
+ {%
+ \tpl_error_argument_required{op}%
+ }
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{op}}
+ {\tpl_method_op_a#1\_nil#2\_nil}%
+ }%
+}
+\def\tpl_method_op_a#1\_nil#2)#3#4\_nil{%
+ {\tpl_x_second\tpl_newtuple_b{\tpl_method_op_b{#1}#3\relax:\relax,}}{1}%
+}
+\def\tpl_method_op_b#1#2:#3,{%
+ \tpl_testifx{\relax#2}
+ {}
+ {#2:\tpl_eval_op{#1}{#2}{#3},\tpl_method_op_b{#1}}%
+}
+%---------------
+% 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}
+ {%
+ \tpl_error_argument_required{filter}%
+ }
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{filter}}
+ {\tpl_method_filter_a#1\_nil#2\_nil}%
+ }%
+}
+\def\tpl_method_filter_a#1\_nil#2)#3#4\_nil{%
+ {\tpl_x_second\tpl_newtuple_b{\tpl_method_filter_b{#1}#3\relax:\relax,}}{1}%
+}
+\def\tpl_method_filter_b#1#2:#3,{%
+ \tpl_testifx{\relax#2}
+ {}
+ {%
+ \tpl_testifnum{\tpl_eval_op{#1}{#2}{#3}=1 }
+ {#2:#3,}
+ {}%
+ \tpl_method_filter_b{#1}%
+ }%
+}
+%---------------
+% 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}
+ {%
+ \tpl_error_argument_required{pos}%
+ }
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{pos}}
+ {\tpl_method_pos_a#1[1]\_nil#2\_nil}%
+ }%
+}
+\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#4:#5,{% #1=occurrence en cours #2=occurrence souhaitée #3=nombre cherché
+ \tpl_testifx{\relax#4}
+ {%
+ -1\tpl_gobtonil% si occurrence non trouvée, renvoyer -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 (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_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
+ \tpl_ifempty{#1}
+ {%
+ \tpl_error_inmethod{Method 'comp' requires arguments}%
+ }
+ {%
+ \tpl_testifnum{#3<1 }
+ {\tpl_error_only_for_tuples{comp}}
+ {\tpl_method_comp_a#1\_nil#2\_nil}%
+ }%
+}
+\def\tpl_method_comp_a#1#2\_nil#3\_nil{%
+ \tpl_testifcsname{tpl_tuple(\tpl_stripsp\detokenize{#2})}
+ {\tpl_x_after\tpl_method_comp_b{{#1}\csname tpl_tuple(\tpl_stripsp\detokenize{#2})\endcsname}#3}
+ {\tpl_error_inmethod{Method 'comp': tuple '#2' undefined}}%
+}
+\def\tpl_method_comp_b#1(#2,#3)#4#5(#6,#7)#8#9{%
+ \tpl_testifnum{#2=#6 }
+ {{\tpl_x_second\tpl_newtuple_b{\tpl_method_comp_c{#1}#4\relax:\relax,\_nil#8\relax:\relax,\_nil}}{1}}
+ {\tpl_error_inmethod{Method 'comp' requires tuple with same length}}%
+}
+\def\tpl_method_comp_c#1#2:#3,#4\_nil#5:#6,#7\_nil{%
+ \tpl_testifx{\relax#3}
+ {}
+ {#2:\tpl_eval_comp{#1}{#6}{#3},\tpl_method_comp_c{#1}#4\_nil#7\_nil}%
+}
+%---------------
+% 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}}
+ {\tpl_error_only_for_tuples{show}}%
+}
+\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 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 }
+ {\tpl_method_end_exe_a#2}
+ {\unexpanded{#2}}% diriger vers l'affichage si flag<1
+ }%
+ {-1}%
+}
+\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}
+ {}%
+ {\tpl_unindex_a{#1}{#2}#3\relax:\relax,}%
+}
+\def\tpl_unindex_a#1#2#3:#4,#5{% #1=macro pour formater un item #2=macro séparateur #3=index courant #4=item courant #5=prochain index
+ \unexpanded\expandafter{#1{#3}{#4}}% afficher l'item
+ \tpl_testifx{\relax#5}
+ {%
+ \tpl_unindex_b
+ }
+ {%
+ #2% afficher le séparateur
+ \tpl_unindex_a{#1}{#2}#5%
+ }%
+}
+\def\tpl_unindex_b#1,{}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% La macro utilisateur \tplexe %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\tplexe#1{%
+ \tpl_exea#1.end_exe.\_nil
+}
+\def\tpl_exea#1.{% #1=nom du tuple TODO:tester trié ou pas
+ \tpl_testifcsname{tpl_tuple(\tpl_stripsp\detokenize{#1})}
+ {\expandafter\expandafter\expandafter\tpl_exeb\csname tpl_tuple(\tpl_stripsp\detokenize{#1})\endcsname1}
+ {\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
+\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
+}
+\def\tpl_exec#1#2{% #1=résultat des dernières méthodes (soit le tuple entier (carac){tupleNTR}{tuple TR}, soit un nombre) #2=flag
+ \tpl_testifnum{#2=-1 }
+ {#1\tpl_gobtonil}% renvoie #1 et ignore toutes les autres méthodes
+ {\tpl_exed{#1}{#2}}%
+}
+\def\tpl_exed#1#2#3.{% #1=résultat des dernières méthodes (soit le tuple entier (carac){tupleNTR}{tuple TR}, soit un nombre) #2=flag #3=méthode (et arguments) en cours de traitement
+ \tpl_x_after\tpl_exee{\tpl_split_method_args{#3}}{#1}{#2}%
+}
+\def\tpl_exee#1#2#3#4{% #1=nom méthode #2=arg méthode #3=argument laissé par les méthodes #4=flag
+ \tpl_testifcsname{tpl_method_#1}
+ {\tpl_x_after\tpl_exec{\csname tpl_method_#1\endcsname{#2}{#3}{#4}}}% 3 arg à chaque méthode 1er=arg méthode #2=résultat précédent #3=flag
+ {\tpl_error{Unknown method "#1"}\tpl_gobtonil}%
+}
+
+\def\tpl_list_methods{len,sum,min,max,mean,med,quantile,stdev,get,set,sorted,store,split,add,op,filter,pos,comp,show,end_exe}
+\def\tpl_iftrueempty#1{\if\relax\detokenize{#1}\relax\tpl_exec_first\fi\tpl_exec_second}
+\tpl_foreach\_temp\in\tpl_list_methods\do{%
+ \tpl_csedef{tpl_try_\_temp}##1{%
+ \tpl_cs_enxp{tpl_try_\_temp _a}##1\noexpand\__nil\_temp\noexpand\___nil\noexpand\_nil
+ }%
+ \tpl_csedef{tpl_try_\_temp _a\expandafter}\expandafter##\expandafter1\_temp##2\_nil{%
+ \noexpand\tpl_iftrueempty{##1}% ##1 ne _doit_ pas être ' ' donc la syntaxe ". method" est invalide
+ {{\_temp}{\noexpand\tpl_sanitize_arg##2}\noexpand\tpl_gobtonil}% <- argument Vrai
+ }%
+}
+\def\tpl_split_method_args#1{% #1=<méthode><arg> -> retour {methode}{arg} ou {methode}{{arg1}{arg2}{arg3}...}
+ \tpl_e_after{\tpl_split_method_args_a{#1}}\tpl_list_methods,\relax,\_nil
+}
+\def\tpl_split_method_args_a#1#2,{%
+ \tpl_testifx{\relax#2}
+ {%
+ {\detokenize{#1}}{}\tpl_gobtonil
+ }
+ {%
+ \csname tpl_try_#2\endcsname{#1}%
+ %{} <- inclus dans la macro \tpl_try_<methode>_a
+ {\tpl_split_method_args_a{#1}}% <- argument Faux
+ }%
+}
+\def\tpl_sanitize_arg#1\__nil#2\___nil{\tpl_stripsp\unexpanded{#1}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% La macro utilisateur \gentuple %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\tpl_strip_lastcomma#1{\tpl_strip_lastcomma_i#1\empty\tpl_gobtonil, \empty\_nil}%
+\def\tpl_strip_lastcomma_i#1, \empty{#1}
+\def\tpl_id#1{#1}
+\def\tpl_is_while#1{\tpl_stripsp{\expandafter\tpl_is_while_a\tpl_id}{#1}\while\_nil}
+\def\tpl_is_while_a#1\while#2\_nil{\tpl_ifempty{#1}{\tpl_is_while_b#2\_nil}{\tpl_exec_second}}
+\def\tpl_is_while_b#1\while#2\_nil{\tpl_ifempty{#1#2}}
+\def\tpl_is_until#1{\tpl_stripsp{\expandafter\tpl_is_until_a\tpl_id}{#1}\until\_nil}
+\def\tpl_is_until_a#1\until#2\_nil{\tpl_ifempty{#1}{\tpl_is_until_b#2\_nil}{\tpl_exec_second}}
+\def\tpl_is_until_b#1\until#2\_nil{\tpl_ifempty{#1#2}}
+\def\gentuple#1{%
+ \tpl_x_second\tpl_strip_lastcomma{\tpl_gentuple_a#1\_nil}%
+}
+\def\tpl_gentuple_a#1\genrule#2;#3\_nil{% #1=amorce #2=expression de génération #3=\while|\until <condition>
+ \tpl_stripsp{\expandafter\tpl_gentuple_b\tpl_id}{#3}\_nil#1\genrule#2;%
+}
+\def\tpl_gentuple_b#1#2\_nil#3\genrule#4;{% #1=\while|\until #2=condition #3=amorce #4=expression de génération
+ \tpl_is_while{#1}
+ {%
+ \tpl_gentuple_c0{}{}#3\relax,{#4}{#2}\tpl_gentuple_g
+ }
+ {%
+ \tpl_is_until{#1}
+ {\tpl_gentuple_c0{}{}#3\relax,{#4}{#2}\tpl_gentuple_f}
+ {\tpl_error{\string\while\space or \string\until\space expected before condition}}%
+ }%
+}
+\def\tpl_gentuple_c#1#2#3#4,{% #1=index en cours #2=n1,n2,n3,... #3={n1}{n2}{n3}... #4=item d'amorce en cours
+ \tpl_testifx{\relax#4}
+ {#2\tpl_gentuple_e{#1}{#1}{#3}}% afficher l'amorce '#2' puis aller à la macro récursive
+ {\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}{\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)
+ #1% afficher '#1,' avant de faire le test
+ \ifnum\tpl_x_second\tpl_subst_val{\tpl_subst_i{#6}{#2}}{#1}=0 % tant que condition d'arrêt non vérifiée
+ \tpl_antefi
+ , % séparateur si pas le dernier
+ \tpl_x_after\tpl_gentuple_e{{\the\numexpr#2+1}{#3}{\tpl_gobone#4{#1}}}{#5}{#6}\tpl_gentuple_f% puis recommencer
+ \fi
+}
+\def\tpl_gentuple_g#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 de poursuite (while)
+ \ifnum\tpl_x_second\tpl_subst_val{\tpl_subst_i{#6}{#2}}{#1}=1 % tant que condition de poursuite en vérifiée
+ \tpl_antefi
+ #1, % séparateur toujours présent, même arès le dernier nombre
+ \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}%
+ \tpl_csedef{tpl_subst_\__temp _b\expandafter}\expandafter##\expandafter1\csname\__temp\endcsname##2\_nil##3{\tpl_cs_enxp{tpl_subst_\__temp}{##1##3##2}{##3}}%
+}
+\def\tpl_subst_allvalues#1#2#3{% #1=nombre de variables #2=expression où il y a \1, \2, etc #3=valeurs pour les variables #4=valeur pour \i
+ \tpl_subst_allvalues_a{1}{#1}{#2}#3{}{}{}{}{}{}{}{}{}\_nil%{#4}% <- ajouter l'index courant qui est la valeur pour \i
+}
+\def\tpl_subst_allvalues_a#1#2#3#4{% #1=n° de remplacement en cours #2=nb total de remplacements #3=expression #4=valeur de la variable n°#1
+ \tpl_testifnum{#1>#2 }
+ {\tpl_firsttonil{\tpl_subst_i{#3}}}% <- mange tout jusqu'au \_nil puis lit la valeur pour \i
+ {\tpl_x_after\tpl_subst_allvalues_a{{\the\numexpr#1+1}{#2}{\csname tpl_subst_#1\endcsname{#3}{#4}}}}%
+}
+
+\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