Sindbad~EG File Manager

Current Path : /usr/home/beeson/Otter-Lambda/yyy/series/
Upload File :
Current File : /usr/home/beeson/Otter-Lambda/yyy/series/scontrol.c

/* M. Beeson, for series.dll
automode control of series operations
3.2.00
Last modified 4.2.00
*/

#define SERIES_DLL
#include <assert.h>
#include <string.h>
#include "globals.h"
#include "graphstr.h"
#include "document.h"
#include "tdefn.h"
#include "checkarg.h" /* for operator typedef */
#include "ops.h"  /* for prototypes of operators */
#include "operator.h"
#include "trig.h"
#include "calc.h"
#include "series.h"
#include "probtype.h"  /* set_control_flags needs values of problemtype */
#include "prover.h"
#include "polynoms.h"
#include "exec.h"
#include "algaux.h"
#include "order.h"
#include "automode.h"
#include "scontrol.h"
#include "optable.h"   /* access_optable */
#include "cflags.h"    /* get_currenttopic */
#include "autosimp.h"  /* get_pathlength */

static int ok_convergence_test(void);

/*____________________________________________________*/
static int ok_convergence_test(void)
/* return 1 if the path contains only - and * before SUM 
*/
{ int i;
  int pathlength = get_pathlength();
  unsigned short *path = get_path();
  if(pathlength == 0)
     return 1;
  for(i=0;path[i];i+=2)
     { if(path[i] == SUM)
           return 1;
       if(path[i] != '-' && path[i] != '*')
           return 0;
       if(path[i+1]==0)
           return 0;
     }
  return 1;
}

/*_________________________________________________________________________________*/
MEXPORT_SERIES void series_preops(term t, actualop *o, int *nops)
/* called by pre_ops to get operators to apply to an infinite series.
These operators try to bring a series to geometric or telescoping form and sum the series
explicitly.  It's necessary to use these in comparison_test too so that the new series 
can eventually be added up.
*/
{ unsigned short g = FUNCTOR(ARG(0,t));
  int i = 0;
  switch(g)
     { case '-' :
          o[i] = minusoutofsigma; ++i;
          break;
       case '+' :
          o[i] = telescopingseries; ++i;
          break;
       case '/' :
          o[i] = constantoutofsigma; ++i;
          if(ONE(ARG(2,t)) &&
             (FUNCTOR(ARG(0,ARG(0,t))) == '^' || ONE(ARG(0,ARG(0,t)))) &&
              FUNCTOR(ARG(1,ARG(0,t))) == '^'
             )
             { o[i] = xoveroneminusxseriesrev; ++i;
             }
          if(
             (FUNCTOR(ARG(0,ARG(0,t))) == '^' || ONE(ARG(0,ARG(0,t)))) &&
              FUNCTOR(ARG(1,ARG(0,t))) == '^'
             )
              { o[i] = oneminusxseriesrev; ++i;
                /* if the lower limit isn't zero, it calls shiftindex first */
              }
               break;
       case '^':
          if(ONE(ARG(2,t)))
             { o[i] = xoveroneminusxseriesrev; ++i;
             }
          else
             { o[i] = oneminusxseriesrev; ++i;
               /* If the lower limit isn't zero,
                  it calls shiftindex first; it also
                  will, via geomseries_aux, make other preparatory steps. */
             }
     }
  *nops = i;
}

/*_________________________________________________________________________________*/
MEXPORT_SERIES void series_ops(term t, actualop *o, int *nops)
/* called by post_ops to get operators to apply to an infinite series */
{ int problemtype = get_problemtype();
  int currenttopic = get_currenttopic();
  int i = 0;
  unsigned short g;
  term v,w,u;
  int pathlength = get_pathlength();
  u = ARG(0,t);
  if(FUNCTOR(t) != SUM || !equals(ARG(3,t),infinity))
     { *nops = 0;
       return;
     }
  if(currenttopic != _integral_test)
     { if(FRACTION(u) || (FUNCTOR(u) == '^' && equals(ARG(1,u),minusone)))
          { o[i] = harmonicseries; ++i;
          }
       if(FRACTION(u) && ONE(ARG(0,u)) && FUNCTOR(ARG(1,u)) == '^' &&
          equals(ARG(0,ARG(1,u)),ARG(1,t))
         )
          { if(equals(ARG(1,ARG(1,u)),two))
               { o[i] = zeta2; ++i;
               }
          }
     }
  if(problemtype == ADDSERIES || problemtype == TESTCONVERGENCE)
     /* an infinite sum and we're supposed to add it up */
     { g = FUNCTOR(ARG(0,t));
       switch(g)
          { case '+' :
               o[i] = seriessum; ++i;
               o[i] = sigmapoly; ++i;
               break;
            case '*' : /* fall-through */
            case '/' :
               o[i] = constantoutofsigma; ++i;
               o[i] = sigmapoly; ++i;
          }
     }
  if(problemtype == TESTCONVERGENCE &&
     ( pathlength == 1 || ok_convergence_test() ) &&
     !CONVERGENT(t)   /* the CONVERGENT bit is set when the convergence or divergence is established */
    )
     { /* which convergence test to use?  */
       /* first internally check if the n-th term tends to zero or not */
       v = limit(arrow(ARG(1,t),infinity),ARG(0,t));
       if(!limval(v,&w) && !ZERO(w))
          { o[i] = divergencetest; ++i;
          }
       if(currenttopic == _integral_test)
          { o[i] = integraltest; ++i;
          }
       else if(currenttopic == _comparison_test)
          { if(contains(t,LN))
               { o[i] = condensationtest; ++i;
               }
            o[i] = limitcomparisontest; ++i;
            o[i] = comparisontest1; ++i;
            o[i] = comparisontest2; ++i;
          }
       else if(currenttopic == _root_ratio_tests)
          { if(get_nvariables() > 1)
               { /* probably a power series, try the root test first */
                 o[i] = roottest; ++i;
                 o[i] = ratiotest; ++i;
               }
            else  /* try the ratio test first */
               { o[i] = ratiotest; ++i;
                 o[i] = roottest; ++i;
               }
          }
       else /* topic doesn't tell us what to do */
          { if(contains(t,FACTORIAL))
               { o[i] = roottest; ++i;
                 o[i] = ratiotest; ++i;
               }
            else
               { o[i] = integraltest; ++i;
                 o[i] = ratiotest; ++i;
                 o[i] = roottest; ++i;
                 o[i] = limitcomparisontest; ++i;
                 o[i] = comparisontest1; ++i;
                 o[i] = comparisontest2; ++i;
               }
          }
     }
   *nops = i;
 }
/*______________________________________________________________________________*/
MEXPORT_SERIES const char * series_fremark(term t)
/* called by fremark to test whether we're finished or not. 
If not, return a message.  If can't reject the answer,
return NULL.
*/

{ unsigned short f;
  if(used4(divergencetest))
     return english(2300);
     /* You started the divergence test, but didn't finish it yet. */
  if(used4(integraltest))
     return english(2301);
     /* You started the integral test, but didn't finish it yet. */
  if(used4(comparisontest1) || used4(comparisontest2))
     return english(2302);
     /* You started the comparison test, but didn't finish it yet. */
  if(used4(limitcomparisontest))
     return english(2303);
     /* You started the limit comparison test, but didn't finish it yet. */
  if(used4(condensationtest))
     return english(2304);
     /* You started the condensation test, but didn't finish it yet. */
  if(used4(roottest))
     return english(2305);
     /* You started the root test, but didn't finish it yet. */
  if(used4(ratiotest))
     return english(2305);
     /* You started the ratio test, but didn't finish it yet. */
  if(used4(finishcomparisontest1) || used4(finishcomparisontest2))
     return english(2404);
  f = FUNCTOR(t);
  if(f == SUM && CONVERGENT(t))
     return NULL;  /* CONVERGENT means the question of convergence is settled. */
  if(!INEQUALITY(f))
     { /* Other than a series with CONVERGENT set, 
          acceptable answers are, where u is the original series,
          of the form   u < infinity, u < some estimate,
          u = infinity, u = undefined, u = minusinfinity, etc.
       */
       return english(2307);
       /* The convergence or divergence is not yet settled. */
     }
   return NULL;
}

/*________________________________________________________________________________*/
static int series_index(actualop code)
/* return one of the identifiers at the top of this file to identify this series
operation.  Code is assumed to be one of the operations on the
series_convergence_tests or series_convergence2 menu.  Return -1
if the operation is not found.
*/
{ if( (void  *) code == (void  *) divergencetest)
       return DIVERGENCETEST;
  if( (void  *) code == (void  *) integraltest)
       return INTEGRALTEST;
  if( (void  *) code == (void  *) ratiotest)
       return RATIOTEST;
  if( (void  *) code == (void  *) roottest)
       return ROOTTEST;
  if( (void  *) code == (void  *) comparisontest1)
       return COMPARISONTEST1;
  if( (void  *) code == (void  *) comparisontest2)
       return COMPARISONTEST2;
  if( (void  *) code == (void  *) limitcomparisontest)
       return LIMITCOMPARISONTEST;
  if( (void  *) code == (void  *) condensationtest)
       return CONDENSATIONTEST;
  if( (void  *) code == (void  *) finishdivergencetest)
       return FINISHDIVERGENCETEST;
  if( (void  *) code == (void  *) finishintegraltest)
       return FINISHINTEGRALTEST;
  if( (void  *) code == (void  *) finishratiotest)
       return FINISHRATIOTEST;
  if( (void  *) code == (void  *) finishroottest)
       return FINISHROOTTEST;
  if( (void  *) code == (void  *) finishcomparisontest1)
       return FINISHCOMPARISONTEST1;
  if( (void  *) code == (void  *) finishcomparisontest2)
       return FINISHCOMPARISONTEST2;
  if( (void  *) code == (void  *) finishlimitcomparisontest)
       return FINISHLIMITCOMPARISONTEST;
  if( (void  *) code == (void  *) finishcondensationtest)
       return FINISHCONDENSATIONTEST;
  if( (void  *) code == (void  *) statefinalbound1)
       return STATEFINALBOUND1;
  if( (void  *) code == (void  *) statefinalbound2)
       return STATEFINALBOUND2;
  if( (void  *) code == (void  *) harmonicseries)
       return HARMONICSERIES;
  if( (void  *) code == (void  *) zeta2)
       return ZETA2;
  return -1;
}
/*________________________________________________________________________________*/
static int closer_index(int index)
/* if index is the identifier of a test-closing operation, return the
index of the corresponding open-test operation.  Return -1 otherwise.
*/
{ switch(index)
     { case FINISHDIVERGENCETEST:
          return DIVERGENCETEST;
       case FINISHINTEGRALTEST:
          return INTEGRALTEST;
       case FINISHRATIOTEST:
          return RATIOTEST;
       case FINISHROOTTEST:
          return ROOTTEST;
       case FINISHCOMPARISONTEST1:
          return COMPARISONTEST1;
       case FINISHCOMPARISONTEST2:
          return COMPARISONTEST2;
       case FINISHLIMITCOMPARISONTEST:
          return LIMITCOMPARISONTEST;
       case FINISHCONDENSATIONTEST:
          return CONDENSATIONTEST;
       case STATEFINALBOUND1:
          return FINISHCOMPARISONTEST1;
       case STATEFINALBOUND2:
          return FINISHCOMPARISONTEST2;
     }
  return -1;
}
/*________________________________________________________________________________*/

int used4(actualop op)
/* return the line at which convergence test 'op'
most recently been used, and its corresponding finish operation
has not been used, and every test opened since then has been closed.
Return 0 if there's no such line.
*/
{ int i,m,currentline;
  int flags[32];
  int index, closer;
  controldata cd;
  operation *opseq;
  actualop code;
  get_controldata(&cd);
  currentline = get_currentline();
  opseq = cd.opseq;
  index = series_index(op);
  if(index < 0)
     return 0; /* assert(0);  should not be called in this case */
  if(index > NCONVERGENCETESTS)
     return 0;
  memset(flags,0,32 * sizeof(int));
  /* flags will keep track of which convergence tests are open */
  for(i=currentline;i>0; i--)
     { if(opseq[i].men != series_convergence_tests &&
          opseq[i].men != series_convergence2
         )
          continue;
       code = access_optable(opseq[i].men)[opseq[i].choice-1];
       m = series_index(code);
       if(m < 0)
          assert(0);   /* series_index must list all operations on those two menus */
       /* m will be one of the identifiers in series.h */
       if(flags[m])
          { --flags[m];  /* an open corresponding to a close we passed already */
             continue;
          }
       if(m == index)
          return i;      /* success */
       closer = closer_index(m);
       if(closer > 0)
          { /* closing a test */
            ++flags[closer];
            closer = closer_index(closer);
            /* for example,  finishcomparisontest1 is both an opener for 
               statefinalbound1 and a closer for comparisontest1. */
            if(closer > 0)
               ++flags[closer];
          }
     }
  return 0;
}
/*________________________________________________________________________________*/

int used3(actualop op, int currentline)
/* return the line at which convergence test 'op'
most recently been, starting from the given line 'currentline' and 
working backward.  Return 0 if the operation hasn't been used.
*/
{ int i;
  controldata cd;
  operation *opseq;
  actualop code;
  get_controldata(&cd);
  opseq = cd.opseq;
  for(i=currentline;i>0; i--)
     { if(opseq[i].men != series_convergence_tests &&
          opseq[i].men != series_convergence2
         )
          continue;
       code = access_optable(opseq[i].men)[opseq[i].choice-1];
       if((void  *) code == (void  *) op)
           return i;
     }
  return 0;
}
/*_____________________________________________________________________________*/
MEXPORT_SERIES void series_toplevel(term t, actualop *o, int *nops)
/* called by postops to add operations that apply at toplevel
when the problemtype is TESTCONVERGENCE, but the current
expression has no sums, limits, or integrals.
*/
{ int i = 0;
  if(used4(integraltest))
     { o[i] = finishintegraltest; ++i;
     }
  else if(used4(roottest))
     { o[i] = finishroottest; ++i;
     }
  else if(used4(ratiotest))
     { o[i] = finishratiotest; ++i;
     }
  else if(used4(comparisontest1))
     { o[i] = finishcomparisontest1; ++i;
     }
  else if(used4(comparisontest2))
     { o[i] = finishcomparisontest2; ++i;
     }
  else if(used4(finishcomparisontest1))
     { o[i] = statefinalbound1; ++i;
     }
  else if(used4(finishcomparisontest2))
     { o[i] = statefinalbound2; ++i;
     }
  else if(used4(divergencetest))
     { o[i] = finishdivergencetest; ++i;
     }
  else if(used4(limitcomparisontest))
     { o[i] = finishlimitcomparisontest; ++i;
     }
  else if(used4(condensationtest))
     { o[i] = finishcondensationtest; ++i;
     }
  *nops = i;
}

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