Sindbad~EG File Manager

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

/* M. Beeson for series.dll
Select series operations for the Term Selection Menu
*/

/* Original date 2.28.00
   Last modified 6.17.00
   1.23.06 added sumtodifofsums and sumtodifofsums0
   5.6.13  include stddef.h, removed unused variable somewhere.
           include sselect.h
   5.15.13  added cotseries, bernoulliseries,tanseries,sinseries,cosseries
   5.24.13  added secseries
   5.29.13 corrected parens at line 238
   6.5.13  put in addtozeta
   6.8.13 Only show the convergence tests when FUNCTOR(t) == SUM and pathlength <= 1
   6.11.13 corrected the start of select_series_op not to access args of input until after checking it's a series.
            added condensationtest and finishcondensationtest to select_series_op
   6.12.13 added multnumdenom to expand_op
   6.12.13 added more to select_series_op
   8.20.13  added lnseriesrev
   1.9.25   added condensationtest for the harmonic series
*/

#include <math.h>
#include <string.h>    /* memset */
#include <assert.h>
#include <stddef.h>
#include "globals.h"
#include "graphstr.h"
#include "mpdoc.h"
#include "tdefn.h"
#include "trig.h"
#include "calc.h"
#include "display.h"
#include "display1.h"  /* needed by lterm.h */
#include "bigrect.h"
#include "lterm.h"
#include "selectop.h"
#include "automode.h"
#include "cflags.h"
#include "probtype.h"
#include "calc.h"
#include "pvalaux.h"   /* twoparts, iseven, isodd */
#include "prover.h"    /* NOTDEFINED             */
#include "docdata.h"   /* history                */
#include "select2.h"
#include "series.h"    /* is_power_series        */
#include "islinear.h"  /* islinear               */
#include "scontrol.h"  /* used4                  */
#include "sselect.h"   /* select_series_op       */
#include "order.h"     /* numerical              */
#include "autosimp.h"  /* get_pathlength         */
#include "polynoms.h"  /* ispolyin               */

static int contains_power_of_minusone(term t);

/*_________________________________________________*/
static int contains_power_of_minusone(term t)
/* return 1 if t contains a power of minusone, 0 if not
*/
{ unsigned short i,n,f;
  if(ATOMIC(t))
     return 0;
  f = FUNCTOR(t);
  if(f == '^' && equals(ARG(0,t),minusone))
     return 1;
  n = ARITY(t);
  for(i=0;i<n;i++)
     { if(contains_power_of_minusone(ARG(i,t)))
          return 1;
     }
  return 0;
}
/*______________________________________________________________________________*/
static void expand_op(term t, actualop *o, int *nops)
/* t is an expression to be expanded in a series;  suggest operations to try.
Also t can be a term of a series,  where we need writeaspoly   */

{ term u,v,x;
  unsigned short f,g,h;
  int i = 0;
  term * varlist = get_varlist();
  int nvars = get_nvariables();
  char reason[DIMREASONBUFFER];
  // we need to get the series variable, but the eigenvariable is the summation variable
  if(nvars > 0)
     x = varlist[0];
  if( (FRACTION(t) || FUNCTOR(t) == '*') && nvars > 0 &&  noccurs(x,t) == 1 && !writeaspoly(t,x,&u,reason))
        // only show  "write as polynomial"  if it's going to work
       { o[i] = writeaspoly; ++i;
       }
  if(FRACTION(t))
     { u = ARG(0,t);
       v = ARG(1,t);
       g = FUNCTOR(u);
       h = FUNCTOR(v);
       if(FUNCTOR(v) == '+' && ARITY(v) == 3 && ispolyin(v,x))
          { o[i] = multnumdenom; ++i;      // example,  x/(x^2+x+1),  multiply num and denom by 1-x
          }
       // partialfractionsop shows up without being listed here
       if(ONE(u) && h == '^' && numerical(ARG(1,v)) && FUNCTOR(ARG(0,v))== '+' && ONE(ARG(0,ARG(0,v))))
           { o[i] = binomialseries; ++i;
           }
       if(ONE(u) && h == '+' && ARITY(v) == 2)
          { if(ONE(ARG(0,v)) && NEGATIVE(ARG(1,v)))
               { o[i] = oneminusxseries; ++i;
                 o[i] = oneminusxseries2; ++i;
                 o[i] = oneminusxseries3; ++i;
               }
            else if(ONE(ARG(0,v)) || ONE(ARG(1,v)))
               { o[i] = oneplusxseries; ++i;
                 o[i] = oneplusxseries2; ++i;
                 o[i] = oneplusxseries3; ++i;
               }
          }
       if(h == '+' && ARITY(v) == 2 && ONE(ARG(1,v)))
          { if(equals(u,ARG(0,v)))
               { o[i] = xoveroneplusxseries; ++i;
                 o[i] = xoveroneplusxseries2; ++i;
                 o[i] = xoveroneplusxseries3; ++i;
               }
          }
       if(h == '+' && ARITY(v) == 2 && ONE(ARG(0,v)))
          { if(equals(u,ARG(1,v)))
               { o[i] = xoveroneplusxseries; ++i;
                 o[i] = xoveroneplusxseries2; ++i;
                 o[i] = xoveroneplusxseries3; ++i;
               }
            if(NEGATIVE(ARG(1,v)) && equals(ARG(0,ARG(1,v)),u))
               { o[i] = xoveroneminusxseries; ++i;
                 o[i] = xoveroneminusxseries2; ++i;
                 o[i] = xoveroneminusxseries3; ++i;
               }
            if(NEGATIVE(ARG(1,v)) &&
               FUNCTOR(ARG(0,ARG(1,v))) ==  '^' &&
               equals(ARG(0,ARG(0,ARG(1,v))),u)
              )
               { o[i] = xmoveroneminusxkseries; ++i;
                 o[i] = xmoveroneminusxkseries2; ++i;
                 o[i] = xmoveroneminusxkseries3; ++i;
               }
            if(NEGATIVE(ARG(1,v)) &&
               FUNCTOR(ARG(0,ARG(1,v))) ==  '^' &&
               ONE(u)
              )
               { o[i] = oneoveroneminusxkseries; ++i;
                 o[i] = oneoveroneminusxkseries2; ++i;
                 o[i] = oneoveroneminusxkseries3; ++i;
               }
            if(ONE(u) && FUNCTOR(ARG(1,v)) == '^')
               { o[i] = oneoveroneplusxkseries; ++i;
                 o[i] = oneoveroneplusxkseries2; ++i;
                 o[i] = oneoveroneplusxkseries3; ++i;
               }
            if(NEGATIVE(ARG(1,v)) && FUNCTOR(u) == '^' &&
               equals(ARG(0,ARG(1,v)),ARG(0,u))
              )
               { o[i] = geometricseriesfromk; ++i;
                 o[i] = geometricseriesfromk2; ++i;
                 o[i] = geometricseriesfromk3; ++i;
               }
            if(g == '^' && equals(ARG(1,v),ARG(0,u)))
               { o[i] = geometricseriesminusfromk; ++i;
                 o[i] = geometricseriesminusfromk2; ++i;
                 o[i] = geometricseriesminusfromk3; ++i;
               }
            if(FUNCTOR(u) == '^' && NEGATIVE(ARG(1,v)) &&
               FUNCTOR(ARG(0,ARG(1,v))) == '^' &&
               equals(ARG(0,u),ARG(0,ARG(0,ARG(1,v))))
              )
               { o[i] = xmoveroneminusxkseries; ++i;
                 o[i] = xmoveroneminusxkseries2; ++i;
                 o[i] = xmoveroneminusxkseries3; ++i;
               }
            if(FUNCTOR(u) == '^' &&
               FUNCTOR(ARG(1,v)) == '^' &&
               equals(ARG(0,u),ARG(0,ARG(1,v)))
              )
               { o[i] = xmoveroneplusxkseries; ++i;
                 o[i] = xmoveroneplusxkseries2; ++i;
                 o[i] = xmoveroneplusxkseries3; ++i;
               }
         }
       if(FUNCTOR(v) == '+' && ARITY(v) == 2 && equals(ARG(1,v),minusone) && 
          FUNCTOR(ARG(0,v)) == '^' && equals(ARG(1,(ARG(0,v))),u) &&
          equals(ARG(0,ARG(0,v)),eulere)
         )
          { o[i] = bernoulliseries; ++i;
            o[i] = bernoulliseries2; ++i;
            o[i] = bernoulliseries3; ++i;
          }         
     }
  f = FUNCTOR(t);
  switch(f)
     { case RIEMANNZETA:
           o[i] = zetaseries; ++i;
           o[i] = zetaseries2; ++i;
           o[i] = zetaseries3; ++i;  
           break;
       case SIN:    
           o[i] = sinseries; ++i;
           o[i] = sinseries2; ++i;
           o[i] = sinseries3; ++i;
           break;
       case COS:
           o[i] = cosseries; ++i;
           o[i] = cosseries2; ++i;
           o[i] = cosseries3; ++i;
           break;
      case TAN:
           o[i] = tanseries; ++i;
           o[i] = tanseries2; ++i;
           o[i] = tanseries3; ++i;
           break;
      case COT:
           o[i] = cotseries; ++i;
           o[i] = cotseries2; ++i;
           o[i] = cotseries3; ++i;
           break;
      case SEC:
           o[i] = secseries; ++i;
           o[i] = secseries2; ++i;
           o[i] = secseries3; ++i;
           break;
      case '*':
           if(ARITY(t) == 2 && FUNCTOR(ARG(1,t))==COT &&
              ( 
                equals(ARG(0,t),ARG(0,ARG(1,t))) ||
                (FUNCTOR(ARG(0,t)) == '^' && equals(ARG(0,ARG(0,t)),ARG(0,ARG(1,t))) && ISINTEGER(ARG(1,ARG(0,t))))
              )
             )
               { o[i] = cotseries; ++i;
                 o[i] = cotseries2; ++i;
                 o[i] = cotseries3; ++i;
               }
           break;         
    }
  * nops = i;
}
/*_________________________________________________________________________________________*/
void select_series_op(term t, actualop *o, int *nops)
/* t is an infinite series, or an expression to be expanded in a series, or an expression inside a series  */
{ int i = 0;
  term lo,indexvar,ldots;
  term u = ARG(0,t);
  term num,denom;
  term a,b,c,s,w,temp;
  char buffer[DIMREASONBUFFER];
  unsigned short g = FUNCTOR(u);
  int nfree;
  if(FUNCTOR(t) != SUM)
     { expand_op(t,o,nops);
       return;
     }
  lo = ARG(2,t);
  indexvar = ARG(1,t);
  ldots = ARITY(t) == 4 ? zero : ARG(4,t);
  if(ARITY(t) == 4)
     { o[i] = ldots0; ++i;
       o[i] = ldots1; ++i;
       o[i] = ldots2; ++i;
     }
  else
     { o[i] = ldotstosigma; ++i;
       o[i] = showanotherterm; ++i;
       o[i] = showmoreterms; ++i;
       if(!EVALFACTORIAL(t))
          { o[i] = showevaluatedterms; ++i;
          }
       else
          { o[i] = showfactorialsinterms; ++i;
          }
       if(DEVALCOEF(t))
          { o[i] = showundevaluatedterms; ++i;
          }
       else
          { o[i] = showdevaluatedterms; ++i;
          }
     }
  if(!contains(u,FUNCTOR(ARG(1,t))))
     { o[i] = sigmaconstant; ++i;
     }
  if(contains_power_of_minusone(u))
     { o[i] = seriesevenandodd; ++i;
     }
  nfree =  numerical_sum(t);
  // if(nfree == 2)
  //    { o[i] = evaluateinfiniteseries; ++i;
  //    }
  if(nfree == 1)
     { o[i] = evalfirstterms; ++i;
     }
  if(ATOMIC(u))
     { *nops = i;
       return;
     }
  if(!equals(lo,minusinfinity))
     { o[i] = seriesfirstterms; ++i;
       o[i] = seriesmoreterms; ++i;
       if(ARITY(t) == 4)
          { o[i] = seriesaddindex; ++i;
            o[i] = seriessubindex; ++i;
          }
	    o[i] = sumtodifofsums; ++i;
	    if(!ZERO(lo))
		  { o[i] = sumtodifofsums0;++i;
		  }
     }
  if(get_problemtype() == TESTCONVERGENCE && FUNCTOR(t) == '=' && ISINFINITE(ARG(1,t)) && FUNCTOR(ARG(0,t)) == SUM)
     { if(used4(condensationtest))
          { o[i] = finishcondensationtest; ++i;
          }
       if(used4(divergencetest))
          { o[i] = finishdivergencetest; ++i;
          }
       if(used4(comparisontest2))
          { o[i] = finishcomparisontest2; ++i;
          }
      }
  if(get_problemtype() == TESTCONVERGENCE && FUNCTOR(t) == SUM && get_pathlength() <= 1)
     { o[i] = divergencetest; ++i;
       o[i] = integraltest; ++i;
       o[i] = ratiotest; ++i;
       o[i] = roottest; ++i;
       o[i] = comparisontest1; ++i;
       o[i] = comparisontest2; ++i;
       o[i] = condensationtest; ++i;
       o[i] = limitcomparisontest; ++i;
       if(used4(comparisontest1))
          { o[i] = finishcomparisontest1; ++i;
          }
       if(used4(comparisontest2))
          { o[i] = finishcomparisontest2; ++i;
          }
       if(used4(finishcomparisontest1))
          { o[i] = statefinalbound1; ++i;
          }
       if(used4(finishcomparisontest2))
          { o[i] = statefinalbound2; ++i;
          }
       if(used4(condensationtest))
          { o[i] = finishcondensationtest; ++i;
          }
     }
  switch(g)
     { case RIEMANNZETA:
          o[i] = zetaseries; ++i;
          break;
       case '-':
          o[i] = minusoutofsigma; ++i;
          break;
       case '/':
          num = ARG(0,u);
          denom = ARG(1,u);
          if(ONE(num) && FUNCTOR(denom) == '^' &&
             equals(ARG(1,denom),indexvar)
            )
             { if(ONE(lo))
                  { o[i] = xoveroneminusxseriesrev; ++i;
                  }
               if(ZERO(lo))
                  { o[i] = oneminusxseriesrev; ++i;
                  }
             }
          twoparts(u,indexvar,&c,&s);
          if(!ONE(c))
             { o[i] = constantoutofsigma; ++i;
             }
          if(!harmonicseries(t,zero,&temp,buffer))
             { o[i] = harmonicseries; ++i;
             }
          if(!alternatingharmonicseries(t,zero,&temp,buffer))
             { o[i] = alternatingharmonicseries;++i;
             }
          if(!zeta2(t,zero,&temp,buffer))
             { o[i] = zeta2; ++i;
             }
          // don't try addtozeta as it might make assumptions
          if(ONE(ARG(0,u)) && FUNCTOR(denom) == '^' && equals(ARG(0,denom),indexvar) && !contains(ARG(1,denom),FUNCTOR(indexvar)))
             { o[i] = addtozeta; ++i;
             }
          if(FUNCTOR(denom) == FACTORIAL && ZERO(lo) && equals(ARG(0,denom),indexvar))
             /* recognize series for e^x, e^-x, sin x, and cos x */
             { if(!contains(u,'-'))
                  { o[i] =  ZERO(ldots) ? expseriesrev : NEGATIVE(ldots) ? expseries3rev : expseries3rev; ++i;
                  }
               else if(FUNCTOR(num) == '*' && ARITY(num) == 2 &&
                       FUNCTOR(ARG(0,num)) == '^' && equals(ARG(0,ARG(0,num)),minusone) &&
                       equals(ARG(1,ARG(0,num)),indexvar) && FUNCTOR(ARG(1,num)) == '^'
                      )
                       { if(equals(ARG(1,ARG(1,num)),indexvar))
                            { o[i] = ZERO(ldots) ? negexpseriesrev: NEGATIVE(ldots) ? negexpseries2rev : negexpseries3rev; ++i;
                            }
                         else if(iseven(ARG(1,ARG(1,num))))
                            { o[i] = ZERO(ldots) ? cosseriesrev : NEGATIVE(ldots) ? cosseries2rev : cosseries3rev; ++i;
                            }
                         else if(isodd(ARG(1,ARG(1,num))))
                            { o[i] = ZERO(ldots) ? sinseriesrev : NEGATIVE(ldots) ? sinseries2rev : sinseries3rev; ++i;
                            }
                       }
             }
          if(equals(denom,indexvar) && FUNCTOR(num) == '^' && equals(indexvar,ARG(1,num)) && ONE(lo))
             { o[i] = ZERO(ldots) ? lnseriesrev : NEGATIVE(ldots) ? lnseries2rev : lnseries3rev; ++i;
             }

       break;
       case '*':
          twoparts(u,indexvar,&c,&s);
          if(!ONE(c))
             { o[i] = constantoutofsigma; ++i;
             }
          if(ARITY(u) == 2 && FUNCTOR(ARG(0,u)) == '^' &&
             equals(ARG(0,ARG(0,u)),minusone) &&
             equals(ARG(1,ARG(0,u)),indexvar) &&
             FUNCTOR(ARG(1,u)) == '^' &&
             !contains(ARG(0,ARG(1,u)),FUNCTOR(indexvar))
            )
             { /*  (-1)^n x^?  */
               term w = ARG(0,ARG(1,u));
               term power = ARG(1,ARG(1,u));
               if(!contains(w,FUNCTOR(indexvar)))
                  { if(equals(power,indexvar))
                       { o[i] = ZERO(ldots) ? oneplusxseriesrev: NEGATIVE(ldots)? oneplusxseries2rev: oneplusxseries3rev; ++i;
                       }
                    else if(FUNCTOR(power) == '*' && !is_linear_in(power,indexvar))
                       { o[i] = ZERO(ldots) ? oneoveroneplusxkseriesrev : NEGATIVE(ldots) ? oneoveroneplusxkseries2rev : oneoveroneplusxkseries3rev; ++i;
                       }
                    else if(FUNCTOR(power) == '+' && !is_linear_in(power,indexvar))
                       { o[i] = ZERO(ldots) ? xmoveroneplusxkseriesrev : NEGATIVE(ldots) ? xmoveroneplusxkseries2rev : xmoveroneplusxkseries3rev; ++i;
                       }
                  }
             }
          if(FUNCTOR(s) == '^' && equals(indexvar,ARG(1,s)))
             { if(FUNCTOR(c) == BINOMIAL && equals(ARG(1,c),indexvar))
                  { o[i] = ZERO(ldots) ? binomialseriesrev: NEGATIVE(ldots) ? binomialseries2rev : binomialseries3rev; ++i;
                  }
               else if(FUNCTOR(c) == '*' && ARITY(c) == 2 &&
                       FUNCTOR(ARG(1,c)) == BINOMIAL &&
                       equals(ARG(1,ARG(1,c)),indexvar) &&
                       FUNCTOR(ARG(0,c)) == '^' &&
                       equals(ARG(0,ARG(0,c)),minusone) &&
                       equals(ARG(1,ARG(0,c)),indexvar)
                      )
                  { o[i] = ZERO(ldots) ? binomialseriesrev: NEGATIVE(ldots) ? binomialseries2rev: binomialseries3rev; ++i;
                  }
             }
          if(ARITY(u) == 2 && FUNCTOR(ARG(1,u)) == '^' &&
             islinear(ARG(1,ARG(1,u)),indexvar,&a,&b) &&
             equals(a,two) &&
             FRACTION(ARG(0,u)) &&
             FUNCTOR(ARG(0,ARG(0,u))) == '^' &&
             equals(ARG(0,ARG(0,ARG(0,u))),minusone) &&
             FUNCTOR(ARG(1,ARG(0,u))) == FACTORIAL &&
             equals(ARG(0,ARG(1,ARG(0,u))),ARG(1,ARG(1,u))) &&
             equals(ARG(1,ARG(0,ARG(0,u))),indexvar)
            )
             { if(ONE(b))
                  { o[i] = sinseriesrev; ++i;
                  }
               else
                  { o[i] = cosseriesrev; ++i;
                  }
             }
          break;
       case '+':
          o[i] = seriessum; ++i;
          if(ARITY(u) == 2 && !telescopingseries(t,zero,&w,buffer))
             { o[i] = telescopingseries; ++i;
             }
              break;
       case '^':
          if(equals(ARG(1,u),indexvar) && ZERO(lo) && !contains(ARG(0,u),FUNCTOR(indexvar)))
             { o[i] = ZERO(ldots) ? oneminusxseriesrev: NEGATIVE(ldots) ? oneminusxseries2rev : oneminusxseries3rev; ++i;
             }
          if(equals(ARG(1,u),indexvar) && ONE(lo) && !contains(ARG(0,u),FUNCTOR(indexvar)))
             { o[i] = ZERO(ldots) ? xoveroneminusxseriesrev : NEGATIVE(ldots) ? xoveroneminusxseries2rev : xoveroneminusxseries3rev; ++i;
             }
          if(FUNCTOR(ARG(1,u)) == '+' &&
             !contains(ARG(0,u),FUNCTOR(indexvar)) &&
             !is_linear_in(ARG(1,u),indexvar)
            )
             { o[i] = ZERO(ldots) ? xmoveroneminusxkseriesrev : NEGATIVE(ldots) ? xmoveroneminusxkseries2rev : xmoveroneminusxkseries3rev; ++i;
             }
          if(FUNCTOR(ARG(1,u)) == '*'&&
             !contains(ARG(0,u),FUNCTOR(indexvar)) &&
             !is_linear_in(ARG(1,u),indexvar)
            )
             { o[i] = ZERO(ldots) ? oneminusxseriesrev: NEGATIVE(ldots) ? oneminusxseries2rev : oneminusxseries3rev; ++i;
             }
          if(equals(ARG(0,u),indexvar) && !contains(ARG(1,u),FUNCTOR(indexvar)))
             { o[i] = addtozeta; ++i;
             }
          break;
       case DIFF:
          o[i] = reversedifseries; ++i;
          break;
       case INTEGRAL:
          o[i] = reverseintseries; ++i;
          break;
     }
  *nops = i;
  return;
}

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