%mathpiper,def="SumFunc"

LocalSymbols(c,d,expr,from,to,summand,sum,predicate,n,r,var,x) [

// Attempt to Sum series

Function() SumFunc(k,from,to,summand, sum, predicate );
Function() SumFunc(k,from,to,summand, sum);
HoldArgument(SumFunc,predicate);
HoldArgument(SumFunc,sum);
HoldArgument(SumFunc,summand);

// Difference code does not work
SumFunc(_sumvar,sumfrom_IsInteger,_sumto,_sumbody,_sum) <--
[
	// Take the given answer and create 2 rules, one for an exact match
	// for sumfrom, and one which will catch sums starting at a different
	// index and subtract off the difference

	`(40 # Sum(@sumvar,@sumfrom,@sumto,@sumbody )	<-- Eval(@sum) );
	`(41 # Sum(@sumvar,p_IsInteger,@sumto,@sumbody)_(p > @sumfrom)
	     <--
	     [
	          Local(sub);
		  (sub := Eval(ListToFunction({Sum,sumvar'arg,@sumfrom,p-1,sumbody'arg})));
		  Simplify(Eval(@sum) - sub );
             ]);
];

SumFunc(_sumvar,sumfrom_IsInteger,_sumto,_sumbody,_sum,_condition) <--
[

	`(40 # Sum(@sumvar,@sumfrom,@sumto,@sumbody)_(@condition)    <-- Eval(@sum) );
	`(41 # Sum(@sumvar,p_IsInteger,@sumto,@sumbody )_(@condition And p > @sumfrom)
	     <--
	     [
	          Local(sub);
		  `(sub := Eval(ListToFunction({Sum,sumvar'arg,@sumfrom,p-1,sumbody'arg})));
		  Simplify(Eval(@sum) - sub );
             ]);
];

// Some type of canonical form is needed so that these match when
// given in a different order, like x^k/k! vs. (1/k!)*x^k
// works !
SumFunc(_k,1,_n,_c + _d,
  Eval(ListToFunction({Sum,sumvar'arg,1,n,c})) +
  Eval(ListToFunction({Sum,sumvar'arg,1,n,d}))
);
SumFunc(_k,1,_n,_c*_expr,Eval(c*ListToFunction({Sum,sumvar'arg,1,n,expr})), IsFreeOf(k,c) );
SumFunc(_k,1,_n,_expr/_c,Eval(ListToFunction({Sum,sumvar'arg,1,n,expr})/c), IsFreeOf(k,c) );

// this only works when the index=1
// If the limit of the general term is not zero, then the series diverges
// We need something like IsUndefined(term), because this croaks when limit return Undefined
//SumFunc(_k,1,Infinity,_expr,Infinity,Eval(Abs(ListToFunction({Limit,sumvar'arg,Infinity,expr})) > 0));
SumFunc(_k,1,Infinity,1/_k,Infinity);

SumFunc(_k,1,_n,_c,c*n,IsFreeOf(k,c) );
SumFunc(_k,1,_n,_k, n*(n+1)/2 );
//SumFunc(_k,1,_n,_k^2, n*(n+1)*(2*n+1)/6 );
//SumFunc(_k,1,_n,_k^3, (n*(n+1))^2 / 4 );
SumFunc(_k,1,_n,_k^_p,(Bernoulli(p+1,n+1) - Bernoulli(p+1))/(p+1), IsInteger(p) );
SumFunc(_k,1,_n,2*_k-1, n^2 );
SumFunc(_k,1,_n,HarmonicNumber(_k),(n+1)*HarmonicNumber(n) - n );

// Geometric series! The simplest of them all ;-)
SumFunc(_k,0,_n,(r_IsFreeOf(k))^(_k), (1-r^(n+1))/(1-r) );

// Infinite Series
// this allows Zeta a complex argument, which is not supported yet
SumFunc(_k,1,Infinity,1/(_k^_d), Zeta(d), IsFreeOf(k,d) );
SumFunc(_k,1,Infinity,_k^(-_d), Zeta(d), IsFreeOf(k,d) );

SumFunc(_k,0,Infinity,_x^(2*_k+1)/(2*_k+1)!,Sinh(x) );
SumFunc(_k,0,Infinity,(-1)^k*_x^(2*_k+1)/(2*_k+1)!,Sin(x) );
SumFunc(_k,0,Infinity,_x^(2*_k)/(2*_k)!,Cosh(x) );
SumFunc(_k,0,Infinity,(-1)^k*_x^(2*_k)/(2*_k)!,Cos(x) );
SumFunc(_k,0,Infinity,_x^(2*_k+1)/(2*_k+1),ArcTanh(x) );
SumFunc(_k,0,Infinity,1/(_k)!,Exp(1) );
SumFunc(_k,0,Infinity,_x^_k/(_k)!,Exp(x) );
40 # Sum(_var,_from,Infinity,_expr)_( `(Limit(@var,Infinity)(@expr)) = Infinity) <-- Infinity;

SumFunc(_k,1,Infinity,1/BinomialCoefficient(2*_k,_k), (2*Pi*Sqrt(3)+9)/27 );
SumFunc(_k,1,Infinity,1/(_k*BinomialCoefficient(2*_k,_k)), (Pi*Sqrt(3))/9 );
SumFunc(_k,1,Infinity,1/(_k^2*BinomialCoefficient(2*_k,_k)), Zeta(2)/3 );
SumFunc(_k,1,Infinity,1/(_k^3*BinomialCoefficient(2*_k,_k)), 17*Zeta(4)/36 );
SumFunc(_k,1,Infinity,(-1)^(_k-1)/_k, Ln(2) );

];

%/mathpiper
