Sindbad~EG File Manager
/* M. Beeson, for MathXpert
9.22.92 original date
1.30.98 last modified
3.4.00 corrected lnleftineq1 and lnleftineq2
3.4.00 corrected logleftineq1 and logleftineq2
6.4.13 polylessexp
6.5.13 added logratbound and logpoly and algebraic
*/
#include <string.h>
#include "globals.h"
#include "ops.h"
#include "errbuf.h"
#include "prover.h"
#include "polynoms.h"
#include "pvalaux.h" /* twoparts */
#include "logineq.h"
/* ____________________________________________________*/
static term ln3(term t)
/* takes the ln, returning u when t has the form e^u */
{ if(ATOMIC(t) || FUNCTOR(t) != '^' || !equals(ARG(0,t),eulere))
return ln1(t);
return ARG(1,t);
}
/* ____________________________________________________*/
static term log3(term t)
/* takes the log, returning u when t has the form 10^u */
{ if(ATOMIC(t) || FUNCTOR(t) != '^' || !equals(ARG(0,t),ten))
return log1(t);
return ARG(1,t);
}
/*______________________________________________________ */
int lnineq1(term ineq, term arg, term *next, char *reason)
/* u < v => ln u < ln v, provided u > 0 */
{ unsigned f = FUNCTOR(ineq);
int err;
term u,v;
if(f != '<' && f != '>')
return 1;
u = f == '<' ? ARG(0,ineq) : ARG(1,ineq);
v = f == '<' ? ARG(1,ineq) : ARG(0,ineq);
err = infer(lessthan(zero,u));
if(err)
{ errbuf(0,english(1184));
/* Left side isn't positive */
return 1;
}
*next = f == '<' ? lessthan(ln3(u),ln3(v)) : greaterthan(ln3(v),ln3(u));
strcpy(reason, f == '<' ? english(1623) : english(1653));
/* u<v iff ln u < ln v */
/* u>v iff ln u > ln v */
return 0;
}
/*______________________________________________________ */
int lnineq2(term ineq, term arg, term *next, char *reason)
/* u \le v => ln u \le ln v provided u > 0*/
{ unsigned f = FUNCTOR(ineq);
int err;
term u,v;
if(f != LE && f != GE)
return 1;
u = f == LE ? ARG(0,ineq) : ARG(1,ineq);
v = f == LE ? ARG(1,ineq) : ARG(0,ineq);
err = infer(lessthan(zero,u));
if(err)
{ errbuf(0, english(1184));
/* Left side isn't positive */
return 1;
}
*next = f == LE ? le(ln3(u),ln3(v)) : ge(ln3(v), ln3(u));
strcpy(reason, f == '<' ? english(1625) : english(1626));
/* u \le v iff ln u \le ln v */
/* u \ge v iff ln u \ge ln v */
return 0;
}
/*______________________________________________________ */
int logineq1(term ineq, term arg, term *next, char *reason)
/* u < v => log u < log v, provided u > 0 */
{ unsigned f = FUNCTOR(ineq);
int err;
term u,v;
if(f != '<' && f != '>')
return 1;
u = f == '<' ? ARG(0,ineq): ARG(1,ineq);
v = f == '<' ? ARG(1,ineq): ARG(0,ineq);
err = infer(lessthan(zero,u));
if(err)
{ errbuf(0, english(1184));
/* Left side isn't positive */
return 1;
}
*next = f == '<' ? lessthan(log3(u),log3(v)): greaterthan(log3(v),log3(u));
strcpy(reason, f == '<' ? english(1624): english(1654));
/* u<v iff log u < log v */
/* u>v iff log u > log v */
return 0;
}
/*______________________________________________________ */
int logineq2(term ineq, term arg, term *next, char *reason)
/* u <= v => log u <= log v provided u > 0*/
{ unsigned f = FUNCTOR(ineq);
int err;
term u,v;
if(f != LE && f != GE)
return 1;
u = f == LE ? ARG(0,ineq): ARG(1,ineq);
v = f == LE ? ARG(1,ineq): ARG(0,ineq);
err = infer(lessthan(zero,u));
if(err)
{ errbuf(0, english(1184));
/* Left side isn't positive */
return 1;
}
*next = f == LE ? le(log3(u),log3(v)): ge(log3(v),log3(u));
strcpy(reason,f == LE ? english(1625): english(1626));
/* u <= v iff log u <= log v */
/* u >=v iff log u >= log v */
return 0;
}
/*______________________________________________________ */
int expineq1(term ineq, term arg, term *next, char *reason)
/* u < v => a^u < a^v if a > 0, takes arg = a */
{ unsigned short f = FUNCTOR(ineq);
unsigned short g,h;
int err;
term u,v,left,right;
if(f != '<' && f != '>')
return 1;
u = f == '<' ? ARG(0,ineq): ARG(1,ineq);
v = f == '<' ? ARG(1,ineq): ARG(0,ineq);
g = FUNCTOR(u);
h = FUNCTOR(v);
if(FUNCTOR(arg) == ILLEGAL)
{ if(g == LOGB)
arg = ARG(0,u);
else if(h == LOGB)
arg = ARG(0,v);
else if(g == LN || h == LN)
arg = eulere;
else if(g == LOG || h == LOG)
arg = ten;
else
return 1;
}
err = infer(lessthan(zero,u));
if(err)
{ errbuf(0, english(1184));
/* Left side isn't positive */
return 1;
}
if(FUNCTOR(u) == LOGB && equals(ARG(0,u),arg))
left = ARG(1,u);
else
left = make_power(arg,u);
if(FUNCTOR(v) == LOGB && equals(ARG(0,v),arg))
right = ARG(1,v);
else
right = make_power(arg,v);
*next = f == '<' ? lessthan(left,right): greaterthan(right,left);
strcpy(reason, f == '<' ? english(1627): english(1628));
/* u < v iff a^u < a^v */
/* u > v iff a^u > a^v */
return 0;
}
/*______________________________________________________ */
int expineq2(term ineq, term arg, term *next, char *reason)
/* u \le v => a^u \le a^v if a > 0, takes arg in menu mode */
{ unsigned short f = FUNCTOR(ineq);
unsigned short g,h;
int err;
term u,v,left,right;
if(f != LE && f != GE)
return 1;
u = f == LE ? ARG(0,ineq) : ARG(1,ineq);
v = f == LE ? ARG(1,ineq) : ARG(0,ineq);
g = FUNCTOR(u);
h = FUNCTOR(v);
if(FUNCTOR(arg) == ILLEGAL)
{ if(g == LOGB)
arg = ARG(0,u);
else if(h == LOGB)
arg = ARG(0,v);
else if(g == LN || h == LN)
arg = eulere;
else if(g == LOG || h == LOG)
arg = ten;
else
return 1;
}
err = infer(lessthan(zero,u));
if(err)
{ errbuf(0, english(1184));
/* Left side isn't positive */
return 1;
}
if(FUNCTOR(u) == LOGB && equals(arg,ARG(0,u)))
left = ARG(1,u);
else
left = make_power(arg,u);
if(FUNCTOR(v) == LOGB && equals(arg,ARG(0,v)))
right = ARG(1,v);
else
right = make_power(arg,v);
*next = f == LE ? le(left,right): ge(right,left);
strcpy(reason, f == LE ? english(1629): english(1630));
/* u \le v iff a^u \le a^v */
/* u \ge v iff a^u \ge a^v */
return 0;
}
/*_________________________________________________________________*/
int lnrightineq1(term t, term arg, term *next, char *reason)
/* u < ln v iff e^u < v */
{ unsigned short f = FUNCTOR(t);
term u,v,left,right;
if(f != '<' && f != '>')
return 1;
u = f == '<' ? ARG(0,t) : ARG(1,t);
right = f == '<' ? ARG(1,t) : ARG(0,t);
if(FUNCTOR(right) != LN)
return 1;
v = ARG(0,right);
if(FUNCTOR(u) == LN)
left = ARG(0,u);
else
left = make_power(eulere,u);
*next = f == '<' ? lessthan(left,v) : greaterthan(v,left);
HIGHLIGHT(*next);
strcpy(reason, f == '<' ? english(1631) : english(1635));
/* u < ln v iff e^u < v */
/* ln u > v iff u > e^v */
return 0;
}
/*_________________________________________________________________*/
int lnrightineq2(term t, term arg, term *next, char *reason)
/* u \le ln v iff e^u \le v */
{ unsigned short f = FUNCTOR(t);
term u,v,left,right;
if(f != LE && f != GE)
return 1;
u = f == LE ? ARG(0,t) : ARG(1,t);
right = f == LE ? ARG(1,t) : ARG(0,t);
if(FUNCTOR(right) != LN)
return 1;
v = ARG(0,right);
if(FUNCTOR(u) == LN)
left = ARG(0,u);
else
left = make_power(eulere,u);
*next = f == LE ? le(left,v) : ge(v,left);
HIGHLIGHT(*next);
strcpy(reason, f == LE ? english(1633): english(1634));
/* u \le ln v iff e^u \le v */
/* ln u \ge v iff u \ge e^v */
return 0;
}
/*_________________________________________________________________*/
int lnleftineq1(term t, term arg, term *next, char *reason)
/* ln u < v iff u < e^v */
{ unsigned short f = FUNCTOR(t);
term u,v,left,right;
if(f != '<' && f != '>')
return 1;
v = f == '<' ? ARG(1,t) : ARG(0,t);
left = f == '<' ? ARG(0,t) : ARG(1,t);
if(FUNCTOR(left) != LN)
return 1;
u = ARG(0,left);
if(FUNCTOR(v) == LN)
right = ARG(0,v);
else
right = make_power(eulere,v);
*next = f == '<' ? lessthan(u,right) : greaterthan(right,u);
HIGHLIGHT(*next);
strcpy(reason, f == '<' ? english(1632) : english(1636));
/* ln u < v iff u < e^v */
/* u > ln v iff e^u > v */
return 0;
}
/*_________________________________________________________________*/
int lnleftineq2(term t, term arg, term *next, char *reason)
/* ln u \le v iff u \le e^v */
{ unsigned short f = FUNCTOR(t);
term u,v,left,right;
if(f != LE && f != GE)
return 1;
v = f == LE ? ARG(1,t) : ARG(0,t);
left = f == LE ? ARG(0,t) : ARG(1,t);
if(FUNCTOR(left) != LN)
return 1;
u = ARG(0,left);
if(FUNCTOR(v) == LN)
right = ARG(0,v);
else
right = make_power(eulere,v);
*next = f == LE ? le(u,right) : ge(right,u);
HIGHLIGHT(*next);
strcpy(reason, f == LE ? english(1637) : english(1638));
/* ln u \le v iff u \le e^v */
/* u \ge ln v iff e^u \ge v */
return 0;
}
/*_________________________________________________________________*/
int logrightineq1(term t, term arg, term *next, char *reason)
/* u < log v iff 10^u < v */
{ unsigned short f = FUNCTOR(t);
term u,v,left,right;
if(f != '<' && f != '>')
return 1;
u = f == '<' ? ARG(0,t) : ARG(1,t);
right = f == '<' ? ARG(1,t) : ARG(0,t);
if(FUNCTOR(right) != LOG)
return 1;
v = ARG(0,right);
if(FUNCTOR(u) == LOG)
left = ARG(0,u);
else
left = make_power(ten,u);
*next = f == '<' ? lessthan(left,v) : greaterthan(v,left);
HIGHLIGHT(*next);
strcpy(reason, f == '<' ? english(1639) : english(1640));
/* u < log v iff 10^u < v */
/* log u > v iff u > 10^v */
return 0;
}
/*_________________________________________________________________*/
int logleftineq1(term t, term arg, term *next, char *reason)
/* log u < v iff u < 10^v */
{ unsigned short f = FUNCTOR(t);
term u,v,left,right;
if(f != '<' && f != '>')
return 1;
v = f == '<' ? ARG(1,t) : ARG(0,t);
left = f == '<' ? ARG(0,t) : ARG(1,t);
if(FUNCTOR(left) != LOG)
return 1;
u = ARG(0,left);
if(FUNCTOR(v) == LOG)
right = ARG(0,v);
else
right = make_power(ten,v);
*next = f == '<' ? lessthan(u,right) : greaterthan(right,u);
HIGHLIGHT(*next);
strcpy(reason, f == '<' ? english(1641) : english(1642));
/* log u < v iff u < 10^v */
/* u > log v iff 10^u > v */
return 0;
}
/*_________________________________________________________________*/
int logrightineq2(term t, term arg, term *next, char *reason)
/* u \le log v iff 10^u \le v */
{ unsigned short f = FUNCTOR(t);
term u,v,left,right;
if(f != LE && f != GE)
return 1;
u = f == LE ? ARG(0,t) : ARG(1,t);
right = f == LE ? ARG(1,t) : ARG(0,t);
if(FUNCTOR(right) != LOG)
return 1;
v = ARG(0,right);
if(FUNCTOR(u) == LOG)
left = ARG(0,u);
else
left = make_power(ten,u);
*next = f == LE ? le(left,v) : ge(v,left);
HIGHLIGHT(*next);
strcpy(reason, f == LE ? english(1643): english(1644));
/* u \le log v iff 10^u \le v */
/* log u \ge v iff u \ge 10^v */
return 0;
}
/*_________________________________________________________________*/
int logleftineq2(term t, term arg, term *next, char *reason)
/* log u \le v iff u \le 10^v */
{ unsigned short f = FUNCTOR(t);
term u,v,left,right;
if(f != LE && f != GE)
return 1;
v = f == LE ? ARG(1,t) : ARG(0,t);
left = f == LE ? ARG(0,t) : ARG(1,t);
if(FUNCTOR(left) != LOG)
return 1;
u = ARG(0,left);
if(FUNCTOR(v) == LOG)
right = ARG(0,v);
else
right = make_power(ten,v);
*next = f == LE ? le(u,right) : ge(right,u);
HIGHLIGHT(*next);
strcpy(reason, f == LE ? english(1645) : english(1646));
/* log u <= v iff u <= 10^v */
/* u >= log v iff 10^u >= v */
return 0;
}
/*______________________________________________________________________*/
/* For the comparison test in infinite series, we need to handle
inequalities like n <= 2^(n/2), which we want to reduce to
n >= M for some constant M. But we don't have an explicit
formula for the constant. So, we introduce a new M.
*/
int polylessexp(term t, term arg, term *next, char *reason)
/* polynomial less than exponential */
{ unsigned short f = FUNCTOR(t);
term left,right,M, c,s,b,deg,p,q;
term n = get_eigenvariable();
int err;
if(f != LE && f != GE && f != '<' && f != '>')
return 1;
right = (f == LE|| f == '<') ? ARG(1,t) : ARG(0,t);
left = (f == LE || f== '<') ? ARG(0,t) : ARG(1,t);
if(! ispolyin(left,n) )
return 1;
if(FUNCTOR(right) == '*')
{ twoparts(right,n,&c,&s);
}
else if(FUNCTOR(right) == '^')
s = right;
else
return 1;
if(FUNCTOR(s) != '^' || !contains(ARG(1,s),FUNCTOR(n)))
return 1;
if(contains(ARG(0,s),FUNCTOR(n)) && !equals(ARG(0,s),n))
return 1;
b = ARG(1,s);
err = check1(positive(ARG(0,s)));
if(err)
return 1;
if(FUNCTOR(b) == '+')
{ leading_term(b,n,zero,&c,°);
err = check1(lessthan(zero,c));
if(err)
return 1;
err = check1(lessthan(zero,deg));
if(err)
return 1;
}
else if(FUNCTOR(b) == '*' || FUNCTOR(b) == '^' || FRACTION(b))
{ twoparts(b,n,&p,&q);
if(!ispolyin(q,n))
return 1;
err = check1(lessthan(zero,p));
if(err)
return 1;
}
else
return 1;
/* OK, input has the right form; operation will succeed */
M = getnewintvar(t,"MmKkCc");
*next = lessthan(M,n);
HIGHLIGHT(*next);
commentbuf(0,"!The new constant stands for a particular large number. The exact value is unimportant.");
strcpy(reason,"exponentials eventually dominate polynomials");
return 0;
}
/*______________________________________________________________________*/
int logpoly(term t, term x)
/* return 1 if t is log(poly in x), or a rational power of such a term. */
{ term u,v;
unsigned short f = FUNCTOR(t);
if(f == '^')
{ u = ARG(0,t);
v = ARG(1,t);
if(NEGATIVE(v))
v = ARG(0,v);
if(INTEGERP(v) || RATIONALP(v))
return logpoly(u,x);
return 0;
}
if(f != LN)
return 0;
u = ARG(0,t);
if(ispolyin(u,x))
return 1;
return 0;
}
/*______________________________________________________________________*/
int algebraic(term t, term x)
/* return 1 if t is an algebraic function of x, 0 if not */
{ term u,v;
unsigned short n;
int i;
unsigned short f = FUNCTOR(t);
if(ispolyin(t,x))
return 1;
if(f == '^')
{ u = ARG(0,t);
v = ARG(1,t);
if(NEGATIVE(v))
v = ARG(0,v);
if(INTEGERP(v) || RATIONALP(v))
return algebraic(u,x);
}
if(f == SQRT || f == '-')
return algebraic(ARG(0,t),x);
if(f == ROOT)
return algebraic(ARG(1,t),x);
if(f != '*' && f != '+' && f != '/')
return 0;
n = ARITY(t);
for(i=0;i<n;i++)
{ if(!algebraic(ARG(i,t),x))
return 0;
}
return 1;
}
/*______________________________________________________________________*/
/* For the comparison test in infinite series, we need to handle
inequalities like (ln n)^2 <= 2(n+1)/n^(1/3), which we want to reduce to
n >= M for some constant M. But we don't have an explicit
formula for the constant. So, we introduce a new M.
*/
int logratbound(term t, term arg, term *next, char *reason)
/* polynomial less than exponential */
{ unsigned short f = FUNCTOR(t);
term left,right,M,u;
term n = get_eigenvariable();
int err;
if(f != LE && f != GE && f != '<' && f != '>')
return 1;
right = (f == LE|| f == '<') ? ARG(1,t) : ARG(0,t);
left = (f == LE || f== '<') ? ARG(0,t) : ARG(1,t);
if(! logpoly(left,n) || !algebraic(right,n) )
return 1;
err = limval(limit(arrow(n,infinity), right), &u);
if(err || !equals(u,infinity))
return 1;
/* OK, input has the right form; operation will succeed */
M = getnewintvar(t,"MmKkCc");
*next = lessthan(M,n);
HIGHLIGHT(*next);
commentbuf(0,"!The new constant stands for a particular large number. The exact value is unimportant.");
strcpy(reason,"algebraic functions dominate logarithms");
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists