Sindbad~EG File Manager

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

/* M. Beeson, for Mathpert */
/* Functions to build the SelectOperator menu, specifically
   for adding operations to solve inequalities and equations.
*/
/*
1.29.95 Original date
11.12.98 last modified
*/

#define AUTOMODE_DLL
#include <math.h>   /* abs */
#include <string.h>    /* memset */
#include <assert.h>
#include "globals.h"
#include "graphstr.h"
#include "display.h"
#include "display1.h"  /* needed by lterm.h */
#include "document.h"
#include "tdefn.h"
#include "checkarg.h"
#include "ops.h"
#include "trig.h"
#include "calc.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 "relrates.h"  /* used                   */
#include "domain.h"    /* contains_defined_variables */
#include "autosub.h"
#include "autosimp.h"  /* contains_calc          */

static int showsub(term t);
static int nonconstant_powers(term t);
static int show_explicitdomain(term t);
static int powersof10(term);
static int higher_powers(term);
static int two_terms(POLYnomial p);
static int contains_powerof(term t, term x);
/*__________________________________________________________________*/
void select_inequality_ops(term t, actualop *o, int *nops)
/* Fill pre-allocated array o with the operators that
could be applied to t.  Return the dimension of the
array in *nops.
*/

{ term u,v,x,context;
  term xx,yy,a,b,c;
  unsigned short f = FUNCTOR(t);
  unsigned short g,h;
  char buffer[DIMREASONBUFFER];
  int i=0;
  int count,sflag;
  term left,right,w;
  if(!INEQUALITY(f))
    { *nops = 0;
      return;
    }
  left = ARG(0,t);
  right = ARG(1,t);
  x = get_eigenvariable();
  if(solved(t,get_eigenvariable()) &&
     !contains_defined_variables(t) &&
     get_nextassumption() > 0
    )
     { o[i] = explicitdomain; ++i;
     }
  if(
     (numerical(left) || select_arith_aux(left)) &&
     (numerical(right) ||  select_arith_aux(right))
    )
     { o[i] = arithmetic; ++i;
     }
  if(econstant(left) && FUNCTOR(right) == '+' && ARITY(right) == 3 &&
     isquadratic(right,&xx,&yy,&a,&b,&c)
    )
     { o[i] = completethesquare; ++i;
     }
  if(econstant(right) && FUNCTOR(left) == '+' && ARITY(left) == 3 &&
     isquadratic(left,&xx,&yy,&a,&b,&c)
    )
     { o[i] = completethesquare; ++i;
     }
  /* on 1 < x^2-x, we need completethesquare;  isquadratic fails on
     arity 2 so we use a different check below. */
  if(econstant(left) && FUNCTOR(right) == '+' && ARITY(right) == 2 &&
     mvpoly(right) && !makepoly(right,x,&w) &&
     (ARITY(w) == 3 || two_terms(w))
     /* two_terms catches a polynomial like 6x^6 + x^3  */
    )
     { o[i] = completethesquare; ++i;
     }
  if(econstant(right) && FUNCTOR(left) == '+' && ARITY(left) == 2 &&
     mvpoly(left) && !makepoly(left,x,&w) &&
     (ARITY(w) == 3 || two_terms(w))
    )
     { o[i] = completethesquare; ++i;
     }
  switch(f)
     { case '>':  /* fall through */
       case '<':
          if(showsub(t))
             { o[i] = makesubstitution; ++i;
             }
          if(f == '>')
             { u = ARG(1,t);
               v = ARG(0,t);
               g = FUNCTOR(u);
               h = FUNCTOR(v);
               o[i] = reversegreaterthan; ++i;
               sflag = 0;
             }
          else
             { v = ARG(1,t);
               u = ARG(0,t);
               g = FUNCTOR(u);
               h = FUNCTOR(v);
               o[i] = reverselessthan; ++i;
               sflag = 1;
             }
          if(seminumerical(t))
             { o[i] = numericalineq; ++i;
               count = 0;
             }
          else if(!iscomplex(t) && !get_complex())
              /* get_complex is necessary so that sqrt(-1) can't be
                 selected when it's a complex-number topic */
             { o[i] = evalatpoint; ++i;
               count = 1;
             }
          context = history(get_activeline());
          if(FUNCTOR(v) == SQRT && obviously_negative(u))
             { o[i] = f == '<' ? sqsqrtineq1 : sqsqrtineq1rev; ++i;
             }
          if(FUNCTOR(v) == ROOT && iseven(ARG(0,v)) &&
             obviously_negative(u)
            )
            { o[i] = f == '<' ? powerrootineq1 : powerrootineq1rev; ++i;
            }
          if(contains(t,SQRT) || contains(t,ABS))
             { o[i] = sflag ? squareineq1 : squareineq1g; ++i;
               o[i] = sflag ? squareineq3 : squareineq3g; ++i;
             }
          if(ZERO(u))
             { if(!is_linear_in(v,x))
                  { o[i] =  droppositive1 ; ++i;
                  }
               if(h == '/')
                  { o[i] = sflag ? mulineqbysquare1 : mulineqbysquare1g; ++i;
                    /* 0 < u/v  => 0 < uv */
                    if(contains_sqrt(ARG(1,v)) == SQRT)
                       { o[i] = sflag ? mulineqsqrt1 : mulineqsqrt1g; ++i;
                        /* 0 < u/sqrt v => 0 < uv */
                       }
                  }
               if(h == '*')
                  { if(sflag)
                       { if(!normalizelinear1(t,zero,&w,buffer))
                            { o[i] = normalizelinear1; ++i;
                            }
                       }
                    else
                       { if(!normalizelinear1g(t,zero,&w,buffer))
                            { o[i] = normalizelinear1g; ++i;
                            }
                       }
                    o[i] = sflag ? intervalspos1 : intervalspos1g; ++i;  /* 0<(x-a)(x-b)=>x<a or b<x (if a<b) */
                  }
             }
          if(ZERO(v))
             { if(!is_linear_in(u,x))
                  { o[i] = droppositive1;  ++i;
                  }
               if(g == ABS)
                  { o[i] = absineqfalse; ++i;  /* abs(u) < 0 is false */
                  }
               if(g == '/')
                  { o[i] = sflag ? mulineqbysquare2 : mulineqbysquare2g; ++i;
                    /* u/v < 0  => uv < 0 */
                    if(contains_sqrt(ARG(1,u)) == SQRT)
                       { o[i] = sflag ? mulineqsqrt2 : mulineqsqrt2g; ++i;
                         /* u/sqrt v < 0 => uv < 0 */
                       }
                  }
               if(g == '+' && count && is_linear_in(u,x))
                  { o[i] = sflag ? normalizelinear1 : normalizelinear1g; ++i;  /* ax � b < 0 iff a(x�b/a) < 0 */
                  }
               if(g == '*')
                  { if(sflag)
                       { if(!normalizelinear1(t,zero,&w,buffer))
                            { o[i] = normalizelinear1; ++i;
                            }
                       }
                    else
                       { if(!normalizelinear1g(t,zero,&w,buffer))
                            { o[i] = normalizelinear1g; ++i;
                            }
                       }
                    o[i] = sflag ? intervalsneg1 : intervalsneg1g; ++i;  /* (x-a)(x-b)<0 => a<x<b (if a<b) */
                  }
             }
          switch(g)
             { case ABS:
                  o[i] = f == '<' ? abslessthan : absgreaterthan; ++i;  /* |u|< v iff -v < u < v */
                  if(FUNCTOR(ARG(0,u)) == SIN)
                     { o[i] = abssinineq; ++i;    /* |sin u| � 1 */
                     }
                  if(FUNCTOR(ARG(0,u)) == COS)
                     { o[i] = abscosineq; ++i;    /* |cos u| � 1 */
                     }
                  if(FUNCTOR(ARG(0,u)) == ATAN)
                     { o[i] = absarctanineq; ++i;  /* |arctan u| � �/2  */
                     }
                  if(!infer(le(v,zero)))
                     { o[i] = f == '<' ? abslessthanneg : absgreaterthanneg; ++i;
                       /* abs(u) < -c is false when c >= 0 */
                       /* -c > abs(u) is flase when c >= 0 */
                     }
                  break;
               case SIN:
                  o[i] = sinineq; ++i;    /* sin u � u  if u�0 */
                  break;
               case ATAN:
                  o[i] = arctanineq; ++i; /* arctan u � u if u�0 */
                  break;
               case SQRT:
                  o[i] = powerineq11; ++i;   /* �u < v => u < v^2     */
                  break;
               case ROOT:
                  if(isodd(ARG(0,u)))
                     { o[i] = sflag ? powerineq14odd :powerineq14oddg; ++i;
                     }
                  else
                     { o[i] = sflag ? powerineq14even : powerineq14eveng; ++i;
                       /* ��u < v => u < v      */
                     }
                  break;
               case '^':
                  if(isinteger(ARG(1,u)) && iseven(ARG(1,u)))
                     { o[i] = sflag ? sqrtineq11 : sqrtineq11g; ++i;
                       /* u^2 < v => |u| < �v */
                       o[i] = sflag ? sqrtineq14 : sqrtineq14g; ++i;
                       /* u^2 < a => -a < u < a */
                     }
                  if(INTEGERP(ARG(1,u)) && iseven(ARG(1,u)))
                     { if(ZERO(v) ||
                          (NEGATIVE(v) && OBJECT(ARG(0,v)))
                         )
                          { if(isinteger(ARG(1,u)) && iseven(ARG(1,u)))
                               { o[i] = sflag ? squarefalse1: squarefalse1g; ++i;
                               }
                            else
                               { o[i] = sflag ? evenpowerineq3 : evenpowerineq3g; ++i;
                               }
                          }
                     }
                  else if(!(INTEGERP(ARG(1,u)) && ISODD(ARG(1,u))))
                     { o[i] = sflag ? rootineq11 : rootineq11g; ++i;
                       /* u^2� < v => |u| < ^2��v */
                       o[i] = sflag ? rootineq13 : rootineq13g; ++i;
                       /* u^2� < a iff -^2��a < u < ^2��a      */
                     }
                  break;
               case '/':
                  count = contains_sqrt(u);
                  if(count == ROOT)
                     { o[i] = sflag ? powerineq13 : powerineq13g; ++i;
                      /* 0 � a(��u) < v => a�u < v� */
                     }
                  /* Now for the reciprocal inequaltiies */
                  if(econstant(v) &&
                     econstant(ARG(0,u)) &&
                     obviously_positive(ARG(0,u))
                    )
                     { if(obviously_positive(v))
                          { o[i] = sflag ? recipineq11 : recipineq11g; ++i;
                            /* 1/x < a iff x < 0 or 1/a < x provided a > 0 */
                          }
                       else if(obviously_positive(strongnegate(v)))
                          { o[i] = sflag ? recipineq31 : recipineq31g; ++i;
                            /* 1/x < -a iff -1/a < x < 0 < x provided a > 0 */
                          }
                     }
                  break;
               case '-':  /* fall through */
               case '*':
                  count = contains_sqrt(u);
                  if(count == ROOT)
                     { o[i] = sflag ? powerineq13 : powerineq13g; ++i;
                      /* 0 � a(��u) < v => a�u < v� */
                     }
                  break;
             }
          if( (g == '^' &&
              !(INTEGERP(ARG(1,u)) && ISEVEN(ARG(1,u))))  || (h == '^' && !(INTEGERP(ARG(1,v)) && ISEVEN(ARG(1,v))))\
            )
             { o[i] = sflag ? oddrootineq : oddrootineqg; ++i;
             }
          o[i] = addeqn1; ++i;
          o[i] = subeqn1; ++i;
          o[i] = changesigns1; ++i;    /*  -u < -v iff  v < u    */
          o[i] = sflag ? changesignsandsense1 : changesignsandsense3; ++i;
            /* change -u < -v to u > v  */
          o[i] = mulineq; ++i;     /* multiply both sides */
          o[i] = divineq; ++i;     /* divide both sides   */
          o[i] = sflag ? sqrtineq13 : sqrtineq13g; ++i;
          /* 0 � u < v => �u < �v */
          o[i] = sflag ? powerineq16 : powerineq16g; ++i;
          /* u < v => u� < v� (n odd, n>0) */
          o[i] = sflag ? powerineq17: powerineq17g; ++i;
          /* 0 � u < v => u� < v� (n > 0)  */
          switch(h)
             { case '^':
                  if(isinteger(ARG(1,v)) && iseven(ARG(1,v)))
                     { o[i] = sflag ? sqrtineq12 : sqrtineq12g; ++i;
                       /* 0 � u < v^2 => �u < |v| */
                       o[i] = sflag ? sqrtineq15 : sqrtineq15g; ++i;
                       /* a < u^2 => u < -�a or �a < u */
                     }
                  if(isinteger(ARG(1,v)) && iseven(ARG(1,v)))
                     { if(NEGATIVE(u) && OBJECT(ARG(0,u)))
                          { if(isinteger(ARG(1,v)) && iseven(ARG(1,v)))
                               { o[i] = sflag ? squaretrue1 : squaretrue1g; ++i;
                               }
                            else
                               { o[i] = sflag ? evenpowerineq1 : evenpowerineq1g; ++i;
                               }
                          }
                     }
                  if( !(INTEGERP(ARG(1,v)) && isodd(ARG(1,v))))
                     { o[i] = sflag ? rootineq12 : rootineq12g; ++i;
                       /* 0 � u < v^2� => ^2��u < |v|  */
                       o[i] = sflag ? rootineq15 : rootineq15g; ++i;
                       /* a < u^2� iff v < -^2��a  or ^2��a < u  */
                     }
                  break;
               case '/':
                  /* Now for the reciprocal inequaltiies */
                  if(econstant(u) &&
                     econstant(ARG(0,v)) &&
                     obviously_positive(ARG(0,v))
                    )
                     { if(obviously_positive(u))
                          { o[i] = sflag ? recipineq21 : recipineq21g; ++i;
                            /* a < 1/x iff 0 < x < 1/a < x provided a > 0 */
                          }
                       else if(obviously_positive(strongnegate(u)))
                          { o[i] = sflag ? recipineq41 : recipineq41g; ++i;
                            /* -a < 1/x iff x < -1/a or 0 < x provided a > 0 */
                          }
                     }
                  break;
               case SQRT:
                  o[i] = sflag ? powerineq12 : powerineq12g; ++i;
                  /* 0 � u < �v => u^2 < v       */
                  break;
               case ROOT:
                  o[i] = sflag ? powerineq15 : powerineq15g; ++i;
                   /* 0 � u < ��v => u� < |v|    */
                  break;
               case TAN:
                  o[i] = tanineq; ++i;         /* u <= tan u  if 0<= u pi/2 */
                  break;
               case COS:
                  o[i] = coslowerbound; ++i;   /* 1 - u^2/2 � cos u           */
                  break;
               case ABS:
                  o[i] = f == '<' ? lessthanabs: greaterthanabs; ++i;     /* u < abs(v) if v < -u or u < v  */
                  if(!infer(lessthan(zero,u)))
                     { o[i] = f == '<' ? absineqtrue3 : absineqtrue3g; ++i;
                       /* -c < abs(u) is true if c > 0 */
                       /* abs(u) > -c is true if c > 0 */
                     }
                  break;
             }
          if(get_nextdefn() > 0 && contains_defined_variables(t))
             { o[i] = unwinddefinition; ++i;
             }

          if(nonconstant_powers(t))
             { o[i] = lnineq1; ++i;
               if(g == '^' && h == '^' && equals(ARG(0,u),ARG(0,v)) && !equals(ARG(0,u),eulere) && !equals(ARG(0,u),ten))
                  { o[i] = expineq1; ++i;
                  }
               if(powersof10(t))
                  { o[i] = logineq1; ++i;
                  }
             }
          if(show_explicitdomain(t))
             { o[i] = explicitdomain; ++i;
             }
          break;

       case GE:
          /* fall through */
       case LE:
          if(f == GE)
             { u = ARG(1,t);
               v = ARG(0,t);
               g = FUNCTOR(u);
               h = FUNCTOR(v);
               o[i] = reversege; ++i;
               sflag = 0;
             }
          else
             { v = ARG(1,t);
               h = FUNCTOR(v);
               u = ARG(0,t);
               g = FUNCTOR(u);
               o[i] = reversele; ++i;
               sflag = 1;
             }
          if(seminumerical(t))
             { o[i] = numericalineq; ++i;
               count = 0;
             }
          else
             count = 1;
          o[i] = evalatpoint; ++i;
          context = history(get_activeline());
          if(FUNCTOR(v) == SQRT && obviously_negative(u))
             { o[i] = f == '<' ? sqsqrtineq2 : sqsqrtineq2rev; ++i;
             }
          if(FUNCTOR(v) == ROOT && iseven(ARG(0,v)) &&
             obviously_negative(u)
            )
            { o[i] = f == '<' ? powerrootineq2 : powerrootineq2rev; ++i;
            }
          if(contains(t,SQRT) || contains(t,ABS))
             { o[i] = sflag ? squareineq2 : squareineq2g; ++i;
               o[i] = sflag ? squareineq4 : squareineq4g; ++i;
             }
          if(ZERO(u))
             { if(!is_linear_in(v,x))
                  { o[i] =  droppositive2 ; ++i;
                  }
               if(h == '/')
                  { o[i] = sflag ? mulineqbysquare3 : mulineqbysquare3g; ++i;
                    /* 0 <= u/v  => 0 < uv or u = 0 */
                    if(contains_sqrt(v) == SQRT)
                       { o[i] = sflag ? mulineqsqrt3 : mulineqsqrt3g; ++i;
                         /* 0 <= u/sqrt v => 0 <= uv */
                       }
                  }
               if(h == '*')
                  { if(sflag)
                       { if(!normalizelinear2(t,zero,&w,buffer))
                            { o[i] = normalizelinear2; ++i;
                            }
                       }
                    else
                       { if(!normalizelinear2g(t,zero,&w,buffer))
                            { o[i] = normalizelinear2g; ++i;
                            }
                       }
                    o[i] = sflag ? intervalspos2 : intervalspos2g; ++i;
                    /* 0�(x-a)(x-b)=>x�a or b�x (if a<b) */
                  }
               if(h == ABS)
                  { o[i] = sflag ? absineqtrue : absineqtrueg; ++i;  /* |u| � 0 is true */
                  }
             }
          if(ZERO(v))
             { if(!is_linear_in(u,x))
                  { o[i] = droppositive2;  ++i;
                  }
               if(g == '/')
                  { o[i] = sflag ? mulineqbysquare4 : mulineqbysquare4g; ++i;
                    /*  u/v <= 0 => uv < 0 or u = 0 */
                    if(contains_sqrt(u) == SQRT)
                       { o[i] = sflag ? mulineqsqrt4 : mulineqsqrt4g; ++i;
                       /* u/sqrt v <= 0 => uv <= 0  */
                       }
                  }
               if(g == '+' && count && is_linear_in(u,x))
                  { o[i] = sflag ? normalizelinear2 : normalizelinear2g; ++i;
                    /* ax � b � 0 iff a(x�b/a) � 0 */
                  }
               if(g == '*')
                  { if(sflag)
                       { if(!normalizelinear2(t,zero,&w,buffer))
                            { o[i] = normalizelinear2; ++i;
                            }
                       }
                    else
                       { if(!normalizelinear2g(t,zero,&w,buffer))
                            { o[i] = normalizelinear2g; ++i;
                            }
                       }
                    o[i] = sflag ? intervalsneg2 : intervalsneg2g; ++i;
                    /* (x-a)(x-b)�0 => a�x�b (if a<b) */
                  }
               if(g == ABS && sflag == 0)
                  { o[i] = absineqfalseg; ++i;  /* 0 > abs(u) is false */
                  }
             }
          switch(g)
             { case ABS:
                  o[i] = f == LE ? absle: absge; ++i;  /* |u| � v iff -v � u � v */
                  if(FUNCTOR(ARG(0,u)) == SIN)
                     { o[i] = abssinineq; ++i;    /* |sin u| � 1 */
                     }
                  if(FUNCTOR(ARG(0,u)) == COS)
                     { o[i] = abscosineq; ++i;    /* |cos u| � 1 */
                     }
                  if(FUNCTOR(ARG(0,u)) == ATAN)
                     { o[i] = absarctanineq; ++i;  /* |arctan u| � �/2  */
                     }
                  if(!infer(lessthan(v,zero)))
                     { o[i] = f == LE ? absleneg : absgeneg; ++i;
                       /* abs(u) <= -c is false (c > 0) */
                       /* -c >= abs(u) is false (c > 0  */
                     }
                  if(!infer(le(v,zero)) && infer(lessthan(v,zero)))
                     /* v is nonpositive but not provably negative */
                     /* example:  abs(x^3-x) <= -x^2  */
                     { o[i] = f == LE ? absleneg2 : absgeneg2; ++i;
                     }
                  break;
               case SIN:
                  o[i] = sinineq; ++i;    /* sin u � u  if u�0 */
                  break;
               case ATAN:
                  o[i] = arctanineq; ++i; /* arctan u � u if u�0 */
                  break;
               case SQRT:
                  o[i] = powerineq21; ++i;   /* �u � v => u � v^2     */
                  break;
               case ROOT:
                  if(isodd(ARG(0,u)))
                     { o[i] = sflag ? powerineq24odd : powerineq24oddg; ++i;
                       /* ��u � v => u � v      */
                     }
                  else
                     { o[i] = sflag ? powerineq24even : powerineq24eveng; ++i;
                     }
                  break;
               case '^':
                  if(isinteger(ARG(1,u)) && iseven(ARG(1,u)))
                     { o[i] = sflag ? sqrtineq21 : sqrtineq21g; ++i;
                       /* u^2 � v => |u| � �v */
                       o[i] = sflag ? sqrtineq24 : sqrtineq24g; ++i;
                       /* u^2 � a => -a � u � a */
                     }
                  if(INTEGERP(ARG(1,u)) && iseven(ARG(1,u)))
                     { if(NEGATIVE(v) && OBJECT(ARG(0,v)))
                          { if(isinteger(ARG(1,u)) && iseven(ARG(1,u)))
                               { o[i] = sflag ? squarefalse2 : squarefalse2g; ++i;
                               }
                            else
                               { o[i] = sflag ? evenpowerineq4 : evenpowerineq4g; ++i;
                               }
                          }
                     }
                  else if(!(INTEGERP(ARG(1,u)) && ISODD(ARG(1,u))))
                     { o[i] = sflag ? rootineq21 : rootineq21g; ++i;
                        /* u^2� � v => |u| � ^2��v */
                       o[i] = sflag ? rootineq23 : rootineq23g; ++i;
                       /* u^2� � a iff -^2��a � u � ^2��a      */
                     }
                  break;
               case '/':
                  count = contains_sqrt(u);
                  if(count == ROOT)
                     { o[i] = sflag ? powerineq23 : powerineq23g; ++i;
                       /* 0 � a(��u) � v => a�u � v� */
                     }
                  /* Now for the reciprocal inequaltiies */
                  if(econstant(v) &&
                     econstant(ARG(0,u)) &&
                     obviously_positive(ARG(0,u))
                    )
                     { if(obviously_positive(v))
                          { o[i] = sflag ? recipineq12 : recipineq12g; ++i;
                            /* 1/x <= a iff x < 0 or 1/a <= x provided a > 0 */
                          }
                       else if(obviously_positive(strongnegate(v)))
                          { o[i] = sflag ? recipineq32 : recipineq32g; ++i;
                            /* 1/x <= -a iff -1/a <= x < 0 provided a > 0 */
                          }
                     }
                  break;
               case '-': /* fall through */
               case '*':
                  count = contains_sqrt(u);
                  if(count == ROOT)
                     { o[i] = sflag ? powerineq23 : powerineq23g; ++i;
                       /* 0 � a(��u) � v => a�u � v� */
                     }
                  break;
             }
          if( (g == '^' && !(INTEGERP(ARG(1,u)) && ISEVEN(ARG(1,u))))  || (h == '^' && !(INTEGERP(ARG(1,v)) && ISEVEN(ARG(1,v)))))
             { o[i] = sflag ? oddrootineq2 : oddrootineq2g; ++i;
             }
          o[i] = addeqn2; ++i;
          o[i] = subeqn1; ++i;
          o[i] = changesigns2; ++i;    /*  -u � -v iff  v � u    */
          o[i] = sflag ? changesignsandsense2 : changesignsandsense4; ++i;
               /* change -u � -v to u � v  */
          o[i] = mulineq; ++i;         /* multiply both sides by ? */
          o[i] = divineq; ++i;         /* divide both sides by ? */
          o[i] = sflag ? sqrtineq23 : sqrtineq23g; ++i;
           /* 0 � u � v => �u � �v */
          o[i] = sflag ? powerineq26 : powerineq26g; ++i;
          /* u � v => u� � v� (n odd, n>0) */
          o[i] = sflag ? powerineq27 : powerineq27g; ++i;
          /* 0 � u � v => u� � v� (n > 0)  */
          o[i] = alltoleft; ++i;
          switch(h)
             { case '^':
                  if(isinteger(ARG(1,v)) && iseven(ARG(1,v)))
                     { o[i] = sflag ? sqrtineq22 : sqrtineq22g; ++i;
                       /* 0 � u � v^2 => �u � |v| */
                       o[i] = sflag ? sqrtineq25 : sqrtineq25g; ++i;
                       /* a � u^2 => u � -�a or �a � u */
                     }
                  if(INTEGERP(ARG(1,v)) && iseven(ARG(1,v)))
                     { if(ZERO(u) ||
                          (NEGATIVE(u) && OBJECT(ARG(0,u)))
                         )
                          { if(isinteger(ARG(1,v)) && iseven(ARG(1,v)))
                               { o[i] = sflag ? squaretrue2: squaretrue2g; ++i;
                               }
                            else
                               { o[i] = sflag ? evenpowerineq2 : evenpowerineq2g; ++i;
                               }
                          }
                     }

                  if( !(INTEGERP(ARG(1,v)) && ISODD(ARG(1,v))))
                     { o[i] = sflag ? rootineq22 : rootineq22g; ++i;
                       /* 0 � u � v^2� => ^2��u � |v|  */
                       o[i] = sflag ? rootineq25 : rootineq25g; ++i;
                       /* a � u^2� iff u � -^2��a  or ^2��a � u  */
                     }
                  break;
               case '/':
                  /* Now for the reciprocal inequaltiies */
                  if(econstant(u) &&
                     econstant(ARG(0,v)) &&
                     obviously_positive(ARG(0,v))
                    )
                     { if(obviously_positive(u))
                          { o[i] = sflag ? recipineq22 : recipineq22g; ++i;
                            /* a <= 1/x iff 0 < x <= 1/a provided a > 0 */
                          }
                       else if(obviously_positive(strongnegate(u)))
                          { o[i] = sflag ? recipineq42 : recipineq42g; ++i;
                            /* -a <= 1/x iff x <= -1/a or 0 < x provided a > 0 */
                          }
                     }
               case SQRT:
                  o[i] = sflag ? powerineq22 : powerineq22g; ++i;
                  /* 0 � u � �v => u^2 � v       */
                  break;
               case ROOT:
                  o[i] = sflag ? powerineq25 : powerineq25g; ++i;
                  /* 0 � u � ��v => u� � |v|    */
                  break;
               case TAN:
                  o[i] = tanineq; ++i;         /* tan u � u if u�0           */
                  break;
               case COS:
                  o[i] = coslowerbound; ++i;   /* 1 - u^2/2 � cos u           */
                  break;
               case ABS:
                  o[i] = f == LE ? leabs : geabs; ++i;     /* u <= abs(v) if v <= -u or u <= v */
                  if(!infer(le(zero,u)))
                     { o[i] = f == LE ? absineqtrue2 : absineqtrue2g; ++i;
                       /* -c <= abs(u) is true if c >= 0 */
                       /* abs(u) >= -c is true if c >= 0 */
                     }
                  break;
             }
          if(get_nextdefn() > 0)
             { o[i] = unwinddefinition; ++i;
             }

          if(nonconstant_powers(t))
             { o[i] = lnineq2; ++i;
               if(g == '^' && h == '^' && equals(ARG(0,u),ARG(0,v)) && !equals(ARG(0,u),eulere) && !equals(ARG(0,u),ten))
                  { o[i] = expineq2; ++i;
                  }
               if(powersof10(t))
                  { o[i] = logineq2; ++i;
                  }
             }
          if(show_explicitdomain(t))
             { o[i] = explicitdomain; ++i;
             }
          break;
       }
  if(status(polyvalop) > LEARNING && !polyval(t,&w))
     { o[i] = polyvalop; ++i;
     }
  *nops = i;
}

/*__________________________________________________________________*/
void select_equation_ops(term t, actualop *o, int *nops)
/* Fill pre-allocated array o with the operators that
could be applied to t.  Return the dimension of the
array in *nops.  t is presumed to be an equation.
*/

{ term u,v,w,c,x,xx,yy,a,b,cc,context,temp,dummy;
  char buffer[DIMREASONBUFFER];
  unsigned short g,h;
  int i=0;
  int err;
  int problemtype = get_problemtype();
  int currenttopic = get_currenttopic();
  if(FUNCTOR(t) != '=')
     assert(0);
  u = ARG(0,t);
  v = ARG(1,t);
  x = get_eigenvariable();
  if(
     (numerical(u) || select_arith_aux(u)) &&
     (numerical(v) ||  select_arith_aux(v))
    )
     { o[i] = arithmetic; ++i;
       if(!rejecteqn(t,zero,&w,buffer))
          { o[i] = rejecteqn; ++i;
            *nops = i;
            return;
          }
     }
  g = FUNCTOR(u);
  h = FUNCTOR(v);
  if(showsub(t))
     { o[i] = makesubstitution; ++i;
     }
  if(problemtype == MINMAX && get_nvariables() > 1 &&
     contains_existentials(t)
    )
     { o[i] = eliminateparameter; ++i;
     }
  if(FUNCTOR(ARG(0,t)) == VECTOR && FUNCTOR(ARG(1,t)) == VECTOR)
     { if(!impossibleeqns(t,zero,&w,buffer))
          { o[i] = impossibleeqns; ++i;
          }
       o[i] = dropzerorow; ++i;
       o[i] = convertmatrixeqn; ++i;
     }
  if(currenttopic == _cramers_rule)
     { o[i] = cramersrule; ++i;
     }
  if(contains(t,MATRIX) &&
      ( currenttopic == _eqns_in_matrix_form  ||
        currenttopic == _gauss_jordan
      )
    )
     { o[i] = addrows; ++i;
       o[i] = subrows; ++i;
       o[i] = addmulrows; ++i;
       o[i] = submulrows; ++i;
       o[i] = swaprows; ++i;
       SETFUNCTOR(dummy,ILLEGAL,0);
       if(!dropduplicaterow(t,dummy,&w,buffer))
          { o[i] = dropduplicaterow; ++i;
          }
       if(!impossibleeqns(t,dummy,&w,buffer))
          { o[i] = impossibleeqns; ++i;
          }
       *nops = i;  /* don't show dividebymatrix on _gauss_jordan */
       return;
     }
  if(contains(t,MATRIX))
     { if(FUNCTOR(ARG(0,t)) == '*' &&
          FUNCTOR(ARG(0,ARG(0,t))) == MATRIX
         )
          { o[i] = dividebymatrix; ++i;
          }
       *nops = i;  /* None of the following operators are
                      for matrix equations */
       return;
     }
  if(FUNCTOR(ARG(0,t)) == VECTOR && FUNCTOR(ARG(1,t)) == VECTOR)
     { *nops = i;
       return;
     }
  if(g == h && SOLVETYPE(problemtype) && equals(u,v))
     { o[i] = trueeqn; ++i;
     }
  if(obviously_nonnegative(u) &&
     obviously_nonnegative(strongnegate(v))
     && !ZERO(u) && !ZERO(v)
    )
     { o[i] = pseudosquare; ++i;
     }
  if(obviously_nonnegative(v) && obviously_nonnegative(strongnegate(u)))
     { o[i] = pseudosquare; ++i;
     }
  if(ZERO(u))
     { u = v;
       v = zero;
       g = FUNCTOR(u);
       h = FUNCTOR(v);
     }
  if(problemtype == SOLVE_EQUATION &&
     ISATOM(ARG(0,t)) &&
     readpending(&temp) == 0
    )
     { o[i] = showcallingcubic; ++i;
     }
  if(status(intsub) == LEARNING)
     { if(ISATOM(ARG(0,t)) && !contains(t,DIFF) &&
          !contains(ARG(1,t),FUNCTOR(ARG(0,t))) &&
          problemtype == INTEGRATION &&
          readpending(&temp) == 0
         )
          /* Integrating by substitution the LEARNING way */
          { o[i] = difsubstitution; ++i;
            *nops = i;
            return;
          }
       if(contains(ARG(0,t),DIFF) && !contains(ARG(1,t),DIFF) &&
          problemtype == INTEGRATION &&
          readpending(&temp) == 0
         )
          { o[i] = showcallingproblem; ++i;
          }
       *nops = i;
       return;   /* you have to compute du/dx first */
     }
  if((contains(t,DIFF) || contains(t,PR)) &&
     currenttopic != _logarithmic_differentiation
    )
     { if(!SOLVETYPE(problemtype))
          { o[i] = difeqn; ++i;
            *nops = i;
            return;   /* don't show equation-solving operations  */
          }
     }
  if(problemtype != LINEAR_EQUATION && problemtype != LINEAR_EQUATIONS)
     { err = cancel(v,u,&c,&w);    /* only show spliteqn2 if it works */
       if(!err)
          { o[i] = cancelfactor; ++i;
            if(!seminumerical(c))
               { o[i] = spliteqn2; ++i;  /* if ab = ac then a=0 or b=c */
               }
          }
       if(problemtype != IMPLICIT_DIFF &&
          problemtype != RELATED_RATES &&
          problemtype != MINMAX
         )
          { o[i] = evalatpoint; ++i;
            if(!contains_calc(t) && !solved(t,get_eigenvariable()))
               { o[i] = solvenumerically; ++i;
               }
          }
     }
  context = history(get_activeline());
  if(FUNCTOR(context) == AND)
     { if(get_selected_equation())
          { o[i] = showalleqns; ++i;
          }
     }
  switch(g)
     { case ABS:
          o[i] = abseqn; ++i;  /* |u|=c iff u=c or u = -c    */
          if(equals(ARG(0,u),v))
             { o[i] = abseqntoineq1; ++i;
             }
          /* the next rule is for abs(p) = -p; it will
             work when v+ARG(0,u) simplifies to zero,
             and there are lots of ways that can happen,
             so let's just run the operation. */

          err = abseqntoineq2(t,zero,&w,buffer);
          if(!err)
             { o[i] = abseqntoineq2; ++i;
             }
          if(!infer(le(v,zero)))
             { o[i] = abseqnneg; ++i;
             }
          break;

       case '*':
          if(h == '*' && status(cancelfactor) >= LEARNING)
             /* cancel common factor on both sides; don't
                show it unless it works */
             { err = cancelfactor(t,zero,&w,buffer);
               if(!err)
                  { o[i] = cancelfactor; ++i;
                  }
             }
          break;
       case '/':
          if(FUNCTOR(ARG(0,u)) == ABS && equals(ARG(1,u),ARG(0,ARG(0,u))))
             { o[i] = abseqn2; ++i;   /* |u|/u=c iff c=�1 */
             }
          break;
       case SIN:
          o[i] = solvesin; ++i;    /* sin u=c iff u= (-1)�arcsin c+n�   */
          o[i] = solvesin2; ++i;   /* sin u=c iff u = arcsin c + 2n� or u = -arcsin c + (2n+1)� */
          o[i] = rejectimpossiblesin; ++i;  /* reject sin u = c if |c|>1 */
          if(ZERO(v))
             { o[i] = solvesin0; ++i;   /* sin u = 0 iff u = n�        */
             }
          if(ONE(v))
             { o[i] = solvesin90; ++i;    /* sin u = 1 iff u = �/2+2n�   */
             }
          if(equals(v,minusone))
             { o[i] = solvesin270; ++i;   /* sin u = -1 iff u = 3�/2+2n� */
             }
          if(FRACTION(v) && equals(ARG(1,v),two))
             { if(ONE(ARG(0,v)))
                  { o[i] = solvesin30; ++i;  /* sin(u)=1/2 iff u=�/6 or 5�/6+2n�     */
                  }
               if(FUNCTOR(ARG(0,v)) == SQRT && equals(ARG(0,ARG(0,v)),three))
                  { o[i] = solvesin60; ++i;   /* sin(u)=�3/2 iff u=�/3 or 2�/3+2n�    */
                  }
             }
          if(NEGATIVE(v) && FRACTION(ARG(0,v)) && equals(ARG(1,ARG(0,v)),two))
             { if(ONE(ARG(0,ARG(0,v))))
                  { o[i] = solvesin330; ++i;  /* sin(u)=-1/2 iff u=-�/6 or -5�/6+2n�     */
                  }
               if(FUNCTOR(ARG(0,ARG(0,v))) == SQRT && equals(ARG(0,ARG(0,ARG(0,v))),three))
                  { o[i] = solvesin300; ++i;   /* sin(u)=-�3/2 iff u=-�/3 or -2�/3+2n�    */
                  }
             }
          if(FRACTION(v) && ONE(ARG(0,v)) &&
             FUNCTOR(ARG(1,v)) == SQRT &&
             equals(ARG(0,ARG(1,v)),two)
            )
             { o[i] = solvesin45; ++i;   /* sin u = 1/�2 if u=�/4 or 3�/4 + 2n� */
             }
          if(NEGATIVE(v) && FRACTION(ARG(0,v)) &&
             ONE(ARG(0,ARG(0,v))) &&
             FUNCTOR(ARG(1,ARG(0,v))) == SQRT &&
             equals(ARG(0,ARG(1,ARG(0,v))),two)
            )
             { o[i] = solvesin315; ++i;  /* sin u=-1/�2 if u=5�/4 or 7�/4 + 2n� */
             }
          break;
       case COS:
          o[i] = solvecos; ++i;   /* cos u=c iff u=�arccos c+2n�       */
          o[i] = rejectimpossiblecos; ++i; /* reject cos u = c if |c|>1 */
          if(ZERO(v))
             { o[i] = solvecos90; ++i; /* sin u = 1 iff u = �/2+2n�   */
             }
          if(ONE(v))
             { o[i] = solvecos0; ++i;   /* cos u = 1 iff u = 2n�       */
             }
          if(equals(v,minusone))
             { o[i] = solvecos180; ++i;   /* cos u = -1 iff u = (2n+1)�  */
             }
          if(FRACTION(v) && equals(ARG(1,v),two))
             { if(ONE(ARG(0,v)))
                  { o[i] = solvecos60; ++i;  /* cos(u)=1/2 iff u=��/3+2n�            */
                  }
               if(FUNCTOR(ARG(0,v)) == SQRT && equals(ARG(0,ARG(0,v)),three))
                  { o[i] = solvecos30; ++i;  /* cos(u)=�3/2 iff u=��/6 + 2n�         */
                  }
             }
          if(NEGATIVE(v) && FRACTION(ARG(0,v)) && equals(ARG(1,ARG(0,v)),two))
             { if(ONE(ARG(0,ARG(0,v))))
                  { o[i] = solvecos120; ++i; /* cos(u)=-1/2 iff u=� 2�/3+2n�         */
                  }
               if(FUNCTOR(ARG(0,ARG(0,v))) == SQRT && equals(ARG(0,ARG(0,ARG(0,v))),three))
                  { o[i] = solvecos150; ++i; /* cos(u)=-�3/2 iff u=�5�/6 + 2n�       */
                  }
             }
          if(FRACTION(v) && ONE(ARG(0,v)) &&
             FUNCTOR(ARG(1,v)) == SQRT &&
             equals(ARG(0,ARG(1,v)),two)
            )
             { o[i] = solvecos45; ++i;    /* cos u = 1/�2 if u=�/4 or 7�/4 + 2n� */
             }
          if(NEGATIVE(v) && FRACTION(ARG(0,v)) &&
             ONE(ARG(0,ARG(0,v))) &&
             FUNCTOR(ARG(1,ARG(0,v))) == SQRT &&
             equals(ARG(0,ARG(1,ARG(0,v))),two)
            )
             { o[i] = solvecos135; ++i;   /* cos u=-1/�2 if u=3�/4 or 5�/4 + 2n� */
             }
          break;
       case COT:
          if(ZERO(v))
             { o[i] = solvecot90; ++i;    /* cot u = 0 iff cos u = 0     */
               /* Then cot can't be converted to 1/tan  */
             }
          break;
       case TAN:
          o[i] = solvetan; ++i;  /* tan u=c iff u=arctan c+n� (c not � i) */
          if(ZERO(v))
             { o[i] = solvetan0; ++i;   /* tan u = 0 iff sin u = 0     */
             }
          if(FRACTION(v) && ONE(ARG(0,v)) &&
             FUNCTOR(ARG(1,v)) == SQRT &&
             equals(ARG(0,ARG(1,v)),three)
            )
             { o[i] = solvetan30; ++i;   /* tan(u)=1/�3 iff u = �/6 + n�         */
             }
          if(h == SQRT && equals(ARG(0,v),three))
             { o[i] = solvetan60; ++i; /* tan(u)=�3 iff u = �/3 + n�           */
             }
          if(NEGATIVE(v) && FUNCTOR(ARG(0,v)) == SQRT && equals(ARG(0,ARG(0,v)),three))
             { o[i] = solvetan120; ++i; /* tan(u)=-�3 iff u = 2�/3 + n�         */
             }
          if(NEGATIVE(v) && FRACTION(ARG(0,v)) &&
             ONE(ARG(0,ARG(0,v))) &&
             equals(ARG(0,ARG(1,ARG(0,v))),three)
            )
             { o[i] = solvetan330; ++i;   /* tan(u)=-1/�3 iff u = -�/6 + n�       */
             }
          if(ONE(v))
             { o[i] = solvetan45; ++i;   /* tan u = 1   if u= �/4 or 5�/4 + 2n� */
             }
          if(equals(v,minusone))
             { o[i] = solvetan135; ++i;   /* tan u = -1  if u=3�/4 or 7�/4 + 2n� */
             }
          break;
     }
  o[i] = switchsides; ++i;
  o[i] = changesigns; ++i;
  o[i] = addeqn; ++i;
  o[i] = subeqn; ++i;
  o[i] = muleqn; ++i;
  o[i] = diveqn; ++i;
  if(problemtype != LINEAR_EQUATIONS && problemtype != LINEAR_EQUATION)
     { o[i] = squareeqn; ++i;
     }
  if(!get_complex() && ZERO(v) && g == '+' && ARITY(u) == 3)
     { o[i] = negativediscriminant; ++i;
     }
  if(contains(t,ROOT) ||
     contains_fractional_exponents(t) ||
     (FUNCTOR(u) == '^' && !INTEGERP(ARG(1,u))) ||
     (FUNCTOR(v) == '^' && !INTEGERP(ARG(1,v)))
    )
    /* otherwise why clutter up the menu with an irrelevant operation?
       especially for the beginning algebra student */
     { o[i] = powereqn; ++i;
     }
  o[i] = alltoleft; ++i;
  if(problemtype != LINEAR_EQUATION && ZERO(v) && FUNCTOR(u) == '*')
     { o[i] = spliteqn; ++i;
     }
  if(FRACTION(u) || FRACTION(v))
     { o[i] = crossmultiply; ++i;
     }
  if(ZERO(v) && FUNCTOR(u) == '+' && ARITY(u) > 3 && !long_quadratic(u,x,&a,&b,&c))
     /* example:  x^2 -2x + 4 + e^2 = 0; these arise from log equations. */
     { o[i] = quadraticformula; ++i;
     }
  if(ZERO(v) && FUNCTOR(u) == '+' && ARITY(u) == 3 &&
     isquadratic(u,&xx,&yy,&a,&b,&cc)
    )
     { o[i] = quadraticformula; ++i;
       o[i] = completethesquare; ++i;
     }
  else if(currenttopic == _complete_the_square)
     { o[i] = completethesquare; ++i;
     }
  else if(FUNCTOR(u) == '+' && ARITY(u) == 2  && numerical(v))
     { term w = make_term('+',3);
       ARGREP(w,0,ARG(0,u));
       ARGREP(w,1,ARG(1,u));
       ARGREP(w,2,tnegate(v));
       if(isquadratic(w,&xx,&yy,&a,&b,&cc))
          { o[i] = completethesquare; ++i;
          }
       RELEASE(w);
     }

  /* What are the conditions for sqrteqn?  Theoretically you
     can apply it to ANY equation, but it will just clutter up
     the screen in many cases where it couldn't possibly be relevant.
     But, in principle it should be shown where legally applicable.
     However, if either side is a nonconstant sum, it's not going to
     help much!  Of course, the sum might factor to a square...*/
  if(!(g == '+' && !econstant(u)) && !(h == '+' && !econstant(v)) &&
     problemtype != LINEAR_EQUATIONS && problemtype != LINEAR_EQUATION
    )
     { o[i] = sqrteqn; ++i;
       if(higher_powers(t))  /* powers other than 2 */
          { o[i]= rooteqn; ++i;
            if(get_complex())
               { o[i] = demoivre; ++i;
               }
          }
     }
  if(!ALGEBRA_TOPIC(currenttopic) &&
      (!ispolyin(u,x) || !ispolyin(v,x))
    )
     { o[i] = functioneqn; ++i;
     }
  if(get_nextdefn() > 0)
     { o[i] = unwinddefinition; ++i;
     }
  if(solved(t,x) &&
     problemtype != LINEAR_EQUATIONS &&
     problemtype != LINEAR_EQUATION &&
     problemtype != MINMAX
    )
     { o[i] = checkroot; ++i;
       if(contains(t,PI_ATOM))
          { term *atomlist;
            int nvars = integer_parameters(t,&atomlist);
            free2(atomlist);
            if(nvars)
               { o[i] = periodicform; ++i;
               }
          }
     }
  if( problemtype != LINEAR_EQUATIONS && problemtype != LINEAR_EQUATION &&
     rejecteqn(t,zero,&w,buffer)==0
    )
     { o[i] = rejecteqn; ++i;
     }
  if(ZERO(v) && !makepoly(u,x,&w) && DEGREE(w) == 3)
     { /* a cubic */
       if(!ZERO(ARG(2,w)))
          { o[i] = eliminatequadraticterm; ++i;
          }
       else if(!ZERO(ARG(1,w)))  /* don't show these on x^3 - 8 = 0 */
          { o[i] = computediscriminant; ++i;
            o[i] = viete; ++i;
            o[i] = get_complex ? cardan : realcardan ; ++i;
            o[i] = cardan2; ++i;
          }
     }

          /* Again, in theory you could always raise any equation to
             an arbitrary power, but you don't want to do it unless
             one side is a logarithm. */
  if(g == LN || h == LN)
     { o[i] = powereqn3; ++i;
       o[i] = powereqn2; ++i;
     }
  if(g == LOG || h == LOG)
     { o[i] = powereqn4; ++i;
       o[i] = powereqn2; ++i;
     }
  if(g == LOGB || h == LOGB)
     { o[i] = powereqn5; ++i;
       o[i] = powereqn2; ++i;
     }
  if(nonconstant_powers(t))
     { o[i] = lneqn; ++i;
       if(g == '^' && h == '^' && equals(ARG(0,u),ARG(0,v)))
          { o[i] = logbeqn; ++i;
          }
       else if (g == '^' && INTEGERP(v) && !logbeqn(t,zero,&w,buffer))
          { o[i] = logbeqn; ++i;
          }
       else if (h == '^' && INTEGERP(u) && !logbeqn(t,zero,&w,buffer))
          { o[i] = logbeqn; ++i;
          }
       if(powersof10(t))
          { o[i] = logeqn; ++i;
          }
     }
  if(status(solvelinear) > LEARNING &&
      !contains_powerof(t,x) &&
      !solvelinear(t,zero,&w,buffer)  /* only show it if it will work */
    )
     { o[i] = solvelinear; ++i;
     }
  if(status(ssolveop) > LEARNING &&
     (!contains_calc(t) || problemtype == RELATED_RATES)
    )
     { o[i] = ssolveop; ++i;
     }
  if(status(polyvalop) > LEARNING && !polyval(t,&w))
     { o[i] = polyvalop; ++i;
     }
  if(get_complex() && !explicitparams(t,zero,&w,buffer))
     { o[i] = explicitparams; ++i;
     }
  *nops = i;
  return;
}
/*___________________________________________________________________*/
static int showsub(term t)
/*  t is an equation or inequality.  Return 1 if the Term Selection
Menu should show "make a substitution (u = ? )" so they can type in a
substitution.  Return 0 if not. */

