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

\NeedsTeXFormat{LaTeX2e}
\ProvidesExplPackage{commalists-tools-l3}{2025-10-17}{0.1.7}{Basic operations for numeral comma separated lists}

%------History
% 0.1.7	Improvements with latex3
% 0.1.6	Initial version (prefixed macros due to legacy package)

%------Variables
\clist_new:N \l__commalists_clist
\fp_new:N \l__commalists_tmpa_fp

%-----Macros (LaTeX3...)
\NewDocumentCommand\ctshowlist{ O{,} m }
{
	\clist_set:Ne \l__commalists_clist { #2 }
	\clist_use:Nn \l__commalists_clist { #1 }
}

\NewDocumentCommand\ctsortasclist{ s m O{\mysortedlist} }
{
	\clist_set:Ne \l_foo_clist {#2}
	\clist_sort:Nn \l_foo_clist{
		\fp_compare:nNnTF { ##1 } > { ##2 }
			{ \sort_return_swapped: }
			{ \sort_return_same: }
	}
	\IfBooleanTF{#1}%if star := just printing // if not, storing
		{
			{\l_foo_clist}
		}
		{
			\tl_gset:Ne \l_tmpa_tl { \l_foo_clist }
			\tl_gset:Ne #3 { \tl_use:N \l_tmpa_tl }
		}
}

\NewDocumentCommand\ctsortdeslist{ s m O{\mysortedlist} }
{
	\clist_set:Ne \l_foo_clist {#2}
	\clist_sort:Nn \l_foo_clist{
		\fp_compare:nNnTF { ##1 } < { ##2 }
			{ \sort_return_swapped: }
			{ \sort_return_same: }
	}
	\IfBooleanTF{#1}%if star := just printing // if not, storing
		{
			{\l_foo_clist}%
		}
		{
			\tl_gset:Ne \l_tmpa_tl { \l_foo_clist }
			\tl_gset:Ne #3 { \tl_use:N \l_tmpa_tl }
		}
}

\NewDocumentCommand\ctreverselist{ s m O{\reverselist} }
{
	\clist_set:Ne \l__commalists_clist {#2}
	\IfBooleanTF{#1}%if star := just printing // if not, storing
	{
		\clist_reverse:N \l__commalists_clist
		\clist_use:Nn \l__commalists_clist { , }
	}
	{
		\clist_set_eq:NN #3 \l__commalists_clist
		\clist_greverse:N #3
	}
}

\NewDocumentCommand{\ctaddvalinlist}{ s m m }
{
	\IfBooleanTF{#1}
		{
			#3, #2
		}
		{
			\tl_gset:Ne #3 { \tl_use:N #3 , #2 }
		}
}

\NewDocumentCommand{\ctboolvalinlist}{ m m O{\resisinlist} }
{
	\clist_set:Ne \l__commalists_clist {#2}
	
	\tl_set:Nn #3 { 0 }
	
	\clist_map_inline:Nn { \l__commalists_clist }
	{
		\tl_if_eq:neT {##1} {#1}
		{
			\tl_gset:Nn #3 { 1 }
			\clist_map_break:
		}
	}
}

\NewDocumentCommand{\cttestifvalinlist}{ m m m m }
{
	\clist_set:Ne \l__commalists_clist {#2}
	
	\bool_set_false:N \l_tmpa_bool
	
	\clist_map_inline:Nn { \l__commalists_clist }
	{
		\tl_if_eq:neT {##1} {#1}
		{
			\bool_set_true:N \l_tmpa_bool
			\clist_map_break:
		}
	}
	\bool_if:NTF \l_tmpa_bool { #3 } { #4 }
}

\NewDocumentCommand{\ctremovevalinlist}{ s m m O{\mytmplist} }
{
	\clist_set:Ne \l__commalists_clist {#3}
	
	\clist_clear_new:N \l_tmpb_clist
	
	\clist_map_inline:Nn { \l__commalists_clist }
	{
		
		\tl_if_eq:neF {##1} {#2}
		{
			\clist_put_right:Nn \l_tmpb_clist { ##1 }
		}
	}
	
	\IfBooleanTF{#1}
	{
		\clist_use:Nn \l_tmpb_clist { , }
	}
	{
		\tl_set:Ne \l_tmpa_tl { \clist_use:Nn \l_tmpb_clist { , } }
		\tl_gset:Ne #4 { \tl_use:N \l_tmpa_tl }
	}
}

\NewDocumentCommand\ctcountvalinlist{ s m m O{\rescount} }{%
	\clist_set:Ne \l__commalists_clist {#3}
	
	\int_zero:N \l_tmpa_int
	\clist_map_inline:Nn { \l__commalists_clist }
	{
		\tl_if_eq:neT {##1} {#2}
		{
			\int_incr:N \l_tmpa_int
		}
	}
	\IfBooleanTF{#1}
	{
		\int_use:N \l_tmpa_int
	}
	{
		\tl_gset:Ne #4 { \int_use:N \l_tmpa_int }
	}
}

\NewDocumentCommand\ctminoflist{ s m O{\resmin} }{%
	\IfBooleanTF{#1}%
	{
		\fp_eval:n { min(#2) }
	}
	{
		\tl_gset:Ne #3 { \fp_eval:n { min(#2) } }
	}
}

\NewDocumentCommand\ctmaxoflist{ s m O{\resmax} }{%
	\IfBooleanTF{#1}%
	{
		\fp_eval:n { max(#2) }
	}
	{
		\tl_gset:Ne #3 { \fp_eval:n { max(#2) } }
	}
}

\NewDocumentCommand\ctsumoflist{ s m O{\ressum} }{%
	\clist_set:Ne \l__commalists_clist {#2}
	\fp_set:Nn \l__commalists_tmpa_fp { 0 }
	\clist_map_inline:Nn { \l__commalists_clist }
	{
		\fp_set:Nn \l__commalists_tmpa_fp { \fp_eval:n {\l__commalists_tmpa_fp + (##1) } }
	}
	\IfBooleanTF{#1}%
	{
		\fp_use:N \l__commalists_tmpa_fp
	}
	{
		\tl_gset:Ne #3 { \fp_use:N \l__commalists_tmpa_fp }
	}
}

\NewDocumentCommand\ctprodoflist{ s m O{\resprod} }{%
	\clist_set:Ne \l__commalists_clist {#2}
	\fp_set:Nn \l__commalists_tmpa_fp { 1 }
	\clist_map_inline:Nn { \l__commalists_clist }
	{
		\fp_set:Nn \l__commalists_tmpa_fp { \fp_eval:n {\l__commalists_tmpa_fp * (##1) } }
	}
	\IfBooleanTF{#1}
	{
		\fp_use:N \l__commalists_tmpa_fp
	}
	{
		\tl_gset:Ne #3 { \fp_use:N \l__commalists_tmpa_fp }
	}
}

\NewDocumentCommand\ctmeanoflist{ s m O{\resmean} }{%
	\clist_set:Ne \l__commalists_clist {#2}
	\fp_set:Nn \l__commalists_tmpa_fp { 0 }
	\clist_map_inline:Nn { \l__commalists_clist }
	{
		\fp_set:Nn \l__commalists_tmpa_fp { \fp_eval:n {\l__commalists_tmpa_fp + (##1) } }
	}
	\fp_set:Nn \l__commalists_tmpa_fp { \fp_eval:n { (\l__commalists_tmpa_fp) / ( \clist_count:N { \l__commalists_clist } ) } }
	\IfBooleanTF{#1}%
	{
		\fp_use:N \l__commalists_tmpa_fp
	}
	{
		\tl_gset:Ne #3 { \fp_use:N \l__commalists_tmpa_fp }
	}
}

\NewDocumentCommand\ctlenoflist{ s m O{\resmylen} }{%
	\clist_set:Ne \l__commalists_clist {#2}
	\IfBooleanTF{#1}
	{
		\clist_count:N { \l__commalists_clist }
	}
	{
		\tl_gset:Ne #3 { \clist_count:N { \l__commalists_clist } }
	}
}

\NewDocumentCommand\ctgetvaluefromlist{ s m m O{\resmyelt} }{%
	\clist_set:Ne \l__commalists_clist {#2}
	\IfBooleanTF{#1}
	{
		\clist_item:Nn \l__commalists_clist { #3 }
	}
	{
		\tl_gset:Ne #4{ \clist_item:Nn \l__commalists_clist { #3 } }
	}
}

\endinput