Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/polyval/
Upload File :
Current File : /usr/home/beeson/MathXpert/polyval/meromorp.c

/* M. Beeson, for Mathpert
   auxiliary functions to help with cancellation in verifying identities.
   See the report "Cancellation in Verifying Identities" submitted
   to Recognix, Inc., March, 2001.
*/
/*
3.1.01  creation date
3.8.01  last modified
11.5.23 deleted two unused variables to silence a warning
*/

#include <assert.h>
#include <math.h>
#include <stdlib.h>   /* qsort */

#include "globals.h"  /* which includes setjmp.h and terms.h */
#include "cancel.h"
#include "pvalaux.h"
#include "meromorp.h"
#include "deval.h"

static int somewhere_defined_and_nonzero(term t);
static int somewhere_positive(term t);
/*___________________________________________________________________*/

int meromorph(term t)
/* return 1 if t is real-analytic and everywhere defined,
or a quotient of such functions.   Return 0 otherwise.
This means, as a function of all its variables.
*/

{ unsigned short f, n;
  int i;
  f = FUNCTOR(t);
  if(ATOMIC(t))
     { if(PREDEFINED_ATOM(f) && f >= LEFT)
          return 0;   /* INFINITYFUNCTOR etc. */
       return 1;
     }
  if(f == DET)
     return 0;
  if(f == ABSFUNCTOR || f == SG || f == SQRT || f == ROOT || f == LN || f == LOG ||
     (BESSELJ <= f && f <= BESSELK)
    )
     { if(!obviously_positive(ARG(0,t)))
          return 0;
       return meromorph(ARG(0,t));
     }
  if(f == LOGB)
     { if(!obviously_positive(ARG(1,t)))
          return 0;
       return meromorph(ARG(1,t));
     }
  if(f == ASEC || f == ACSC)
     return 0;  /* these don't have connected domains */
  if(f == ASIN || f == ACOS)
     return 0;  /* these are not total  */
  if(f == FACTORIAL)
     return 0;
  if(f >= FLOOR && f < BESSELJ)
     return 0;
  if(f == '^')
     { if(isinteger(ARG(1,t)))
          return meromorph(ARG(0,t));
       else
          return 0;
     }
  if(f >= GCD && f <= MATRIX)
     return 0;
  if(f >= GAMMA)
     return 0;
  n = ARITY(t);
  for(i=0;i<n;i++)
     { if(!meromorph(ARG(i,t)))
           return 0;
     }
  return 1;
}

/*______________________________________________________________________*/
static int continuous2(term t)
/* Return 1 if t is continuous on its domain, as a function of all its variables;
   return 0 otherwise.  */
/* similar to meromorphic, but ABSFUNCTOR, DET, SQRT, ROOT, and fractional exponents are allowed.   */
{ unsigned short f, n;
  int i;
  f = FUNCTOR(t);
  if(ATOMIC(t))
     { if(PREDEFINED_ATOM(f) && f >= LEFT)
          return 0;   /* INFINITYFUNCTOR etc. */
       return 1;
     }
  if(f >= FLOOR && f < BESSELJ)
     return 0;
  if(f == SG || f == FACTORIAL)
     return 0;
  if(f == LOGB)
     return continuous2(ARG(1,t));
  if(f == '^')
     { if( isinteger(ARG(1,t)) ||
           obviously_nonzero(ARG(1,t)) ||
           obviously_nonzero(ARG(0,t))
         )
          return continuous2(ARG(0,t));
       else
          return 0;
     }
  if(f >= GCD && f <= MATRIX)
     return 0;
  if(f >= GAMMA)
     return 0;
  n = ARITY(t);
  for(i=0;i<n;i++)
     { if(!continuous2(ARG(i,t)))
           return 0;
     }
  return 1;
}

/*_____________________________________________________________________*/
int ok_to_cancel(term f, term u, term v)
/* in verifying the identity u = v,
is it legal to cancel f?  Return 1 if it is,
0 if not.
*/
{ term g,h;
  if(meromorph(f) &&
     continuous2(u) && continuous2(v) &&
     somewhere_nonzero(f) &&
     !equals(f,u) && !equals(f,v)   /*  don't divide by sin x  in   sin x cos x/cos x = sin x */
    )
     return 1;
  /* There is another case in which it's legal:  when u = fg and v = fh
     and g and h are meromorphic, and f is continuous and defined and nonzero on
     some interval.  For example,
     you can cancel sqrt(x) or ln(x)  if the rest of the identity is meromorphic.
     The example  x sqrt x = |x| sqrt x  depends on |x| not being meromorphic.
  */
  if(!continuous2(f))
     return 0;
  polyval(make_fraction(u,f),&g);
  if(!meromorph(g))
     return 0;
  polyval(make_fraction(v,f),&h);
  if(!meromorph(h))
     return 0;
  if(ONE(g) && ONE(h))
     return 0;   /* example,   cos(x) sin(x)/ sin(x) = cos(x).  Don't divide by cos(x) getting 1=1. */
  if(somewhere_defined_and_nonzero(f))
     return 1;
  else
     return 0;
}


/*___________________________________________________________________________*/
int somewhere_nonzero(term t)
/* return 1 if we can find a point where the
almost-everywhere-defined expression t is nonzero.
It is assumed that t is meromorphic, so the zeroes of
its denominator and its own zeroes are measure-zero,
unless it's identically zero.
Therefore numerical substitutions should soon
find a nonzero point if there is one.
*/

{ term *atomlist;
  int count,nvars,i;
  double z;
  if(obviously_nonzero(t))
     return 1;   /* x^2 + 1  for example */
  /* Now make numerical substitutions */
  nvars = variablesin(t,&atomlist);
  if(nvars == 0)
     { deval(t,&z);
       if(fabs(z) > VERYSMALL || OBJECT(t))
          return 1;
       return 0;
     }
  if(nvars >= MAXVARIABLES)
     return 0;  /* this will never happen */
  for(count = 0; count < 100; ++count)
     { /* assign more or less random values to the variables
          The values assigned are all between 0 and 1 */
       for(i=0;i<nvars;i++)
          {  if (TYPE(atomlist[i])==INTEGER)
                { SETVALUE(atomlist[i], 1.0+i);
                }
             else
                { SETVALUE(atomlist[i], (count % 10)/10.0 + i* 0.02 + 0.001 * (count/10));
                }
          }
       deval(t,&z);
       if(z != BADVAL && fabs(z) > VERYSMALL)
          { free2(atomlist);
            return 1;
          }

     }
  free2(atomlist);
  return 0;
}

/*_________________________________________________________________*/
static int somewhere_defined_and_nonzero(term t)
/* return 1 if t is defined and nonzero on some interval.
It's presumed that t is continuous, but not necessarily
meromorphic.  We can't use numerical substitution because
we don't know how to find points in the domain of t */
{ unsigned short f;
  term c,s;
  double z;
  if(ATOMIC(t))
     return 1;
  if(meromorph(t))
     return somewhere_nonzero(t);
  f = FUNCTOR(t);
  if(f == '^' && isinteger(ARG(1,t)) && !ZERO(ARG(1,t)))
     return somewhere_defined_and_nonzero(ARG(0,t));
  if(f == '^')
     return somewhere_positive(ARG(0,t));
  if(f == '*')
     { ratpart2(t,&c,&s);
       deval(c,&z);
       if(z != BADVAL && fabs(z) > VERYSMALL)
          return somewhere_defined_and_nonzero(s);
       else
          return 0;
     }
  if(f == '+')
     return 0;  /* sum of two non-meromorphic terms,  who knows where it's defined. */
  switch(f)
    { case LN:
      case SQRT:
         return somewhere_positive(ARG(0,t));
      case ROOT:
         return somewhere_positive(ARG(1,t));
      case SIN:
      case COS:
      case ABSFUNCTOR:
      case TAN:
      case ATAN:
      case TANH:
      case ATANH:
      case SINH:
         return somewhere_defined_and_nonzero(ARG(0,t));
    }
  return 0;
}
/*_________________________________________________________________*/
static int somewhere_positive(term t)
/* return 1 if t is defined and positive on some interval.
It's presumed that t is continuous, but not necessarily
meromorphic.  We can't use numerical substitution because
we don't know how to find points in the domain of t */
{ unsigned short f;
  term c,s;
  double z;
  if(ATOMIC(t))
     return 1;
  f = FUNCTOR(t);
  if(f == '^')
     return somewhere_positive(ARG(0,t));
  if(f == '*')
     { ratpart2(t,&c,&s);
       deval(c,&z);
       if(z != BADVAL)
         { if(z > VERYSMALL)
              return somewhere_positive(s);
           else
              return 0;
          }
       else
          return 0;
     }
  if(f == '+')
     return 0;  /* sum of two non-meromorphic terms,  who knows where it's defined. */
  switch(f)
    { case LN:
         return 0;  /* give up */
      case SQRT:
         return somewhere_positive(ARG(0,t));
      case ROOT:
         return somewhere_positive(ARG(1,t));
      case SIN:
      case COS:
      case TAN:
         return 0;  /* give up */
      case ABSFUNCTOR:
         return somewhere_defined_and_nonzero(ARG(0,t));
      case ATAN:
      case TANH:
      case ATANH:
      case SINH:
         return somewhere_positive(ARG(0,t));
    }
  return 0;
}

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