Sindbad~EG File Manager
/* M. Beeson for series.dll
Select series operations for the Term Selection Menu
*/
/* Original date 2.28.00
Last modified 6.17.00
1.23.06 added sumtodifofsums and sumtodifofsums0
5.6.13 include stddef.h, removed unused variable somewhere.
include sselect.h
5.15.13 added cotseries, bernoulliseries,tanseries,sinseries,cosseries
5.24.13 added secseries
5.29.13 corrected parens at line 238
6.5.13 put in addtozeta
6.8.13 Only show the convergence tests when FUNCTOR(t) == SUM and pathlength <= 1
6.11.13 corrected the start of select_series_op not to access args of input until after checking it's a series.
added condensationtest and finishcondensationtest to select_series_op
6.12.13 added multnumdenom to expand_op
6.12.13 added more to select_series_op
8.20.13 added lnseriesrev
1.9.25 added condensationtest for the harmonic series
*/
#include <math.h>
#include <string.h> /* memset */
#include <assert.h>
#include <stddef.h>
#include "globals.h"
#include "graphstr.h"
#include "mpdoc.h"
#include "tdefn.h"
#include "trig.h"
#include "calc.h"
#include "display.h"
#include "display1.h" /* needed by lterm.h */
#include "bigrect.h"
#include "lterm.h"
#include "selectop.h"
#include "automode.h"
#include "cflags.h"
#include "probtype.h"
#include "calc.h"
#include "pvalaux.h" /* twoparts, iseven, isodd */
#include "prover.h" /* NOTDEFINED */
#include "docdata.h" /* history */
#include "select2.h"
#include "series.h" /* is_power_series */
#include "islinear.h" /* islinear */
#include "scontrol.h" /* used4 */
#include "sselect.h" /* select_series_op */
#include "order.h" /* numerical */
#include "autosimp.h" /* get_pathlength */
#include "polynoms.h" /* ispolyin */
static int contains_power_of_minusone(term t);
/*_________________________________________________*/
static int contains_power_of_minusone(term t)
/* return 1 if t contains a power of minusone, 0 if not
*/
{ unsigned short i,n,f;
if(ATOMIC(t))
return 0;
f = FUNCTOR(t);
if(f == '^' && equals(ARG(0,t),minusone))
return 1;
n = ARITY(t);
for(i=0;i<n;i++)
{ if(contains_power_of_minusone(ARG(i,t)))
return 1;
}
return 0;
}
/*______________________________________________________________________________*/
static void expand_op(term t, actualop *o, int *nops)
/* t is an expression to be expanded in a series; suggest operations to try.
Also t can be a term of a series, where we need writeaspoly */
{ term u,v,x;
unsigned short f,g,h;
int i = 0;
term * varlist = get_varlist();
int nvars = get_nvariables();
char reason[DIMREASONBUFFER];
// we need to get the series variable, but the eigenvariable is the summation variable
if(nvars > 0)
x = varlist[0];
if( (FRACTION(t) || FUNCTOR(t) == '*') && nvars > 0 && noccurs(x,t) == 1 && !writeaspoly(t,x,&u,reason))
// only show "write as polynomial" if it's going to work
{ o[i] = writeaspoly; ++i;
}
if(FRACTION(t))
{ u = ARG(0,t);
v = ARG(1,t);
g = FUNCTOR(u);
h = FUNCTOR(v);
if(FUNCTOR(v) == '+' && ARITY(v) == 3 && ispolyin(v,x))
{ o[i] = multnumdenom; ++i; // example, x/(x^2+x+1), multiply num and denom by 1-x
}
// partialfractionsop shows up without being listed here
if(ONE(u) && h == '^' && numerical(ARG(1,v)) && FUNCTOR(ARG(0,v))== '+' && ONE(ARG(0,ARG(0,v))))
{ o[i] = binomialseries; ++i;
}
if(ONE(u) && h == '+' && ARITY(v) == 2)
{ if(ONE(ARG(0,v)) && NEGATIVE(ARG(1,v)))
{ o[i] = oneminusxseries; ++i;
o[i] = oneminusxseries2; ++i;
o[i] = oneminusxseries3; ++i;
}
else if(ONE(ARG(0,v)) || ONE(ARG(1,v)))
{ o[i] = oneplusxseries; ++i;
o[i] = oneplusxseries2; ++i;
o[i] = oneplusxseries3; ++i;
}
}
if(h == '+' && ARITY(v) == 2 && ONE(ARG(1,v)))
{ if(equals(u,ARG(0,v)))
{ o[i] = xoveroneplusxseries; ++i;
o[i] = xoveroneplusxseries2; ++i;
o[i] = xoveroneplusxseries3; ++i;
}
}
if(h == '+' && ARITY(v) == 2 && ONE(ARG(0,v)))
{ if(equals(u,ARG(1,v)))
{ o[i] = xoveroneplusxseries; ++i;
o[i] = xoveroneplusxseries2; ++i;
o[i] = xoveroneplusxseries3; ++i;
}
if(NEGATIVE(ARG(1,v)) && equals(ARG(0,ARG(1,v)),u))
{ o[i] = xoveroneminusxseries; ++i;
o[i] = xoveroneminusxseries2; ++i;
o[i] = xoveroneminusxseries3; ++i;
}
if(NEGATIVE(ARG(1,v)) &&
FUNCTOR(ARG(0,ARG(1,v))) == '^' &&
equals(ARG(0,ARG(0,ARG(1,v))),u)
)
{ o[i] = xmoveroneminusxkseries; ++i;
o[i] = xmoveroneminusxkseries2; ++i;
o[i] = xmoveroneminusxkseries3; ++i;
}
if(NEGATIVE(ARG(1,v)) &&
FUNCTOR(ARG(0,ARG(1,v))) == '^' &&
ONE(u)
)
{ o[i] = oneoveroneminusxkseries; ++i;
o[i] = oneoveroneminusxkseries2; ++i;
o[i] = oneoveroneminusxkseries3; ++i;
}
if(ONE(u) && FUNCTOR(ARG(1,v)) == '^')
{ o[i] = oneoveroneplusxkseries; ++i;
o[i] = oneoveroneplusxkseries2; ++i;
o[i] = oneoveroneplusxkseries3; ++i;
}
if(NEGATIVE(ARG(1,v)) && FUNCTOR(u) == '^' &&
equals(ARG(0,ARG(1,v)),ARG(0,u))
)
{ o[i] = geometricseriesfromk; ++i;
o[i] = geometricseriesfromk2; ++i;
o[i] = geometricseriesfromk3; ++i;
}
if(g == '^' && equals(ARG(1,v),ARG(0,u)))
{ o[i] = geometricseriesminusfromk; ++i;
o[i] = geometricseriesminusfromk2; ++i;
o[i] = geometricseriesminusfromk3; ++i;
}
if(FUNCTOR(u) == '^' && NEGATIVE(ARG(1,v)) &&
FUNCTOR(ARG(0,ARG(1,v))) == '^' &&
equals(ARG(0,u),ARG(0,ARG(0,ARG(1,v))))
)
{ o[i] = xmoveroneminusxkseries; ++i;
o[i] = xmoveroneminusxkseries2; ++i;
o[i] = xmoveroneminusxkseries3; ++i;
}
if(FUNCTOR(u) == '^' &&
FUNCTOR(ARG(1,v)) == '^' &&
equals(ARG(0,u),ARG(0,ARG(1,v)))
)
{ o[i] = xmoveroneplusxkseries; ++i;
o[i] = xmoveroneplusxkseries2; ++i;
o[i] = xmoveroneplusxkseries3; ++i;
}
}
if(FUNCTOR(v) == '+' && ARITY(v) == 2 && equals(ARG(1,v),minusone) &&
FUNCTOR(ARG(0,v)) == '^' && equals(ARG(1,(ARG(0,v))),u) &&
equals(ARG(0,ARG(0,v)),eulere)
)
{ o[i] = bernoulliseries; ++i;
o[i] = bernoulliseries2; ++i;
o[i] = bernoulliseries3; ++i;
}
}
f = FUNCTOR(t);
switch(f)
{ case RIEMANNZETA:
o[i] = zetaseries; ++i;
o[i] = zetaseries2; ++i;
o[i] = zetaseries3; ++i;
break;
case SIN:
o[i] = sinseries; ++i;
o[i] = sinseries2; ++i;
o[i] = sinseries3; ++i;
break;
case COS:
o[i] = cosseries; ++i;
o[i] = cosseries2; ++i;
o[i] = cosseries3; ++i;
break;
case TAN:
o[i] = tanseries; ++i;
o[i] = tanseries2; ++i;
o[i] = tanseries3; ++i;
break;
case COT:
o[i] = cotseries; ++i;
o[i] = cotseries2; ++i;
o[i] = cotseries3; ++i;
break;
case SEC:
o[i] = secseries; ++i;
o[i] = secseries2; ++i;
o[i] = secseries3; ++i;
break;
case '*':
if(ARITY(t) == 2 && FUNCTOR(ARG(1,t))==COT &&
(
equals(ARG(0,t),ARG(0,ARG(1,t))) ||
(FUNCTOR(ARG(0,t)) == '^' && equals(ARG(0,ARG(0,t)),ARG(0,ARG(1,t))) && ISINTEGER(ARG(1,ARG(0,t))))
)
)
{ o[i] = cotseries; ++i;
o[i] = cotseries2; ++i;
o[i] = cotseries3; ++i;
}
break;
}
* nops = i;
}
/*_________________________________________________________________________________________*/
void select_series_op(term t, actualop *o, int *nops)
/* t is an infinite series, or an expression to be expanded in a series, or an expression inside a series */
{ int i = 0;
term lo,indexvar,ldots;
term u = ARG(0,t);
term num,denom;
term a,b,c,s,w,temp;
char buffer[DIMREASONBUFFER];
unsigned short g = FUNCTOR(u);
int nfree;
if(FUNCTOR(t) != SUM)
{ expand_op(t,o,nops);
return;
}
lo = ARG(2,t);
indexvar = ARG(1,t);
ldots = ARITY(t) == 4 ? zero : ARG(4,t);
if(ARITY(t) == 4)
{ o[i] = ldots0; ++i;
o[i] = ldots1; ++i;
o[i] = ldots2; ++i;
}
else
{ o[i] = ldotstosigma; ++i;
o[i] = showanotherterm; ++i;
o[i] = showmoreterms; ++i;
if(!EVALFACTORIAL(t))
{ o[i] = showevaluatedterms; ++i;
}
else
{ o[i] = showfactorialsinterms; ++i;
}
if(DEVALCOEF(t))
{ o[i] = showundevaluatedterms; ++i;
}
else
{ o[i] = showdevaluatedterms; ++i;
}
}
if(!contains(u,FUNCTOR(ARG(1,t))))
{ o[i] = sigmaconstant; ++i;
}
if(contains_power_of_minusone(u))
{ o[i] = seriesevenandodd; ++i;
}
nfree = numerical_sum(t);
// if(nfree == 2)
// { o[i] = evaluateinfiniteseries; ++i;
// }
if(nfree == 1)
{ o[i] = evalfirstterms; ++i;
}
if(ATOMIC(u))
{ *nops = i;
return;
}
if(!equals(lo,minusinfinity))
{ o[i] = seriesfirstterms; ++i;
o[i] = seriesmoreterms; ++i;
if(ARITY(t) == 4)
{ o[i] = seriesaddindex; ++i;
o[i] = seriessubindex; ++i;
}
o[i] = sumtodifofsums; ++i;
if(!ZERO(lo))
{ o[i] = sumtodifofsums0;++i;
}
}
if(get_problemtype() == TESTCONVERGENCE && FUNCTOR(t) == '=' && ISINFINITE(ARG(1,t)) && FUNCTOR(ARG(0,t)) == SUM)
{ if(used4(condensationtest))
{ o[i] = finishcondensationtest; ++i;
}
if(used4(divergencetest))
{ o[i] = finishdivergencetest; ++i;
}
if(used4(comparisontest2))
{ o[i] = finishcomparisontest2; ++i;
}
}
if(get_problemtype() == TESTCONVERGENCE && FUNCTOR(t) == SUM && get_pathlength() <= 1)
{ o[i] = divergencetest; ++i;
o[i] = integraltest; ++i;
o[i] = ratiotest; ++i;
o[i] = roottest; ++i;
o[i] = comparisontest1; ++i;
o[i] = comparisontest2; ++i;
o[i] = condensationtest; ++i;
o[i] = limitcomparisontest; ++i;
if(used4(comparisontest1))
{ o[i] = finishcomparisontest1; ++i;
}
if(used4(comparisontest2))
{ o[i] = finishcomparisontest2; ++i;
}
if(used4(finishcomparisontest1))
{ o[i] = statefinalbound1; ++i;
}
if(used4(finishcomparisontest2))
{ o[i] = statefinalbound2; ++i;
}
if(used4(condensationtest))
{ o[i] = finishcondensationtest; ++i;
}
}
switch(g)
{ case RIEMANNZETA:
o[i] = zetaseries; ++i;
break;
case '-':
o[i] = minusoutofsigma; ++i;
break;
case '/':
num = ARG(0,u);
denom = ARG(1,u);
if(ONE(num) && FUNCTOR(denom) == '^' &&
equals(ARG(1,denom),indexvar)
)
{ if(ONE(lo))
{ o[i] = xoveroneminusxseriesrev; ++i;
}
if(ZERO(lo))
{ o[i] = oneminusxseriesrev; ++i;
}
}
twoparts(u,indexvar,&c,&s);
if(!ONE(c))
{ o[i] = constantoutofsigma; ++i;
}
if(!harmonicseries(t,zero,&temp,buffer))
{ o[i] = harmonicseries; ++i;
}
if(!alternatingharmonicseries(t,zero,&temp,buffer))
{ o[i] = alternatingharmonicseries;++i;
}
if(!zeta2(t,zero,&temp,buffer))
{ o[i] = zeta2; ++i;
}
// don't try addtozeta as it might make assumptions
if(ONE(ARG(0,u)) && FUNCTOR(denom) == '^' && equals(ARG(0,denom),indexvar) && !contains(ARG(1,denom),FUNCTOR(indexvar)))
{ o[i] = addtozeta; ++i;
}
if(FUNCTOR(denom) == FACTORIAL && ZERO(lo) && equals(ARG(0,denom),indexvar))
/* recognize series for e^x, e^-x, sin x, and cos x */
{ if(!contains(u,'-'))
{ o[i] = ZERO(ldots) ? expseriesrev : NEGATIVE(ldots) ? expseries3rev : expseries3rev; ++i;
}
else if(FUNCTOR(num) == '*' && ARITY(num) == 2 &&
FUNCTOR(ARG(0,num)) == '^' && equals(ARG(0,ARG(0,num)),minusone) &&
equals(ARG(1,ARG(0,num)),indexvar) && FUNCTOR(ARG(1,num)) == '^'
)
{ if(equals(ARG(1,ARG(1,num)),indexvar))
{ o[i] = ZERO(ldots) ? negexpseriesrev: NEGATIVE(ldots) ? negexpseries2rev : negexpseries3rev; ++i;
}
else if(iseven(ARG(1,ARG(1,num))))
{ o[i] = ZERO(ldots) ? cosseriesrev : NEGATIVE(ldots) ? cosseries2rev : cosseries3rev; ++i;
}
else if(isodd(ARG(1,ARG(1,num))))
{ o[i] = ZERO(ldots) ? sinseriesrev : NEGATIVE(ldots) ? sinseries2rev : sinseries3rev; ++i;
}
}
}
if(equals(denom,indexvar) && FUNCTOR(num) == '^' && equals(indexvar,ARG(1,num)) && ONE(lo))
{ o[i] = ZERO(ldots) ? lnseriesrev : NEGATIVE(ldots) ? lnseries2rev : lnseries3rev; ++i;
}
break;
case '*':
twoparts(u,indexvar,&c,&s);
if(!ONE(c))
{ o[i] = constantoutofsigma; ++i;
}
if(ARITY(u) == 2 && FUNCTOR(ARG(0,u)) == '^' &&
equals(ARG(0,ARG(0,u)),minusone) &&
equals(ARG(1,ARG(0,u)),indexvar) &&
FUNCTOR(ARG(1,u)) == '^' &&
!contains(ARG(0,ARG(1,u)),FUNCTOR(indexvar))
)
{ /* (-1)^n x^? */
term w = ARG(0,ARG(1,u));
term power = ARG(1,ARG(1,u));
if(!contains(w,FUNCTOR(indexvar)))
{ if(equals(power,indexvar))
{ o[i] = ZERO(ldots) ? oneplusxseriesrev: NEGATIVE(ldots)? oneplusxseries2rev: oneplusxseries3rev; ++i;
}
else if(FUNCTOR(power) == '*' && !is_linear_in(power,indexvar))
{ o[i] = ZERO(ldots) ? oneoveroneplusxkseriesrev : NEGATIVE(ldots) ? oneoveroneplusxkseries2rev : oneoveroneplusxkseries3rev; ++i;
}
else if(FUNCTOR(power) == '+' && !is_linear_in(power,indexvar))
{ o[i] = ZERO(ldots) ? xmoveroneplusxkseriesrev : NEGATIVE(ldots) ? xmoveroneplusxkseries2rev : xmoveroneplusxkseries3rev; ++i;
}
}
}
if(FUNCTOR(s) == '^' && equals(indexvar,ARG(1,s)))
{ if(FUNCTOR(c) == BINOMIAL && equals(ARG(1,c),indexvar))
{ o[i] = ZERO(ldots) ? binomialseriesrev: NEGATIVE(ldots) ? binomialseries2rev : binomialseries3rev; ++i;
}
else if(FUNCTOR(c) == '*' && ARITY(c) == 2 &&
FUNCTOR(ARG(1,c)) == BINOMIAL &&
equals(ARG(1,ARG(1,c)),indexvar) &&
FUNCTOR(ARG(0,c)) == '^' &&
equals(ARG(0,ARG(0,c)),minusone) &&
equals(ARG(1,ARG(0,c)),indexvar)
)
{ o[i] = ZERO(ldots) ? binomialseriesrev: NEGATIVE(ldots) ? binomialseries2rev: binomialseries3rev; ++i;
}
}
if(ARITY(u) == 2 && FUNCTOR(ARG(1,u)) == '^' &&
islinear(ARG(1,ARG(1,u)),indexvar,&a,&b) &&
equals(a,two) &&
FRACTION(ARG(0,u)) &&
FUNCTOR(ARG(0,ARG(0,u))) == '^' &&
equals(ARG(0,ARG(0,ARG(0,u))),minusone) &&
FUNCTOR(ARG(1,ARG(0,u))) == FACTORIAL &&
equals(ARG(0,ARG(1,ARG(0,u))),ARG(1,ARG(1,u))) &&
equals(ARG(1,ARG(0,ARG(0,u))),indexvar)
)
{ if(ONE(b))
{ o[i] = sinseriesrev; ++i;
}
else
{ o[i] = cosseriesrev; ++i;
}
}
break;
case '+':
o[i] = seriessum; ++i;
if(ARITY(u) == 2 && !telescopingseries(t,zero,&w,buffer))
{ o[i] = telescopingseries; ++i;
}
break;
case '^':
if(equals(ARG(1,u),indexvar) && ZERO(lo) && !contains(ARG(0,u),FUNCTOR(indexvar)))
{ o[i] = ZERO(ldots) ? oneminusxseriesrev: NEGATIVE(ldots) ? oneminusxseries2rev : oneminusxseries3rev; ++i;
}
if(equals(ARG(1,u),indexvar) && ONE(lo) && !contains(ARG(0,u),FUNCTOR(indexvar)))
{ o[i] = ZERO(ldots) ? xoveroneminusxseriesrev : NEGATIVE(ldots) ? xoveroneminusxseries2rev : xoveroneminusxseries3rev; ++i;
}
if(FUNCTOR(ARG(1,u)) == '+' &&
!contains(ARG(0,u),FUNCTOR(indexvar)) &&
!is_linear_in(ARG(1,u),indexvar)
)
{ o[i] = ZERO(ldots) ? xmoveroneminusxkseriesrev : NEGATIVE(ldots) ? xmoveroneminusxkseries2rev : xmoveroneminusxkseries3rev; ++i;
}
if(FUNCTOR(ARG(1,u)) == '*'&&
!contains(ARG(0,u),FUNCTOR(indexvar)) &&
!is_linear_in(ARG(1,u),indexvar)
)
{ o[i] = ZERO(ldots) ? oneminusxseriesrev: NEGATIVE(ldots) ? oneminusxseries2rev : oneminusxseries3rev; ++i;
}
if(equals(ARG(0,u),indexvar) && !contains(ARG(1,u),FUNCTOR(indexvar)))
{ o[i] = addtozeta; ++i;
}
break;
case DIFF:
o[i] = reversedifseries; ++i;
break;
case INTEGRAL:
o[i] = reverseintseries; ++i;
break;
}
*nops = i;
return;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists