%mathpiper,def="!!"

/// even/odd double factorial: product of even or odd integers up to n
1# (n_IsPositiveInteger)!! _ (n<=3) <-- n;
2# (n_IsPositiveInteger)!! <--
[
	Check(n<=65535, "Argument", "Double factorial: Error: the argument " : ( PipeToString() Write(n) ) : " is too large, you may want to avoid exact calculation");
	Factorial'double(2+Modulo(n, 2), n);
];
// special cases
3# (_n)!! _ (n= -1 Or n=0)<-- 1;

// the purpose of this mess "Quotient(a+b,2)+1+Modulo(Quotient(a+b,2)+1-a, 2)" is to obtain the smallest integer which is >= Quotient(a+b,2)+1 and is also odd or even when a is odd or even; we need to add at most 1 to (Quotient(a+b,2)+1)
2# Factorial'double(_a, _b) _ (b-a>=6) <-- Factorial'double(a, Quotient(a+b,2)) * Factorial'double(Quotient(a+b,2)+1+Modulo(Quotient(a+b,2)+1-a, 2), b);
3# Factorial'double(_a, _b) _ (b-a>=4) <-- a*(a+2)*(a+4);
4# Factorial'double(_a, _b) _ (b-a>=2) <-- a*(a+2);
5# Factorial'double(_a, _b) <-- a;

/// double factorial for lists is threaded
30 # (n_IsList)!! <-- MapSingle("!!",n);

%/mathpiper



%mathpiper_docs,name="!!",categories="Operators"
*CMD !!  --- double factorial operator

*CALL
    n!!

*PARMS
{n} -- integer, half-integer, or list

*DESC
The "double factorial" function {n!!} calculates $n*(n-2)*(n-4)*...$. 
This product terminates either with $1$ or with $2$ depending on 
whether $n$ is odd or even. If $n=0$ the function returns $1$.

The factorial functions are threaded, meaning that if the argument {n} is a
list, the function will be applied to each element of the list.

The factorial functions terminate and print an error message if the arguments are too large (currently the limit 
is $n < 65535$) because exact factorials of such large numbers are computationally expensive and most probably 
not useful. One can call {Internal'LnGammaNum()} to evaluate logarithms of such factorials to desired precision.
*E.G.
In> 7!!;
Result: 105;

*SEE BinomialCoefficient, Product, Gamma, !, ***, Subfactorial
%/mathpiper_docs