Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/series/
Upload File :
Current File : /usr/home/beeson/MathXpert/series/rseries.c

/* infinite series "reversal" operations for summing series */
/* M. Beeson, for Mathpert */
/*
1.12.99 original date
1.13.99 last modified
6.5.13 corrected geomseries_aux
6.11.13  added && seminumerical(ARG(0,n) in four places prior to SetShowStepOperation(reversecollectpowers)
8.20.13 corrected sign in lnseriesrev in rseries.c
*/

#include <string.h>
#include <assert.h>

#include "globals.h"
#include "series.h"
#include "match.h"
#include "prover.h"  /*  getnewintvar1 */
#include "symbols.h"
#include "errbuf.h"
#include "psubst.h"
#include "pvalaux.h"  /* twoparts */
#include "ssolve.h"
#include "islinear.h"
#include "cancel.h"
#include "pathtail.h"
#include "autosimp.h"  /* SetShowStepOperation */
#include "deval.h"     /* seminumerical */
/*_______________________________________________________________*/
#if 0
int oneminusxseriesrev(term t, term arg, term *next, char *reason)
/* 1 + x + x^2 + ... = 1/(1-x) */
{ term u,n,lo,x;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(FUNCTOR(u) != '^')
     return 1;
  if(!ZERO(lo))
     return 1;
  x = ARG(0,u);
  if(contains(x,FUNCTOR(n)))
     return 1;
  *next = reciprocal(sum(one,tnegate(x)));
  HIGHLIGHT(*next);
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum(x^n,n,0,infinity) = 1/(1-x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"1+x+x^2+... = 1/(1-x)");
  else
     strcpy(reason,"1+x+...+x^n... =      1/(1-x)");
  return 0;
}
#endif
/*______________________________________________________________*/
static int geomseries_aux(term t, term arg, term *next, char *reason)
/* bring a series into geometric form using some other operator,
and call SetShowStepOperator and set_pathtail */
{ term u,v,n,num,denom,temp,base,exp;
  int err;
  unsigned short path[10];
  n = ARG(1,t);
  u = ARG(0,t);
  if(FUNCTOR(u) == '^' && NEGATIVE(ARG(1,u)))
     { err = eliminatenegexp(u,arg,&v,reason);
       *next = indexedsum(v,n,ARG(2,t),ARG(3,t));
       path[0] = SUM;
       path[1] = 1;
       path[2] = 0;
       set_pathtail(path);
       SetShowStepOperation(eliminatenegexp);
       return 0;
     }
  if(FRACTION(u))
     {  denom = ARG(1,u);
        num  = ARG(0,u);
        if(FUNCTOR(denom) == '^')
           { base = ARG(0,denom);
             exp = ARG(1,denom);
           }    
     }
  if(FRACTION(u) && ONE(ARG(0,u)) &&          /* e.g.   1/2^n */
     FUNCTOR(ARG(1,u)) == '^'  && !contains(ARG(0,ARG(1,u)),FUNCTOR(n))  /* reject 1/n^n for example  */
    )
    { if(equals(exp,n))
         { u = make_power(reciprocal(base),n);  /* e.g. (1/2)^n */
           return oneminusxseriesrev(indexedsum(u,n,ARG(2,t),ARG(3,t)),arg,next,reason);
         }
      else if(FUNCTOR(exp) == '+' && is_linear_in(exp,n))
         { /* eg. 1/2^(n+3), convert this to 1/(2^n 2^3) */
           err = reversecollectpowers(ARG(1,u),arg,&temp,reason);
           if(err)
              return 1;
           PROTECT(temp);
           *next = sigma(reciprocal(temp),n,ARG(2,t),ARG(3,t));
           SetShowStepOperation(reversecollectpowers);
           path[0] = SUM;
           path[1] = 1;
           path[2] = '/';
           path[3] = 2;
           path[4] = 0;
           set_pathtail(path);
           return 0;
         }
      else if(FRACTION(exp))  /* e.g. 1/2^(n/2) */
         { if(equals(ARG(0,exp),n) && INTEGERP(ARG(1,exp)))
              { err = pulloutdenom(exp,arg,&temp,reason);
                if(err)
                   return 1;
                *next = sigma(reciprocal(make_power(base,temp)),n,ARG(2,t),ARG(3,t));
                SetShowStepOperation(pulloutdenom);
                path[0] = SUM;
                path[1] = 1;
                path[2] = '/';
                path[3] = 2;
                path[4] = '^';
                path[5] = 2;
                path[6] = 0;
                set_pathtail(path);
                return 0;
              }
           else if(is_linear_in(ARG(0,exp),n) && INTEGERP(ARG(1,exp)))
              { err = pulloutrational(ARG(1,ARG(1,u)),arg,&temp,reason);
                if(err)
                   return 1;
                *next = sigma(reciprocal(make_power(base,temp)),n,ARG(2,t),ARG(3,t));
                SetShowStepOperation(pulloutrational);
                path[0] = SUM;
                path[1] = 1;
                path[2] = '/';
                path[3] = 2;
                path[4] = '^';
                path[5] = 2;
                path[6] = 0;
                set_pathtail(path);
                return 0;
              }
         }
    }
  if(FRACTION(u) &&           /* e.g.   2^(n+1)/5^n */
     FUNCTOR(num) == '^' && FUNCTOR(ARG(1,num)) == '+' && is_linear_in(ARG(1,num),n) && !contains(ARG(0,num),FUNCTOR(n)) &&
     FUNCTOR(denom) == '^' && is_linear_in(exp,n) && !contains(base,FUNCTOR(n))
    )
     { err = reversecollectpowers(num,arg,&temp,reason);
       if(err)
          return 1;
       PROTECT(temp);
       *next = sigma(make_fraction(temp,denom),n,ARG(2,t),ARG(3,t));
       SetShowStepOperation(reversecollectpowers);
       path[0] = SUM;
       path[1] = 1;
       path[2] = '/';
       path[3] = 1;
       path[4] = 0;
       set_pathtail(path);
       return 0;
     }
  if(FRACTION(u) &&   /* e^(n pi_term)/a^(cn) = (e^pi_term)^n/a^(cn)  */
     FUNCTOR(num) == '^' &&
     !contains(ARG(0,num),FUNCTOR(n)) &&
     FUNCTOR(ARG(1,num)) == '*' && ARITY(ARG(1,num)) == 2 &&
     equals(ARG(1,ARG(1,num)),n) &&
     !contains(ARG(0,ARG(1,num)),FUNCTOR(n)) &&
     FUNCTOR(denom) == '^' &&
     !contains(base,FUNCTOR(n)) &&
     is_linear_in(exp,n)
    )
     { err = reversepowertopower1(ARG(0,u),arg,&v,reason);
       if(!err)
          { path[0] = SUM;
            path[1] = 1;
            path[2] = '/';
            path[3] = 1;
            path[4] = 0;
            set_pathtail(path);
            SetShowStepOperation(reversepowertopower1);
            *next = indexedsum(make_fraction(v,ARG(1,u)),n,ARG(2,t),ARG(3,t));
            return 0;
          }
     }
  /* Now the same with the args of the product in the exponent of the numerator in the other order. */
  if(FRACTION(u) &&   /* e^(npi)/a^(cn) = (e^pi_term)^n/a^(cn)  */
     FUNCTOR(num) == '^' &&
     !contains(ARG(0,num),FUNCTOR(n)) &&
     FUNCTOR(ARG(1,num)) == '*' && ARITY(ARG(1,num)) == 2 &&
     equals(ARG(1,ARG(1,ARG(0,u))),n) &&
     !contains(ARG(2,ARG(1,num)),FUNCTOR(n)) &&
     FUNCTOR(ARG(1,u)) == '^' &&
     !contains(base,FUNCTOR(n)) &&
     is_linear_in(exp,n)
    )
     { err = reversepowertopower2(num,arg,&v,reason);
       if(!err)
          { path[0] = SUM;
            path[1] = 1;
            path[2] = '/';
            path[3] = 1;
            path[4] = 0;
            SetShowStepOperation(reversepowertopower2);
            *next = indexedsum(make_fraction(v,denom),n,ARG(2,t),ARG(3,t));
            return 0;
          }
     }



  if(FRACTION(u) &&     /*  1/a^2n  =>  1/((a^2)^n) ;  also  a^n/e^(npi) = a^n/(e^pi_term)^n  */
     (ONE(num) || (FUNCTOR(num) == '^' && equals(ARG(1,ARG(0,u)),n) && !contains(ARG(0,ARG(0,u)),FUNCTOR(n)))) &&
     FUNCTOR(denom) == '^' &&
     FUNCTOR(exp) == '*' &&
     ARITY(exp) == 2 &&
     equals(ARG(1,exp),n) &&
     !contains(ARG(0,exp),FUNCTOR(n))
    )
     { err = reversepowertopower1(denom,arg,&v,reason);
       if(!err)
          { path[0] = SUM;
            path[1] = 1;
            path[2] = '/';
            path[3] = 2;
            path[4] = 0;
            set_pathtail(path);
            SetShowStepOperation(reversepowertopower1);
            *next = indexedsum(make_fraction(num,v),n,ARG(2,t),ARG(3,t));
            return 0;
          }
     }
  /* Now the same with the args in the exponent in the other order */
  if(FRACTION(u) &&     /*  1/a^2n  =>  1/((a^2)^n) ;  also  a^n/e^(npi) = a^n/(e^pi_term)^n  */
     (ONE(num) || (FUNCTOR(num) == '^' && equals(ARG(1,num),n) && !contains(ARG(0,num),FUNCTOR(n)))) &&
     FUNCTOR(denom) == '^' &&
     FUNCTOR(exp) == '*' &&
     ARITY(exp) == 2 &&
     equals(ARG(0,exp),n) &&
     !contains(ARG(1,exp),FUNCTOR(n))
    )
     { err = reversepowertopower2(denom,arg,&v,reason);
       if(!err)
          { path[0] = SUM;
            path[1] = 1;
            path[2] = '/';
            path[3] = 2;
            path[4] = 0;
            set_pathtail(path);
            SetShowStepOperation(reversepowertopower2);
            *next = indexedsum(make_fraction(num,v),n,ARG(2,t),ARG(3,t));
            return 0;
          }
     }
  if(FRACTION(u) && ONE(num) &&    /*  1/a^2(n+3)  =>  1/(a^(4n+6)  */
     FUNCTOR(denom) == '^' &&
     FUNCTOR(exp) == '*' &&
     ARITY(exp) == 2 &&
     is_linear_in(ARG(1,exp),n) &&
     !contains(ARG(0,exp),FUNCTOR(n))
    )
     { err = distriblaw(ARG(1,denom),arg,&v,reason);
       if(err)
          return 1;
       path[0] = SUM;
       path[1] = 1;
       path[2] = '/';
       path[3] = 2;
       path[4] = '^';
       path[5] = 2;
       path[6] = 0;
       set_pathtail(path);
       SetShowStepOperation(distriblaw);
       *next = indexedsum(reciprocal(make_power(base,v)),n,ARG(2,t),ARG(3,t));
       return 0;
     }
  if(FRACTION(u))
     { if(FUNCTOR(num) == '^' && equals(ARG(1,num),n) &&
          FUNCTOR(denom) == '^' && equals(ARG(1,denom),n)
         )
          { err = poweroutoffraction(u,arg,&v,reason);
            if(err)
               return 1;
            SetShowStepOperation(poweroutoffraction);
            path[0] = SUM;
            path[1] = 1;
            path[2] = 0;
            set_pathtail(path);
            PROTECT(v);
            *next = indexedsum(v,n,ARG(2,t),ARG(3,t));
            return 0;
          }
     }
  return 1;
}

