Sindbad~EG File Manager
/* M. Beeson, for Mathpert */
/* Functions to build the SelectOperator menu */
/*
1.29.95 Original date
3.18.99 modified
1.2.99 modified select_limit_op to not show limcontinuous when f is SUM or PRODUCT
7.10.00 modified conditions for limoscsin, limosccos, limosctan.
8.31.07 Added line 1529 to conditions for difpoly
5.6.13 include <stddef.h>
6.4.13 modified select_dif_op to produce difpoly on (ln 2) x^n, etc.
6.9.13 modified condition to show intexp6
6.10.13 modified condition to show invertlim
6.11.13 corrected condition to show intexp6
6.13.24 modified select_integration_op to not put choosesubstitution on the menu,
for reasons explained at the modification.
*/
#include <math.h> /* abs */
#include <string.h> /* memset */
#include <assert.h>
#include <stddef.h>
#include "globals.h"
#include "graphstr.h"
#include "display.h"
#include "mpdoc.h"
#include "tdefn.h"
#include "checkarg.h"
#include "ops.h"
#include "trig.h"
#include "calc.h"
#include "display1.h" /* needed by lterm.h */
#include "bigrect.h"
#include "lterm.h"
#include "selectop.h"
#include "automode.h"
#include "cflags.h"
#include "exec.h" /* erasecolors, finish_exec */
#include "probtype.h"
#include "ops.h"
#include "trig.h"
#include "calc.h"
#include "pvalaux.h" /* content_factor */
/* rawcollectpowers */
/* contains_at_toplevel */
#include "order.h" /* additive_sortargs, common_variables */
#include "prover.h" /* NOTDEFINED */
#include "cancel.h" /* cancel */
#include "mplimits.h" /* LIMITAND */
#include "match.h" /* matchstring */
#include "polynoms.h" /* ispolyin */
#include "sigma.h" /* freevars */
#include "factor.h" /* numerical_poly */
#include "eqn.h" /* econstant */
#include "solvelin.h" /* is_linear_in */
#include "intsub.h" /* readpending */
#include "exponent.h" /* possible_int */
#include "deval.h"
#include "optable.h" /* access_optable */
#include "docdata.h" /* history */
#include "chkinput.h" /* mathematical */
#include "pda.h" /* seminumerical2 */
#include "nfactor.h" /* small_prime */
#include "autocalc.h" /* use_leading_terms */
#include "autosimp.h" /* GetShowStepOperation */
#include "select2.h"
#include "limval2.h" /* contains_in_exponent */
#include "series.h" /* is_power_series */
#include "islinear.h" /* islinear */
#define MAXFLAGS 300
#define ZEROFLAG 255
#define ONEFLAG 256
#define SINSQ 257
#define TANSQ 258
#define COTSQ 259
#define COSSQ 260
#define SECSQ 261
#define CSCSQ 262
#define SINHSQ 263
#define COSHSQ 264
#define TANHSQ 265
#define SECHSQ 266
#define CSCHSQ 267
#define COTHSQ 268
#define DEFINT (CSCSQ + 1)
#define TRIGF(h) (h==SIN || h==COS || h==TAN || h==COT || h==SEC || h==CSC)
#define ISIPI(v) ((equals(ARG(0,v),complexi) && equals(ARG(1,v),pi_term)) || (equals(ARG(0,v),pi_term) && equals(ARG(1,v),complexi)))
static int islinearproduct(term t, term x);
static int numerically_indeterminate(term u, term x, term a);
/*______________________________________________________________________*/
static int islinearproduct(term t, term x)
/* return 1 if t has the form ax, or x/a, or cx/a */
{ term c,s;
if(NEGATIVE(t))
t = ARG(0,t);
if(FUNCTOR(t) != '*' && FUNCTOR(t) != '/')
return 0;
twoparts(t,x,&c,&s);
if(!equals(s,x))
return 0;
return 1;
}
/*__________________________________________________________________*/
void select_limit_op(term t, actualop *o, int *nops)
/* t is a LIMIT term selected by the user. Fill in o with
operators that might apply, and return their number in *nops. */
{ unsigned short n = ARITY(t);
unsigned short m;
int i = 0;
int k, logflag, logpowerflag, expflag, negpowerflag,trigflag,sincosflag;
unsigned short h;
term u = LIMITAND(t);
term x = ARG(0,ARG(0,t));
term a = ARG(1,ARG(0,t)); /* lim(x->a,t) or lim(x->a,dir,t) */
term c,s,b,d,dir,v,w,num,denom;
char buffer[DIMREASONBUFFER];
unsigned short f = FUNCTOR(u);
int j,p,q;
if(n==3)
dir = ARG(1,t);
if(!depends(u,x))
{ o[i] = limconst; ++i; /* lim(t\32a,c) = c (c constant) */
}
if(equals(u,x))
{ o[i] = limident; ++i; /* lim(t\32a,t) = a */
}
if(ATOMIC(u))
{ *nops = i;
return;
}
if(NOTDEFINED(a) && FRACTION(u) && rational_function(u,x))
/* limits of rational functions at infinity */
{ if(status(limrationalfunction) >= KNOWN)
{ o[i] = limrationalfunction; ++i;
}
else if(use_leadingterms(u,x))
{ o[i] = limleadingterms; ++i;
/* this will work and not look mysterious
when applied to a rational function */
}
}
if(!NOTDEFINED(a) && !ZERO(a) && FRACTION(u) &&
rational_function(u,x) &&
(FUNCTOR(ARG(0,u)) == '+' || FUNCTOR(ARG(1,u)) == '+')
)
{ o[i] = factorunderlimit; ++i;
}
switch(f)
{ case '+':
if(NEGATIVE(ARG(ARITY(u)-1,u)))
{ o[i] = limdif; ++i;
}
else
{ o[i] = limsum; ++i; /* lim u \pm v = lim u \pm lim v */
}
if(ispolyin(u,x))
{ o[i] = limpoly; ++i;
}
if(FUNCTOR(ARG(0,u)) == SQRT ||
(FUNCTOR(ARG(0,u)) == '^' && FRACTION(ARG(1,ARG(0,u))) &&
ONE(ARG(0,ARG(1,ARG(0,u)))) && equals(ARG(1,ARG(1,ARG(0,u))),two)
)
)
{ o[i] = rationalizesum; ++i;
}
if(status(sumleadingterm) >= LEARNING)
{ o[i] = sumleadingterm; ++i;
}
break;
case '*':
j = 0;
m = ARITY(u);
for(k=0;k<m;k++)
{ if(contains(ARG(k,u),FUNCTOR(x)))
++j;
}
if(j<m)
{ o[i] = limlinear; ++i; /* lim cu=c lim u (c const) */
}
if(m==2 && ZERO(a) && status(limtlnt) >= LEARNING)
{ if(equals(ARG(0,u),x) && FUNCTOR(ARG(1,u)) == LN && equals(ARG(0,ARG(1,u)),x))
{ o[i] = limtlnt; ++i;
}
if(equals(ARG(0,u),x) &&
FUNCTOR(ARG(1,u)) == '^' &&
obviously_positive(ARG(1,ARG(1,u))) &&
FUNCTOR(ARG(0,ARG(1,u))) == LN &&
equals(ARG(0,ARG(0,ARG(1,u))),x)
)
{ o[i] = limtlntpower; ++i;
}
if(FUNCTOR(ARG(0,u)) == '^' &&
equals(ARG(0,ARG(0,u)),x) &&
obviously_positive(ARG(1,ARG(0,u))) &&
FUNCTOR(ARG(1,u)) == LN &&
equals(ARG(0,ARG(1,u)),x)
)
{ o[i] = limtpowerlnt; ++i;
}
if(FUNCTOR(ARG(0,u)) == '^' &&
equals(ARG(0,ARG(0,u)),x) &&
obviously_positive(ARG(1,ARG(0,u))) &&
FUNCTOR(ARG(1,u)) == '^' &&
FUNCTOR(ARG(0,ARG(1,u))) == LN &&
equals(ARG(0,ARG(0,ARG(1,u))),x) &&
obviously_positive(ARG(1,ARG(1,u)))
)
{ o[i] = limtpowerlntpower; ++i;
}
}
o[i] = limprod; ++i;
if(m == 2 && FUNCTOR(ARG(0,u)) == LN && FUNCTOR(ARG(0,ARG(0,u))) == '+')
{ o[i] = limprod2left; ++i;
}
if(m == 2 && FUNCTOR(ARG(1,u)) == LN && FUNCTOR(ARG(0,ARG(1,u))) == '+')
{ o[i] = limprod2right; ++i;
}
if(mvpoly2(u))
{ o[i] = limpoly; ++i;
}
o[i] = createcompoundfraction; ++i; /* lim uv = lim v/(1/u) */
logflag = logpowerflag = negpowerflag = 0;
expflag = trigflag = sincosflag = 0;
for(k=0;k<m;k++)
{ v = ARG(k,u);
h = FUNCTOR(v);
if(h == LN)
++logflag;
if(h == '^' && FUNCTOR(ARG(0,v)) == LN && constant(ARG(1,v)))
++logpowerflag;
if(h == '^' && equals(ARG(0,v),eulere) && !constant(ARG(1,v)))
++expflag;
if(h == '^' && NEGATIVE(ARG(1,v)) && !constant(ARG(0,v)))
++negpowerflag;
if(TRIGFUNCTOR(h))
++trigflag;
if(h == '^')
{ unsigned short hh = FUNCTOR(ARG(0,v));
if(TRIGFUNCTOR(hh))
++trigflag;
if(hh == SIN || hh == COS)
++sincosflag;
}
if(h==SIN || h==COS)
++sincosflag;
}
if(logflag)
{ o[i] = isolateln; ++i;
}
if(logpowerflag)
{ o[i] = isolatelnpower; ++i;
}
if(negpowerflag)
{ o[i] = negexptodenom; ++i;
}
if(expflag)
{ o[i] = exptodenom; ++i;
}
if(trigflag)
{ o[i] = trigtodenom; ++i;
}
if(sincosflag)
{ o[i] = squeezetheorem; ++i;
}
break;
case '-':
v = ARG(0,u);
if(FUNCTOR(v) == '*')
{ m = ARITY(v);
j=0;
for(k=0;k<m;k++)
{ if(contains(ARG(k,v),FUNCTOR(x)))
++j;
}
if(j<m)
{ o[i] = limlinear; ++i; /* lim cu=c lim u (c const) */
}
}
if(FRACTION(v))
{ twoparts(v,x,&c,&s);
if(!ONE(c))
{ o[i] = limlinear; ++i;
}
}
o[i] = limminus; ++i; /* lim -u = -lim u */
if(mvpoly2(v))
{ o[i] = limpoly; ++i;
}
break;
case '^':
p = depends(ARG(0,u),x);
q = depends(ARG(1,u),x);
if(p && !q)
{ o[i] = limpower; ++i; /* lim u^n = (lim u)^n */
}
if(q && !p)
{ o[i] = limexponent2; ++i; /* lim c^v=c^(lim v) (c constant > 0) */
o[i] = limexptolog; ++i; /* lim u^v = lim e^(v ln u) */
}
if(q && p)
{ o[i] = limexponent; ++i; /* lim u^v=(lim u)^(lim v) */
o[i] = limexptolog; ++i; /* lim u^v = lim e^(v ln u) */
}
if(mvpoly2(u))
{ o[i] = limpoly; ++i;
}
if(!matchstring(u,x,"^(+(1,x),/(1,x))",&c))
{ o[i] = defnofe; ++i;
}
if(equals(ARG(0,u),eulere) ||
equals(ARG(0,u),pi_term) ||
(INTEGERP(ARG(0,u)) && !ONE(ARG(0,u)))
)
{ o[i] = limthruexp; ++i;
}
break;
case ABSFUNCTOR:
o[i] = limabs; ++i;
break;
case SQRT:
o[i] = limsqrt; ++i; /* lim sqrt u=sqrt (lim u) if lim u>0 */
break;
case ROOT:
if(iseven(ARG(0,u)))
{ o[i] = limevenroot; ++i; /* lim ^n sqrt u = ^n sqrt (lim u) if lim u > 0 */
}
else if(isodd(ARG(0,u)))
{ o[i] = limoddroot; ++i; /* lim ^n sqrt u = ^n sqrt (lim u) if n is odd */
}
else
{ o[i] = limevenroot; ++i;
o[i] = limoddroot; ++i;
}
break;
case '/':
twoparts(u,x,&c,&s);
if(!ONE(c))
{ o[i] = limlinear; ++i;
}
num = ARG(0,u);
denom = ARG(1,u);
h = FUNCTOR(num);
if(!depends(num,x))
{ o[i] = limrecip; ++i;
}
o[i] = limquotient; ++i;
o[i] = pulloutnonzerolimit; ++i;
o[i] = multnumdenom; ++i;
o[i] = divnumdenom2; ++i;
o[i] = divnumdenom; ++i;
if(equals(a,infinity))
{ if(FUNCTOR(num) == LN &&
equals(ARG(0,num),x) &&
equals(denom,x)
)
{ o[i] = limlntovert; ++i;
}
if(FUNCTOR(num) == '^' &&
FUNCTOR(ARG(0,num)) == LN &&
equals(ARG(0,ARG(0,num)),x) &&
equals(denom,x)
)
{ o[i] = limlntpowerovert; ++i;
}
if(FUNCTOR(num) == LN &&
equals(ARG(0,num),x) &&
FUNCTOR(denom) == '^' &&
FUNCTOR(ARG(0,denom)) == LN &&
equals(ARG(0,ARG(0,denom)),x) &&
obviously_positive(ARG(1,denom))
)
{ o[i] = limlntovertpower; ++i;
}
if(FUNCTOR(num) == '^' &&
FUNCTOR(ARG(0,num)) == LN &&
equals(ARG(0,ARG(0,num)),x) &&
obviously_positive(ARG(1,num)) &&
FUNCTOR(denom) == '^' &&
equals(ARG(0,denom),t) &&
obviously_positive(ARG(1,denom))
)
{ o[i] = limlntpowerovertpower; ++i;
}
if(FUNCTOR(denom) == LN &&
equals(ARG(0,denom),x) &&
equals(num,x)
)
{ o[i] = limtoverlnt; ++i;
}
if(equals(num,x) &&
FUNCTOR(denom) == '^' &&
FUNCTOR(ARG(0,denom)) == LN &&
equals(ARG(0,ARG(0,denom)),x) &&
obviously_positive(ARG(1,denom))
)
{ o[i] = limtoverlntpower; ++i;
}
if(FUNCTOR(denom) == LN &&
equals(ARG(0,denom),x) &&
FUNCTOR(num) == '^' &&
equals(ARG(0,num),x) &&
obviously_positive(ARG(1,num))
)
{ o[i] = limtpoweroverlnt; ++i;
}
if(FUNCTOR(num) == '^' &&
equals(ARG(0,num),x) &&
obviously_positive(ARG(1,num)) &&
FUNCTOR(denom) == '^' &&
FUNCTOR(ARG(0,denom)) == LN &&
equals(ARG(0,ARG(0,denom)),x) &&
obviously_positive(ARG(1,denom))
)
{ o[i] = limtpoweroverlntpower; ++i;
}
}
if(h == '+' && ARITY(num) >= 3)
{ o[i] = limapartandfactor; ++i;
}
if(status(lhopital) >= LEARNING ||
numerically_indeterminate(u,x,a)
)
{ o[i] = lhopital; ++i;
}
if(contains_in_exponent(num,FUNCTOR(x)) &&
contains_in_exponent(denom,FUNCTOR(x))
)
{ o[i] = limlog; ++i;
}
/* special limits: */
if(ZERO(a))
{ if(equals(denom,x) && h == SIN && equals(ARG(0,num),x))
{ o[i] = limsin1; ++i; /* (sin x)/x */
}
else if(equals(num,x) && FUNCTOR(denom) == SIN &&
equals(ARG(0,denom),x)
)
{ o[i] = limsin1; ++i; /* x/(sin x) */
}
else if(equals(denom,x) && h == TAN && equals(ARG(0,num),x))
{ o[i] = limtan1; ++i; /* (tan x)/x */
}
else if(equals(num,x) && FUNCTOR(denom) == TAN &&
equals(ARG(0,denom),x)
)
{ o[i] = limtan1; ++i;
}
else if(equals(denom,x) && h == SINH && equals(ARG(0,num),x))
{ o[i] = limsinh1; ++i; /* (sinh x)/x */
}
else if(equals(num,x) && FUNCTOR(denom) == SINH &&
equals(ARG(0,denom),x)
)
{ o[i] = limsinh1; ++i; /* x/(sinh x) */
}
else if(equals(denom,x) && h == TANH && equals(ARG(0,num),x))
{ o[i] = limtanh1; ++i; /* (tanh x)/x */
}
else if(equals(num,x) && FUNCTOR(denom) == TANH &&
equals(ARG(0,denom),x)
)
{ o[i] = limtanh1; ++i;
}
else if(!matchstring(u,x,"/(+(1,-(cos(x))),x)",&c))
{ o[i] = limcos1; ++i;
}
else if(!matchstring(u,x,"/(+(cos(x),-(1)),x)",&c))
{ o[i] = limcos1; ++i;
}
else if(!matchstring(u,x,"/(+(1,-(cos(x))),^(x,2))",&c))
{ o[i] = limcos2; ++i;
}
else if(!matchstring(u,x,"/(+(cos(x),-(1))),^(x,2))",&c))
{ o[i] = limcos2; ++i;
}
else if(!matchstring(u,x,"/(^(x,2),+(cos(x),-(1)))",&c))
{ o[i] = limcos2; ++i;
}
else if(!matchstring(u,x,"/(^(x,2),+(1,-(cos(x))))",&c))
{ o[i] = limcos2; ++i;
}
else if(!matchstring(u,x,"/(+(1,-(cosh(x))),x)",&c))
{ o[i] = limcosh1; ++i;
}
else if(!matchstring(u,x,"/(+(cosh(x),-(1)),x)",&c))
{ o[i] = limcosh1; ++i;
}
else if(!matchstring(u,x,"/(+(1,-(cosh(x))),^(x,2))",&c))
{ o[i] = limcosh2; ++i;
}
else if(!matchstring(u,x,"/(+(cosh(x),-(1))),^(x,2))",&c))
{ o[i] = limcosh2; ++i;
}
else if(!matchstring(u,x,"/(^(x,2),+(cosh(x),-(1)))",&c))
{ o[i] = limcosh2; ++i;
}
else if(!matchstring(u,x,"/(^(x,2),+(1,-(cosh(x))))",&c))
{ o[i] = limcosh2; ++i;
}
else if(!matchstring(u,x,"^(+(1,x),/(1,x))",&c))
{ o[i] = defnofe; ++i;
}
else if(!matchstring(u,x,"/(ln(+(1,x)),x)",&c))
{ o[i] = limln1; ++i; /* lim(x->0, ln(1+x)/x) = 1 */
}
else if(!matchstring(u,x,"/(x,ln(+(1,x)))",&c))
{ o[i] = limln1; ++i;
}
else if(!matchstring(u,x,"/(ln(+(x,-(1))),x)",&c))
{ o[i] = limln1; ++i; /* lim(x->0, ln(1+x)/x) = 1 */
}
else if(!matchstring(u,x,"/(ln(+(1,-(x))),x)",&c))
{ o[i] = limln1; ++i; /* lim(x->0, ln(1+x)/x) = 1 */
}
else if(!matchstring(u,x,"/(x,ln(+(x,-(1))))",&c))
{ o[i] = limln1; ++i;
}
else if(!matchstring(u,x,"/(x,ln(+(1,-(x))))",&c))
{ o[i] = limln1; ++i;
}
else if(!matchstring(u,x,"/(+(^(e,x),-(1)),x)",&c))
{ o[i] = limexp1; ++i;
}
else if(!matchstring(u,x,"/(+(^(e,-(x)),-(1)),x)",&c))
{ o[i] = limexp2; ++i;
}
else if(!matchstring(u,x,"/(x,+(^(e,x),-(1)))",&c))
{ o[i] = limexp1; ++i;
}
/* infinite limits: */
if(ONE(num) && FUNCTOR(denom) == '^' && equals(ARG(0,denom),x))
{ if(iseven(ARG(1,denom)))
{ o[i] = liminverseevenpower; ++i; /* 1/x^2n */
}
else if(isodd(ARG(1,denom)))
{ o[i] = liminverseoddpower; ++i;
}
else
{ o[i] = liminverseevenpower; ++i;
o[i] = liminverseoddpower; ++i;
}
}
else if(ONE(num) && FUNCTOR(denom) == '^' && n == 3)
{ if(FUNCTOR(dir) == LEFT)
{ o[i] = lim1inverseleft; ++i;
}
else
{ o[i] = lim1inverseright; ++i;
}
}
}
if(status(limleadingterms) >= LEARNING)
{ o[i] = limleadingterms; ++i;
}
o[i] = limquoinfinite; ++i;
if(h == SIN || h == COS)
{ o[i] = squeezetheorem; ++i;
}
if(
(h == '*' || h =='^' || h == '+') &&
(contains(num,COS) || contains(num,SIN))
)
{ o[i] = squeezetheorem; ++i;
}
break;
case COS:
if((ZERO(a) || ISINFINITE(a)) &&
contains(t,'/') && /* don't show limosccos on lim(t->infinity,cos t) */
!limosccos(t,zero,&w,buffer)
)
{ o[i] = limosccos; ++i;
}
if(ISINFINITE(a) && !liminfcos(t,zero,&w,buffer))
{ o[i] = liminfcos; ++i;
}
o[i] = squeezetheorem; ++i;
o[i] = limthrucos; ++i;
break;
case SIN:
if((ZERO(a) || ISINFINITE(a)) &&
contains(t,'/') && /* don't show limsoscsin on lim(t->infinity, sin t) */
!limoscsin(t,zero,&w,buffer)
)
{ o[i] = limoscsin; ++i;
}
if(ISINFINITE(a) && !liminfsin(t,zero,&w,buffer))
{ o[i] = liminfsin; ++i;
}
o[i] = squeezetheorem; ++i;
o[i] = limthrusin; ++i;
break;
case TAN:
if(ZERO(a) &&
contains(t,'/') && /* don't show limosctan on lim(t->infinity, tan t) */
!limosctan(t,zero,&w,buffer)
)
{ o[i] = limosctan; ++i;
}
if(ISINFINITE(a) && !liminftan(t,zero,&w,buffer))
{ o[i] = liminftan; ++i;
}
if(equals(ARG(0,u),x))
/* find out if a has the form (2n+1)pi/2 */
{ polyval(sum(a,tnegate(piover2)),&c);
if(!decompose(c,&b,&d) && ZERO(b)) /* c = b + d pi */
{ o[i] = limtansing; ++i;
}
}
break;
case SEC:
if(equals(ARG(0,u),x))
/* find out if a has the form (2n+1)pi/2 */
{ polyval(sum(a,tnegate(piover2)),&c);
if(!decompose(c,&b,&d) && ZERO(b)) /* c = b + d pi */
{ o[i] = limsecsing; ++i;
}
}
break;
case COT:
if(equals(ARG(0,u),x) && !decompose(a,&b,&d) && ZERO(d))
{ o[i] = limcotsing; ++i;
}
break;
case CSC:
if(equals(ARG(0,u),x) && !decompose(a,&b,&d) && ZERO(d))
{ o[i] = limcscsing; ++i;
}
break;
case LN:
o[i] = limlogisloglim; ++i;
o[i] = limlnsing; ++i;
o[i] = limthrulog; ++i;
break;
}
if(status(limpoly) > LEARNING)
{ o[i] = limvalop; ++i;
if(f != SUM && f != PRODUCT)
{ o[i] = limcontinuous; ++i;
}
o[i] = changelimitvariable; ++i;
}
if(equals(a,infinity))
{ /* limits at infinity */
switch(f)
{ case '/':
if(FRACTION(u) && !contains(ARG(0,u),FUNCTOR(x)) &&
(
(FUNCTOR(ARG(1,u)) == '^' && equals(ARG(0,ARG(1,u)),x)) ||
equals(ARG(1,u),x)
)
)
{ o[i] = inflimpower1; ++i;
}
break;
case '^':
if(equals(ARG(0,u),eulere) &&
(is_linear_in(ARG(1,u),x) ||
ispolyin(ARG(1,u),x)
/* ispolyin gets monomials or sums of monomials but
misses c(x+b) which is accepted by is_linear_in */
)
)
{ o[i] = limexpinf; ++i;
if(contains(ARG(1,u),'-'))
{ o[i] = limexpinf2; ++i;
}
}
if(equals(ARG(0,u),x))
{ o[i] = inflimpower2; ++i;
if(NEGATIVE(ARG(1,u)))
{ o[i] = inflimpower1; ++i;
}
}
break;
case LN:
o[i] = limlnright; ++i;
break;
case SQRT:
o[i] = limsqrtinf; ++i;
break;
case ROOT:
o[i] = limsqrtinf; ++i;
break;
case ATAN:
o[i] = limarctaninf; ++i;
break;
case TANH:
o[i] = limtanhinf; ++i;
break;
}
if(! contains_calc(u)) // no integrals, limits, sums in the limitand
{ o[i] = invertlim; ++i;
}
/* limleading terms has already been thrown in */
}
if(equals(a,minusinfinity))
{ switch(f)
{ case '/':
if(FRACTION(u) && !contains(ARG(0,u),FUNCTOR(x)) &&
(
(FUNCTOR(ARG(1,u)) == '^' && equals(ARG(0,ARG(1,u)),x)) ||
equals(ARG(1,u),x)
)
)
{ o[i] = inflimpower1; ++i;
}
break;
case '^':
if(equals(ARG(0,u),x))
{ o[i] = inflimpower2; ++i;
if(NEGATIVE(ARG(1,u)))
{ o[i] = inflimpower1; ++i;
}
}
if(equals(ARG(0,u),eulere) && ispolyin(ARG(1,u),x))
{ o[i] = limexpinf2; ++i;
if(contains(ARG(1,u),'-'))
{ o[i] = limexpinf; ++i;
}
}
break;
case ATAN:
o[i] = limarctaninf; ++i;
break;
case TANH:
o[i] = limtanhinf; ++i;
break;
}
o[i] = invertlim; ++i;
}
*nops = i;
}
/*__________________________________________________________________*/
void select_integration_op(term t, actualop *o, int *nops)
/* t is an INTEGRAL term selected by the user. Fill in o with
operators that might apply, and return their number in *nops. */
{ term x = ARG(1,t); /* the variable of integration */
term u = ARG(0,t); /* the integrand */
unsigned short n = ARITY(t); /* 4 for a definite integral */
unsigned short m = ARITY(u);
int nextdefn = get_nextdefn();
int i=0;
int j,k,nvars;
term a,b,num,denom,lo,hi,base,power,v,w;
term *atomlist;
unsigned short f = FUNCTOR(u);
unsigned short g,h;
double zlo,zhi,wlo,whi;
unsigned short hh;
char buffer[DIMREASONBUFFER];
if(FUNCTOR(u) != '+' &&
/* for integrands which are sums, polyvalop has already been thrown in */
!polyvalop(t,zero,&w,buffer) &&
(FUNCTOR(w) != INTEGRAL || n == 4) &&
/* n == 4 because polyvalop can simplify both limits of integration,
in which case the focus is the integral. */
!GetShowStepOperation()
/* If polyvalop just imitates intlinear or intminus, it will have called
SetShowStepOperation, and so we won't show it here. */
)
{ o[i] = polyvalop; ++i;
}
if(!equatetoproblem(t,zero,&w,buffer))
{ o[i] = equatetoproblem; ++i;
}
if(n == 4)
{ o[i] = switchlimits; ++i;
if(equals(ARG(2,t),ARG(3,t)))
{ o[i] = integrateemptyinterval; ++i;
}
}
if(n == 4 && !contains(t,DIFF))
{ /* a definite integral; !contains(t,DIFF) is meant to rule out the situation where integration
by parts is in progress and you have ...du/dx dx. It will also rule out fundamental-theorem
problems. */
o[i] = insertpoint; ++i;
if(FUNCTOR(u) == ABSFUNCTOR)
{ o[i] = breakabsint; ++i;
}
if(!IMPROPER(t) && seminumerical(ARG(2,t)) && seminumerical(ARG(3,t)))
/* Mathpert doesn't offer numerical integration
of improper integrals. You have to transform it to a proper integral first.
Eventually you should be able to integrate numerically if the function has a
finite limit at the endpoint(s).
Also, the limits must be numerical--the parameter, if any, can only
occur in the integrand.
*/
{ nvars = freevars(t,&atomlist);
if(nvars > 0)
{ o[i] = integratenumerically; ++i;
}
else
{ o[i] = pureintegratenumerically; ++i;
}
free2(atomlist);
}
lo = ARG(2,t);
hi = ARG(3,t);
if(equals(hi,infinity))
{ o[i] = intdivtest1; ++i;
/* example, integral(arctan x,x,0, infinity). The
integral can be done, but evaluating the limit of
the integral as it goes to infinity is horrendous,
and the integral has to come out infinity because
the integrand doesn't go to zero. */
o[i] = integraltolimit; ++i;
}
else if(equals(lo,minusinfinity))
{ o[i] = intdivtest2; ++i;
o[i] = integraltolimit2; ++i;
}
if(IMPROPER(t)) /* potentially improper integral */
{ double z;
term v;
subst(lo,x,u,&v);
deval(v,&z);
if(z == BADVAL)
{ o[i] = integraltolimit3; ++i;
}
subst(hi,x,u,&v);
deval(v,&z);
if(z == BADVAL)
{ o[i] = integraltolimit4; ++i;
}
if(
(NEGATIVE(lo) && equals(ARG(0,lo),hi)) ||
(NEGATIVE(hi) && equals(ARG(0,hi),lo))
)
{ /* can't evaluate at endpoints to see if evenintegrand
or oddintegrand might be applicable */
if(!evenintegrand(t,zero,&w,buffer))
{ o[i] = evenintegrand; ++i;
}
else if(!oddintegrand(t,zero,&w,buffer))
{ o[i] = oddintegrand; ++i;
}
}
}
else if(equals(lo,minusinfinity) && equals(hi,infinity))
{ if(!evenintegrand(t,zero,&w,buffer))
{ o[i] = evenintegrand; ++i;
}
else if(!oddintegrand(t,zero,&w,buffer))
{ o[i] = oddintegrand; ++i;
}
}
if(
(
(NEGATIVE(lo) && equals(ARG(0,lo),hi)) ||
(NEGATIVE(hi) && equals(ARG(0,hi),lo))
) &&
!IMPROPER(t)
)
{ deval(lo,&zlo);
deval(hi,&zhi);
/* evaluate the integrand numerically at the
endpoints to see if it might be odd or even.
If there are parameters, their current values
will be used. Of course this doesn't prove that
the integrand is odd or even but it rejects
cases that are NOT odd or even.
*/
if(zlo != BADVAL && zhi != BADVAL)
{ SETVALUE(x,zlo);
deval(u,&wlo);
SETVALUE(x,zhi);
deval(u,&whi);
if(wlo != BADVAL && whi != BADVAL)
{ if(fabs(wlo-whi) < VERYSMALL)
{ o[i] = evenintegrand; ++i;
}
if(fabs(wlo+whi) < VERYSMALL)
/* not 'else if' in case the function is odd but
zero at the endpoints; in that case both
operators will be shown. */
{ o[i] = oddintegrand; ++i;
}
}
}
}
}
if(ONE(u))
{ o[i] = int1; ++i;
*nops = i;
return;
}
if(!depends(u,x))
{ o[i] = intconst; ++i;
o[i] = intlinear; ++i;
if(NEGATIVE(u))
{ o[i] = intminus; ++i;
}
*nops = i;
return;
}
if(equals(u,x))
{ o[i] = intident; ++i;
*nops = i;
return;
}
if(ATOMIC(u))
{ *nops = i;
return;
}
if(FUNCTOR(u) == DIFF)
{ o[i] = fundamentaltheorem; ++i;
*nops = i;
return;
}
if(
(FUNCTOR(u) == '*' && contains_at_toplevel(u,SG)) ||
(FRACTION(u) &&
(FUNCTOR(ARG(0,u)) == SG ||
(FUNCTOR(ARG(0,u)) == '*' && contains_at_toplevel(ARG(0,u),SG))
)
)
)
{ o[i] = sgint; ++i;
}
if(nextdefn > 0 && status(intsub)==LEARNING)
{ controldata d;
operation *opseq;
actualop op;
int currentline = get_currentline();
get_controldata(&d);
opseq = d.opseq;
for(k=currentline;k>0;k--)
{ op = access_optable(opseq[k].men)[opseq[k].choice-1];
if((void *) op == (void *)changeintegrationvariable)
break;
if((void *) op == (void *) trysubstitution)
{ o[i] = changeintegrationvariable; ++i;
twoparts(u,x,&a,&b);
if(!ONE(a))
{ o[i] = intlinear; ++i;
}
*nops = i;
return;
}
if((void *) op == (void *) showcallingproblem)
{ o[i] = trysubstitution; ++i;
twoparts(u,x,&a,&b);
if(!ONE(a))
{ o[i] = intlinear; ++i;
}
*nops = i;
return;
}
}
}
if(!ispolyin(u,x))
{ int s = status(intsub);
if(s == LEARNING)
{ o[i] = autochoosesubstitution; ++i;
o[i] = choosesubstitution; ++i;
/* choosesubstitution expects arg to be the substitution.
So when t (the selected term) is an INTEGRAL, it can't be the arg.
(It will be rejected as an arg). But it needs an arg, so process_selectMenuChoice
will put up a GetArg dialog. But then, it's the same as intsub. So it's
useless to have it on the menu. Except ShowStep wants to select it...
*/
}
if(s >= LEARNING)
{ o[i] = autointsub; ++i;
o[i] = intsub; ++i;
o[i] = intsubwithdisplay; ++i;
}
if(status(integratebyparts) >= LEARNING)
{ o[i] = autointegratebyparts; ++i;
o[i] = integratebyparts; ++i;
}
}
else
{ o[i] = intpoly; ++i;
}
if(possible_trigsub(u,x))
{ o[i] = trigsubsin; ++i;
o[i] = trigsubtan; ++i;
o[i] = trigsubsec; ++i;
o[i] = trigsubsinh; ++i;
o[i] = trigsubcosh; ++i;
o[i] = trigsubtanh; ++i;
}
else if(use_trigsubtan(u,x)) /* catch 1/(a^2+x^2)^n */
{ o[i] = trigsubtan; ++i;
}
else if(use_trigsubsec(u,x))
{ o[i] = trigsubsec; ++i;
}
else if(ftrig(u,x))
{ o[i] = weierstrass; ++i;
}
if(m == 1 && !NEGATIVE(u) && equals(ARG(0,u),x))
{ switch(f)
{ case SG:
o[i] = intsg; ++i;
break;
case ABSFUNCTOR:
o[i] = intabs; ++i;
if(n==4)
{ o[i] = breakabsint; ++i;
}
break;
case '-':
o[i] = intminus; ++i;
break;
case SIN:
o[i] = intsin; ++i;
break;
case COS:
o[i] = intcos; ++i;
break;
case TAN:
o[i] = inttan; ++i;
break;
case COT:
o[i] = intcot; ++i;
break;
case SEC:
o[i] = intsec; ++i;
break;
case CSC:
o[i] = intcsc; ++i;
break;
case LN:
o[i] = intln; ++i;
break;
case ASIN:
o[i] = intasin; ++i;
break;
case ACOS:
o[i] = intacos; ++i;
break;
case ATAN:
o[i] = intatan; ++i;
break;
case ACOT:
o[i] = intacot; ++i;
break;
case ASEC:
o[i] = intasecplus; ++i;
o[i] = intasecminus; ++i;
break;
case ACSC:
o[i] = intacscplus; ++i;
o[i] = intacscminus; ++i;
break;
case SINH:
o[i] = intsinh; ++i;
break;
case COSH:
o[i] = intcosh; ++i;
break;
case TANH:
o[i] = inttanh; ++i;
break;
case COTH:
o[i] = intcoth; ++i;
break;
case CSCH:
o[i] = intcsch; ++i;
break;
case SECH:
o[i] = intsech; ++i;
break;
}
*nops = i;
return;
}
if(m == 1 && !NEGATIVE(u) && islinearproduct(ARG(0,u),x))
{ switch(f)
{ case SIN:
o[i] = intsin2; ++i;
break;
case COS:
o[i] = intcos2; ++i;
break;
case TAN:
o[i] = inttan2; ++i;
break;
case COT:
o[i] = intcot2; ++i;
break;
case SEC:
o[i] = intsec2; ++i;
break;
case CSC:
o[i] = intcsc2; ++i;
break;
}
*nops = i;
return;
}
switch(f)
{ case '-':
o[i] = intminus; ++i;
break;
case '+':
o[i] = intsum; ++i;
o[i] = intlinearity; ++i;
break;
case '*':
twoparts(u,x,&a,&b);
if(!ONE(a))
{ o[i] = intlinear; ++i;
}
if(m==2)
{ term p,q;
p = ARG(0,u);
q = ARG(1,u);
g = FUNCTOR(p);
h = FUNCTOR(q);
if(
ARITY(p) == 1 && ARITY(q) == 1 &&
equals(ARG(0,p),x) && equals(ARG(0,q),x)
)
{ /* integration formulas for p(x) q(x) */
if((g == SEC && h == TAN) || (g == TAN && h == SEC))
{ o[i] = inttosec; ++i;
*nops = i;
return;
}
if((g == CSC && h == COT) || (g == COT && h == CSC))
{ o[i] = inttocsc; ++i;
*nops = i;
return;
}
}
else if(
ARITY(p) == 1 && ARITY(q) == 1 &&
islinearproduct(ARG(0,p),x) &&
equals(ARG(0,p),ARG(0,q))
)
{ /* integration formulas for p(x) q(x) */
if((g == SEC && h == TAN) || (g == TAN && h == SEC))
{ o[i] = inttosec2; ++i;
*nops = i;
return;
}
if((g == CSC && h == COT) || (g == COT && h == CSC))
{ o[i] = inttocsc2; ++i;
*nops = i;
return;
}
}
}
if(trigpower(u,x))
/* sin^m x cos^n x or sec^n x tan^m x */
{ trigpowers(t,i,o,nops);
return;
}
else if(FUNCTOR(u) == '*')
{ /* look for a power of sin or cos even if the other factor
isn't a trig power */
for(j=0;j<ARITY(u);j++)
{ v = ARG(j,u);
if(FUNCTOR(v) != '^')
continue;
if(!INTEGERP(ARG(1,v)) || !ISEVEN(ARG(1,v)))
continue;
if(FUNCTOR(ARG(0,v)) == SIN && equals(ARG(0,ARG(0,v)),x))
{ o[i] = intsinsq; ++i;
}
if(FUNCTOR(ARG(0,v)) == COS && equals(ARG(0,ARG(0,v)),x))
{ o[i] = intcossq; ++i;
}
}
}
break;
case '^':
base = ARG(0,u);
power = ARG(1,u);
g = FUNCTOR(base);
if(equals(base,x) && !equals(power,minusone))
{ o[i] = intpower; ++i;
}
if(equals(base,x) && equals(power,minusone))
{ o[i] = intrecip; ++i;
}
if(equals(base,eulere))
{ if(equals(power,x))
{ o[i] = intexp1; ++i; /* \int e^t dt = e^t */
}
if(FUNCTOR(power) == '*')
{ o[i] = intexp2; ++i; /* \int e^at dt =(1/a) e^(at) */
}
if(NEGATIVE(power))
{ o[i] = intexp3; ++i; /* \int e^(-t)dt = -e^(-t) */
o[i] = intexp4; ++i; /* \int e^(-at)dt = -(1/a) e^(-at) */
}
if(FRACTION(power))
{ o[i] = intexp5; ++i; /* \int e^(t/a)dt = a e^(t/a) */
}
if(NEGATIVE(power) &&
FUNCTOR(ARG(0,power)) == '^' &&
equals(ARG(1,ARG(0,power)),two) &&
equals(ARG(0,ARG(0,power)),x)
)
{ o[i] = inttoerf; ++i; /* int e^(-t^2) dt = sqrt pi/2 Erf(t) */
}
}
else if(!depends(base,x))
{ o[i] = intexp6; ++i;
}
if(equals(power,minusone))
{ if(equals(base,x))
{ o[i] = intrecip; ++i;
}
if(FUNCTOR(base) == '+' &&
(equals(ARG(0,base),x) || equals(ARG(ARITY(base)-1,base),x))
)
{ o[i] = intrecip2; ++i;
}
else if(is_linear_in(base,x))
{ o[i] = intrecip3; ++i;
}
}
if(equals(power,two) && !ATOMIC(base) && ARITY(base) == 1)
/* integration formulas for f^2(x) */
{ if(equals(ARG(0,base),x))
{ switch(g)
{ case SEC:
o[i] = intsecsq; ++i;
o[i] = intsubtan; ++i;
*nops = i;
return;
case CSC:
o[i] = intcscsq; ++i;
o[i] = intsubcos; ++i;
*nops = i;
return;
case TAN:
o[i] = inttansq; ++i;
o[i] = intsubtan; ++i;
*nops = i;
return;
case COT:
o[i] = intcotsq; ++i;
o[i] = intsubcot; ++i;
*nops = i;
return;
}
}
if(islinearproduct(ARG(0,base),x))
{ switch(g)
{ case SEC:
o[i] = intsecsq2; ++i;
o[i] = intsubtan; ++i;
*nops = i;
return;
case CSC:
o[i] = intcscsq2; ++i;
o[i] = intsubcot; ++i;
*nops = i;
return;
case TAN:
o[i] = inttansq2; ++i;
o[i] = intsubtan; ++i;
*nops = i;
return;
case COT:
o[i] = intcotsq2; ++i;
o[i] = intsubcot; ++i;
*nops = i;
return;
}
}
}
if(INTEGERP(power) && TRIGFUNCTOR(g))
{ /* trig power integrals: integral( g^n (x), x) */
switch(g)
{ case COS:
o[i] = intsubsin; ++i; /* useful when power is odd */
/* u=sin x after using cos^2=1-sin^2 */
o[i] = intcossq; ++i; /* useful when power is even */
/* cos^2 t = (1+cos 2t)/2 in integral */
break;
case SIN:
o[i] = intsubcos; ++i; /* useful when power is odd */
/* u=cos x after using sin^2=1-cos^2 */
o[i] = intsinsq; ++i; /* useful when power is even */
/* sin^2 t = (1-cos 2t)/2 in integral */
break;
case TAN:
o[i] = intsubtan; ++i; /* odd or even power,
tan^n becomes u^n /(1+u^2) */
break;
case SEC:
o[i] = intsubtan; ++i; /* useful when power is even */
/* u=tan x after using sec^2=1+tan^2 */
o[i] = intsecpower; ++i; /* useful when power is odd */
break;
case COT:
o[i] = intsubcot; ++i;
break;
case CSC:
o[i] = intsubcot; ++i;
o[i] = intcscpower; ++i;
break;
}
}
break;
case '/':
twoparts(u,x,&a,&b);
if(!ONE(a))
{ o[i] = intlinear; ++i;
}
num = ARG(0,u);
denom = ARG(1,u);
g = FUNCTOR(denom);
h = FUNCTOR(num);
if(g == '+' && ARITY(denom) == 2 &&
(ONE(ARG(0,denom)) || ONE(ARG(1,denom)))
) /* given .../(1-cos x), you can
multiply num and denom by (1+cos x) */
{ term p = ONE(ARG(0,denom)) ? ARG(1,denom) : ARG(0,denom);
if(NEGATIVE(p))
p = ARG(0,p);
if(FUNCTOR(p) == COS && equals(ARG(0,p),x))
{ o[i] = trigrationalizedenom1; ++i;
o[i] = trigrationalizedenom4; ++i;
}
if(FUNCTOR(p) == SIN && equals(ARG(0,p),x))
{ o[i] = trigrationalizedenom2; ++i;
o[i] = trigrationalizedenom5; ++i;
}
}
if(h == '+' && ARITY(num) == 2 &&
(ONE(ARG(0,num)) || ONE(ARG(1,num)))
) /* given (1-cos x)/..., you can
multiply num and denom by (1+cos x) */
{ term p = ONE(ARG(0,num)) ? ARG(1,num) : ARG(0,num);
if(NEGATIVE(p))
p = ARG(0,p);
if(FUNCTOR(p) == COS && equals(ARG(0,p),x))
{ o[i] = trigrationalizedenom1; ++i;
o[i] = trigrationalizedenom4; ++i;
}
if(FUNCTOR(p) == SIN && equals(ARG(0,p),x))
{ o[i] = trigrationalizedenom2; ++i;
o[i] = trigrationalizedenom5; ++i;
}
}
if(is_sincos(num,x) || is_sincos(denom,x))
{ o[i] = trigrationalizedenom3; ++i;
o[i] = trigrationalizedenom6; ++i;
}
if(equals(denom,x) && !depends(num,x))
{ o[i] = intrecip; ++i;
}
if(ONE(num) && g == '+' && ARITY(denom) == 2 &&
(
(FUNCTOR(ARG(1,denom)) == '^' && equals(ARG(1,ARG(1,denom)),two) &&
equals(ARG(0,ARG(1,denom)),x) && !contains(ARG(0,denom),FUNCTOR(x))
)
||
(FUNCTOR(ARG(0,denom)) == '^' && equals(ARG(1,ARG(0,denom)),two) &&
equals(ARG(0,ARG(0,denom)),x) && !contains(ARG(1,denom),FUNCTOR(x))
)
)
)
{ o[i] = inttoatan; ++i;
o[i] = inttoacoth; ++i;
o[i] = inttolnratio1; ++i;
}
if(ONE(num) && g == '+' && ARITY(denom) == 2 &&
(
(!contains(ARG(0,denom),FUNCTOR(x)) && NEGATIVE(ARG(1,denom)) &&
FUNCTOR(ARG(0,ARG(1,denom))) == '^' &&
equals(ARG(1,ARG(0,ARG(1,denom))),two) &&
equals(ARG(0,ARG(0,ARG(1,denom))),x)
)
||
(!contains(ARG(1,denom),FUNCTOR(x)) && NEGATIVE(ARG(0,denom)) &&
FUNCTOR(ARG(0,ARG(0,denom))) == '^' &&
equals(ARG(1,ARG(0,ARG(0,denom))),two) &&
equals(ARG(0,ARG(0,ARG(0,denom))),x)
)
)
)
{ o[i] = inttoatanh; ++i;
o[i] = inttolnratio2; ++i;
}
if(!(contains(num,FUNCTOR(x))) && (g == '+' || g == '*') && is_linear_in(denom,x))
{ if(g == '+' && (equals(ARG(0,denom),x) || equals(ARG(ARITY(denom)-1,denom),x)))
{ o[i] = intrecip2; ++i;
}
else
{ o[i] = intrecip3; ++i;
}
}
if(g == '^' && !depends(num,x) && is_linear_in(ARG(0,denom),x))
{ o[i] = intinversepower; ++i;
}
if(ONE(num) && g == SQRT && FUNCTOR(ARG(0,denom)) == '+' &&
ARITY(ARG(0,denom)) == 2 &&
(
(FUNCTOR(ARG(1,ARG(0,denom))) == '^' && equals(ARG(1,ARG(1,ARG(0,denom))),two) && equals(ARG(0,ARG(1,ARG(0,denom))),x) ) ||
(FUNCTOR(ARG(0,ARG(0,denom))) == '^' && equals(ARG(1,ARG(0,ARG(0,denom))),two) && equals(ARG(0,ARG(0,ARG(0,denom))),x) )
)
)
{ o[i] = inttolnratio3; ++i;
o[i] = inttoacos; ++i;
}
if(ONE(num) && g == SQRT && FUNCTOR(ARG(0,denom)) == '+' &&
ARITY(ARG(0,denom)) == 2 && NEGATIVE(ARG(1,ARG(0,denom))) &&
FUNCTOR(ARG(0,ARG(1,ARG(0,denom)))) == '^' &&
equals(ARG(1,ARG(0,ARG(1,ARG(0,denom)))),two) &&
equals(ARG(0,ARG(0,ARG(1,ARG(0,denom)))),x)
)
{ o[i] = inttoasin; ++i;
}
if(ONE(num) && TRIGFUNCTOR(g))
{ /* reciprocals of trig functions */
switch(g)
{ case SIN:
o[i] = intsubcos; ++i;
break;
case COS:
o[i] = intsubsin; ++i;
break;
case TAN:
o[i] = intsubsec; ++i;
/* dx/tan x = tan x sec x dx/ tan^2 x = du/(u^2-1) with u = sec x */
break;
case SEC:
o[i] = secrule; ++i;
break;
case CSC:
o[i] = cscrule; ++i;
break;
case COT:
o[i] = cottotan; ++i;
break;
}
}
if(
(
ONE(num) ||
(TRIGFUNCTOR(h) && equals(ARG(0,num),x)) ||
(
h == '^' && TRIGFUNCTOR(FUNCTOR(ARG(0,num))) &&
INTEGERP(ARG(1,num)) && equals(ARG(0,ARG(0,num)),x)
)
)
&&
(
(TRIGFUNCTOR(g) && equals(ARG(0,denom),x)) ||
(
g == '^' && INTEGERP(ARG(1,denom)) &&
TRIGFUNCTOR(FUNCTOR(ARG(0,denom))) && equals(ARG(0,ARG(0,denom)),x)
)
)
)
/* reciprocals or quotients of trig powers */
{ base = g == '^' ? ARG(0,denom) : denom;
hh = FUNCTOR(base);
switch(hh)
{ case SIN: /* integral (1/sin^n x ,x) */
o[i] = intsinsq; ++i; /* useful when power is even */
/* sin^2 t = (1-cos 2t)/2 in integral */
o[i] = intsubcos; ++i; /* u=cos x after using sin^2=1-cos^2 */
o[i] = intsubsin; ++i;
break;
case COS:
o[i] = intcossq; ++i; /* when power is even */
/* cos^2 t = (1+cos 2t)/2 in integral */
o[i] = intsubsin; ++i;
o[i] = intsubcos; ++i;
/* u=sin x after using cos^2=1-sin^2 */
break;
case TAN:
o[i] = tantosecinint; ++i;
o[i] = intsubsec; ++i; /* u=sec x after using tan^2=sec^2-1 */
o[i] = intsubtan; ++i;
break;
case SEC:
o[i] = intsubtan; ++i; /* u=tan x after using sec^2=1+tan^2 */
o[i] = intsubsec; ++i;
o[i] = intsecpower; ++i; /* useful when power is odd */
break;
case COT:
break;
case CSC:
break;
}
}
break;
case SUM:
if(equals(ARG(3,u),infinity))
{ if(is_power_series(u,x,&a))
{ o[i] = intseries; ++i;
}
}
else if(!equals(ARG(2,u),minusinfinity))
{ o[i] = intsigma; ++i;
}
break;
}
*nops = i;
}
/*__________________________________________________________________*/
void select_dif_op(term t, actualop *o, int *nops)
/* t is a DIFF/2 term selected by the user. Fill in o with
operators that might apply, and return their number in *nops. */
/* higher-order derivatives have the form diff(u,n,x) */
{ term x = ARG(1,t);
term u = ARG(0,t);
term v,w,c,s;
char buffer[DIMREASONBUFFER];
int k;
int i=0;
unsigned short m;
unsigned short g = FUNCTOR(u);
if(!depends(u,x))
{ o[i] = difconstant; ++i;
}
if(equals(u,x))
{ o[i] = difidentity; ++i;
}
if(ATOMIC(u))
/* FINISH THIS: du/dx = du/dv dv/dx */
{ *nops = i;
return;
}
if(FUNCTOR(u) == '*')
twoparts(u,x,&c,&s);
if(
(FUNCTOR(u) == '+' ||
(FRACTION(u) && contains(u,'^')) ||
monomial(u) || // monomial requires rational coefficients and won't accept (ln 2) x
(FUNCTOR(u) == '*' && monomial(s)) || // that will take (ln 2) x
(FRACTION(u) && numerical(ARG(1,u)) && ATOMIC(ARG(0,u)))
) &&
ispolyin(u,x) && status(difpoly) >= KNOWN
)
{ o[i] = difpoly; ++i;
}
v = ARG(0,u);
switch(g)
{ case '+':
o[i] = difsum; ++i;
break;
case '-':
o[i] = difminus; ++i;
break;
case '*':
m = ARITY(u);
for(k=0;k<m;k++)
{ if(!depends(ARG(k,u),x))
break;
}
if(k < m)
{ o[i] = diflinear; ++i;
}
if(k == 0 && FUNCTOR(ARG((unsigned short)(m-1),u)) == '^' && !difpower(t,zero,&w,buffer))
{ o[i] = difpower; ++i;
}
o[i] = difproduct; ++i;
if(status(logdif) >= LEARNING)
{ o[i] = logdif; ++i;
}
break;
case '^':
w = ARG(1,u); /* v is already ARG(0,u), so u = v^w */
o[i] = equals(v,x) ? difpower : difpower2; ++i;
/* Put it in anyway even if the exponent is not constant,
so the student can learn that it doesn't apply */
if(equals(v,eulere))
{ o[i] = equals(ARG(1,u),x) ? difexp : difexp2; ++i;
}
else if(!depends(v,x))
{ o[i] = equals(ARG(1,u),x) ? difatox : difatox2; ++i;
}
else if(depends(w,x))
{ o[i] = difexponential; ++i; /* d/dx u^v= (d/dx) e^(v ln u) */
}
break;
case '/':
if(!depends(ARG(0,u),x))
{ o[i] = difrecip; ++i;
if(FUNCTOR(ARG(1,u)) == '^' && equals(ARG(0,ARG(1,u)),x))
{ o[i] = difinversepower; ++i;
}
}
if(!diflinear2(t,zero,&w,buffer))
{ o[i] = diflinear2; ++i;
}
if(status(logdif) >= LEARNING)
{ o[i] = logdif; ++i;
}
o[i] = difquotient; ++i;
break;
case INTEGRAL:
o[i] = fundamentaltheorem2; ++i;
break;
case LN:
switch(FUNCTOR(v))
{ case ABSFUNCTOR:
o[i] = equals(ARG(0,v),x) ? diflnabs : diflnabs2; ++i;
break;
case SIN:
o[i] = diflnsin; ++i;
break;
case COS:
o[i] = diflncos; ++i;
break;
case SINH:
o[i] = diflnsinh; ++i;
case COSH:
o[i] = diflncosh; ++i;
}
o[i] = equals(v,x) ? difln : difln2; ++i;
/* always show this basic law for differentiating ln */
break;
case SG:
o[i] = difsg; ++i;
break;
case ABSFUNCTOR:
o[i] = equals(v,x) ? difabs: difabs2; ++i;
break;
case SQRT:
o[i] = equals(v,x) ? difsqrt: difsqrt2; ++i;
if(status(logdif) >= LEARNING)
{ o[i] = logdif; ++i;
}
break;
case ROOT:
o[i] = difroots; ++i;
break;
case SIN:
o[i] = equals(v,x) ? difsin : difsin2; ++i;
break;
case COS:
o[i] = equals(v,x) ? difcos : difcos2; ++i;
break;
case SEC:
o[i] = equals(v,x) ? difsec : difsec2; ++i;
break;
case CSC:
o[i] = equals(v,x) ? difcsc : difcsc2; ++i;
break;
case TAN:
o[i] = equals(v,x) ? diftan : diftan2; ++i;
break;
case COT:
o[i] = equals(v,x) ? difcot : difcot2; ++i;
break;
case ATAN:
o[i] = equals(v,x) ? difatan: difatan2; ++i;
break;
case ASIN:
o[i] = equals(v,x) ? difasin: difasin2; ++i;
break;
case ACOS:
o[i] = equals(v,x) ? difacos: difacos2; ++i;
break;
case ACOT:
o[i] = equals(v,x) ? difacot: difacot2; ++i;
break;
case ASEC:
o[i] = equals(v,x) ? difasec: difasec2; ++i;
break;
case ACSC:
o[i] = equals(v,x) ? difacsc: difacsc2; ++i;
break;
case DIFF:
if(ARITY(u)==2)
{ o[i] = secondderiv; ++i;
}
else
{ o[i] = highderiv; ++i;
}
break;
case SINH:
o[i] = difsinh; ++i;
break;
case COSH:
o[i] = difcosh; ++i;
break;
case TANH:
o[i] = diftanh; ++i;
break;
case COTH:
o[i] = difcoth; ++i;
break;
case SECH:
o[i] = difsech; ++i;
break;
case CSCH:
o[i] = difcsch; ++i;
break;
case ASINH:
o[i] = difasinh; ++i;
break;
case ACOSH:
o[i] = difacosh; ++i;
break;
case ATANH:
o[i] = difatanh; ++i;
break;
case ACOTH:
o[i] = difacoth; ++i;
break;
case ASECH:
o[i] = difasech; ++i;
break;
case ACSCH:
o[i] = difacsch; ++i;
break;
case SUM:
o[i] = difsigma; ++i;
break;
case BESSELJ:
o[i] = ZERO(ARG(0,u)) ? difj0 : ONE(ARG(0,u)) ? difj1 : difjn; ++i;
break;
case BESSELY:
o[i] = ZERO(ARG(0,u)) ? dify0 : ONE(ARG(0,u)) ? dify1 : difyn; ++i;
break;
case BESSELI:
o[i] = ZERO(ARG(0,u)) ? difi0 : ONE(ARG(0,u)) ? difi1 : difin; ++i;
break;
case BESSELK:
o[i] = ZERO(ARG(0,u)) ? difk0 : ONE(ARG(0,u)) ? difk1 : difkn; ++i;
break;
}
if(status(derivop) >= LEARNING)
{ o[i] = derivop; ++i;
}
*nops = i;
}
/*_______________________________________________________*/
static int numerically_indeterminate(term u, term x, term a)
/* return 1 if we need to show L'Hopital even if its status is UNKNOWN;
0 otherwise.
*/
{ double saveit,aval,z,w;
term num,denom;
if(!FRACTION(u))
return 0;
if(ISINFINITE(a))
return 1;
num = ARG(0,u);
denom = ARG(1,u);
saveit = VALUE(x);
deval(a,&aval);
if(aval == BADVAL)
return 0;
SETVALUE(x,aval);
deval(num,&z);
deval(denom,&w);
SETVALUE(x,saveit);
if(z == BADVAL && w == BADVAL)
return 1;
if(fabs(z) < VERYSMALL && fabs(w) < VERYSMALL)
return 1;
return 0;
}
/*_________________________________________________________________*/
void select_identity_op(term t, actualop *o, int *nops)
/* finish selectops1 on identities
*/
{ int i = 0;
unsigned short g;
term x,a,b,w;
char buffer[DIMREASONBUFFER];
o[i] = checknumerically; ++i;
x = get_eigenvariable();
if(SIGNEDFRACTION(ARG(0,t)) && SIGNEDFRACTION(ARG(1,t)))
{ o[i] = crossmultiply; ++i;
}
if(trigargs(t,&a,&b) == 2)
{ term *atomlist;
int nvars = variablesin(t,&atomlist);
free2(atomlist);
if(nvars >= 2)
{ o[i] = trigdoublesub; ++i;
}
}
g = contains_sqrt(t);
if(g == ABSFUNCTOR || g == SQRT)
{ o[i] = squareeqn; ++i;
}
else if(g == ROOT)
{ o[i] = powereqn; ++i;
}
else if(
(FUNCTOR(ARG(1,t)) == '^' && RATIONALP(ARG(1,ARG(1,t))) && equals(ARG(1,ARG(1,ARG(1,t))),two)) ||
(FUNCTOR(ARG(0,t)) == '^' && RATIONALP(ARG(1,ARG(0,t))) && equals(ARG(1,ARG(1,ARG(0,t))),two))
)
{ o[i] = squareeqn; ++i;
}
else if(
(FUNCTOR(ARG(1,t)) == '^' && RATIONALP(ARG(1,ARG(1,t)))) ||
(FUNCTOR(ARG(0,t)) == '^' && RATIONALP(ARG(1,ARG(0,t))))
)
{ o[i] = powereqn; ++i;
}
else if( polyprod(ARG(0,t),x) && polyprod(ARG(1,t),x) &&
!cancelfactor(t,zero,&w,buffer)
)
{ o[i] = cancelfactor; ++i;
}
if(!polyvalop(t,seven,&w,buffer))
{ o[i] = polyvalop; ++i;
}
if(contains(t,UNDEFINED))
{ o[i] = undefinedpart; ++i;
}
*nops = i;
return;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists