Sindbad~EG File Manager
/*
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,°1);
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,°1,&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,°1,&ldeg1);
if(err)
return 1;
err = log_leading_term(ARG(1,t),x,a,&d,°2,&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