/*______________________________________________________________*/
int oneminusxseriesrev(term t, term arg, term *next, char *reason)
/* sum(x^n,n,0,infinity) = 1/(1-x) */
{ term u,n,temp,v,test;
  int err;
  unsigned short path[7];
  if(FUNCTOR(t) != SUM || ARITY(t) < 4 || !equals(ARG(3,t),infinity))
     return 1;
  if(ONE(ARG(2,t)))
     return 1;
  n = ARG(1,t);
  if(!ISATOM(n))
     return 1;
  u = ARG(0,t);
  if(!ZERO(ARG(2,t)))
     { /* shift the index variable till it is zero */
       /* But first make sure this is really a geometric series */
       subst(sum(n,one),n,u,&test);
       polyval(make_fraction(test,u),&v);
       if(contains(v,FUNCTOR(n)))
          return 1;  /* not geometric */
       err = seriesaddindex(t,ARG(2,t),next,reason);
       if(err)
          return 1;
       SetShowStepOperation(seriesaddindex);
       return 0;
     }
  err = geomseries_aux(t,arg,next,reason);
  if(!err)
     return 0;
  if(FUNCTOR(u) != '^')
     return 1;
  if(!equals(ARG(1,u),n) && seminumerical(ARG(0,u)))
     { /* example, (1/2)^(n+3)  */
       if(FUNCTOR(ARG(1,u)) != '+' || !is_linear_in(ARG(1,u),n))
          return 1;
       err = reversecollectpowers(u,zero,&temp,reason);
       if(err)
          return 1;
       PROTECT(temp);
       *next = sigma(temp,ARG(1,t),ARG(2,t),ARG(3,t));
       SetShowStepOperation(reversecollectpowers);
       path[0] = SUM;
       path[1] = 1;
       path[2] = 0;
       set_pathtail(path);
       return 0;
     }
  if(!equals(ARG(1,u),n))
      return 1;
  *next = make_fraction(one,sum(one,tnegate(ARG(0,u))));
  HIGHLIGHT(*next);
  if(ARITY(t)== 4)
     strcpy(reason,"$$sum(x^n,n,0,infinity) = 1/(1-x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"1+x+x^2+...= 1/(1-x)");
  else
     strcpy(reason, "1+x+...+x^n = 1/(1-x)");
  return 0;
}

/*______________________________________________________________*/
int xoveroneminusxseriesrev(term t, term arg, term *next, char *reason)
/* sum(x^n,n,1,infinity) = x/(1-x) */
{ term u,n,temp;
  unsigned short path[7];
  int err;
  if(FUNCTOR(t) != SUM || ARITY(t) < 4 || !equals(ARG(3,t),infinity))
     return 1;
  if(!ONE(ARG(2,t)))
     return 1;
  n = ARG(1,t);
  if(!ISATOM(n))
     return 1;
  u = ARG(0,t);
  if(FRACTION(u) && ONE(ARG(0,u)) &&          /* e.g.   1/2^n */
     FUNCTOR(ARG(1,u)) == '^'
    )
    { if(equals(ARG(1,ARG(1,u)),n))
         u = make_power(reciprocal(ARG(0,ARG(1,u))),n);  /* e.g. (1/2)^n */
      else if(is_linear_in(ARG(1,ARG(1,u)),n) && seminumerical(ARG(0,u)))
         { /* eg. 1/2^(n+3), convert this to 1/(2^n 2^3) */
           err = reversecollectpowers(ARG(1,u),arg,&temp,reason);
           if(err)
              return 1;
           PROTECT(temp);
           *next = sigma(reciprocal(temp),n,ARG(2,t),ARG(3,t));
           SetShowStepOperation(reversecollectpowers);
           path[0] = SUM;
           path[1] = 1;
           path[2] = '/';
           path[3] = 2;
           path[4] = 0;
           set_pathtail(path);
           return 0;
         }
      else
         return 1;
    }
  if(FUNCTOR(u) != '^')
     return geomseries_aux(t,arg,next,reason);
  if(!equals(ARG(1,u),n))
     { /* example, (1/2)^(n+3)  */
       if(FUNCTOR(ARG(1,u)) != '+' || !is_linear_in(ARG(1,u),n))
          return 1;
       err = reversecollectpowers(u,zero,&temp,reason);
       if(err)
          return 1;
       PROTECT(temp);
       *next = sigma(temp,ARG(1,t),ARG(2,t),ARG(3,t));
       SetShowStepOperation(reversecollectpowers);
       path[0] = SUM;
       path[1] = 1;
       path[2] = 0;
       set_pathtail(path);
       return 0;
     }
  *next = make_fraction(ARG(0,u),sum(one,tnegate(ARG(0,u))));
  HIGHLIGHT(*next);
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum(x^n,n,1,infinity)=1/(1-x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"x+x^2+x^3+...= x/(1-x)");
  else
     strcpy(reason, "x+x^2+...+x^n = x/(1-x)");
  return 0;
}
/*______________________________________________________________*/
int xoveroneminusxseries2rev(term t, term arg, term *next, char *reason)
/* sum(x^n,n,1,infinity) = x/(1-x) */
{ return xoveroneminusxseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int xoveroneminusxseries3rev(term t, term arg, term *next, char *reason)
/* sum(x^n,n,1,infinity) = x/(1-x) */
{ return xoveroneminusxseriesrev(t,arg,next,reason);
}

/*______________________________________________________________*/
int xoveroneplusxseriesrev(term t, term arg, term *next, char *reason)
/* sum((-1)^(n+1)x^n,n,1,infinity) = x/(1+x) */
{ term u,n,temp;
  unsigned short path[9];
  int err;
  if(FUNCTOR(t) != SUM || ARITY(t) < 4 || !equals(ARG(3,t),infinity))
     return 1;
  if(!ONE(ARG(2,t)))
     return 1;
  n = ARG(1,t);
  if(!ISATOM(n))
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
     FUNCTOR(ARG(0,u)) == '^' &&
     equals(ARG(0,ARG(0,u)),minusone) &&
     FUNCTOR(ARG(1,ARG(0,u))) == '+' &&
     (
       (equals(ARG(0,ARG(1,ARG(0,u))),n) && ONE(ARG(1,ARG(1,ARG(0,u))))) ||
       (equals(ARG(0,ARG(1,ARG(0,u))),n) && equals(ARG(1,ARG(1,ARG(0,u))),minusone)) ||
       (equals(ARG(1,ARG(1,ARG(0,u))),n) && ONE(ARG(0,ARG(1,ARG(0,u)))))
     )
    )
     u = ARG(1,u);
  else if(FUNCTOR(u) == '^' && NEGATIVE(ARG(0,u)))
     u = make_power(ARG(0,ARG(0,u)),ARG(1,u));

  if(FRACTION(u) && ONE(ARG(0,u)) &&          /* e.g.   1/2^n */
     FUNCTOR(ARG(1,u)) == '^'
    )
    { if(equals(ARG(1,ARG(1,u)),n))
         u = make_power(reciprocal(ARG(0,ARG(1,u))),n);  /* e.g. (1/2)^n */
      else if(is_linear_in(ARG(1,ARG(1,u)),n)&& seminumerical(ARG(0,u)))
         { /* eg. 1/2^(n+3), convert this to 1/(2^n 2^3) */
           err = reversecollectpowers(ARG(1,u),arg,&temp,reason);
           if(err)
              return 1;
           PROTECT(temp);
           *next = sigma(reciprocal(temp),n,ARG(2,t),ARG(3,t));
           SetShowStepOperation(reversecollectpowers);
           path[0] = SUM;
           path[1] = 1;
           path[2] = FUNCTOR(ARG(0,t));
           path[3] = path[2] == '*' ? 2 : 1;
           path[4] = '/';
           path[5] = 2;
           path[6] = 0;
           set_pathtail(path);
           return 0;
         }
      else
         return 1;
    }
  if(FUNCTOR(u) != '^')
     return geomseries_aux(t,arg,next,reason);
  if(!equals(ARG(1,u),n) && seminumerical(ARG(0,u)))
     { /* example, (1/2)^(n+3)  */
       if(FUNCTOR(ARG(1,u)) != '+' || !is_linear_in(ARG(1,u),n))
          return 1;
       err = reversecollectpowers(u,zero,&temp,reason);
       if(err)
          return 1;
       PROTECT(temp);
       *next = sigma(temp,ARG(1,t),ARG(2,t),ARG(3,t));
       SetShowStepOperation(reversecollectpowers);
       path[0] = SUM;
       path[1] = 1;
       path[2] = FUNCTOR(ARG(0,t));
       path[3] = path[2] == '*' ? 2 : 1;
       path[4] = 0;
       set_pathtail(path);
       return 0;
     }
  *next = make_fraction(ARG(0,u),sum(one,tnegate(ARG(0,u))));
  HIGHLIGHT(*next);
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum(x^n,n,1,infinity)=1/(1-x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"x+x^2+x^3+...= x/(1-x)");
  else
     strcpy(reason, "x+x^2+...+x^n = x/(1-x)");
  return 0;
}

/*______________________________________________________________*/
int xoveroneplusxseries2rev(term t, term arg, term *next, char *reason)
{ return xoveroneplusxseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int xoveroneplusxseries3rev(term t, term arg, term *next, char *reason)
/* sum(x^n,n,1,infinity) = x/(1-x) */
{ return xoveroneplusxseriesrev(t,arg,next,reason);
}

/*_______________________________________________________________*/
int oneminusxseries2rev(term t, term arg, term *next, char *reason)
{ return oneminusxseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int oneminusxseries3rev(term t, term arg, term *next, char *reason)
{ return oneminusxseriesrev(t,arg,next,reason);
}

/*_______________________________________________________________*/
int oneplusxseriesrev(term t, term arg, term *next, char *reason)
/* 1-x+x^2... = 1/(1+x) */
{ term u,n,lo,x;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(FUNCTOR(u) == '^' && NEGATIVE(ARG(0,u)))  /* (-x)^n  */
     x = ARG(0,ARG(0,u));
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&   /* (-1)^n x^n */
          FUNCTOR(ARG(0,u)) == '^' &&
          FUNCTOR(ARG(1,u)) == '!' &&
          equals(ARG(0,ARG(0,u)),minusone)
         )
     x = ARG(0,ARG(1,u));
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
     return 1;
  if(!ZERO(lo))
     return 1;
  x = ARG(0,u);
  *next = reciprocal(sum(one,x));
  HIGHLIGHT(*next);
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum((-1)^nx^n,n,0,infinity) = 1/(1+x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"1-x+x^2-... = 1/(1+x)");
  else
     strcpy(reason,"1-x+...+(-1)^nx^n... =  1/(1+x)");
  return 0;
}
/*_______________________________________________________________*/
int oneplusxseries2rev(term t, term arg, term *next, char *reason)
{ return oneplusxseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int oneplusxseries3rev(term t, term arg, term *next, char *reason)
{ return oneplusxseriesrev(t,arg,next,reason);
}

/*_______________________________________________________________*/
int lnseriesrev(term t, term arg, term *next, char *reason)
/* x+x^2/2+x^3/3+... =     -ln(1-x) */
{ term u,n,lo,x;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ONE(lo))
     return 1;
  if(FRACTION(u) && equals(ARG(1,u),n) &&
     FUNCTOR(ARG(0,u)) == '^' && equals(ARG(1,ARG(0,u)),n)
    )
     x = ARG(0,ARG(0,u));
  else if(FUNCTOR(u) == '*' && FRACTION(ARG(0,u)) &&
          ONE(ARG(0,ARG(0,u))) && equals(ARG(1,ARG(0,u)),n) &&
          FUNCTOR(ARG(1,u)) == '^' && equals(ARG(1,ARG(1,u)),n)
         )
     x = ARG(0,ARG(1,u));
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
     return 1;
  *next = tnegate(ln1(sum(one,tnegate(x))));
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum(x^n/n,n,1,infinity) = -ln(1-x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"x+x^2/2+x^3/3+... =     -ln(1-x)");
  else
     strcpy(reason,"x+x^2/2+...+x^n/n+...=  -ln(1-x)");
  return 0;
}
/*_______________________________________________________________*/
int lnseries2rev(term t, term arg, term *next, char *reason)
{ return lnseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int lnseries3rev(term t, term arg, term *next, char *reason)
{ return lnseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int lnseriesminusrev(term t, term arg, term *next, char *reason)
/* x-x^2/2+x^3/3+... =     ln(1+x) */
{ term u,n,lo,x;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ONE(lo))
     return 1;
  if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
     FUNCTOR(ARG(0,u)) == '^' && equals(ARG(0,ARG(0,u)),minusone) &&
     FRACTION(ARG(1,u)) && equals(ARG(1,ARG(1,u)),n) &&
     FUNCTOR(ARG(0,ARG(1,u))) == '^'
    )
     x = ARG(0,ARG(0,ARG(1,u)));
  else if(FRACTION(u) && equals(ARG(1,u),n) &&
          FUNCTOR(ARG(0,u)) == '*' && ARITY(ARG(0,u)) == 2 &&
          FUNCTOR(ARG(0,ARG(0,u))) == '^' &&
          equals(ARG(0,ARG(0,ARG(0,u))),minusone) &&
          FUNCTOR(ARG(1,ARG(0,u))) == '^'
         )
     x = ARG(0,ARG(1,ARG(0,u)));
  else if(FRACTION(u) && equals(ARG(1,u),n) &&
          FUNCTOR(ARG(0,u)) == '^' && NEGATIVE(ARG(0,ARG(0,u)))
         )
     x = ARG(0,ARG(0,u));
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
     return 1;
  *next = ln1(sum(one,x));
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum((-1)^nx^n/n!,n,1,infinity) = ln(1+x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"x-x^2/2+x^3/3+... =     ln(1+x)");
  else
     strcpy(reason,"x-x^2/2+...+x^n/n+... = ln(1+x)");
  return 0;
}
/*_______________________________________________________________*/
int lnseriesminus2rev(term t, term arg, term *next, char *reason)
{ return lnseriesminusrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int lnseriesminus3rev(term t, term arg, term *next, char *reason)
{ return lnseriesminusrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int expseriesrev(term t, term arg, term *next, char *reason)
/* 1+x+x^2/2!+x^3/3!+... =    e^x */
{ term u,n,lo,x;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ZERO(lo))
     return 1;
  if(FRACTION(u) && ONE(ARG(0,u)) &&
     FUNCTOR(ARG(1,u)) == FACTORIAL &&
     equals(ARG(0,ARG(1,u)),n)
    )
     x = one;
  else if(FRACTION(u) && FUNCTOR(ARG(1,u)) == FACTORIAL &&
          equals(ARG(0,ARG(1,u)),n) &&
          FUNCTOR(ARG(0,u)) == '^' && equals(ARG(1,ARG(0,u)),n)
         )
     x = ARG(0,ARG(0,u));
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 && FRACTION(ARG(0,u)) &&
          ONE(ARG(0,ARG(0,u))) &&
          FUNCTOR(ARG(1,ARG(0,u))) == FACTORIAL &&
          equals(ARG(0,ARG(1,ARG(0,u))),n) &&
          FUNCTOR(ARG(1,u)) == '^' && equals(ARG(1,ARG(1,u)),n)
         )
     x = ARG(0,ARG(1,u));
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
     return 1;
  *next = make_power(eulere,x);
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum(x^n/n!,n,0,infinity) = e^x$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"1+x+x^2/2!+...=e^x");
  else
     strcpy(reason,"1+x+...+x^n/n!...=e^x");
  return 0;
}
/*______________________________________________________________*/
int expseries2rev(term t, term arg, term *next, char *reason)
{ return expseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int expseries3rev(term t, term arg, term *next, char *reason)
{ return expseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int negexpseriesrev(term t, term arg, term *next, char *reason)
/* x-x^2/2!+x^3/3!+... =     e^-x */
{ term u,n,lo,x;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ZERO(lo))
     return 1;
  if(FRACTION(u) && FUNCTOR(ARG(0,u)) == '^' &&  /* catch the case e^-1 */
     equals(ARG(0,ARG(0,u)),minusone) &&
     FUNCTOR(ARG(1,u)) == FACTORIAL &&
     equals(ARG(0,ARG(1,u)),n)
    )
      x = one;
  else if(FRACTION(u) && FUNCTOR(ARG(1,u)) == FACTORIAL &&
          equals(ARG(0,ARG(1,u)),n) &&
          FUNCTOR(ARG(0,u)) == '^' && NEGATIVE(ARG(0,ARG(0,u))) &&
          equals(ARG(1,ARG(0,u)),n)
         )
     x = ARG(0,ARG(0,ARG(0,u)));
  else if(FRACTION(u) && FUNCTOR(ARG(1,u)) == FACTORIAL &&
          equals(ARG(0,ARG(1,u)),n) &&
          FUNCTOR(ARG(0,u)) == '*' && ARITY(ARG(0,u)) == 2 &&
          FUNCTOR(ARG(0,ARG(0,u))) == '^' &&
          equals(ARG(0,ARG(0,ARG(0,u))),minusone) &&
          FUNCTOR(ARG(1,ARG(0,u))) == '^' &&
          equals(ARG(1,ARG(1,ARG(0,u))),n)
         )
     x = ARG(0,ARG(1,ARG(0,u)));  /* (-1)^n x^n/n! */
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 && FRACTION(ARG(0,u)) &&
          ONE(ARG(0,ARG(0,u))) &&
          FUNCTOR(ARG(1,ARG(0,u))) == FACTORIAL &&
          equals(ARG(0,ARG(1,ARG(0,u))),n) &&
          FUNCTOR(ARG(1,u)) == '^' && NEGATIVE(ARG(0,ARG(1,u)))
         )
     x = ARG(0,ARG(0,ARG(1,u)));  /* (-x)^n/n!  */
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
          FUNCTOR(ARG(0,u)) == '^' && equals(ARG(1,ARG(0,u)),n) &&
          equals(ARG(0,ARG(0,u)),minusone) &&
          FRACTION(ARG(1,u)) &&
          FUNCTOR(ARG(1,ARG(1,u))) == FACTORIAL &&
          equals(ARG(0,ARG(1,ARG(1,u))),n) &&
          FUNCTOR(ARG(0,ARG(1,u))) == '^' &&
          equals(ARG(1,ARG(0,ARG(1,u))),n)
         )
     x = ARG(0,ARG(0,ARG(1,u)));   /* (-1)^n (x^n/n!) */
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
     return 1;
  *next = make_power(eulere,tnegate(x));
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum((-1)^nx^n/n!,n,0,infinity) = e^(-x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"1-x+x^2/2!+... = e^-x");
  else
     strcpy(reason,"1-x+...+(-1)^nx^n/n! =  e^(-x)");
  return 0;
}
/*______________________________________________________________*/
int negexpseries2rev(term t, term arg, term *next, char *reason)
{ return negexpseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int negexpseries3rev(term t, term arg, term *next, char *reason)
{ return negexpseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int sinseriesrev(term t, term arg, term *next, char *reason)
/* x-x^3/3!+x^5/5!+... =  sin x */
{ term u,n,lo,x,num,denom,a,b;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ZERO(lo))
     return 1;
  if(FRACTION(u))   /* (-1)^n x^(2n+1)/(2n+1)!  or (-x)^(2n+1)/(2n+1)! */
     { num = ARG(0,u);
       denom = ARG(1,u);
       if(FUNCTOR(denom) != FACTORIAL)
          return 1;
       if(FUNCTOR(ARG(0,denom)) != '+')
          return 1;
       if(!islinear(ARG(0,denom),n,&a,&b))
          return 1;
       if(!equals(two,a) || !ONE(b))
          return 1;
       /* denom is (2n+1)!  or equal to it */
       if(FUNCTOR(num)=='^' && NEGATIVE(ARG(0,num)) &&
          (equals(ARG(1,num),ARG(0,denom)) || (islinear(ARG(1,num),n,&a,&b) && equals(two,a) && ONE(b)))
         )
            /* Now the exponent is 2n+1 */
          x = ARG(0,ARG(0,num));    /* (-x)^(2n+1)/(2n+1)! */
       else if(FUNCTOR(num) == '*' && ARITY(num) == 2 &&
               FUNCTOR(ARG(0,num)) == '^' &&
               equals(ARG(0,ARG(0,num)),minusone) &&
               equals(ARG(1,ARG(0,num)),n) &&
               FUNCTOR(ARG(1,num)) == '^' &&
               equals(ARG(1,ARG(1,num)),ARG(0,denom))
              )
          x = ARG(0,ARG(1,num));
       else
          return 1;
     }
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
          FUNCTOR(ARG(0,u)) == '^' &&
          equals(ARG(1,ARG(0,u)),n) &&
          equals(ARG(0,ARG(0,u)),minusone) &&
          FRACTION(ARG(1,u))
         )
     { num = ARG(0,ARG(1,u));
       denom = ARG(1,ARG(1,u));
       if(FUNCTOR(denom) != FACTORIAL)
          return 1;
       if(FUNCTOR(ARG(0,denom)) != '+')
          return 1;
       if(!islinear(ARG(0,denom),n,&a,&b))
          return 1;
       if(!equals(two,a) || !ONE(b))
          return 1;
       /* Now denom = 2n+1 */
       if(FUNCTOR(num) == '^' && equals(ARG(1,num),ARG(0,denom)))
          x = ARG(0,num);  /* (-1)^n (x^n/(2n+1)!)  */
       else
          return 1;
     }
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&   /* (-1)^n/(2n+1)! x^(2n+1) */
          FRACTION(ARG(0,u)) && FUNCTOR(ARG(1,u)) == '^' &&
          FUNCTOR(ARG(1,ARG(0,u))) == FACTORIAL &&
          FUNCTOR(ARG(0,ARG(1,ARG(0,u)))) == '+' &&
          islinear(ARG(0,ARG(1,ARG(0,u))),n,&a,&b) && equals(two,a) && ONE(b) &&
          equals(ARG(1,ARG(1,u)),ARG(0,ARG(1,ARG(0,u))))
         )
     x = ARG(0,ARG(1,u));
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
     return 1;
  *next = sin1(x);
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum((-1)^nx^(2n+1)/(2n+1)!,n,0,infinity) = sin x$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"x-x^3/3!+x^5/5!-... =   sin x");
  else
     strcpy(reason,"$$series((-1)^nx^(2n+1)/(2n+1)!,n,0,infinity,2) = sin x$$");
  return 0;
}
/*______________________________________________________________*/
int sinseries2rev(term t, term arg, term *next, char *reason)
{ return sinseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int sinseries3rev(term t, term arg, term *next, char *reason)
{ return sinseriesrev(t,arg,next,reason);
}

/*______________________________________________________________*/
int cosseriesrev(term t, term arg, term *next, char *reason)
/* 1-x^2/2!+x^4/4!+... =  cos x */
{ term u,n,lo,x,num,denom;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ZERO(lo))
     return 1;
  if(FRACTION(u))   /* (-1)^n x^(2n)/(2n)!  or (-x)^(2n)/(2n)! */
     { num = ARG(0,u);
       denom = ARG(1,u);
       if(FUNCTOR(denom) != FACTORIAL)
          return 1;
       if(FUNCTOR(ARG(0,denom)) != '*' || ARITY(ARG(0,denom)) != 2)
          return 1;
       if(!equals(two,ARG(0,ARG(0,denom))) || !equals(ARG(1,ARG(0,denom)),n))
          return 1;
       /* denom is (2n)!  */
       if(FUNCTOR(num)=='^' && NEGATIVE(ARG(0,num)))
          { if(!equals(ARG(1,num),ARG(0,denom)))
               return 1;
            /* Now the exponent is 2n */
            x = ARG(0,ARG(0,num));    /* (-x)^(2n)/(2n)! */
          }
       else if(FUNCTOR(num) == '*' && ARITY(num) == 2 &&
               FUNCTOR(ARG(0,num)) == '^' &&
               equals(ARG(0,ARG(0,num)),minusone) &&
               equals(ARG(1,ARG(0,num)),n) &&
               FUNCTOR(ARG(1,num)) == '^' &&
               equals(ARG(1,ARG(1,num)),ARG(0,denom))
              )
          x = ARG(0,ARG(1,num));
       else
          return 1;
     }
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
          FUNCTOR(ARG(0,u)) == '^' &&
          equals(ARG(1,ARG(0,u)),n) &&
          equals(ARG(0,ARG(0,u)),minusone) &&
          FRACTION(ARG(1,u))
         )
     { num = ARG(0,ARG(1,u));
       denom = ARG(1,ARG(1,u));
       if(FUNCTOR(denom) != FACTORIAL)
          return 1;
       if(FUNCTOR(ARG(0,denom)) != '*' || ARITY(ARG(0,denom)) != 2)
          return 1;
       if(!equals(two,ARG(0,ARG(0,denom))))
          return 1;
       if(!equals(ARG(1,ARG(0,denom)),n))
          return 1;
       /* Now denom = 2n */
       if(FUNCTOR(num) == '^' && equals(ARG(1,num),ARG(0,denom)))
          x = ARG(0,num);  /* (-1)^n (x^n/(2n)!)  */
       else
          return 1;
     }
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&   /* (-1)^n/(2n)! x^(2n) */
          FRACTION(ARG(0,u)) && FUNCTOR(ARG(1,u)) == '^' &&
          FUNCTOR(ARG(1,ARG(0,u))) == FACTORIAL &&
          FUNCTOR(ARG(0,ARG(1,ARG(0,u)))) == '*' &&
          ARITY(ARG(0,ARG(1,ARG(0,u)))) == 2 &&
          equals(two,ARG(0,ARG(0,ARG(1,ARG(0,u))))) &&
          equals(ARG(1,ARG(0,ARG(1,ARG(0,u)))),n)
         )
     x = ARG(0,ARG(1,u));
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
     return 1;
  *next = cos1(x);
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum((-1)^nx^(2n)/(2n)!,n,0,infinity) = cos x$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"1-x^2/2!+x^4/4!-... =   cos x");
  else
     strcpy(reason,"$$series((-1)^nx^(2n)/(2n)!,n,0,infinity,2) = cos x$$");
  return 0;
}
/*______________________________________________________________*/
int cosseries2rev(term t, term arg, term *next, char *reason)
{ return cosseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int cosseries3rev(term t, term arg, term *next, char *reason)
{ return cosseriesrev(t,arg,next,reason);
}

/*______________________________________________________________*/
int atanseriesrev(term t, term arg, term *next, char *reason)
/* x-x^3/3 +...(-1)^nx^(2n+1)/(2n+1) = arctan x */
{ term u,n,lo,x,num,denom,a,b;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ZERO(lo))
     return 1;
  if(FRACTION(u))
     { num = ARG(0,u);
       denom = ARG(1,u);
       if(FUNCTOR(denom) != '+' || ARITY(denom) != 2)
          return 1;
       if(!islinear(denom,n,&a,&b) || !equals(two,a) || !ONE(b))
          return 1;
       if(ONE(num))
          x = one;
       else
          { if(FUNCTOR(num) != '^')
               return 1;
            if(equals(ARG(1,num),denom))
               x = ARG(0,num);
            if(FUNCTOR(ARG(1,num)) != '+' || ARITY(ARG(1,num)) != 2)
               return 1;
            if(islinear(ARG(1,num),n,&a,&b) && equals(two,a) && ONE(b))
               x = ARG(0,num);
            else
               return 1;
         }
     }
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&    /* (-1)^n x^(2n+1)/(2n+1) */
          FUNCTOR(ARG(0,u)) == '^' && FRACTION(ARG(1,u)) &&
          equals(ARG(1,ARG(0,u)),n) &&
          equals(ARG(0,ARG(0,u)),minusone)
         )
     { denom = ARG(1,ARG(1,u));
       if(FUNCTOR(denom) != '+' || ARITY(denom) != 2)
          return 1;
       if(!islinear(denom,n,&a,&b) || !equals(two,a) || !ONE(b))
          return 1;
       num = ARG(0,ARG(1,u));
       if(FUNCTOR(num) == '^' && FUNCTOR(ARG(1,num)) == '+' &&
          ARITY(ARG(1,num)) == 2 &&
          (equals(ARG(1,num),denom) || (islinear(ARG(1,num),n,&a,&b) && equals(two,b) && ONE(a)))
         )
          x = ARG(0,num);
       else
          return 1;
     }
  else
     return 1;
  *next = atan1(x);
  HIGHLIGHT(*next);
  if(ARITY(t) == 4)
     strcpy(reason,"$$sum((-1)^nx^(2n+1)/(2n+1),n,0,infinity) = arctan x$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"x-x^3/3+x^5/5+... =     arctan x");
  else
     strcpy(reason,"$$series((-1)^nx^(2n+1)/(2n+1),n,0,infinity,2) = arctan x$$");
  return 0;
}
/*______________________________________________________________*/
int atanseries2rev(term t, term arg, term *next, char *reason)
{ return atanseriesrev(t,arg,next,reason);
}
/*______________________________________________________________*/
int atanseries3rev(term t, term arg, term *next, char *reason)
{ return atanseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int oneoveroneminusxkseriesrev(term t, term arg, term *next, char *reason)
/* sum(x^(nk),n,0,infinity)=  1/(1-x^k) */
{ term u,n,lo,x,b,k;
  int err;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ZERO(lo))
     return 1;
  if(FUNCTOR(u) != '^')
     return 1;
  x = ARG(0,u);
  if(contains(x,FUNCTOR(n)))
     return 1;
  err = cancel(ARG(1,u),n,&b,&k);
  if(err)
     return 1;
  if(contains(k,FUNCTOR(n)))
     return 1;
  *next = reciprocal(sum(one,tnegate(make_power(ARG(0,u),k))));
  HIGHLIGHT(*next);
  strcpy(reason,"$1+x^k+x^(2k)+...+x^(nk)= 1/(1-x^k)$");
  return 0;
}
/*_______________________________________________________________*/
int oneoveroneminusxkseries2rev(term t, term arg, term *next, char *reason)
{ return oneoveroneminusxkseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int oneoveroneminusxkseries3rev(term t, term arg, term *next, char *reason)
{ return oneoveroneminusxkseriesrev(t,arg,next,reason);
}

/*_______________________________________________________________*/
int oneoveroneplusxkseriesrev(term t, term arg, term *next, char *reason)
/* sum((-1)^n x^(nk),n,0,infinity)=  1/(1+x^k) */
{ term u,n,lo,x,b,c,k;
  int err;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(!ZERO(lo))
     return 1;
  if(FUNCTOR(u) == '^' && NEGATIVE(ARG(0,u)))
     { x = ARG(0,ARG(0,u));
       b = ARG(1,u);
     }
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
          FUNCTOR(ARG(0,u)) == '^' &&
          equals(ARG(0,ARG(0,u)),minusone) &&
          equals(ARG(1,ARG(0,u)),n) &&
          FUNCTOR(ARG(1,u)) == '^'
         )
          { x = ARG(0,ARG(1,u));
            b = ARG(1,ARG(1,u));
          }
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
     return 1;
  err = cancel(b,n,&c,&k);
  if(err)
     return 1;
  if(contains(k,FUNCTOR(n)))
     return 1;
  *next = reciprocal(sum(one,make_power(ARG(0,u),k)));
  HIGHLIGHT(*next);
  strcpy(reason,"$1-x^k+x^(2k)+...x^(nk) = 1/(1+x^k)$");
  return 0;
}

/*_______________________________________________________________*/
int oneoveroneplusxkseries2rev(term t, term arg, term *next, char *reason)
{ return oneoveroneplusxkseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int oneoveroneplusxkseries3rev(term t, term arg, term *next, char *reason)
{ return oneoveroneplusxkseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int xmoveroneminusxkseriesrev(term t, term arg, term *next, char *reason)
/* x^m + x^(m+k) + ... x^(m+nk) = x^m/(1-x^k) */
{ term u,n,m,lo,x,b,k;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(FUNCTOR(u) != '^')
     return 1;
  x = ARG(0,u);
  if(contains(x,FUNCTOR(n)))
    return 1;
  subst(lo,n,ARG(1,u),&b);
  polyval(b,&m);
  if(!islinear(ARG(1,u),n,&b,&k))
     return 1;
  *next = make_fraction(make_power(x,m),sum(one,tnegate(make_power(x,k))));
  HIGHLIGHT(*next);
  strcpy(reason,"$x^m+x^(k+m)+x^(2k+m)+... = x^m/(1-x^k)$");
  return 0;
}

/*_______________________________________________________________*/
int xmoveroneminusxkseries2rev(term t, term arg, term *next, char *reason)
{ return xmoveroneminusxkseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int xmoveroneminusxkseries3rev(term t, term arg, term *next, char *reason)
{ return xmoveroneminusxkseriesrev(t,arg,next,reason);
}

/*_______________________________________________________________*/
int xmoveroneplusxkseriesrev(term t, term arg, term *next, char *reason)
/* x^m - x^(m+k) + ... x^(m+nk) = x^m/(1+x^k) */
{ term u,n,m,lo,x,b,k,power;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(FUNCTOR(u) == '^' && NEGATIVE(ARG(0,u)))
     { x = ARG(0,ARG(0,u));
       power = ARG(1,u);
     }
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
          FUNCTOR(ARG(0,u)) == '^' && equals(ARG(0,ARG(0,u)),minusone) &&
          equals(ARG(1,ARG(0,u)),n) && FUNCTOR(ARG(1,u)) == '^'
         )
         { x = ARG(0,ARG(1,u));
           power = ARG(1,ARG(1,u));
         }
  else
     return 1;
  if(contains(x,FUNCTOR(n)))
    return 1;
  subst(lo,n,power,&b);
  polyval(b,&m);
  if(!islinear(ARG(1,u),n,&b,&k))
     return 1;
  *next = make_fraction(make_power(x,m),sum(one,make_power(x,k)));
  HIGHLIGHT(*next);
  strcpy(reason,"$x^m-x^(k+m)+x^(2k+m)-... = x^m/(1+x^k)$");
  return 0;
}

/*_______________________________________________________________*/
int xmoveroneplusxkseries2rev(term t, term arg, term *next, char *reason)
{ return xmoveroneplusxkseriesrev(t,arg,next,reason);
}
/*_______________________________________________________________*/
int xmoveroneplusxkseries3rev(term t, term arg, term *next, char *reason)
{ return xmoveroneplusxkseriesrev(t,arg,next,reason);
}

/*_________________________________________________________________*/
int geometricseriesfromkrev(term t, term arg, term *next, char *reason)
/* sum(x^n,n,k,infinity) = x^k/(1-x) */
{ term u,x,lo,n;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(FUNCTOR(u) != '^' || !equals(ARG(1,u),n))
     return 1;
  x = ARG(0,u);
  *next = make_fraction(make_power(x,lo),sum(one,tnegate(x)));
  HIGHLIGHT(*next);
  if(ARITY(t)==4)
     strcpy(reason,"$$sum(x^n,n,k,infinity) = x^k/(1-x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"$x^k+x^(k+1)+...=x^k/(1-x)$");
  else
     strcpy(reason,"$x^k+x^(k+1)+...x^n+...     =x^k/(1-x)$");
  return 0;
}
/*_________________________________________________________________*/
int geometricseriesfromk2rev(term t, term arg, term *next, char *reason)
{ return geometricseriesfromkrev(t,arg,next,reason);
}
/*_________________________________________________________________*/
int geometricseriesfromk3rev(term t, term arg, term *next, char *reason)
{ return geometricseriesfromkrev(t,arg,next,reason);
}

/*_________________________________________________________________*/
int geometricseriesminusfromkrev(term t, term arg, term *next, char *reason)
/* sum((-1)^n x^n,n,k,infinity) = x^k/(1+x) */
{ term u,x,lo,n;
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
    return 1;
  u = ARG(0,t);
  n = ARG(1,t);
  lo = ARG(2,t);
  if(FUNCTOR(u) == '^' && NEGATIVE(ARG(0,u)) && equals(ARG(1,u),n))
     x = ARG(0,ARG(0,u));
  else if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
          FUNCTOR(ARG(0,u)) == '^' &&
          equals(ARG(0,ARG(0,u)),minusone) &&
          equals(ARG(1,ARG(0,u)),n) &&
          FUNCTOR(ARG(1,u)) == '6' &&
          equals(ARG(1,ARG(1,u)),n)
         )
     x = ARG(0,ARG(1,u));
  else
     return 1;
  *next = make_fraction(make_power(x,lo),sum(one,x));
  HIGHLIGHT(*next);
  if(ARITY(t)==4)
     strcpy(reason,"$$sum((-1)^nx^n,n,k,infinity) = x^k/(1+x)$$");
  else if(NEGATIVE(ARG(4,t)))
     strcpy(reason,"$x^k-x^(k+1)+...=x^k/(1+x)$");
  else
     strcpy(reason,"$x^k-x^(k+1)+...(-1)^nx^n+..=x^k/(1+x)$");
  return 0;
}

/*_________________________________________________________________*/
int geometricseriesminusfromk2rev(term t, term arg, term *next, char *reason)
{ return geometricseriesminusfromkrev(t,arg,next,reason);
}

/*_________________________________________________________________*/
int geometricseriesminusfromk3rev(term t, term arg, term *next, char *reason)
{ return geometricseriesminusfromkrev(t,arg,next,reason);
}

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