Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/trigcalc/
Upload File :
Current File : /usr/home/beeson/MathXpert/trigcalc/sg.c

/* 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