#	functional equation solver;
#	solve functional, difference and recurrence equation for function f(x) with independent variable x;
#	e.g. fsolve( difference(f(x))=x ); fsolve( f(x+1)=f(x)+2 );
#fsolve( difference(f(x_),x_)=y_,x_):=sum(y,x)+C1;
#fsolve( difference(f(x))+y_,x_):=sum(-y,x)+C1;
#fsolve( -f(x_)+f(x_+1)+z_,x_):=sum(-z,x)+C1;
#fsolve( a_-f(x_)+f(x_+1),x_):=sum(-a,x)+C1;
#fsolve( -f(x_-1)+f(x_)+z_,x_):=sum(-z,x)+C1;
#fsolve( a_-f(x_-1)+f(x_),x_):=sum(-a,x)+C1;
#fsolve(a_):=fsolve(a,y);


fsolve(f(x_)+b_):= -b;
fsolve(a_*f(x_)+b_):= -b/a;
fsolve(f(x_^n_)+b_):= -replace(b,x,x^(1/n));
fsolve(a_*f(x_^n_)+b_):= -replace(b/a,x,x^(1/n));

fsolve(f(x_^a_)+b_):= -replace(b,x,x^(1/a));
fsolve(f(x_^a_)+b_*f(x_)):=if(a==b and a<0,C_1*abs(log(x)),if(a+b==0,C_1*log(x),0 ));
fsolve(f(x_^a_)+f(x_^b_)):=if(a+b==0,C_1*log(x),0);
fsolve(f(a_*x_)+b_*f(x_)):=if(a+b==0,C_1*x,0);
fsolve(f(a_*x_)+b_*f(x_)+c_):=if(a+b==0,C_1*x-c);

fsolve( d_+a_*f(x_)+c_*f(b_+x_)):=if(hasnot(a,c,d,x),(-a/c)^(x/b)*C_1-d/(a+c));
fsolve( d_+f(x_)+c_*f(b_+x_)):=if(hasnot(c,d,x),(-1/c)^(x/b)*C_1-d/(1+c));
fsolve( f(x_+b_)+a_*f(x_)+c_):=if(hasnot(a,c,x),(-a)^(x/b)*C_1-c/(a+1));
fsolve( f(x_+b_)+f(x_)+c_):=if(hasnot(c,x),(-1)^(x/b)*C_1-c/2);
fsolve( a_*f(x_)+c_*f(b_+x_)):=if(hasnot(a,c,x),(-a/c)^(x/b)*C_);
fsolve( f(x_)+a_*f(b_+x_)):=if(hasnot(a,x),(-a)^(-x/b)*C_1);
fsolve( f(x_+b_)+a_*f(x_)):=if(hasnot(a,x),(-a)^(x/b)*C_1);

fsolve( a_*f(x_)+b_*f(1/x_)+c_*x_):=if(hasnot(a,b,c,x), b*c/(a^2-b^2)/x-a*c/(a^2-b^2)*x);
fsolve( f(x_)+f(1/x_)):=C_1*log(x);
fsolve( f(x_)-f(1/x_)):=C_1*abs(log(x));
fsolve( f(1/x_)-f(x_)):=C_1*abs(log(x));

fsolve( f(x_)-f(-1+x_)+z_):=sum(-z,x)+C_1;
fsolve( f(x_)-f(-1+x_)+a_):=sum(-a,x)+C_1;
fsolve( f(x_+1)-f(x_)+z_):=sum1(-z,x)+C_1;
fsolve( f(x_+1)-f(x_)+a_):=sum(-a,x)+C_1;
fsolve( f(x_+1)-f(x_)-1/x_):=H(x);
fsolve( f(x_+1)-f(x_)-x_):=x^2/2-x/2+C_1;
fsolve( f(x_+1)-f(x_)-x_+c_):=if(hasnot(c,x),x^2/2-x/2-c*x+C_1);
fsolve(f(x_+1)-f(x_)*(1+x_)):=C_1*x!;
fsolve(f(x_+1)-f(x_)*x_-f(x_)):=C_1*x!;
fsolve(f(x_+1)-f(x_)*x_):=C_1*Gamma(x);
fsolve(f(1-x_)+f(-x_)*x_):=C_1*Gamma(x);

fsolve(f(x_+y_)-f(x_)*f(y_)):=exp(x);
fsolve(f(x_-y_)-f(x_)/f(y_)):=exp(x);
fsolve(f(x_+y_)-f(x_)-f(y_)):=C_1*x;
fsolve(f(x_*y_)-f(x_)-f(y_)):=C_1*log(x);
fsolve(f(x_*y_)-f(x_)*f(y_)):=x^n;
fsolve(f(x_+y_)-f(x_)*f(y_)/f(x_+y_)):=C_1/x;
fsolve(f(x_^n_)-f(x_)^n_):=x^C_1;
fsolve(f(2x_)-2f(x_)^2+1):=cos(x);
fsolve(f(2x_^2-1)-2f(x_)):=C_1*acos(x);

#fsolve(f(x_+2)+c_*f(x_)):=if(hasnot(c,x),C_1*sqrt(-c)^x+C_2*(-sqrt(-c))^x);
#fsolve(f(x_+2)+b_*f(x_+1)+c_*f(x_)):=if(hasnot(b,c,x),C_1*(-b/2+sqrt(b*b-4c)/2)^x+C_2*(-b/2-sqrt(b*b-4c)/2)^x);
#fsolve(f(x_+2)-f(x_+1)-f(x_)):=C_1*fib(x)+C_2*lucas(x);
fsolve(f(x_+2pi)-f(x_)):=C_1*trig(x);
fsolve(f(x_)-f(x_+2pi)):=C_1*trig(x);
fsolve(f(x_+pi)-f(x_)):=C_1*trig(2x);
fsolve(f(x_)-f(x_+pi)):=C_1*trig(2x);

fsolve(f(-x_)+f(x_)):=C_1*odd(x);
fsolve(f(-x_)-f(x_)):=C_1*even(x);
fsolve(f(x_)-f(-x_)):=C_1*even(x);
fsolve(f(-x_)-1/f(x_)):=exp(x);
fsolve(1/f(x_)-f(-x_)):=exp(x);
fsolve(-1+f(-x_)*f(x_)):=exp(x);
fsolve(f(2+x_)+c_*f(x_)) := if(hasnot(c,x),C_1*(-sqrt(-c))^x+C_2*sqrt(-c)^x);
fsolve(f(2+x_)+c_*f(x_)+ak_) := if(hasnot(c,ak,x), if(c==-1,c_2* (-1)^x + c_1 + 1/4ak*((-1)^(2 x) - 2 x),C_1*(-sqrt(-c))^x+C_2*sqrt(-c)^x-k/(1+c)) );
fsolve(f(2+x_)+b_*f(1+x_)) :=C_2+fsolve(f(x+1)+b*f(x));
fsolve(f(g(x))-g(f(x))):=x;

fsolve(f(x_+y_)+f(x_-y_)+(-2)*f(x_)*f(y_)):=cos(c_1*x);
fsolve(f(2+x_)+f(1+x_)+c_*f(x_)) :=rsolution(1,2,1,1,c);
fsolve(f(2+x_)+b_*f(1+x_)+f(x_)) :=rsolution(1,2,b,1,1);
fsolve(f(2+x_)+b_*f(1+x_)+c_*f(x_)) :=rsolution(1,2,b,1,c);
fsolve(a_*f(2+x_)+b_*f(1+x_)+c_*f(x_)) :=rsolution(a,2,b,1,c);

fsolve(f(2+x_)+b_*f(1+x_)+c_*f(x_)+ak_) := if(hasnot(ak,x), if(1+b+c==0,-ak/(2+b)*x+C_1+C_2*c^x, -ak/(1+b+c)+rsolution(1,2,b,1,c) ));
fsolve(f(2+x_)+b_*f(1+x_)+f(x_)+ak_) := if(hasnot(ak,x), if(b==-2,-ak*x^2/2+C_1+C_2*x,-ak/(2+b)+rsolution(1,2,b,1,1) ));


fsolve(a_=b_):=fsolve(a-b);
fsolve( f(x_)-f(-1+x_)=a_):=sum(a,x)+C_1;
fsolve( f(x_+1)-f(x_)=a_):=sum1(a,x)+C_1;
fsolve(2f(x_+1)=f(x_)*f(x_+1)+1):=x/(x+1);
fsolve(f(x_+1)=f(x_)+f(-1+x_)):=C_1*fibonacci(x);