Sindbad~EG File Manager

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

/* improper integration */
/*
8.13.98 original date
8.15.98 last modified.
8.26.04 modified finish_divtest 
*/

#include <string.h>
#include <assert.h>
#include <search.h>
#include <math.h>       /* fabs */

#include "globals.h"
#include "calc.h"
#include "domain.h"
#include "eqn.h"
#include "numint.h"
#include "sigma.h"
#include "prover.h"
#include "deval.h"
#include "mathmode.h"   /* get_mathmode */
#include "errbuf.h"
#include "pvalaux.h"    /* obviously_nonnegative */
#include "defint.h"     /* insertpoint_aux       */
#include "improper.h"
#include "mplimits.h"   /* get_sign */

static int split_and_finish(term t);
static int convergent_aux(term t);
/*________________________________________________________________________________________*/
int convergent(term t)
/* return 0 if t is a convergent definite integral, 1 if divergent,
   2 if we could not determine.
   Presumes that fillbinders has been called so that x can be inferred to
   be between a and b, i.e. a <= x <= b is the binder inequality.
   When the parent integral was accepted, it was verified that there are
   at most finitely many undefined places between a and b.
      This is used to block illegal applications of intlinearity, intsum,
   and intdif.
*/
{ int err,k;
  term x,a,b,u,dom,p,v,arg,temp;
  unsigned short n;
  int i;
  if(FUNCTOR(t) != INTEGRAL || ARITY(t) != 4)
     return 1;
  if(!IMPROPER(t))
     return 0;
  u = ARG(0,t);
  x = ARG(1,t);
  a = ARG(2,t);
  b = ARG(3,t);
  dom = lpt(domain(u));
  err = infer(dom);
  if(!err)
     /* no singularities in the interior or at finite endpoints */
     { if(ISINFINITE(a) && ISINFINITE(b))
          { err = convergent_aux(definite_integral(u,x,a,zero));
            if(err)
               return err;
            return convergent_aux(definite_integral(u,x,zero,b));
          }
       if(ISINFINITE(a) || ISINFINITE(b))
          return convergent_aux(t);
       /* We still have to worry about a discontinuous function
       defined by cases, e.g.  f(x) = if(x=0) 0 else 1/x  */
       if(!contains(u,CASES))
          return 0;
       return 2;   /* CASES not allowed in improper integrals */
     }
  if(FUNCTOR(dom) == AND && ARITY(dom) == 2 &&
     FUNCTOR(ARG(0,dom)) == NE &&
     FUNCTOR(ARG(1,dom)) == NE &&
     equals(ARG(0,ARG(0,dom)),x) &&
     equals(ARG(0,ARG(1,dom)),x) &&
     (
       (equals(ARG(1,ARG(0,dom)),a) && equals(ARG(1,ARG(1,dom)),b)) ||
       (equals(ARG(1,ARG(1,dom)),a) && equals(ARG(1,ARG(0,dom)),b))
     )
    )
     { /* no interior singularities but singular at both (finite)
          endpoints. */
       return split_and_finish(t);

     }
  if(FUNCTOR(dom) == NE && equals(ARG(0,dom),x) && equals(ARG(1,dom),a))
     { /* singular only at left endpoint */
       if(ISINFINITE(b))
          return split_and_finish(t);
       return convergent_aux(t);
     }
  if(FUNCTOR(dom) == NE && equals(ARG(0,dom),x) && equals(ARG(1,dom),b))
     { /* singular only at right endpoint */
       if(ISINFINITE(a))
          return split_and_finish(t);
       return convergent_aux(t);
     }

  /* Now we have interior singularities */
  /* dom should be an AND of NE terms of the form x != c */
  if(FUNCTOR(dom) == NE)
     { /* just one singularity */

       if(equals(ARG(0,dom),x) && !contains(ARG(1,dom),FUNCTOR(x)))
          arg = ARG(1,dom);
       else
          return 2;
       insertpoint_aux(t,arg,&temp,1);
       if(FUNCTOR(temp) != '+' || ARITY(temp) != 2)
          assert(0);
       for(i=0;i<2;i++)
          { err = convergent_aux(ARG(i,t));
            if(err)
               return err;
          }
       return 0;
     }
  if(FUNCTOR(dom) != AND)
     return 1;
  n = ARITY(dom);
  for(i=0;i<n;i++)
     { v = ARG(i,dom);
       if(!equals(ARG(0,v),x) || contains(ARG(1,v),FUNCTOR(x)))
          return 2;
     }


  arg = make_term(AND,n);
  k = 0;
  for(i=0;i<n;i++)
     { p = ARG(i,dom);
       if(equals(ARG(1,p),a) || equals(ARG(1,p),b))
          continue;
       ARGREP(arg,k,ARG(1,p));
       ++k;
     }
  if(k == 0)
     assert(0);  /* singular only at a and/or b, these cases trapped above */
  if(k == 1)
     { temp = ARG(0,arg);
       RELEASE(arg);
       arg = temp;
     }
  else
     SETFUNCTOR(arg,AND,k);
  insertpoint_aux(t,arg,&temp,1);
       /* the 1 says, do not check if the points are between a and b */
       /* temp is now a sum of integrals without internal singularities
          and singular at at most one endpoint */
  for(i=0;i<ARITY(temp);i++)
     { err = convergent_aux(ARG(i,t));
       if(err)
          return err;
     }
  return 0;
}
/*__________________________________________________________*/
static int split_and_finish(term t)
/* finish convergent, assuming we need to insert just one point
somewhere between a and b */
{ term a,b,temp,arg;
  int i,err;
  a = ARG(2,t);
  b = ARG(3,t);
  arg = split(a,b);
  insertpoint_aux(t,arg,&temp,1);
  if(FUNCTOR(temp) != '+' || ARITY(temp) != 2)
     assert(0);
  for(i=0;i<2;i++)
     { err = convergent_aux(ARG(i,temp));
       if(err)
         return err;
     }
  return 0;
}
/*_____________________________________________________________*/
term split(term a, term b)
/* return a value somewhere between a and b, at which it will be
convenient to split an integral which is singular at both a and b
but nowhere in between. */

{ term ans;
  double za,zb,z;
  if(equals(a,b))
     return a;  /* should never happen */
  if(equals(a,infinity))
     return split(b,a);
  if(equals(b,minusinfinity))
     return split(b,a);
  if(equals(b,infinity))
     { if(ZERO(a))
          return one;
       if(obviously_negative(a))
          return zero;
       if(!obviously_nonnegative(a) && !infer(lessthan(a,zero)))
          return zero;
       if(contains(a,FUNCTOR(pi_term)))
          polyval(sum(a,pi_term),&ans);
       else
          polyval(sum(a,one),&ans);
       return ans;
     }
  if(equals(a,minusinfinity))
     { if(ZERO(b))
          return minusone;
       if(obviously_positive(b))
          return zero;
       if(!obviously_negative(b) && !infer(lessthan(zero,b)))
          return zero;
       if(contains(b,FUNCTOR(pi_term)))
          polyval(sum(b,tnegate(pi_term)),&ans);
       else
          polyval(sum(b,minusone),&ans);
       return ans;
     }
  /* Now neither a nor b is infinite */
  if(seminumerical(a) && seminumerical(b) &&
     !deval(a,&za) && !deval(b,&zb) &&
     za != BADVAL &&
     zb != BADVAL
    )
     { if(za < 0.0 && zb > 0.0)
          return zero;
       if(zb < 0.0 && za > 0.0)
          return zero;
       if(fabs(zb-za) > 1.0)
          { /* find an integer in between a and b */
            z = floor(zb);
            if(z < (double) 0xeffffffL)
                return make_int( (int)(z + 0.001));
         }
     }
  if(obviously_positive(b) && obviously_negative(a))
     return zero;
  polyval(make_fraction(sum(a,b),two),&ans);
  return ans;
}
/*______________________________________________________________*/
static int convergent_aux(term t)
/* t is a definite integral known to have no internal singularities
and to be singular at at most one end.  The limits of integration
can be finite or infinite but at most one is infinite.
Return 0 for convergence, 1 for divergence, 2 for can't tell.
*/
{ term u,v,temp,x,a,b,c,deg,dir,p;
  int err;
  double za,zb;
  u = ARG(0,t);
  x = ARG(1,t);
  a = ARG(2,t);
  b = ARG(3,t);
  if(ISINFINITE(a))
     { temp = a;
       a = b;
       b = temp;
     }
  if(ISINFINITE(b))
     { /* get the leading term at infinity
         (or minusinfinity as the case may be) */
       err = leading_term(u,x,b,&c,&deg);
       if(!err)
          { /* u goes as cx^deg.  So if deg is < -1, it converges,
               and otherwise it diverges. */
            temp = lpt(lessthan(deg,minusone));
            err = infer(temp);
            if(!err)
               return 0;
            if(err == 2)
               /* refutation */
               return 1;
            assume(temp);
               return 0;
          }
       /* Could not get the leading term */
       v = limit(arrow(x,b),u);
       err = limval(v,&temp);
       if(!err && !ZERO(temp))
          return 1;  /* divergent */
       /* This will take care of u = sin(x) etc. also as the limval is
          bounded_oscillations */
       v = limit(arrow(x,b),product(u,make_power(x,two)));
       err = limval(v,&temp);
       if(!err && !NOTDEFINED(temp))
          return 0;   /* convergent if u = O(1/x^2) */
       v = limit(arrow(x,b),product(u,x));
       err = limval(v,&temp);
       if(!err && !ZERO(temp))
          return 1;  /* divergent unless u = o(1/x) */
       /* What have we left unsettled here?  integrands without
       leading term which are neither O(1/x^2) nor o(1/x). That is
       1/x^2 << u <= 1/x, e.g. u = O(x^(-3/2), but that would have a
       leading term.  I can't think of an example we haven't touched.
       */
       return 2;
     }
  /* Now, both a and b are finite values.  Supposedly u is singular
  at just one of them.  Which one? */
  deval(a,&za);
  deval(b,&zb);
  if(za == BADVAL && zb == BADVAL)
     return 2;  /* assert(0) */
  p = za == BADVAL ? a : b;
  err = leading_term(u,x,p,&c,&deg);
  if(!err)
     { /* u goes as c(x-b)^deg.  So if deg is <= -1, it diverges,
          and otherwise it converges. */
       temp = lpt(le(deg,minusone));
       err = infer(temp);
       if(!err)
          return 1;
       if(err == 2)
         /* refutation */
         return 0;
       assume(temp);
       return 0;
     }
  /* Could not get the leading term */
  dir = za == BADVAL ? right : left;
  v = limit3(arrow(x,p),dir,product(x,u));
  err = limval(v,&temp);
  if(!err && !ZERO(temp))
          return 1;  /* divergent, 1/x <= cu */
  v = limit3(arrow(x,p),dir,product(make_power(x,two),u));
  err = limval(v,&temp);
  if(!err && !NOTDEFINED(temp))
      return 0;   /* convergent if  1/x^2 >= cu */
  return 2;
}
/*__________________________________________________________*/
static int finish_divtest(term v,term *next,char *reason)
/* evaluate the limit v and if it exists and is nonzero, return 0
for success, with either infinity or minusinfinity in *next (as the 
value of an integral of v).  Note that if the limit fails to exist,
e.g. if v oscillates, we can't conclude that the integral is undefined.
  Return 1 for failure.
*/
{ term u,w,dom;
  int err,sign;
  short savenextassumption;
  double z;
  err = limval(v,&w);
  if(err)
     { errbuf(0,english(2283));
       /* MathXpert cannot evaluate the limit. */
       return 1;
     }
  if(NOTDEFINED(w) && !ISINFINITE(w))
     { *next = undefined;
       errbuf(0, english(2293));
       /* limit of integrand is undefined */
       return 1;  /* Not 0 as was originally here */
     }
  if(ZERO(w))
     { errbuf(0,english(2284));
       /* The limit is zero. */
       return 1;
     }
  if(seminumerical(w) && !ISINFINITE(w))
     { deval(w,&z);
       if(z == 0.0 || fabs(z) < VERYSMALL)
          { errbuf(0, english(2284));  /* The limit is zero */
            return 1;
          }
       sign = z > 0.0 ? 1 : -1;
     }
  else
     { savenextassumption = get_nextassumption();
       if(equals(w,infinity))
          sign = 1;
       else if(equals(w,minusinfinity))
          sign = -1;
       else
          sign = get_sign(w);  /* making new assumptions if necessary */
       if(sign == 0)
          { errbuf(0,english(2284));
            set_nextassumption(savenextassumption);
            return 1;
          }
     }
  u = ARG(1,v);
  dom = lpt(domain(u));
  err = infer(dom);
  if(!err)
     { *next = sign > 0 ? infinity : minusinfinity;
       strcpy(reason, english(2285));  /* limit of integrand is not zero. */
       return 0;
     }
  /* Now there are other singularities, either at a or interior */
  if(obviously_nonnegative(u))
     { *next = infinity;
       strcpy(reason, english(2285));
       commentbuf(0, english(2286));
       commentbuf(1, english(2287));
       /* Although there are singularities, the integrand is nonnegative,
          so the integral is infinite rather than just undefined. */
       return 0;
     }
  commentbuf(0, english(2288));
  commentbuf(1, english(2289));
  commentbuf(2, english(2290));
  /*  There are singularities.  You might be able to get the answer
      $infinity $ or $-infinity$ if you first break the integral, unless it contains
      infinities of both signs. */
  *next = undefined;
  return 0;
}
/*___________________________________________________________*/
int intdivtest1(term t, term arg, term *next, char *reason)
/* an integral to infinity diverges if the limit of the integrand exists and 
is not zero.  
*/
{ term b,u,v,x;
  if(FUNCTOR(t) != INTEGRAL || ARITY(t) != 4)
     return 1;
  b = ARG(3,t);
  if(!equals(b,infinity))
     return 1;
  u = ARG(0,t);
  x = ARG(1,t);
  v = limit(arrow(x,infinity),u);
  return finish_divtest(v,next,reason);
}

/*___________________________________________________________*/
int intdivtest2(term t, term arg, term *next, char *reason)
/* an integral from minusinfinity diverges if the limit of the integrand 
exists and is not zero. */
{ term a,u,v,x;
  if(FUNCTOR(t) != INTEGRAL || ARITY(t) != 4)
     return 1;
  a = ARG(2,t);
  if(!equals(a,minusinfinity))
     return 1;
  u = ARG(0,t);
  x = ARG(1,t);
  v = limit(arrow(x,minusinfinity),u);
  return finish_divtest(v,next,reason);
}

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