Sindbad~EG File Manager
/* M. Beeson, for MathXpert.
Operations to handle the sg function.
Original date 6.19.97
Last modified 2.27.98
1.27.06 Four new operations at the end, and added HIGHLIGHT(*next) where it was missing in a couple of other operations
*/
#include <string.h>
#include "globals.h"
#include "pvalaux.h" /* isinteger, iseven */
#include "errbuf.h"
#include "calc.h"
#include "autosimp.h" /* SetShowStepOperation */
#include "prover.h" /* infer */
#include "cancel.h"
/*___________________________________________________________*/
int sgpos(term t, term arg, term *next, char *reason)
/* sg(x) = 1 if x > 0 */
{ term x;
int err;
if(FUNCTOR(t) != SG)
return 1;
x = ARG(0,t);
err = infer(lessthan(zero,x));
if(err)
return 1;
*next = one;
HIGHLIGHT(*next);
strcpy(reason, english(1928)); /* sg(x) = 1 if x > 0 */
return 0;
}
/*___________________________________________________________*/
int sgneg(term t, term arg, term *next, char *reason)
/* sg(x) = -1 if x < 0 */
{ term x;
int err;
if(FUNCTOR(t) != SG)
return 1;
x = ARG(0,t);
err = infer(lessthan(x,zero));
if(err)
return 1;
*next = one;
HIGHLIGHT(*next);
strcpy(reason, english(1929)); /* sg(x) = -1 if x < 0 */
return 0;
}
/*__________________________________________________________*/
int sgzero(term t, term arg, term *next, char *reason)
/* sg(0) = 0 */
{ if(FUNCTOR(t) != SG)
return 1;
if(!ZERO(ARG(0,t)))
return 1;
*next = zero;
HIGHLIGHT(*next);
strcpy(reason, "sg(0) = 0");
return 0;
}
/*___________________________________________________________*/
int sgodd(term t, term arg, term *next, char *reason)
/* sg(-x) = -sg(x) */
{ term x;
if(FUNCTOR(t) != SG)
return 1;
if(!NEGATIVE(ARG(0,t)))
return 1;
x = ARG(0,ARG(0,t));
*next = tnegate(sg1(x));
strcpy(reason, "sg(-x) = -sg(x)");
HIGHLIGHT(*next);
return 0;
}
/*___________________________________________________________*/
int sgodd2(term t, term arg, term *next, char *reason)
/* -sg(x) = sg(-x) */
{ term x;
if(!NEGATIVE(t) || FUNCTOR(ARG(0,t)) != SG)
return 1;
x = ARG(0,ARG(0,t));
*next = sg1(tnegate(x));
HIGHLIGHT(*next);
strcpy(reason, "-sg(x) = sg(-x)");
return 0;
}
/*___________________________________________________________*/
int sgabs1(term t, term arg, term *next, char *reason)
/* sg(x) = abs(x)/x (x nonzero) */
{ term x;
int err;
if(FUNCTOR(t) != SG)
return 1;
x = ARG(0,t);
err = infer(nonzero(x));
if(err)
return 1;
*next = make_fraction(abs1(x),x);
HIGHLIGHT(*next);
strcpy(reason,english(1930));
/* sg(x)=|x|/x (x nonzero) */
return 0;
}
/*___________________________________________________________*/
int sgabs2(term t, term arg, term *next, char *reason)
/* sg(x) = x/abs(x) (x nonzero) */
{ term x;
int err;
if(FUNCTOR(t) != SG)
return 1;
x = ARG(0,t);
err = infer(nonzero(x));
if(err)
return 1;
*next = make_fraction(x,abs1(x));
HIGHLIGHT(*next);
strcpy(reason,english(1931));
/* sg(x)=x/|x| (x nonzero) */
return 0;
}
/*___________________________________________________________*/
int abssg(term t, term arg, term *next, char *reason)
/* abs(x) = x sg(x) */
{ term x;
if(FUNCTOR(t) != ABSFUNCTOR)
return 1;
copy(ARG(0,t),&x);
*next = product(ARG(0,t), sg1(x));
HIGHLIGHT(*next);
strcpy(reason, "|x| = x sgn x");
return 0;
}
/*___________________________________________________________*/
int sgevenpower(term t, term arg, term *next, char *reason)
/* sg(x)^(2n) = 1, also sg(x)^(even/odd) */
{ term power;
if(FUNCTOR(t) != '^' || FUNCTOR(ARG(0,t)) != SG)
return 1;
power = ARG(1,t);
if(isinteger(power) && iseven(power))
;
else if(FRACTION(power) && isodd(ARG(1,power)) && iseven(ARG(0,power)))
;
else if(NEGATIVE(power) && FRACTION(ARG(0,power)) &&
isodd(ARG(1,ARG(0,power))) && iseven(ARG(0,ARG(0,power)))
)
;
else
return 1;
*next = one;
HIGHLIGHT(*next);
strcpy(reason,"$sg(x)^(2n) = 1$");
return 0;
}
/*___________________________________________________________*/
int sgoddpower(term t, term arg, term *next, char *reason)
/* sg(x)^(2n+1) = sg(x), also sg(x)^odd/odd */
{ term power;
if(FUNCTOR(t) != '^' || FUNCTOR(ARG(0,t)) != SG)
return 1;
power = ARG(1,t);
if(isinteger(power) && isodd(power))
;
else if(FRACTION(power) && isodd(ARG(1,power)) && isodd(ARG(0,power)))
;
else if(NEGATIVE(power) && FRACTION(ARG(0,power)) &&
isodd(ARG(1,ARG(0,power))) && iseven(ARG(0,ARG(0,power)))
)
;
else
return 1;
*next = sg1(ARG(0,ARG(0,t)));
HIGHLIGHT(*next);
strcpy(reason,"sg(x)^(2n+1) = sg(x)");
return 0;
}
/*___________________________________________________________*/
int sgrecip(term t, term arg, term *next, char *reason)
/* 1/sg(x) = sg(x) */
{ term denom,newdenom;
unsigned short n;
int i,j;
if(!FRACTION(t))
return 1;
denom = ARG(1,t);
if(FUNCTOR(denom) == SG)
*next = denom;
else if(FUNCTOR(denom) == '*')
{ n = ARITY(denom);
for(i=0;i<n;i++)
{ if(FUNCTOR(ARG(i,denom)) == SG)
break;
}
if(i==n)
return 1;
if(n == 2)
newdenom = ARG(i ? 0 : 1, denom);
else
{ newdenom = make_term('*',(unsigned short)(n-1));
for(j=0;j<n-1;j++)
ARGREP(newdenom,j, ARG(j < i ? j : j+1, denom));
}
*next = product(ARG(i,denom),make_fraction(ARG(0,t),newdenom));
}
else
return 1;
HIGHLIGHT(*next);
strcpy(reason,"1/sg(x) = sg(x)");
return 0;
}
/*___________________________________________________________*/
int difsg(term t, term arg, term *next, char *reason)
/* d/dx sg(u) = 0 (u nonzero) */
{ term u;
int err;
if(FUNCTOR(t) != DIFF)
return 0;
u = ARG(0,t);
err = infer(ne(u,zero));
if(err)
return 1;
*next = zero;
strcpy(reason, english(1932));
/* d/dx sg(u) = 0 (u nonzero) */
return 0;
}
/*___________________________________________________________*/
int intsg(term t, term arg, term *next, char *reason)
/* integral sg(x) = x sg(x) */
{ term x;
if(FUNCTOR(t) != INTEGRAL)
return 1;
if(FUNCTOR(ARG(0,t)) != SG)
return 1;
x = ARG(1,t);
if(!equals(ARG(0,ARG(0,t)),x))
return 1;
*next = product(x,sg1(x));
HIGHLIGHT(*next);
strcpy(reason,"$\\int sg(x) = x sg(x)$");
return 0;
}
/*___________________________________________________________*/
int sgint(term t, term arg, term *next, char *reason)
/* integral(sg(u)v,x) = sg(u) integral(v,x) if u is nonzero */
{ term u,v,w,q,x;
int i,j,err;
unsigned short n;
if(FUNCTOR(t) != INTEGRAL)
return 1;
if(ARITY(t) != 2)
return 1; /* this only works on indefinite integrals */
x = ARG(1,t);
if(FRACTION(ARG(0,t)))
w = ARG(0,ARG(0,t));
else
w = ARG(0,t);
if(FUNCTOR(w) == SG)
{ u = ARG(0,w);
v = one;
}
else if(FUNCTOR(w) == '*')
{ /* search for SG among the factors */
n = ARITY(w);
for(i=0;i<n;i++)
{ if(FUNCTOR(ARG(i,w)) == SG)
{ u = ARG(0,ARG(i,w));
break;
}
}
if(i==n)
return 1;
if(n == 2)
v = ARG(i ? 0 : 1, w);
else
{ v = make_term('*',(unsigned short)(n-1));
for(j=0;j<n-1;j++)
ARGREP(v,j,ARG(j<i? j : j+1,w));
}
}
else
return 1;
err = check1(ne(u,zero));
if(err)
{ errbuf(0, english(1934));
/* Expression inside sgn may be zero. */
return 1;
}
if(FRACTION(ARG(0,t)))
q = make_fraction(v,ARG(1,ARG(0,t)));
else
q = v;
*next = product(sg1(u),integral(q,x));
HIGHLIGHT(*next);
strcpy(reason,english(1933));
/* \int sg(u)v dx=sg(u) \int v dx (u nonzero) */
return 0;
}
/*___________________________________________________________*/
int sgassumepos(term t, term arg, term *next, char *reason)
/* sg(x) = 1 assuming x > 0 */
{ term x;
int err;
if(FUNCTOR(t) != SG)
return 1;
x = ARG(0,t);
err = infer(le(x,zero));
if(!err)
{ errbuf(0, english(1935));
/* The expression inside the sgn function cannot be positive. */
return 1;
}
assume(lessthan(zero,x));
*next = x;
HIGHLIGHT(*next);
strcpy(reason, english(1936));
/* sg(x)=1 assuming x>0 */
return 0;
}
/*___________________________________________________________*/
int sgassumeneg(term t, term arg, term *next, char *reason)
/* sg(x) = -1 assuming x < 0 */
{ term x;
int err;
if(FUNCTOR(t) != SG)
return 1;
x = ARG(0,t);
err = infer(le(zero,x));
if(!err)
{ errbuf(0, english(1937));
/* The expression inside the sgn function cannot be negative. */
return 1;
}
assume(lessthan(x,zero));
*next = x;
HIGHLIGHT(*next);
strcpy(reason, english(1938));
/* sg(x)=-1 assuming x<0 */
return 0;
}
/*_________________________________________________________________*/
static int sgprod_aux(term u, term *ans, int *sign)
/* u is a product. Throw out the factors whose sign can be
determined and put the rest in *ans. Return in *sign either
+1 or -1, depending if an even or odd number of negative
factors were discarded. Return 1 if there are no factors
to discard, in which case *ans is garbage; otherwise return
0 for success.
*/
{ unsigned short n = ARITY(u);
int k,i,flag,err;
term p,v;
k = 0;
p = make_term('*',n);
flag = 0;
for(i=0;i<n;i++)
{ v = ARG(i,u);
if(obviously_positive(v))
continue;
err = infer(lessthan(zero,v));
if(!err)
continue;
err = infer(lessthan(v,zero));
if(!err)
{ ++flag;
continue;
}
ARGREP(p,k,v);
++k;
}
if(k==n)
{ RELEASE(p);
return 1;
}
*sign = (flag & 1) ? -1 : 1;
if(k==0)
{ *ans = one;
RELEASE(p);
return 0;
}
if(k == 1)
{ *ans = ARG(0,p);
RELEASE(p);
return 0;
}
SETFUNCTOR(p,'*',k);
*ans = p;
return 0;
}
/*______________________________________________________________*/
int sgprod2(term t, term arg, term * next, char *reason)
/* sg(au) = -sg(u) if a < 0 */
/* Not called in auto mode */
{ return sgprod1(t, arg, next, reason);
}
/*______________________________________________________________*/
int sgprod1(term t, term arg, term * next, char *reason)
/* sg(au) = sg(u) if a > 0 */
/* Also does the work of sgprod2,
sg(au) = -sg(u) if a < 0 */
{ term u,v;
int sign;
int err;
if(FUNCTOR(t) != SG)
return 1;
u = ARG(0,t);
if(FUNCTOR(u) != '*')
return 1;
err = sgprod_aux(u,&v,&sign);
if(err)
return 1;
if(ONE(v))
{ *next = sign > 0 ? one : minusone;
HIGHLIGHT(*next);
strcpy(reason, sign > 0 ? english(1928) : english(1929));
/* sg(x) = 1 if x > 0 */
/* sg(x) = -1 if x < 0 */
SetShowStepOperation(sign > 0 ? sgpos : sgneg);
return 0;
}
if(sign > 0)
{ *next = sg1(v);
HIGHLIGHT(*next);
strcpy(reason, english(1940));
/* sg(ax) = sg(x) if a>0 */
return 0;
}
else
{ *next = tnegate(sg1(v));
HIGHLIGHT(*next);
strcpy(reason,english(1941));
/* sg(ax) = -sg(x) if a<0 */
SetShowStepOperation(sgprod2);
return 0;
}
}
/*______________________________________________________________*/
int sgfract1(term t, term arg, term * next, char *reason)
/* sg(au/b) = sg(u) if a/b > 0 */
/* also does sg(au/b) = -sg(u) if a/b < 0 */
{ term u,v,num,denom;
int err,sign1,sign2,sign;
if(FUNCTOR(t) != SG)
return 1;
if(!FRACTION(ARG(0,t)))
return 1;
num = ARG(0,ARG(0,t));
denom = ARG(1,ARG(0,t));
if(FUNCTOR(num) == '*')
{ err = sgprod_aux(num,&u,&sign1);
if(err)
u = num;
}
else if(!infer(lessthan(zero,num)))
{ u = one;
sign1 = 1;
}
else if(!infer(lessthan(num,zero)))
{ u = one;
sign1 = -1;
}
else
{ u = num;
sign1 = 1;
}
if(FUNCTOR(denom) == '*')
{ err = sgprod_aux(denom,&v,&sign2);
if(err)
v = denom;
}
else if(!infer(le(zero,denom)))
{ v = one;
sign2 = 1;
}
else if(!infer(le(denom,zero)))
{ v = one;
sign2 = -1;
}
else
{ v = denom;
sign2 = 1;
}
if(equals(u,num) && equals(v,denom))
return 1;
sign = sign1 * sign2;
if(sign > 0)
{ *next = ONE(v) ? sg1(u) : sg1(make_fraction(u,v));
HIGHLIGHT(*next);
strcpy(reason, english(1942));
/* sg(ax/b)=sg(x), a/b>0 */
return 0;
}
else
{ *next = ONE(v) ? tnegate(sg1(u)) : tnegate(sg1(make_fraction(u,v)));
HIGHLIGHT(*next);
strcpy(reason, english(1943));
/* sg(ax/b)=-sg(x),a/b<0 */
SetShowStepOperation(sgfract2);
return 0;
}
}
/*______________________________________________________________*/
int sgfract2(term t, term arg, term * next, char *reason)
/* sg(au/b) = - sg(u) if a/b < 0 */
{ return sgfract1(t,arg,next,reason);
}
/*______________________________________________________________*/
int sgpower(term t, term arg, term * next, char *reason)
/* sg(x^(2n+1)) = sg(x) */
{ term u,power;
if(FUNCTOR(t) != SG)
return 1;
u = ARG(0,t);
if(FUNCTOR(u) != '^')
return 1;
power = ARG(1,u);
if(
(isinteger(power) && isodd(power)) ||
(FRACTION(power) && isinteger(ARG(0,power)) &&
isinteger(ARG(1,power)) && isodd(ARG(0,power)) &&
isodd(ARG(1,power))
)
)
{ *next = sg1(ARG(0,u));
HIGHLIGHT(*next);
strcpy(reason,"sg(x^(2n+1)) = sg(x)");
return 0;
}
return 1;
}
/*______________________________________________________________*/
int sgrecip2(term t, term arg, term * next, char *reason)
/* sg(1/u) = sg(u) */
{ term u;
if(FUNCTOR(t) != SG)
return 1;
u = ARG(0,t);
if(!FRACTION(u))
return 1;
if(!ONE(ARG(0,u)))
return 1;
*next = sg1(ARG(1,u));
HIGHLIGHT(*next);
strcpy(reason, "sg(1/u) = sg(u)");
return 0;
}
/*______________________________________________________________*/
int sgrecip3(term t, term arg, term * next, char *reason)
/* sg(c/u) = sg(u) if c > 0 */
{ term u;
if(FUNCTOR(t) != SG || !FRACTION(ARG(0,t)))
return 1;
u = ARG(0,t);
if(!obviously_positive(ARG(0,u)))
return 1;
*next = sg1(ARG(1,u));
HIGHLIGHT(*next);
strcpy(reason, "sg(c/u) = sg(u) (c>0)");
return 0;
}
/*______________________________________________________________*/
int sgtoabs(term t, term arg, term * next, char *reason)
/* u sg(u) = |u| */
{ term v,w,cancelled, rest;
int i,n,flag = -1;
if(FUNCTOR(t) != '*')
return 1;
n = ARITY(t);
for(i=0;i<n;i++)
{ if(FUNCTOR(ARG(i,t)) == SG)
{ flag = i;
v = ARG(0,ARG(i,t));
}
}
if(flag == -1)
return 1;
if(n == 2)
{ if(equals(ARG( flag ? 0 : 1, t),v))
{ *next = abs1(v);
goto out;
}
return 1;
}
w = make_term('*',n-1);
for(i=0;i<n-1;i++)
{ if(i==flag) continue;
if(i<flag)
ARGREP(w,i,ARG(i,t));
else
ARGREP(w,i,ARG(i+1,t));
}
if(!cancel(w,v,&cancelled,&rest))
{ if(ONE(rest))
*next = abs1(v);
else
*next = product(rest,abs1(v));
}
out:
HIGHLIGHT(*next);
strcpy(reason, "u sg(u) = |u|");
return 0;
}
/*______________________________________________________________*/
int abstimessg(term t, term arg, term * next, char *reason)
/* |u| sg(u) = u */
{ term v,w;
int i,n,flag = -1;
if(FUNCTOR(t) != '*')
return 1;
n = ARITY(t);
for(i=0;i<n;i++)
{ if(FUNCTOR(ARG(i,t)) == SG)
{ flag = i;
v = ARG(0,ARG(i,t));
}
}
if(flag == -1)
return 1;
if(n > 2)
return 1;
w = ARG(flag ? 0 : 1, t);
if(FUNCTOR(w) == ABSFUNCTOR && equals(v,ARG(0,w)))
{ *next = v;
HIGHLIGHT(*next);
strcpy(reason, "|u| sg(u) = u");
return 0;
}
return 1;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists