Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/prover/
Upload File :
Current File : /usr/home/beeson/MathXpert/prover/trigpoly.c

/* trigrational, recognizes rational functions of trig functions of a variable */
/* M. Beeson, for Mathpert */
/* See trigpoly.h for brief descriptions of the public functions here. */
/*
9.28.93 original date
8.6.98 last modified
*/

#include "globals.h"
#include "prover.h"
#include "algaux.h"
#include "trigpoly.h"
#include "cancel.h"
#include "trig.h"
#include "polynoms.h"   /* ispolyin  */
#include "pvalaux.h"    /* isinteger */
#include "order.h"      /* monomial  */
#include "deval.h"      /* seminumerical */

static int trigrational_aux(term);
/*__________________________________________________________________*/
int trigrational(term t)
/* Return 1 if t is a rational function of trigonometric functions
of one variable such as sin x, cos x.  The arguments of the trig
functions must all be the same atom x, or else x + pi or x+n pi)
Return 0 otherwise.   Equations of rational functions of trig arguments
are also acceptable.  Some trig function must actually occur; constants
are not acceptable.
Input checking will not allow nested = so we can allow it here.  */

{ term *atomlist;
  int natoms = atomsin(t,&atomlist);
  if(natoms > 2 || natoms == 0)
     { free2(atomlist);
       return 0;
     }
  if(natoms == 1 && ( equals(atomlist[0],pi_term) || TYPE(atomlist[0]) == INTEGER))
     { free2(atomlist);
       return 0;
     }
  if(natoms == 2)
     { if(
          (!equals(atomlist[0],pi_term) && !equals(atomlist[1],pi_term)) ||
          (equals(atomlist[0],pi_term) && TYPE(atomlist[1]) == INTEGER) ||
          (equals(atomlist[1],pi_term) && TYPE(atomlist[0]) == INTEGER)
         )
         { free2(atomlist);
           return 0;
         }
     }
  free2(atomlist);
  if(natoms == 0)
     return 0;
  return trigrational_aux(t);
}
/*____________________________________________________________________*/
static int trigrational_aux(term t)
/* do as trigrational, but ASSUME that there is at most one atom in t
   (other than possibly pi_term)  */
{ unsigned short f;
  unsigned short n;
  int i,err;
  term u,p,cancelled;
  if(OBJECT(t))
     return 1;
     /* constants are allowed, but e and pi aren't allowed. */
  if(ISATOM(t))
     return 0;
  f = FUNCTOR(t);
  if(f==SIN || f==COS || f==SEC || f==TAN || f==COT || f==CSC)
     { u = ARG(0,t);
       if(equals(u,pi_term))
          return 0;   /* we don't count sin pi etc. because e.g. cot pi
                         is undefined */
       if(ISATOM(u))
          return 1;
       /* but we also accept sin(x+pi) etc., via the following code */
       if(FUNCTOR(u) != '+' || ARITY(u) != 2 || !ISATOM(ARG(0,u)))
          return 0;
       u = ARG(1,u);
       if(!contains(u,FUNCTOR(pi_term)))
          return 0;  /* without wasting time trying to cancel it */
       err = cancel(u,pi_term,&cancelled,&p);
       if(err)
          return 0;
       if(INTEGERP(p) || isinteger(p))
          return 1;
       return 0;
     }
  switch(f)
     { case '-' : return trigrational_aux(ARG(0,t));
       case '^' : return INTEGERP(ARG(1,t)) && trigrational_aux(ARG(0,t));
       case '=' : /* fall-through */
       case '+' : /* fall-through */
       case '/' : /* fall-through */
       case '*' : n = ARITY(t);
                  for(i=0;i<n;i++)
                     { if(!trigrational_aux(ARG(i,t)))
                          return 0;
                     }
                  return 1;
     }
  return seminumerical(t);  /* sqrt 3 for example is acceptable,
                          hence sqrt(3) tan x is acceptable. */
}
/*______________________________________________________*/
int trigrat(term t, term x)
/* return 1 if t is a quotient of polynomials in positive (possibly fractional)
powers of x and trig functions of x.
Specifically:
    trigrat ::=  s/s | - s/s
    s ::= -s | s * s | s^n  where n > 0, s+s| seminumerical | x | trig(x)
Thus it rejects expressions like ln u involving variables other than x.
*/
{ if(NEGATIVE(t))
     return trigrat(ARG(0,t),x);
  if(FRACTION(t))
     return trigpoly(ARG(0,t),x) && trigpoly(ARG(1,t),x);
  return trigpoly(t,x);
}
/*______________________________________________________*/
int trigrat2(term t, term x)
/* return 1 if t is a quotient of polynomials in positive (possibly fractional)
powers of x and trig functions of x.  Like trigrat except that it
accepts expressions not containing x as constants.
*/
{ if(NEGATIVE(t))
     return trigrat2(ARG(0,t),x);
  if(FRACTION(t))
     return trigpoly2(ARG(0,t),x) && trigpoly2(ARG(1,t),x);
  return trigpoly2(t,x);
}

/*______________________________________________________*/
int trigpoly(term t, term x)
/* return 1 if t is a polynomial in x and trig functions of x,
as given by nonterminal s in the above grammar.
Examples:  x sin x is accepted, u sin x is rejected.  See
stricttrigpoly which rejects x sin x and trigpoly2 which
accepts u sin x, and stricttrigpoly2 which rejects
x sin x and u sin x but accepts u + sin x.
*/
{ unsigned short f = FUNCTOR(t);
  unsigned short n;
  int i;
  if(seminumerical(t) || equals(t,x))
     return 1;
  if(ISATOM(t))
     return 0;
  if(NEGATIVE(t))
     return trigpoly(ARG(0,t),x);
  if(FRACTION(t))
     return 0;
  if(TRIGFUNCTOR(f))
     return equals(ARG(0,t),x);
  if(f == '^')
     { if(INTEGERP(ARG(1,t)))
          return trigpoly(ARG(0,t),x);
       else
          return 0;
     }
  if(f != '+' && f != '*')
     return contains(t,FUNCTOR(x)) ? 0 : 1;
     /* accept for example ln u  as a trigpoly in x, where u
        doesn't contain x.
     */
  n = ARITY(t);
  for(i=0;i<n;i++)
     { if(!trigpoly(ARG(i,t),x))
          return 0;
     }
  return 1;
}

/*______________________________________________________*/
int trigpoly2(term t, term x)
/* return 1 if t is a polynomial in x and trig functions of x,
but accepting expressions not containing x as constant.
*/
{ unsigned short f = FUNCTOR(t);
  unsigned short n;
  int i;
  if(ATOMIC(t))
     return 1;
  if(NEGATIVE(t))
     return trigpoly2(ARG(0,t),x);
  if(FRACTION(t))
     return 0;
  if(TRIGFUNCTOR(f))
     return equals(ARG(0,t),x);
  if(f == '^')
     { if(INTEGERP(ARG(1,t)))
          return trigpoly2(ARG(0,t),x);
       else
          return 0;
     }
  if(f != '+' && f != '*')
     return contains(t,FUNCTOR(x)) ? 0 : 1;
     /* accept for example ln u  as a trigpoly in x, where u
        doesn't contain x.
     */
  n = ARITY(t);
  for(i=0;i<n;i++)
     { if(!trigpoly2(ARG(i,t),x))
          return 0;
     }
  return 1;
}


/*__________________________________________________________________*/
int trigpolyargs2(term t, term x)
/* return nonzero if t is a polynomial in u,v,..., where the u,v are
either x or trig functions whose args are polynomial functions of x.
Example:  x^2 + tan^3 (3x).  Return 0 otherwise. The nonzero return
value is 1 if there are no trig functions and 2 if there are trig
functions; that is it's 1 if t is really (equal to) a polynomial.
Accepts functions not containing x as constants, e.g. u sin x.
*/
{ unsigned short n,f;
  int i,ans, temp;
  if(ATOMIC(t))
     return 1;
  f = FUNCTOR(t);
  if(TRIGFUNCTOR(f))
     return ispolyin(ARG(0,t),x) ? 2 : 0;
  if(f == '^')
     { term p = ARG(1,t);
       if(NEGATIVE(p))
          p = ARG(0,p);
       if(POSNUMBER(p))
          return trigpolyargs2(ARG(0,t),x);
       else
          return 0;
     }
  if(f == '-')
     return trigpolyargs2(ARG(0,t),x);
  if(f == '+' || f == '*')
     { n = ARITY(t);
       ans = 0;
       for(i=0;i<n;i++)
          { temp = trigpolyargs2(ARG(i,t),x);
            if(!temp)
               return 0;
            if(temp > ans)
               ++ans;
          }
       return ans;
     }
  if(f == '/' && !contains(ARG(1,t),FUNCTOR(x)))
     return trigpolyargs2(ARG(0,t),x);
  if(!contains(t,FUNCTOR(x)))
     return 1;   /* accept non-numerical constants like sqrt 2
                    as well as expressions like ln u which don't contain x */
  return 0;
}
/*__________________________________________________________________*/
int trigalg(term t, term x)
/* return nonzero if t is an algebraic function of x and trig functions of x,
0 if not.  Expressions involving other variables are rejected.
Use trigalg2(t,x) to accept such expressions.
*/
{ unsigned short n,f;
  int i,ans, temp;
  if(OBJECT(t))
     return 1;
  if(ISATOM(t))
     return equals(t,x);
  f = FUNCTOR(t);
  if(TRIGFUNCTOR(f))
     return equals(ARG(0,t),x);
  if(f == '^')
     { term p = ARG(1,t);
       if(NEGATIVE(p))
          p = ARG(0,p);
       if(POSNUMBER(p) || RATIONALP(p))
          return trigalg(ARG(0,t),x);
       else
          return 0;
     }
  if(f == '-')
     return trigalg(ARG(0,t),x);
  if(f == '+' || f == '*' || f == '/')
     { n = ARITY(t);
       ans = 0;
       for(i=0;i<n;i++)
          { temp = trigalg(ARG(i,t),x);
            if(!temp)
               return 0;
            if(temp > ans)
               ++ans;
          }
       return ans;
     }
  if(seminumerical(t))
     return 1;   /* accept non-numerical constants like sqrt 2 */
  return 0;
}

/*______________________________________________________*/
int trigalg2(term t, term x)
/* return 1 if t is a  built up from trigrats in x using +, *, -, and
rational powers, or more precisely, an algebraic function of x and trig
functions, whose args are polynomial in x.
Expressions not containing x are accepted as constants.
*/
{ unsigned short f = FUNCTOR(t);
  unsigned short n = ARITY(t);
  int i;
  if(ATOMIC(t))
     return 1;
  if(f == '+' || f == '*')
     { for(i=0;i<n;i++)
          { if(!trigalg2(ARG(i,t),x))
               return 0;
          }
       return 1;
     }
  if(f=='-')
     return trigalg2(ARG(0,t),x);
  if(f == '^')
     { term p = ARG(1,t);
       if(NEGATIVE(p))
          p = ARG(0,p);
       if(POSNUMBER(p))
          return trigalg2(ARG(0,t),x);
       else
          return 0;
     }
  if(f == '/')
     return (trigalg2(ARG(0,t),x) && trigalg2(ARG(1,t),x)) ? 1 : 0;
  if(!TRIGFUNCTOR(f))
     return 0;
  return ispolyin(ARG(0,t),x);
}
/*__________________________________________________________________*/
int stricttrigpoly(term t, term x)
/* return nonzero if t is a polynomial in trig functions of x,
0 if not.  The 'strict' means it doesn't accept x or polynomials
in x, but only polynomials in sin x, cos x, etc.  It does not
accept expressions involving other variables; use
stricttrigpoly2 for that.
*/
{ unsigned short n,f;
  int i,ans, temp;
  if(OBJECT(t))
     return 1;
  if(ISATOM(t))
     return 0;
  f = FUNCTOR(t);
  if(TRIGFUNCTOR(f))
     return equals(ARG(0,t),x);
  if(f == '^')
     { if(POSNUMBER(ARG(1,t)))
          return stricttrigpoly(ARG(0,t),x);
       else
          return 0;
     }
  if(f == '-')
     return stricttrigpoly(ARG(0,t),x);
  if(f == '+' || f == '*')
     { n = ARITY(t);
       ans = 0;
       for(i=0;i<n;i++)
          { temp = stricttrigpoly(ARG(i,t),x);
            if(!temp)
               return 0;
            if(temp > ans)
               ++ans;
          }
       return ans;
     }
  if(f == '/' && !contains(ARG(1,t),FUNCTOR(x)))
     return stricttrigpoly(ARG(0,t),x);
  if(seminumerical(t))
     return 1;   /* accept non-numerical constants like sqrt 2 */
  return 0;
}
 
/*__________________________________________________________________*/
int stricttrigpoly2(term t, term x)
/* return nonzero if t is a polynomial in trig functions of x,
0 if not.  The 'strict' means it doesn't accept x or polynomials
in x, but only polynomials in sin x, cos x, etc.  The 2 means
it allows expressions not involving x as constants.
*/
{ unsigned short n,f;
  int i,ans, temp;
  if(ATOMIC(t))
     return !equals(t,x);
  f = FUNCTOR(t);
  if(TRIGFUNCTOR(f))
     return equals(ARG(0,t),x) || ISATOM(ARG(0,t));   // so cos(y) can appear for example
  if(f == '^')
     { if(POSNUMBER(ARG(1,t)))
          return stricttrigpoly2(ARG(0,t),x);
       else
          return 0;
     }
  if(f == '-')
     return stricttrigpoly2(ARG(0,t),x);
  if(f == '+' || f == '*')
     { n = ARITY(t);
       ans = 0;
       for(i=0;i<n;i++)
          { temp = stricttrigpoly2(ARG(i,t),x);
            if(!temp)
               return 0;
            if(temp > ans)
               ++ans;
          }
       return ans;
     }
  if(f == '/' && !contains(ARG(1,t),FUNCTOR(x)))
     return stricttrigpoly2(ARG(0,t),x);
  if(!contains(t,FUNCTOR(x)))
     return 1;   /* accept non-numerical constants like sqrt 2
                    as well as expressions in other variables */
  return 0;
}
/*_________________________________________________________________*/
int eqpoly2(term t)
/*  Return 1 if t is equal to a multivariate polynomiall; 0 if not.
For example a product of polynomials satisfies poly2.  This is different
from mvpoly2 in that mvpoly2 also allows entire functions to occur.
*/

{ unsigned short n,i;
  unsigned short f = FUNCTOR(t);
  if(monomial(t))
     return 1;
  if(ATOMIC(t))
     return 1;
  n = ARITY(t);
  if(f == '*' || f == '+')
     { for(i=0;i<n;i++)
          { if(!eqpoly2(ARG(i,t)) )
               return 0;
          }
       return 1;
     }
  if(f == '^' && INTEGERP(ARG(1,t)) && !ZERO(ARG(1,t)))
     return eqpoly2(ARG(0,t));
  if(f == '-')
     return eqpoly2(ARG(0,t));
  return 0;
}
/*_________________________________________________________________*/
int algpoly(term t)
/* return 1 if t is an algebraic function without division
i.e. is built up from +,-,*, ROOT, SQRT, and positive constant numerical
exponents, including positive fractions, with additional restrictions
described below.
   This is the test used in autolimit for applying divnumdenom; the
numerator and denom of the limitand must be algpoly's.
*/
{ unsigned short f,n;
  int i;
  if(ATOMIC(t))
     return 1;
  f = FUNCTOR(t);
  n = ARITY(t);
  if(f == '^')
     { if(!POSNUMBER(ARG(1,t)))
          return 0;
       return algpoly(ARG(0,t));
     }
  if(f == ROOT)
     { if(!INTEGERP(ARG(0,t)))
          return 0;
       return algpoly(ARG(1,t));
     }
  if(f == SQRT || f == '-')
     return algpoly(ARG(0,t));
  if(f == '*' || f == '+')
     { for(i=0;i<n;i++)
          { if(!algpoly(ARG(i,t)))
               return 0;
          }
       return 1;
     }
  return 0;
}
/*_________________________________________________________________*/
int algpoly3(term t)
/* return 1 if t is an algebraic function without division
i.e. is built up from +,-,*, ROOT, SQRT, ABSFUNCTOR, and positive constant numerical
exponents, including positive fractions, with additional restrictions
described below.  This is used in limval_aux.
*/
{ unsigned short f,n;
  int i;
  if(ATOMIC(t))
     return 1;
  f = FUNCTOR(t);
  n = ARITY(t);
  if(f == '^')
     { if(!POSNUMBER(ARG(1,t)))
          return 0;
       return algpoly3(ARG(0,t));
     }
  if(f == ROOT)
     { if(!INTEGERP(ARG(0,t)))
          return 0;
       return algpoly3(ARG(1,t));
     }
  if(f == SQRT || f == '-' || f == ABSFUNCTOR)
     return algpoly3(ARG(0,t));
  if(f == '*' || f == '+')
     { for(i=0;i<n;i++)
          { if(!algpoly3(ARG(i,t)))
               return 0;
          }
       return 1;
     }
  return 0;
}
/*_________________________________________________________________*/
int algrat(term t)
/* return 1 if t is an algebraic function built up from '/',
+,-,*, ROOT, SQRT, ABSFUNCTOR, and positive constant numerical
exponents, including positive fractions, with additional restrictions
described below.  This is used in limval_aux.  Note that
these functions can have jumps, e.g. abs(x)/x.
*/
{ unsigned short f,n;
  int i;
  if(ATOMIC(t))
     return 1;
  f = FUNCTOR(t);
  n = ARITY(t);
  if(f == '^')
     { if(!POSNUMBER(ARG(1,t)))
          return 0;
       return algrat(ARG(0,t));
     }
  if(f == ROOT)
     { if(!INTEGERP(ARG(0,t)))
          return 0;
       return algrat(ARG(1,t));
     }
  if(f == SQRT || f == '-' || f == ABSFUNCTOR)
     return algrat(ARG(0,t));
  if(f == '*' || f == '+' || f == '/')
     { for(i=0;i<n;i++)
          { if(!algrat(ARG(i,t)))
               return 0;
          }
       return 1;
     }
  return 0;
}

/*_________________________________________________________________*/
int algpoly2(term t)
/* return 1 if t is an algebraic function without division
i.e. is built up from +,-,*, ROOT, SQRT, and positive constant numerical
exponents, including positive fractions, with additional restrictions
described below.
   This is the test used in autolimit for applying sumleadingterm:
numerator and denom of the limitand must be algpoly2's.
   It's also the test used for sumleadingterm.  In order to avoid
applying sumleadingterm to sqrt(x+h)-sqrt(x), which is correct but
too big a step, we require that an algpoly2 have only eqpoly2's
inside sums.
*/
{ unsigned short f,n;
  int i;
  if(ATOMIC(t))
     return 1;
  f = FUNCTOR(t);
  n = ARITY(t);
  if(f == '^')
     { if(!POSNUMBER(ARG(1,t)))
          return 0;
       return algpoly2(ARG(0,t));
     }
  if(f == ROOT)
     { if(!INTEGERP(ARG(0,t)))
          return 0;
       return algpoly2(ARG(1,t));
     }
  if(f == SQRT || f == '-')
     return algpoly2(ARG(0,t));
  if(f == '*')
     { for(i=0;i<n;i++)
          { if(!algpoly2(ARG(i,t)))
               return 0;
          }
       return 1;
     }
  if(f == '+')
     { for(i=0;i<n;i++)
          { if(!eqpoly2(ARG(i,t)))  /* Not algpoly2 */
               return 0;
          }
       return 1;
     }
  return 0;
}

/*_________________________________________________________________*/
int algebraic_in2(term t, term x)
/* return 1 if t is an algebraic function of x,
i.e. is built up from +,-,*, /,ROOT, SQRT, and positive constant numerical
exponents, including positive fractions.  It accepts expressions not
containing x as constants.
   This is the test used in limval for using leading terms at infinity,
where trig functions have no leading terms.
*/
{ unsigned short f,n;
  int i;
  if(ATOMIC(t))
     return 1;
  f = FUNCTOR(t);
  n = ARITY(t);
  if(f == '^')
     { if(POSNUMBER(ARG(1,t)))
          return algebraic_in2(ARG(0,t),x);
       if(NEGATIVE(ARG(1,t)) && POSNUMBER(ARG(0,ARG(1,t))))
          return algebraic_in2(ARG(0,t),x);
       return 0;
     }
  if(f == ROOT)
     { if(!INTEGERP(ARG(0,t)))
          return 0;
       return algebraic_in2(ARG(1,t),x);
     }
  if(f == SQRT || f == '-')
     return algebraic_in2(ARG(0,t),x);
  if(f == '/')
     return algebraic_in2(ARG(0,t),x) && algebraic_in2(ARG(1,t),x);
  if(f != '*' && f != '+')
     return contains(t,FUNCTOR(x)) ? 0 : 1;
  for(i=0;i<n;i++)
     { if(!algebraic_in2(ARG(i,t),x))
          return 0;
     }
  return 1;
}
/*____________________________________________________________________*/
int logpoly2(term t, term x)
/* Return 1 if t is a log or power of log of trigpolyargs2 in x */
{ if(FUNCTOR(t) == '^' && !contains(ARG(1,t),FUNCTOR(x)))
     t = ARG(0,t);
  if(FUNCTOR(t) == LN || FUNCTOR(t) == LOG)
     return trigpolyargs2(ARG(0,t),x);
  if(FUNCTOR(t) == LOGB)
     return trigpolyargs2(ARG(1,t),x);
  return 0;
}

/*____________________________________________________________________*/
int logtrigalg(term t, term x)
/* Return a if t is a log or power of log of trigalg in x */
{ if(FUNCTOR(t) == '^' && !contains(ARG(1,t),FUNCTOR(x)))
     t = ARG(0,t);
  if(FUNCTOR(t) == LN || FUNCTOR(t) == LOG)
     return trigalg(ARG(0,t),x);
  if(FUNCTOR(t) == LOGB)
     return trigalg(ARG(1,t),x);
  return 0;
}

/*____________________________________________________________________*/
int logtrigalg2(term t, term x)
/* Return 1 if t is a log or power of log of trigalg2 in x */
{ if(FUNCTOR(t) == '^' && !contains(ARG(1,t),FUNCTOR(x)))
     t = ARG(0,t);
  if(FUNCTOR(t) == LN || FUNCTOR(t) == LOG)
     return trigalg2(ARG(0,t),x);
  if(FUNCTOR(t) == LOGB)
     return trigalg2(ARG(1,t),x);
  return 0;
}

/*_____________________________________________________*/
int logexpalg(term t, term x)
/* built up from logs and exponentials and algebraic operations (no trig) */
/* These functions have finitely many zeroes and the class is closed
under derivatives, so they are eventually monotone, and hence can be used
in the integral test for convergence of series. */

{ unsigned short f,n;
  int i;
  if(ATOMIC(t))
     return 1;
  f = FUNCTOR(t);
  n = ARITY(t);
  if(f == '^' || f == '/')
     return logexpalg(ARG(0,t),x) && logexpalg(ARG(1,t),x);
  if(f == ROOT || f == LOG)
     return logexpalg(ARG(1,t),x);
  if(f == SQRT || f == '-' || f == LN)
     return logexpalg(ARG(0,t),x);
  if(f != '*' && f != '+')
     return contains(t,FUNCTOR(x)) ? 0 : 1;
  for(i=0;i<n;i++)
     { if(!logexpalg(ARG(i,t),x))
          return 0;
     }
  return 1;
}

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