Sindbad~EG File Manager
/* infinite series */
/*
2.6.92 original date
1.21.99 last modified
9.2.04 added get_new_fname, which used to be in userfunc.c
*/
#include <string.h>
#include <assert.h>
#define SERIES_DLL
#include "globals.h"
#include "series.h"
#include "match.h"
#include "prover.h" /* getnewindexvar */
#include "symbols.h"
#include "errbuf.h"
#include "psubst.h"
#include "pvalaux.h" /* twoparts */
#include "ssolve.h"
#include "userfunc.h"
/*________________________________________________________________*/
MEXPORT_SERIES int oneminusxseries(term t, term arg, term *next, char *reason)
{ int flag=0;
term a,temp,denom;
int err;
term n;
short savenextassumption = get_nextassumption();
if(!FRACTION(t))
return 1;
denom = ARG(1,t);
if(FUNCTOR(denom) != '+' || ARITY(denom) != 2)
return 1;
temp = make_fraction(one,sum(one,tnegate(var0)));
err = unify1(temp,t,&a,&flag);
if(err)
{ RELEASE(ARG(1,temp));
RELEASE(temp);
return 1;
}
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
err = check(lessthan(abs1(a),one));
if(err)
{ errbuf(0,english(2325)); /* The resulting series would not be convergent */
set_nextassumption(savenextassumption);
return 1;
}
err = infer(equation(a,zero));
if(!err)
{ errbuf(0,english(2326)); /* The resulting series would converge only at isolated points */
set_nextassumption(savenextassumption);
return 1;
}
*next = sigma(make_power(a,n),n,zero,infinity);
HIGHLIGHT(*next);
strcpy(reason,"$$1/(1-x) = sum(x^n,n,0,infinity)$$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int oneminusxseries2(term t, term arg, term *next, char *reason)
/* 1/(1-x) = ... with 3 terms and ldots */
{ term temp;
int err = oneminusxseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"$1/(1-x)=1+x+x^2+...$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int oneminusxseries3(term t, term arg, term *next, char *reason)
/* 1/(1-x) = ... with 2 terms and ldots and general term */
{ term temp;
int err = oneminusxseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
HIGHLIGHT(*next);
strcpy(reason,"$1/(1-x)=1+x+...x�...$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int oneplusxseries(term t, term arg, term *next, char *reason)
{ int flag=0;
term a,temp,denom;
short savenextassumption = get_nextassumption();
int err;
term n;
if(!FRACTION(t))
return 1;
denom = ARG(1,t);
if(FUNCTOR(denom) != '+' || ARITY(denom) != 2)
return 1;
if(ONE(ARG(1,denom)))
temp = make_fraction(one,sum(var0,one));
else
temp = make_fraction(one,sum(one,var0));
err = unify1(temp,t,&a,&flag);
if(err)
{ RELEASE(ARG(1,temp));
RELEASE(temp);
return 1;
}
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
err = check(lessthan(abs1(a),one));
if(err)
{ errbuf(0,english(2325)); /* The resulting series would not be convergent */
set_nextassumption(savenextassumption);
return 1;
}
err = infer(equation(a,zero));
if(!err)
{ errbuf(0,english(2326)); /* The resulting series would converge only at isolated points */
set_nextassumption(savenextassumption);
return 1;
}
*next = sigma(product(make_power(minusone,n),make_power(a,n)),n,zero,infinity);
HIGHLIGHT(*next);
strcpy(reason,"$$1/(1+x) = sum((-1)^nx^n,n,0,infinity)$$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int oneplusxseries2(term t, term arg, term *next, char *reason)
/* 1/(1+x) = ... with 3 terms and ldots */
{ term temp;
int err = oneplusxseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"$1/(1+x)=1-x+x^2+...$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int oneplusxseries3(term t, term arg, term *next, char *reason)
/* 1/(1+x) = ... with 2 terms and ldots and general term */
{ term temp;
int err = oneplusxseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
HIGHLIGHT(*next);
strcpy(reason,"$1/(1+x)=1-x+...x�...$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int lnseries(term t, term arg, term *next, char *reason)
/* ln(1-x) = x+x^2/2+...+x�/n... */
{ int flag=0;
term a,temp;
int err;
term n;
short savenextassumption;
temp = ln1(sum(one,tnegate(var0)));
err = unify1(temp,t,&a,&flag);
if(err)
{ RELEASE(ARG(0,temp));
RELEASE(temp);
temp = ln1(sum(one,var0));
err = unify1(temp,t,&a,&flag);
if(err)
{ RELEASE(ARG(0,temp));
RELEASE(temp);
return 1;
}
}
savenextassumption = get_nextassumption();
err = check(lessthan(abs1(a),one));
if(err)
{ errbuf(0,english(2325)); /* The resulting series would not be convergent */
set_nextassumption(savenextassumption);
return 1;
}
err = infer(equation(a,zero));
if(!err)
{ errbuf(0,english(2326)); /* The resulting series would converge only at isolated points */
set_nextassumption(savenextassumption);
return 1;
}
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
*next = sigma(make_fraction(make_power(a,n),n),n,one,infinity);
strcpy(reason,"$$ln(1-x) = sum(x^n/n,n,1,infinity)$$");
HIGHLIGHT(*next);
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int lnseries2(term t, term arg, term *next, char *reason)
/* ln(1-x) = ... with 3 terms and ldots */
{ term temp;
int err = lnseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"ln(1-x) = x+x^2/2+x^3/3...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int lnseries3(term t, term arg, term *next, char *reason)
/* 1/(1+x) = ... with 2 terms and ldots and general term */
{ term temp;
int err = lnseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
strcpy(reason,"ln(1+x) = x+x^2/2+...x^n/3...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int lnseriesminus(term t, term arg, term *next, char *reason)
/* ln(1+x) = x-x^2/2+...+x�/n... */
{ int flag=0;
term a,temp;
int err;
term n;
short savenextassumption;
temp = ln1(sum(one,var0));
err = unify1(temp,t,&a,&flag);
if(err)
{ RELEASE(ARG(0,temp));
RELEASE(temp);
temp = ln1(sum(one,var0));
err = unify1(temp,t,&a,&flag);
if(err)
{ RELEASE(ARG(0,temp));
RELEASE(temp);
return 1;
}
}
savenextassumption = get_nextassumption();
err = check(lessthan(abs1(a),one));
if(err)
{ errbuf(0,english(2325)); /* The resulting series would not be convergent */
set_nextassumption(savenextassumption);
return 1;
}
err = infer(equation(a,zero));
if(!err)
{ errbuf(0,english(2326)); /* The resulting series would converge only at isolated points */
set_nextassumption(savenextassumption);
return 1;
}
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
*next = sigma(product(make_power(minusone,sum(n,one)),make_fraction(make_power(a,n),n)),n,one,infinity);
strcpy(reason,"$$ln(1-x)= sum((-1)^nx^(n+1),n,1,infinity)$$");
HIGHLIGHT(*next);
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int lnseriesminus2(term t, term arg, term *next, char *reason)
/* ln(1+x) = ... with 3 terms and ldots */
{ term temp;
int err = lnseriesminus(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"ln(1+x) = x-x^2/2+x^3/3-...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int lnseriesminus3(term t, term arg, term *next, char *reason)
/* 1/(1+x) = ... with 2 terms and ldots and general term */
{ term temp;
int err = lnseriesminus(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
strcpy(reason,"ln(1+x) = x+x^2/2+...x^n/3...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int expseries(term t, term arg, term *next, char *reason)
/* e^x = 1+x+...x�/n!... */
{ term a,n;
if(FUNCTOR(t) != '^')
return 1;
if(!equals(ARG(0,t),eulere))
return 1;
a = ARG(1,t);
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
*next = sigma(make_fraction(make_power(a,n),factorial1(n)),n,zero,infinity);
HIGHLIGHT(*next);
strcpy(reason,"$$e^x = sum(x^n/n!,n,0,infinity)$$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int expseries2(term t, term arg, term *next, char *reason)
/* 1/(1-x) = ... with 3 terms and ldots */
{ term temp;
int err = expseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"e^x = 1+x+x^2/2!+...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int expseries3(term t, term arg, term *next, char *reason)
/* 1/(1-x) = ... with 2 terms and ldots and general term */
{ term temp;
int err = expseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
HIGHLIGHT(*next);
strcpy(reason,"e^x = 1+x+...x^n/n!...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int negexpseries(term t, term arg, term *next, char *reason)
/* e^-x = 1-x+...x�/n!... */
{ term a,n;
if(FUNCTOR(t) != '^')
return 1;
if(!equals(ARG(0,t),eulere))
return 1;
a = ARG(1,t);
if(!NEGATIVE(a))
return 1;
a = ARG(0,a);
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
*next = sigma(make_fraction(product(make_power(minusone,n),make_power(a,n)),factorial1(n)),n,zero,infinity);
HIGHLIGHT(*next);
strcpy(reason,"$$e^x = sum((-1)^nx^n/n!,n,0,infinity)$$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int negexpseries2(term t, term arg, term *next, char *reason)
/* 1/(1-x) = ... with 3 terms and ldots */
{ term temp;
int err = negexpseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"e^-x = 1-x+x^2/2!+...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int negexpseries3(term t, term arg, term *next, char *reason)
/* 1/(1-x) = ... with 2 terms and ldots and general term */
{ term temp;
int err = negexpseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
HIGHLIGHT(*next);
strcpy(reason,"e^x = 1-x+...x^n/n!...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int sinseries(term t, term arg, term *next, char *reason)
/* expand sin x in a power series */
{ term a,twonplusone,n;
if(FUNCTOR(t) != SIN)
return 1;
a = ARG(0,t);
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
twonplusone = sum(product(two,n),one);
*next = sigma(product(make_fraction(make_power(minusone,n),factorial1(twonplusone)),
make_power(a,twonplusone)
),
n,zero,infinity
);
SETCOLOR(*next,YELLOW);
strcpy(reason,"$$sin x = sum((-1)^n/(2n+1)! x^(2n+1),n,0,infinity)$$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int sinseries2(term t, term arg, term *next, char *reason)
/* sin x = ... with 3 terms and ldots */
{ term temp;
int err = sinseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"sin x = x-x^3/3!+x^5/5!+...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int sinseries3(term t, term arg, term *next, char *reason)
/* sin x = ... with 2 terms and ldots and general term */
{ term temp;
int err = sinseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
HIGHLIGHT(*next);
strcpy(reason,"sin x = x-x^3/3!+(-1)^nx^n/n!+...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int cosseries(term t, term arg, term *next, char *reason)
/* expand cos x in a power series */
{ term a,twon,n;
if(FUNCTOR(t) != COS)
return 1;
a = ARG(0,t);
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
twon = product(two,n);
*next = sigma(product(make_fraction(make_power(minusone,n),factorial1(twon)),
make_power(a,twon)
),
n,zero,infinity
);
HIGHLIGHT(*next);
strcpy(reason, "$$cos x = sum((-1)^n/(2n)! x^(2n),n,0,infinity)$$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int cosseries2(term t, term arg, term *next, char *reason)
/* cos x = ... with 3 terms and ldots */
{ term temp;
int err = cosseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"cos x = 1-x^2/2+x^4/4!+...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int cosseries3(term t, term arg, term *next, char *reason)
/* cos x = ... with 2 terms and ldots and general term */
{ term temp;
int err = cosseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
HIGHLIGHT(*next);
strcpy(reason,"cos x = 1-x^2/2!+(-1)^nx^(2n)/(2n)!+...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int atanseries(term t, term arg, term *next, char *reason)
/* atan x = x - x^3/3 + x^5/5... */
{ term a,twonplusone,n;
int err;
short savenextassumption;
if(FUNCTOR(t) != ATAN)
return 1;
a = ARG(0,t);
savenextassumption = get_nextassumption();
err = check(lessthan(abs1(a),one));
if(err)
{ errbuf(0,english(2325)); /* The resulting series would not be convergent */
set_nextassumption(savenextassumption);
return 1;
}
err = infer(equation(a,zero));
if(!err)
{ errbuf(0,english(2326)); /* The resulting series would converge only at isolated points */
set_nextassumption(savenextassumption);
return 1;
}
n = getnewindexvar(t,"knmjpqrs");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
twonplusone = sum(product(two,n),one);
*next = sigma(product(make_power(minusone,n),
make_fraction(make_power(a,twonplusone),twonplusone)
),
n,zero,infinity
);
HIGHLIGHT(*next);
strcpy(reason,"$$arctan x = sum((-1)^k (x^(2k+1)/(2k+1)),k,0,infinity)$$");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int atanseries2(term t, term arg, term *next, char *reason)
/* atan x = ... with 3 terms and ldots */
{ term temp;
int err = atanseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),tnegate(three));
HIGHLIGHT(*next);
strcpy(reason,"atan x = x-x^3/3+x^5/5+...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int atanseries3(term t, term arg, term *next, char *reason)
/* atan x = ... with 2 terms and ldots and general term */
{ term temp;
int err = atanseries(t,arg,&temp,reason);
if(err)
return 1;
*next = series(ARG(0,temp),ARG(1,temp),ARG(2,temp),ARG(3,temp),two);
HIGHLIGHT(*next);
strcpy(reason,"atan x = x-x^3/3+... +x^(2n+1)/(2n+1)+...");
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int difseries(term t, term arg, term *next, char *reason)
/* Push d/dx into sigma for a power series */
{ term u,n,lo,hi,s,x,a;
if(FUNCTOR(t) != DIFF)
return 1;
x = ARG(1,t);
s = ARG(0,t);
if(!is_power_series(s,x,&a))
return 1;
u = ARG(0,s);
n = ARG(1,s);
lo = ARG(2,s);
hi = ARG(3,s);
*next = ARITY(s) == 4 ? sigma(diff(u,arg),n,lo,hi) : series(diff(u,arg),n,lo,hi,ARG(4,s));
strcpy(reason,"$d/dx( u) = � du/dx$");
if(equals(hi,infinity))
strcat(reason,english(2170)); /* for power series */
HIGHLIGHT(ARG(0,*next));
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int intseries(term t, term arg, term *next, char *reason)
/* Integrate a power series term by term */
{ term u,n,s,x,lo,a,w,c,b,newpower;
if(FUNCTOR(t) != INTEGRAL)
return 1;
s = ARG(0,t);
x = ARG(1,t);
if(!is_power_series(s,x,&a))
return 1;
u = ARG(0,s);
n = ARG(1,s);
lo = ARG(2,s);
twoparts(u,x,&c,&b);
if(FUNCTOR(b)!='^')
return 1; /* assert(0), since is_power_series succeeded */
polyval(sum(ARG(1,b),one),&newpower);
/* make w the evaluated indefinite integral of u */
polyval(make_fraction(product(c,make_power(ARG(0,b),newpower)),newpower),&w);
if(ARITY(t) == 2)
{ /* an indefinite integral */
*next = ARITY(s) == 4 ? sigma(w,n,lo,infinity) : series(w,n,lo,infinity,ARG(4,s));
/* Mathpert's general machinery will insert a constant of integration */
}
else
{ /* a definite integral */
*next = ARITY(s) == 4 ? sigma(evalat(w,x,ARG(2,t),ARG(3,t)),n,lo,infinity):
series(evalat(w,x,ARG(2,t),ARG(3,t)),n,lo,infinity,ARG(4,s));
}
strcpy(reason, english(2327)); /* integrate power series term by term */
SETCOLOR(ARG(0,*next),YELLOW);
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int reversedifseries(term t, term arg, term *next, char *reason)
/* pull d/dx out of a series. */
{ term u,n,lo,hi,w;
if(FUNCTOR(t) != SUM)
return 1;
u = ARG(0,t);
n = ARG(1,t);
lo = ARG(2,t);
hi = ARG(3,t);
if(FUNCTOR(u) != DIFF)
return 1;
w = ARITY(t) == 4 ? sigma(ARG(0,u),n,lo,hi) : series(ARG(0,u),n,lo,hi,ARG(4,t));
*next = diff(w,ARG(1,u));
strcpy(reason,"$ � du/dx = d/dx � u$");
if(equals(hi,infinity))
strcat(reason,english(2170)); /* for power series */
HIGHLIGHT(ARG(0,*next));
return 0;
}
/*________________________________________________________________*/
MEXPORT_SERIES int reverseintseries(term t, term arg, term *next, char *reason)
{ term u,n,lo,hi,w;
if(FUNCTOR(t) != SUM)
return 1;
u = ARG(0,t);
n = ARG(1,t);
lo = ARG(2,t);
hi = ARG(3,t);
if(FUNCTOR(u) != INTEGRAL)
return 1;
w = ARITY(t) == 4 ? sigma(ARG(0,u),n,lo,hi) : series(ARG(0,u),n,lo,hi,ARG(4,t));
if(ARITY(u) == 2)
*next = integral(w,ARG(1,u));
else
*next = definite_integral(w,ARG(1,u),ARG(2,u),ARG(3,u));
strcpy(reason,"$�(� u) dx = � �u dx$");
if(equals(hi,infinity))
strcat(reason,english(2170)); /* for power series */
SETCOLOR(ARG(0,*next),YELLOW);
return 0;
}
/*________________________________________________________________________*/
MEXPORT_SERIES int seriesfirstterms(term t, term arg, term *next, char *reason)
/* split off the first few terms (how many is given by arg) of an infinite series. */
/* The number of terms is limited to 1000 */
{ long nn;
unsigned short n;
term l,newlo,temp,index,q,last,u;
int saveflag;
int i;
aflag flag1, flag2;
if(!ISINTEGER(arg))
return 1;
nn = INTDATA(arg);
if(nn > 1000)
{ errbuf(0, english(828));
/* You can't show more than 1000 terms */
return 1;
}
flag1 = flag2 = get_arithflag();
flag1.intexp = flag1.ratexp = flag1.negexp = flag1.fract = flag1.gcd = 0;
set_arithflag(flag1);
n = (unsigned short) nn;
if(FUNCTOR(t) != SUM)
return 1;
if(!equals(ARG(3,t),infinity))
return 1;
q = ARG(0,t); /* summand */
l = ARG(2,t); /* lower limit of sum */
index = ARG(1,t); /* index variable */
saveflag = get_polyvalzeropowerflag();
set_polyvalzeropowerflag(1);
if(ZERO(l))
newlo = arg;
else
{ temp = sum(l,arg);
polyval(temp,&newlo);
}
*next = make_term('+',(unsigned short)(n+1));
for(i=0;i<n;i++)
{ polyval(sum(make_int(i),l),&temp);
subst(temp,index,q,&u);
polyval(u,ARGPTR(*next) + i);
HIGHLIGHT(ARG(i,*next));
}
set_polyvalzeropowerflag(saveflag);
set_arithflag(flag2);
copy(t,&last);
ARGREP(last,2,newlo);
HIGHLIGHT(ARG(2,last));
ARGREP(*next,n,last);
strcpy(reason, english(831)); /* split off first terms */
return 0;
}
/*________________________________________________________________________*/
MEXPORT_SERIES int seriesmoreterms(term t, term arg, term *next, char *reason)
/* lower the first limit of an infinite series, subtracting off the
corresponding terms. Example: sum(x^n,n,2,infinity) becomes
sum(x^n,n,0,infinity) - (1+x) */
/* The number of terms is limited to 1000 */
/* The prompt is, Decrease the lower limit by how much? */
{ long nn;
unsigned short n;
term l,newlo,temp,index,q,p,newseries;
int i;
if(!ISINTEGER(arg))
return 1;
nn = INTDATA(arg);
if(nn > 1000)
{ errbuf(0, english(2245));
/* You can't insert more than 1000 terms */
return 1;
}
n = (unsigned short) nn;
if(FUNCTOR(t) != SUM)
return 1;
if(!equals(ARG(3,t),infinity))
return 1;
if(equals(ARG(2,t),minusinfinity))
return 1;
q = ARG(0,t); /* summand */
l = ARG(2,t); /* lower limit of sum */
index = ARG(1,t); /* index variable */
if(ZERO(l))
newlo = tnegate(arg);
else if(equals(arg,l))
newlo = zero;
else
{ temp = sum(l,tnegate(arg));
polyval(temp,&newlo);
}
p = make_term('+',n);
for(i=0;i<n;i++)
{ polyval(sum(make_int(i),newlo),&temp);
subst(temp,index,q,ARGPTR(p) + i);
}
HIGHLIGHT(p);
copy(t,&newseries);
ARGREP(newseries,2,newlo);
HIGHLIGHT(ARG(2,newseries));
*next = sum(newseries,tnegate(p));
strcpy(reason, english(2252)); /* decrease lower limit */
return 0;
}
/*________________________________________________________________________*/
MEXPORT_SERIES int seriessubindex(term t, term arg, term *next, char *reason)
/* arg is in response to, Subtract ? from the index variable? */
{ term k; /* the index variable */
term hi,lo; /* the limits */
term u; /* the summand */
term newlo, v,kk;
if(FUNCTOR(t) != SUM || ARITY(t) != 4)
return 1;
u = ARG(0,t);
k = ARG(1,t);
lo = ARG(2,t);
hi = ARG(3,t);
if(!equals(hi,infinity))
return 1;
if(contains(arg,FUNCTOR(k)))
{ errbuf(0, english(2239));
/* expression to shift by cannot depend on the index variable */
return 1;
}
if(equals(lo,minusinfinity))
newlo = minusinfinity;
else
polyval(sum(lo,arg),&newlo);
polyval(sum(k,tnegate(arg)),&kk);
HIGHLIGHT(kk);
subst(kk,k,u,&v);
*next = make_term(SUM,4);
ARGREP(*next,0,v);
ARGREP(*next,1,k);
HIGHLIGHT(newlo);
ARGREP(*next,2,newlo);
ARGREP(*next,3,infinity);
strcpy(reason, english(2247)); /* subtract from index variable */
return 0;
}
/*________________________________________________________________________*/
MEXPORT_SERIES int seriesaddindex(term t, term arg, term *next, char *reason)
/* arg is in response to, Add ? to the index variable? */
{ int err = seriessubindex(t,tnegate(arg),next,reason);
if(err)
return 1;
strcpy(reason,english(2246)); /* add to index variable */
return 0;
}
/*________________________________________________________________________*/
MEXPORT_SERIES int seriesintdif(term t, term arg, term *next, char *reason)
/* */
{ term x;
if(!equals(t,history(get_currentline())))
return 1;
x = get_eigenvariable();
if(!contains(t,FUNCTOR(x)))
return 1;
*next = integral(diff(t,x),x);
HIGHLIGHT(*next);
strcpy(reason,"$$u = integral(diff(u,x),x)$$");
return 0;
}
/*________________________________________________________________________*/
MEXPORT_SERIES int seriesintdifdef(term t, term arg, term *next, char *reason)
/* $$u = integral(diff(u,t),t,0,x) + u0$$ */
{ term x,v,t0,tofv;
x = get_eigenvariable();
if(!equals(t,history(get_currentline())))
return 1;
x = get_eigenvariable();
if(!contains(t,FUNCTOR(x)))
return 1;
v = getnewvar(t,"tuvwz");
psubst(zero,x,t,&t0);
subst(v,x,t,&tofv);
*next = sum(definite_integral(diff(tofv,v),v,zero,x),t0);
HIGHLIGHT(*next);
strcpy(reason,"$$u = integral(diff(u,t),t,0,x) + u0$$");
return 0;
}
/*________________________________________________________________________*/
MEXPORT_SERIES int seriesdifint(term t, term arg, term *next, char *reason)
/* $$u = diff(integral(u,x),x)$$ */
{ term x;
if(!equals(t,history(get_currentline())))
return 1;
x = get_eigenvariable();
if(!equals(t,history(get_currentline())))
return 1;
if(!contains(t,FUNCTOR(x)))
return 1;
*next = diff(integral(t,x),x);
HIGHLIGHT(*next);
strcpy(reason,"$$u = diff(integral(u,x),x)$$");
return 0;
}
/*________________________________________________________________________*/
static int get_origin(term t, term x, term *a)
/* if t contains a power series in (x-a) return a in *a;
if t contains a power series in x return zero in *a.
Return 0 for success.
*/
{ unsigned short i,n;
if(ATOMIC(t))
return 1;
if(FUNCTOR(t) == SUM && equals(ARG(3,t),infinity))
{ if(is_power_series(t,x,a))
return 0;
return 1;
}
n = ARITY(t);
for(i=0;i<n;i++)
{ if(get_origin(ARG(i,t),x,a) == 0)
return 0;
}
return 1;
}
/*________________________________________________________________________*/
static int get_cofi(term t, term *ans)
/* return a subterm of t with functor CONSTANTOFINTEGRATION in *ans,
if one exists, returning 0 for success.
*/
{ unsigned short i,n;
if(FUNCTOR(t) == CONSTANTOFINTEGRATION)
{ *ans = t;
return 0;
}
if(ATOMIC(t))
return 1;
n = ARITY(t);
for(i=0;i<n;i++)
{ if(get_cofi(ARG(i,t),ans) == 0)
return 0;
}
return 1;
}
/*________________________________________________________________________*/
MEXPORT_SERIES int eliminatecofi(term t, term arg, term *next, char *reason)
/* Solve for constant of integration */
/* example, once we have reduced arctan x to
x-x^3/3 + ... + C
we change C to arctan(0) with this operation
*/
{ term orig,x,a,u,v,w,r,q,ans;
int err;
int saveflag;
if(!equals(t,history(get_currentline())))
return 1;
x = get_eigenvariable();
if(contains(t,INTEGRAL))
return 1;
orig = history(0);
/* check if t contains a power series in x or (x-a) */
err = get_origin(t,x,&a);
if(err)
return 1;
subst(a,x,t,&u); /* example, t = x-x^2/2 +x^3/3 + ... + c1, a = 0 */
saveflag = get_polyvalzeropowerflag();
set_polyvalzeropowerflag(1);
polyval(u,&v); /* In the example v comes out 0 since polyval can simplify
a series with general term 0 to 0 */
subst(a,x,orig,&w); /* in the example, orig is ln(1+x) so w comes out ln 1 */
polyval(w,&q);
set_polyvalzeropowerflag(saveflag);
if(FUNCTOR(arg) != CONSTANTOFINTEGRATION)
{ err = get_cofi(t,&arg);
if(err)
return 1;
}
subst(x,arg,equation(v,q),&r); /* r comes out 0 + x = ln 1 */
err = ssolve(r,x,&ans); /* x = ln 1 */
if(err || FUNCTOR(ans) != '=')
return 1;
HIGHLIGHT(ARG(1,ans));
subst(ARG(1,ans),arg,t,next);
strcpy(reason, english(2324)); /* solve for constant of integration */
return 0;
}
/*____________________________________________________________________________________*/
MEXPORT_SERIES int is_power_series(term t, term x, term *a)
/* return 1 if t is a power series in x about x=a. Return a in *a. */
{ term c,s,base,u,c2,s2;
if(FUNCTOR(t) != SUM)
return 1;
if(!equals(ARG(3,t),infinity))
return 1;
u = ARG(0,t);
twoparts(u,x,&c,&s);
if(FUNCTOR(s) != '^')
{ if(FUNCTOR(s) == '/' || FUNCTOR(s) == '*')
twoparts(s,x,&c2,&s2);
if(FUNCTOR(s2)!= '^')
return 1;
polyval(product(c,c2),&c);
s = s2;
}
if(equals(ARG(0,s),x))
{ *a = zero;
return 1;
}
base = ARG(0,s);
if(FUNCTOR(base) != '+')
return 0;
polyval(sum(x,tnegate(base)),a);
return contains(*a,FUNCTOR(x)) ? 0 : 1;
}
/*____________________________________________________________*/
MEXPORT_SERIES int get_new_fname(unsigned short *f, char *buffer)
/* return a new function name suitable for use as coefficients in a
power series defined by series division; in this case Mathpert has
to make a (recursive) function definition internally. Return 0 for
success or 1 if there is no room for more function definitions, or
(very unlikely) all the candidate letters in the 'letters' array below
are used up.
*/
{ int i,j;
char *letters = "cabdpqrsuvwzCABPQRSUVWZ";
int nletters = strlen(letters);
char c;
char *name;
term *varlist = get_varlist();
int nvars = get_nvariables();
int nextfunction = nuserfunctions();
if(nextfunction == MAXUSERFUNCTIONS)
return 1;
/* pick the first member of 'letters' that is not in varlist or
already used for a function definition. */
for(i=0;i<nletters;i++)
{ c = letters[i];
for(j=0;j<nvars;j++)
{ if(FUNCTOR(varlist[j])==c)
break;
}
if(j<nvars)
continue;
for(j=0;j< (int)nextfunction;j++)
{ name = get_defnstring(j);
if(c == name[0] && name[1] == '(')
break;
}
if(j == (int)nextfunction)
break;
}
if(i==nletters)
return 1;
*f = (unsigned short) c;
buffer[0] = c;
buffer[1] = '\0';
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists