# AVSLib :: 'numeric' package :: 'powseries' module
# Copyright (c) 2005 George Zarkadas (gzarkadas@users.sourceforge.net)

# This program is free software; you can redistribute it and/or modify it under the terms of 
# the GNU General Public License as published by the Free Software Foundation; either 
# version 2 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
# PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this program; 
# if not, write to the "Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
# MA  02111-1307  USA"

DefineModule("avslib", "numeric", "powseries")

# Returns the factorial of x.
#
Function Factorial(int x)
{
	Assert(x >= 0, "Factorial: cannot accept negative values")
	return (x >= 1) ? x * Factorial(x - 1) : 1
}

# Returns the power series of 'x' generated by summing 
#     coef_func(i, coef_args) * Pow( x, power_func(i, power_args) ) 
# for all i's in the range [start_index..end_index), ie 'end_index' is NOT included.
# If 'xxx_args' contains any string arguments, they must be quoted, else the function 
# will fail.
# 'start_index' must be <= 'end_index' and 'increment' must be >=1.
# If 'start_index' == 'end_index' the function returns zero.
# NOTE that since 'coef_func' and 'power_func' are the first constituents of the 
# constructed string for Eval you can perform simple operations with constants 
# and globals inside those strings, such as multiplication and addition 
# (eg. set coef_func to "2 +  funcname"). 
#
Function PowSeries(float x, string coef_func, string power_func, int start_index, \
	int end_index, int "increment", string "coef_args", string "power_args") 
{
	increment = Default(increment, 1)
	Assert(increment >= 1, \
		"PowSeries: 'increment' must be >= 1.")
	Assert(start_index <= end_index, \
		"PowSeries: 'start_index' must be <= 'end_index'.")
	co_str = coef_func + "(" + String(start_index) + \
		(Defined(coef_args) ? "," + coef_args : "") + ")"
	pw_str = power_func + "(" + String(start_index) + \
		(Defined(power_args) ? "," + power_args : "") + ")"
	# do not evaluate series term if we are at the end 
	return (start_index < end_index) \
		? Eval(co_str) * Pow(x, Eval(pw_str)) + PowSeries(x, coef_func, \
			power_func, start_index + increment, end_index, increment, \
			coef_args, power_args) \
		: 0
}

# Returns the polynomial of x generated by summing
#     coef_func(i, coef_args) * Pow( x, i)
# for all i's in the range [start_index..end_index) (end_index is NOT included).
# For an explanation of each argument see the 'PowSeries' documentation.
#
Function Polynomial(float x, string coef_func, int start_index, int end_index, \
	int "increment", string "coef_args") 
{
	return PowSeries(x, coef_func, "__self", start_index, end_index, \
		increment, coef_args)
}
