Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/automode/
Upload File :
Current File : /usr/home/beeson/MathXpert/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.
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