{ short savenextassumption = get_nextassumption();
  char buffer[DIMREASONBUFFER];
  int saveit = get_nvariables();
  int savenextdefn = get_nextdefn();
  int saveeigen = get_eigenindex();
  term sub,ans;
  int err = autosub(t,&sub,&ans);
    /* this tries gcdsubstitution, but not fractionalsubstitution */
  if(err)
      err = fractionalsubstitution(t,zero,&ans,buffer);
  set_eigenvariable(saveeigen);
  set_nvariables(saveit);
  set_nextdefn(savenextdefn);
  set_nextassumption(savenextassumption);
  return !err;
}

/*__________________________________________________________________*/
static int nonconstant_powers(term t)
/* Return 1 if t contains a power in which the exponent is not
numerical */
{ unsigned short n;
  int k;
  if(ATOMIC(t))
     return 0;
  if(FUNCTOR(t) == '^')
     { if(!numerical(ARG(1,t)))
          return 1;
       return nonconstant_powers(ARG(0,t));
     }
  n = ARITY(t);
  for(k=0;k<n;k++)
     { if(nonconstant_powers(ARG(k,t)))
          return 1;
     }
  return 0;
}
/*_____________________________________________________________________*/
static int show_explicitdomain(term t)
/* return 1 if the term selection menu should show explicit domain
when inequality t (or interval_as_and t) is selected.  Specifically,
return 1 if there were any assumptions at line 0, and if t
is a solved inequality or OR of solved inequalities.
*/

{ unsigned short f = FUNCTOR(t);
  term x;
  int nextassumption;
  int i;
  assumption **assumptions;
  if(f != '<' && f != LE && f != '>' && f != GE)
     return 1;
  nextassumption = get_nextassumption();
  if(nextassumption == 0)
     return 0;
  assumptions = get_assumptions();
  for(i=0;i<nextassumption;i++)
     { if(assumptions[i]->line > 0)
          break;
     }
  if(i==0)
     return 0;
  x = get_eigenvariable();
  return solved(t,x) ? 1 : 0;
}
/*__________________________________________________________________*/
static int powersof10(term t)
/* return 1 if t contains a power with base 10 */
{ unsigned short n;
  int i;
  if(ATOMIC(t))
     return 0;
  if(FUNCTOR(t) == '^' && equals(ARG(0,t),ten))
     return 1;
  n = ARITY(t);
  for(i=0;i<n;i++)
     { if(powersof10(ARG(i,t)))
          return 1;
     }
  return 0;
}
/*__________________________________________________________________*/
static int higher_powers(term t)
/* return 1 if t contains a power with exponent other than 2 */
{ unsigned short n;
  int i;
  if(ATOMIC(t))
     return 0;
  if(FUNCTOR(t) == '^' && !equals(ARG(1,t),two))
     return 1;
  n = ARITY(t);
  for(i=0;i<n;i++)
     { if(higher_powers(ARG(i,t)))
          return 1;
     }
  return 0;
}
/*___________________________________________________________________*/
static int two_terms(POLYnomial p)
/* return 1 if p has exactly two nonzero terms x^n and x^2n */
{ int i, founda=0,foundb=0;
  unsigned short n = ARITY(p);
  for(i=0;i<n;i++)
     { if(!ZERO(ARG(i,p)))
          { if(!founda)
               founda = i+1;
            else if(foundb)
               return 0;
            else if(i != 2 * (founda-1))
               return 0;
            else
               foundb = i+1;
          }
     }
  return 1;
}

/*________________________________________________________________________*/
static int contains_powerof(term t, term x)
/* x is a variable.  Return 1 if t contains a power
which contains x, either in the base or the exponent */
{ int i;
  unsigned short n;
  if(ATOMIC(t))
     return 0;
  if(FUNCTOR(t) == '^')
     return contains(t,FUNCTOR(x));
  n = ARITY(t);
  for(i=0;i<n;i++)
     { if(contains_powerof(ARG(i,t),x))
          return 1;
     }
  return 0;
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists