Sindbad~EG File Manager

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

/*
M. Beeson. Limits by leading terms of logarithmic algebraic functions.
Original date 8.19.98
6.9.13 corrected log_leading_term to fail on constant input (formerly it returned zero, which was 
        responsible for creating a zero denominator).
8.8.24  changed math.h to sincos.h
2.18.25 and back again
*/

#include <assert.h>
#include <math.h>
#include "globals.h"
#include "ops.h"
#include "prover.h"
#include "mpmem.h"
#include "polynoms.h"
#include "fraction.h"
#include "deriv.h"
#include "mplimits.h"
#include "deval.h"
#include "term2.h"
#include "trig.h"
#include "evaltrig.h"
#include "cancel.h"
#include "pvalaux.h"
#include "probtype.h"  /* get_problemtype */
#include "evalpoly.h"
#include "loglead.h"

static int log_lt_plus(term *args,int n, term x, term a, term *c, term *deg, term *logdeg);
/*__________________________________________________________________*/
int log_leading_term(term t, term x, term a, term *c,  term *deg, term *logdeg)
/*  Find c and deg and logdeg such that
    t = c(x-a)^deg ln(x-a)^logdeg + higher order terms,
    where c is nonzero.  Deg and logdeg come out as
    a positive or negative integer or rational (if the function
    succeeds).  If a = infinity or minusinfinity,
    t = cx^deg ln(x)^logdeg + lower order terms.
    Return zero for success,
           1 for failure,
           2 for domain error (point x = a is not in the closure of domain of t),
           3 for function t(x) not differentiable at a, as in abs(x)/x.
*/

{ term b,d,deg1,deg2,ldeg1,ldeg2,power;
  term coef, nextcoef,m,temp,temp2,exp;
  int err,i;
  unsigned short n = ARITY(t);
  unsigned short f = FUNCTOR(t);
  if(!contains(t,LN))
     { *logdeg = zero;
       return leading_term(t,x,a,c,deg);
     }
  if(f == LN)
     { err = leading_term(ARG(0,t),x,a,&b,&deg1);
       if(err)
          return 1;
       if(ZERO(deg1))
          return 1;   /* ARG(0,t) was constant, so t itself is constant */
       /* ln(bx^deg1)= log b + deg1 ln x; the constant logb is neglible */
       
       *logdeg = one;
       *c = deg1;
       *deg = zero;
       return 0;
     }
  if(f == '^' && !contains(ARG(1,t),FUNCTOR(x)))
     { power = ARG(1,t);
       if(!obviously_nonzero(power))
          return 1;
       err = log_leading_term(ARG(0,t),x,a,&b,&deg1,&ldeg1);
       if(err)
          return 1;
       /* [bx^deg1 (ln x)^ldeg1]^power =
          b^power x^(deg1 * power) (ln x)^(ldeg1 *power ) */
       polyval(make_power(b,power),c);
       polyval(product(deg1,power),deg);
       polyval(product(ldeg1,power),logdeg);
       return 0;
     }
  if(f == '-')
     { err = log_leading_term(ARG(0,t),x,a,&b,deg,logdeg);
       if(err)
          return 1;
       tneg(b,c);
       return 0;
     }
  if(f == '*')
     { coef = one;  /* avoid a warning */
       for(i=0;i<n;i++)
          { err = log_leading_term(ARG(i,t),x,a,&nextcoef,&m,&ldeg1);
            if(err)
               return err;
            if(i == 0)
               { coef = nextcoef;
                 exp = m;
                 ldeg2 = ldeg1;
               }
            else
               { if(equals(coef,bounded_oscillations) ||
                    equals(nextcoef,bounded_oscillations)
                   )
                    temp = bounded_oscillations;
                 else
                    polyval(product(coef,nextcoef),&temp);
                 if(i > 1)
                    destroy_term(coef);  /* left in fresh space by polyval */
                 coef = temp;
                 polyval(sum(exp,m),&temp2);
                 if(i > 1)
                    destroy_term(exp);
                 exp = temp2;
                 polyval(sum(ldeg2,ldeg1),&temp);
                 if(i > 1)
                    destroy_term(ldeg2);
                 ldeg2 = temp;
               }    
          }
       *c = coef;
       *deg = exp;
       *logdeg = ldeg2;
       return 0;
     }
  if(f == '+')
     return log_lt_plus(ARGPTR(t),n,x,a,c,deg,logdeg);
  if(f == '/')
     { err = log_leading_term(ARG(0,t),x,a,&b,&deg1,&ldeg1);
       if(err)
          return 1;
       err = log_leading_term(ARG(1,t),x,a,&d,&deg2,&ldeg2);
       if(err)
          return 1;
       polyval(make_fraction(b,d),c);
       polyval(sum(deg1,tnegate(deg2)),deg);
       polyval(sum(ldeg1,tnegate(ldeg2)),logdeg);
       return 0;
     }
  return 1;
}
/*_______________________________________________________________________*/
static int log_lt_plus(term *args,int n, term x, term a, term *c, term *deg, term *logdeg)
/*   args points to an array of n terms, the args of a sum.
Get the log leading term of the sum--the term or sum of terms with the
least-power log leading terms themselves.  In case the leading terms
cancel, this function can return a zero coeficient.  In case two
of the summands have bounded_oscillation leading terms of the same
(leading) degree, we fail, because we can't guarantee the terms
don't cancel, e.g. lim (x->infinity, sin(2x) - 2sin x cos x);
limval will return bounded_oscillations for both terms.
   Return 0 for success, 1 for failure, 2 for domain error (x=a is not
in the closure of the domain of t), 3 for not-differentiable at a.
*/

{ int i,err;
  term coef,exp,lexp,temp;
  term nextcoef,m,lm;
  double mm,expm,lmm,lexpm;
  for(i=0;i<n;i++)
     { err = log_leading_term(args[i],x,a,&nextcoef,&m,&lm);
       if(err)
          return err;
       if(!seminumerical(m))
          return 1;
       if(!seminumerical(lm))
          return 1;
       if(i==0)
         { coef = nextcoef;
           exp = m;
           lexp = lm;
         }
       else
         { deval(m,&mm);
           if(mm == BADVAL)
              return 1;
           deval(exp,&expm);
           if(expm == BADVAL)
              return 1;
           deval(lm,&lmm);
           if(lmm == BADVAL)
              return 1;
           deval(lexp,&lexpm);
           if(lexpm == BADVAL)
              return 1;
           if( (mm < expm && !NOTDEFINED(a)) ||
                 /* LOWER powers dominate when a is finite    */
               (mm > expm && NOTDEFINED(a))
                 /* HIGHER powers dominate when a is infinite */
             )
              { exp = m;
                coef = nextcoef;
                lexp = lm;
              }
           else if(fabs(mm-expm) < 1.0e-10) /* watch for roundoff error */
              { /* check the log exponents */
                if( (lmm < lexpm && !NOTDEFINED(a)) ||
                 /* LOWER powers dominate when a is finite    */
                    (lmm > lexpm && NOTDEFINED(a))
                 /* HIGHER powers dominate when a is infinite */
                  )
                   { exp = m;
                     lexp = lm;
                     coef = nextcoef;
                   }
                else if(fabs(lmm-lexpm) < 1.0e-10) /* watch for roundoff error */
                   { if(equals(nextcoef,bounded_oscillations) &&
                        equals(coef, bounded_oscillations)
                       )
                        return 1;
                     else if(equals(coef, bounded_oscillations) ||
                             equals(nextcoef, bounded_oscillations)
                            )
                        temp = bounded_oscillations;
                     else
                        polyval(sum(coef,nextcoef),&temp);
                     coef = temp;
                   }
              }
          }
     }
  *c = coef;
  *deg = exp;
  *logdeg = lexp;
  return 0;
}

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