Sindbad~EG File Manager

Current Path : /usr/home/beeson/Otter-Lambda/yyy/automode/
Upload File :
Current File : /usr/home/beeson/Otter-Lambda/yyy/automode/select2.c

/* 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.
*/

#define AUTOMODE_DLL
#include <math.h>   /* abs */
#include <string.h>    /* memset */
#include <assert.h>
#include "globals.h"
#include "graphstr.h"
#include "display.h"
#include "document.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 "dowith.h"    /* dowith                 */
#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)) || (equals(ARG(0,v),pi) && 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�v = lim u � 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� = (lim u)� */
             }
          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) ||
             (INTEGERP(ARG(0,u)) &&  !ONE(ARG(0,u)))
            )
             { o[i] = limthruexp; ++i;
             }
          break;
       case ABS:
          o[i] = limabs; ++i;
          break;
       case SQRT:
          o[i] = limsqrt; ++i;  /* lim �u=�(lim u) if lim u>0 */
          break;
       case ROOT:
          if(iseven(ARG(0,u)))
             { o[i] = limevenroot; ++i; /* lim ��u = ��(lim u) if lim u > 0 */
             }
          else if(isodd(ARG(0,u)))
             { o[i] = limoddroot; ++i;  /* lim ��u = ��(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;
          }
       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) == ABS)
          { 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;
          }
       if(s >= LEARNING)
          { o[i] = autointsub; ++i;
            o[i] = intsub; ++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)�  */
     { 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 ABS:
               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;   /* �e^t dt = e^t           */
                  }
               if(FUNCTOR(power) == '*')
                  { o[i] = intexp2; ++i;   /* �e^at dt =(1/a) e^(at)  */
                  }
               if(NEGATIVE(power))
                  { o[i] = intexp3; ++i;   /* �e^(-t)dt = -e^(-t)     */
                    o[i] = intexp4; ++i;   /* �e^(-at)dt = -(1/a) e^(-at) */
                  }
               if(FRACTION(power))
                  { o[i] = intexp5; ++i;   /* �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;  /* �e^(-t^2) dt = ��/2 Erf(t) */
                  }
             }
          else
             { 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�(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� becomes  u�/(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� 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;
  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) == '+' ||
      (FRACTION(u)  && contains(u,'^')) ||
      monomial(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 ABS:
                  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 ABS:
          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 == ABS || 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