% Author     : C. Pierquet
% licence    : Released under the LaTeX Project Public License v1.3c or later, see http://www.latex-project.org/lppl.txtf

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{commalists-tools}[2024/09/25 0.1.0 Basic operations for numeral comma separated lists]

%------History
% 0.1.0	Initial version

%------Packages
\RequirePackage{listofitems}
\RequirePackage{xintexpr}
\RequirePackage{xstring}

%-----Macros (LaTeX3...) for sorting
\ExplSyntaxOn
\NewDocumentCommand\sortasclist{ s m }
{
	\clist_set:Nx \l_foo_clist {#2}
	\clist_sort:Nn \l_foo_clist{
		\int_compare:nNnTF { ##1 } > { ##2 }
			{ \sort_return_swapped: }
			{ \sort_return_same: }
	}
	\IfBooleanTF{#1}%if star := just printing // if not, storing
		{%
			{\l_foo_clist}%
		}%
		{%
			\xdef#2{\l_foo_clist}%
		}%
}

\NewDocumentCommand\sortdeslist{ s m }
{
	\clist_set:Nx \l_foo_clist {#2}
	\clist_sort:Nn \l_foo_clist{
		\int_compare:nNnTF { ##1 } < { ##2 }
			{ \sort_return_swapped: }
			{ \sort_return_same: }
	}
	\IfBooleanTF{#1}%if star := just printing // if not, storing
		{%
			{\l_foo_clist}%
		}%
		{%
			\xdef#2{\l_foo_clist}%
		}%
} 
\ExplSyntaxOff

%----Macros (LaTeX2)
\NewDocumentCommand\addvalinlist{ s m m }{%
	\IfBooleanTF{#1}%if star := just printing // if not, storing
		{%
			#3,#2%
		}%
		{%
			\xdef#3{#3,#2}%
		}%
}

\NewDocumentCommand\removevalinlist{ s m m }{%
	\readlist*\tmplistread{#3}%
	\xdef\tmpresremovelist{}%
	\xintFor* ##1 in {\xintSeq{1}{\tmplistreadlen}}\do{%
		\xintifboolexpr{ \tmplistread[##1] == #2}%
			{}%
			{%
				\xintifboolexpr{ ##1 == 1 }%
					{%
						\xdef\tmpresremovelist{\tmplistread[##1]}%
					}%
					{%
						\xdef\tmpresremovelist{\tmpresremovelist,\tmplistread[##1]}%
					}%
			}%
	}%
	\IfBooleanTF{#1}%if star := just printing // if not, storing
		{%
			\tmpresremovelist%
		}%
		{%
			\xdef#3{\tmpresremovelist}%
		}%
}

\NewDocumentCommand\boolvalinlist{ m m O{\resisinlist} }{%
	\IfSubStr{,#2,}{,#1,}{\def#3{1}}{\def#3{0}}%
}

\NewDocumentCommand\xintifvalinlist{ m m m m }{%
	\IfSubStr{,#2,}{,#1,}{\xdef\RESTMPVALUE{1}}{\xdef\RESTMPVALUE{0}}%
	\xintifboolexpr{ \RESTMPVALUE == 1}{#3}{#4}%
}

\NewDocumentCommand\countvalinlist{ s m m O{\rescount} }{%
	\readlist*\tmplistread{#3}%
	\xdef#4{0}%
	\xintFor* ##1 in {\xintSeq{1}{\tmplistreadlen}}\do{%
		\xintifboolexpr{ \tmplistread[##1] == #2}%
		{%
			\xdef#4{\fpeval{#4+1}}%
		}%
		{}%
	}%
	\IfBooleanT{#1}%if star := just printing // if not, storing
		{%
			#4%
		}%
}

\NewDocumentCommand\minoflist{ s m O{\resmin} }{%
	\IfBooleanTF{#1}%
		{%
			\fpeval{min(#2)}%
		}%
		{%
			\xdef#3{\fpeval{min(#2)}}%
		}%
}

\NewDocumentCommand\maxoflist{ s m O{\resmax} }{%
	\IfBooleanTF{#1}%
		{%
			\fpeval{max(#2)}%
		}%
		{%
			\xdef#3{\fpeval{max(#2)}}%
		}%
}

\NewDocumentCommand\meanoflist{ s m O{\resmean} }{%
	\xdef#3{0}%
	\readlist*\tmpmeanlist{#2}%
	\xintFor* ##1 in {\xintSeq{1}{\tmpmeanlistlen}}\do{%
		\xdef#3{\fpeval{#3+\tmpmeanlist[##1]}}%
	}%
	\xdef#3{\fpeval{(#3)/\tmpmeanlistlen}}%
	\IfBooleanT{#1}%if star := just printing // if not, storing
		{%
			#3%
		}%
}

\NewDocumentCommand\sumoflist{ s m O{\ressum} }{%
	\xdef#3{0}%
	\readlist*\tmpsumlist{#2}%
	\xintFor* ##1 in {\xintSeq{1}{\tmpsumlistlen}}\do{%
		\xdef#3{\fpeval{#3+\tmpsumlist[##1]}}%
	}%
	\IfBooleanT{#1}%if star := just printing // if not, storing
		{%
			#3%
		}%
}

\NewDocumentCommand\prodoflist{ s m O{\resprod} }{%
	\xdef#3{1}%
	\readlist*\tmpprodlist{#2}%
	\xintFor* ##1 in {\xintSeq{1}{\tmpprodlistlen}}\do{%
		\xdef#3{\fpeval{(#3)*\tmpprodlist[##1]}}%
	}%
	\IfBooleanT{#1}%if star := just printing // if not, storing
		{%
			#3%
		}%
}

\NewDocumentCommand\reverselist{ s m O{\resrevlist} }{%
	\readlist*\tmpreverselist{#2}%
	\xdef#3{\tmpreverselist[-1]}%
	\xintFor* ##1 in {\xintSeq{2}{\tmpreverselistlen}}\do{%
		\xdef#3{#3,\tmpreverselist[-##1]}%
	}%
	\IfBooleanT{#1}%if star := just printing // if not, storing
		{%
			#3%
		}%
}

\NewDocumentCommand\getvaluefromlist{ s m m O{\resmyelt} }{%
	\readlist*\tmpreadlist{#2}%
	\xdef#4{\tmpreadlist[#3]}%
	\IfBooleanT{#1}{#4}%
}

\endinput