Sindbad~EG File Manager

Current Path : /usr/home/beeson/Otter-Lambda/yyy/trigcalc/
Upload File :
Current File : /usr/home/beeson/Otter-Lambda/yyy/trigcalc/basicint.c

/* operators for basic_integration menu  */
/* but intminus and intlinear are in algint.c in algebra.dll */
/*
M. Beeson, for MathXpert
11.3.91  Original date
2.28.98 code last modified
*/
#include <string.h>
#include <assert.h>
#define TRIGCALC_DLL
#include "globals.h"
#include "ops.h"
#include "calc.h"
#include "factor.h"
#include "cancel.h"
#include "intsub.h"
#include "algaux.h"
#include "polynoms.h"
#include "order.h"
#include "integral.h"
#include "prover.h"
#include "symbols.h"
#include "islinear.h"
#include "errbuf.h"
#include "autosimp.h"
#include "dispfunc.h"
#include "pvalaux.h"   /* twoparts */
#include "improper.h"  /* convergent */
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int int1(term t, term arg, term *next, char *reason)
{ if(FUNCTOR(t) != INTEGRAL)
     return 1;
  if(!ONE(ARG(0,t)))
    return 1;
  if(ARITY(t) == 2)  /* an indefinite integral */
      *next = ARG(1,t);
  else if (ARITY(t)==4)  /* a definite integral */
      *next = sum(ARG(3,t),tnegate(ARG(2,t)));
  HIGHLIGHT(*next);
  strcpy(reason,"$� 1 dt = t$");
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intconst(term t, term arg, term *next, char *reason)
{ term u,x;
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  u = ARG(0,t);
  x = ARG(1,t);
  if(depends(u,x))
     return 1;
  if(ARITY(t) == 2)  /* an indefinite integral */
      *next = product(u,x);
  else if (ARITY(t)==4)  /* a definite integral */
      *next = evalat(product(u,x),x,ARG(2,t),ARG(3,t));
  HIGHLIGHT(*next);
  strcpy(reason, english(712)); /* �c dt=ct (c constant) */
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intpoly(term t, term arg, term *next, char *reason)
{ term x,u,mid,v;
  unsigned short n;
  int i,err;
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  x = ARG(1,t);
  u = ARG(0,t);
  if(ARITY(t)==4)  /* definite integral */
     { err = intpoly(integral(u,x),arg,&mid,reason);
       if(err)
          return 1;
       if(contains(mid,INTEGRAL))  /* e.g. if u = x^(1/2) + x^2,
                                      mid is a sum of an integral and x^3/3 */
         { if(FUNCTOR(mid) != '+')
              return 1;
           n = ARITY(mid);
           *next = make_term('+',n);
           for(i=0;i<n;i++)
              { v = ARG(i,mid);
                if(FUNCTOR(v)==INTEGRAL)
                   { ARGREP(*next,i,definite_integral(ARG(0,v),x,ARG(2,t),ARG(3,t)));
                   }
                else
                   { ARGREP(*next,i,evalat(v,x,ARG(2,t),ARG(3,t)));
                   }
              }
           goto out;
         }
       *next = evalat(mid,x,ARG(2,t),ARG(3,t));
       goto out;
     }
  if(FUNCTOR(u) != '+' && !monomial(u))
     return 1;
  if(ispolyin(u,x))
    { err = simple_integral(u,x,next);
      if(err)
         return 1;  /* it CAN fail, e.g. if u is yx^2 where the user has
              answered (to ask_user_about_parameters) that y depends on x */
    }
  else if(FUNCTOR(u) != '+')
     return 1;
  else   /* e.g.  x + 3x^2 + sin x  + x^4 */
     { n = ARITY(u);
       *next = make_term('+',n);
       for(i=0;i<n;i++)
         { if(monomial(ARG(i,u)))
              { err = simple_integral(ARG(i,u),x,ARGPTR(*next)+i);
                if(err)
                   return 1;
              }
           else
              ARGREP(*next,i,integral(ARG(i,u),x));
         }
     }
  out:
  HIGHLIGHT(*next);
  strcpy(reason, english(800));  /* integrate polynomial */
  return 0;
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intident(term t, term arg, term *next, char *reason)
{ term u,x,temp;
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  u = ARG(0,t);
  x = ARG(1,t);
  if(!equals(u,x))
     return 1;
  temp= make_fraction(make_power(x,two),two);
  if(ARITY(t) == 2)  /* an indefinite integral */
     *next = temp;
  else if (ARITY(t)==4)  /* a definite integral */
     *next = evalat(temp,x,ARG(2,t),ARG(3,t));
  HIGHLIGHT(*next);
  strcpy(reason, "$�t dt= t^2/2$");
  return 0;
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intsum(term t, term arg, term *next, char *reason)
{ term u,v,x;
  int i,err;
  int flag = 0; /* set when we encounter a minus sign */
  unsigned short n;
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  u = ARG(0,t);
  x = ARG(1,t);
  if(FUNCTOR(u) != '+')
     return 1;
  n = ARITY(u);
  *next = make_term('+',n);
  if(ARITY(t) == 2)  /* an indefinite integral */
     { for(i=0;i<n; i++)
          { if(FUNCTOR(ARG(i,u))=='-')
               { flag = 1;
                 ARGREP(*next,i,tnegate(integral(ARG(0,ARG(i,u)),x)));
               }
            else
               ARGREP(*next,i, integral(ARG(i,u),x));
          }
     }
  else if (ARITY(t)==4)  /* a definite integral */
     { for(i=0;i<n; i++)
          { if(FUNCTOR(ARG(i,u)) == '-')
               { flag = 1;
                 v  =  definite_integral(ARG(0,ARG(i,u)),x,ARG(2,t),ARG(3,t));
                 ARGREP(*next,i,tnegate(v));
               }
            else
               { v = definite_integral(ARG(i,u),x,ARG(2,t),ARG(3,t));
                 ARGREP(*next,i,v);
               }
           if(IMPROPER(t))
              { /* then we have to check that the new integrals are defined.  Example:
                   integral(sqrt(x) - sqrt(x+1),x,0,infinity) shouldn't be broken up
                   into the difference of two divergent integrals. */
                SETIMPROPER(v);
                err = convergent(v);
                if(err)
                   { errbuf(0,english(2278));
                     /* The new integrals would not be defined, so this operation is illegal */
                     return 1;
                   }
              }

          }
     }
  HIGHLIGHT(*next);
  if(flag)
     strcpy(reason,"$�u�v dt=�u dt � �v dt$");
  else
     strcpy(reason,"$�u+v dt=�u dt + �v dt$");
  return 0;
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intdif(term t, term arg, term *next, char *reason)
{ term u;
  unsigned short n;
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '+')
     return 1;
  n = ARITY(u);
  if(FUNCTOR(ARG(n-1,u)) != '-')
     return 1;
  intsum(t,arg,next,reason);
  if(ARITY(t)==2)
     strcpy(reason,"$�u-v dt=�u dt - �v dt$");
  /* else leave the reason in place that intsum produced (with the � sign) */
  return 0;
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intlinearity(term t, term arg, term *next, char *reason)
/* �au�bv dt = a�u dt � b�v dt */
{ term u,v,w,c,s,x,a,b,q;
  int i,err,flag;
  unsigned short n;
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  u = ARG(0,t);
  x = ARG(1,t);
  if(FUNCTOR(u) == '*')
     return intlinear(t,arg,next,reason);
  if(FUNCTOR(u) != '+')
     return 1;
  n = ARITY(u);
  *next = make_term('+',n);
  if(ARITY(t) == 2)  /* an indefinite integral */
     { for(i=0;i<n; i++)
          { v = ARG(i,u);
            if(NEGATIVE(v))
               { flag = 1;
                 v = ARG(0,v);
               }
            else
               flag = 0;
            twoparts(v,x,&c,&s);
            w = signedproduct(c,integral(s,x));
            if(flag)
               w = tnegate(w);
            ARGREP(*next,i,w);
          }
     }
  else if (ARITY(t)==4)  /* a definite integral */
     { a = ARG(2,t);
       b = ARG(3,t);
       for(i=0;i<n; i++)
          { v = ARG(i,u);
            if(NEGATIVE(v))
               { flag = 1;
                 v = ARG(0,v);
               }
            else
               flag = 0;
            twoparts(v,x,&c,&s);
            q = definite_integral(s,x,a,b);
            if(IMPROPER(t))
               { /* then we have to check that the new integrals are defined.  Example:
                    integral(sqrt(x) - sqrt(x+1),x,0,infinity) shouldn't be broken up
                    into the difference of two divergent integrals.  Another example:
                    1/((x-1)(x+1))  can be put into partial fraction form 1/(2(x-1)) + 1/(2(x+1))
                    and if integrated to infinity, these two would give divergent integrals.
                    Also, if the integrand has interior singularities, or singularities at
                    both endpoints,  insertpoint should be used first.
                  */
                 SETIMPROPER(q);
                 err = convergent(q);
                 if(err)
                    { errbuf(0,english(2278));
                      /* The new integrals would not be defined, so this operation is illegal */
                      return 1;
                    }
               }
            w = signedproduct(c,q);
            if(flag)
               w = tnegate(w);
            ARGREP(*next,i,w);
          }
     }
  HIGHLIGHT(*next);
  strcpy(reason,"$�au�bv dt=a�udt�b�vdt$");
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intpower(term t, term arg, term *next, char *reason)
{ term u,x,n,m,temp;
  int err;
  char buffer[128];
  char *r = "$�t� dt= t^(n+1)/(n+1)$";
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  x = ARG(1,t);
  if(equals(ARG(0,t),x))
     { SetShowStepOperation(intident);
       return intident(t,arg,next,reason);
     }
  if(FUNCTOR(ARG(0,t)) != '^')
     return 1;
  u = ARG(0,ARG(0,t));
  n = ARG(1,ARG(0,t));
  if(depends(n,x))
     { strcpy(buffer, english(713));  /* Exponent depends on  */
       strcat(buffer,atom_string(x));
       strcat(buffer,",");
       errbuf(0,buffer);
       errbuf(1, english(714)); /* so you can't use that operator. */
       return 1;
     }
  if(!equals(u,x))
     return 1;
  err = check(ne(n,minusone));
  if(err)
     { errbuf(0, english(715)); /* When the exponent is -1 */
       errbuf(1,english(716)); /* the power rule does not apply. */
       return 1;
     }
  temp = sum(n,one);
  if(status(intpower) <= LEARNING)  /* then don't evaluate new exponent */
     m = temp;
  else
     { err = value(temp,&m);
       if(err != 0 && err != 2)
          m = temp;
     }
  temp = make_fraction(make_power(x,m),m);
  if(ARITY(t) == 2)  /* an indefinite integral */
     *next = temp;
  else if (ARITY(t)==4)  /* a definite integral */
     *next = evalat(temp,x,ARG(2,t),ARG(3,t));
  HIGHLIGHT(*next);
  strcpy(reason,r);
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intinversepower(term t, term arg, term *next, char *reason)
{ term u,x,n,m,temp,denom,a,b;
  int err;
  char buffer[128];
  char *r = "$�1/t^(n+1) dt$ =          -1/(nt^n)";
  char *r2 = "$�1/(t+a)^(n+1) dt$ =     -1/(n(t+a)^n)";
  char *r3=  "$�1/(at+b)^(n+1) dt$ =    -1/(an(at+b)^n)";
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  if(IMPROPER(t))
     { errbuf(0,english(2364));
       /* It is not correct to apply this operation to an improper integral */
       return 1;
     }
  x = ARG(1,t);
  if(FUNCTOR(ARG(0,t)) != '/')
     return 1;
  if(!ONE(ARG(0,ARG(0,t))))
     return 1;   /* numerator must be 1 */
  denom = ARG(1,ARG(0,t));
  if(FUNCTOR(denom) != '^')
     return 1;
  u = ARG(0,denom);
  n = ARG(1,denom);
  if(depends(n,x))
     { strcpy(buffer, english(713)); /* Exponent depends on  */
       strcat(buffer,atom_string(x));
       strcat(buffer,",");
       errbuf(0,buffer);
       errbuf(1,english(714)); /* so you can't use that operator. */
       return 1;
     }
  if(!equals(u,x) && status(intsub) <= LEARNING)
     return 1;
  if(!islinear(u,x,&a,&b))
     return 1;
  err = check(ne(n,one));
  if(err)
     { errbuf(0,english(717)); /* When the exponent is 1 */
       errbuf(1,english(718)); /* that rule does not apply */
       return 1;
     }
  temp = sum(n,minusone);
  if(status(intinversepower) <= LEARNING)  /* then don't evaluate new exponent */
     m = temp;
  else
     { err = value(temp,&m);
       if(err != 0 && err != 2)
          m = temp;
     }
  temp = tnegate(make_fraction(one,product3(a,m,make_power(u,m))));
  if(ARITY(t) == 2)  /* an indefinite integral */
     *next = temp;
  else if (ARITY(t)==4)  /* a definite integral */
     *next = evalat(temp,x,ARG(2,t),ARG(3,t));
  HIGHLIGHT(*next);
  if(ONE(a) && ONE(b))
     strcpy(reason,r);
  else if(ONE(a))
     strcpy(reason,r2);
  else
     strcpy(reason,r3);
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intsqrt(term t, term arg, term *next, char *reason)
{ term u,x;
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  u = ARG(0,t);
  x = ARG(1,t);
  if(FUNCTOR(u) != SQRT)
     return 1;
  if(!equals(ARG(0,u),x))
     return 1;
  if(ARITY(t) == 2)  /* an indefinite integral */
     *next = integral(make_power(ARG(0,u),make_fraction(one,two)),x);
  else if (ARITY(t)==4)  /* a definite integral */
     *next = definite_integral(
                               make_power(ARG(0,u),make_fraction(one,two)),
                               x, ARG(2,t),ARG(3,t)
                              );
  HIGHLIGHT(*next);
  strcpy(reason,"$�t = t^(1/2)$");
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intrecip(term t, term arg, term *next, char *reason)
/* � (1/t) dt = ln |t| */
/* also � 1/(t�a) dt = ln |t�a| */
{ term u,v,x,lo,hi,a,b,denom;
  int err;
  char buffer[128];
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  x = ARG(1,t);
  u = ARG(0,t);
  if(FUNCTOR(u) == '^' && equals(ARG(1,u),minusone))
     u = reciprocal(ARG(0,u));
  if(FUNCTOR(u) != '/')
     return 1;
  if(!ONE(ARG(0,u)))
     return 1;
  denom = ARG(1,u);
  if(!islinear(denom,x,&a,&b))
     return 1;
  if(ARITY(t) == 2)  /* an indefinite integral */
    { err = infer(le(zero,denom));  /* le is enough, don't need lessthan */
      if(err)
         { v = ln1(abs1(denom));
           SETPRIME(ARG(0,v));
           /* so we won't waste time trying to infer its sign later */
         }
      else
         v = ln1(denom);
      *next = ONE(a) ? v :  signedproduct(reciprocal(a),v);
      goto out;
    }
  assert(ARITY(t)==4);  /* a definite integral */
  lo = ARG(2,t);
  hi = ARG(3,t);
  err = infer(le(lo,hi));
  if(err)
     { err = infer(le(hi,lo));
       if(!err)
           { hi = ARG(2,t);
             lo = ARG(3,t);
           }
       else
          assume(le(lo,hi));
     }
  err = infer(lessthan(zero, sum(signedproduct(a,lo),b)));
  if(!err)
     { *next = evalat(ONE(a) ? ln1(denom): signedproduct(reciprocal(a),ln1(denom)),x,ARG(2,t),ARG(3,t));
       goto out;
     }
  err = infer(lessthan(sum(signedproduct(a,hi),b),zero));
  if(!err)
     { *next = evalat(ONE(a) ? ln1(tnegate(denom)): signedproduct(reciprocal(a),ln1(tnegate(denom))),x,ARG(2,t),ARG(3,t));
       goto out;
     }
  /* can't infer that ax+b is on one side or the other of 0 */
  errbuf(0,english(719));
     /*  Can't verify that the interval of integration */
  errbuf(1, english(720));
     /*  does not include a singularity.  You can't */
  strcpy(buffer, english(721)); /* integrate 1/ */
  strcat(buffer, equals(a,zero) ? english(722) : english(723));
                /* t across t=0. */  /* t-a across t=a */
  errbuf(2,buffer);
  return 1;
  out:
     HIGHLIGHT(*next);
     if(ZERO(a) && ZERO(b))
        strcpy(reason,"$�(1/t) dt = ln |t|$");
     else if(ZERO(a) && FUNCTOR(b)=='-')
        strcpy(reason,"$�1/(t-b)dt = ln|t-b|$");
     else if(ZERO(a))
        strcpy(reason,"$�1/(t+b)dt = ln|t+b|$");
     else if(ZERO(b))
        strcpy(reason,"$�1/(ct)dt=(1/c)ln|ct|$");
     else if(FUNCTOR(b)== '-')
        strcpy(reason,"$�1/(ct-b) dt$ =        (1/c)ln|ct-b|");
     else
        strcpy(reason,"$�1/(ct+b) dt$ =        (1/c)ln|ct+b|");
     return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intrecip2(term t, term arg, term *next, char *reason)
/* � 1/(t�a) dt = ln |t�a|  */
/* also � (1/t) dt = ln |t| */
{ return intrecip(t,arg,next,reason);
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int intrecip3(term t, term arg, term *next, char *reason)
/* �1/(at+b) dt =        (1/a)ln|at+b| */
{ return intrecip(t,arg,next,reason);
}

/*____________________________________________________________________*/
MEXPORT_TRIGCALC int expandintegrand(term t, term arg, term *next, char *reason)
/* apply binomial theorem in integrand */

{ term u,v,temp,temp2;
  unsigned short f,n;
  int i,j,err;
  int flag = 0;   /* whether the integrand is a fraction or not */
  unsigned short path[31];
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  u = ARG(0,t);
  f = FUNCTOR(u);
  if(ATOMIC(u))
     return 1;
  if(f == '/')
     { flag = 2;
       path[0] = INTEGRAL;
       path[1] = 1;
       path[2] = '/';
       path[3] = 1;
       u = ARG(0,u);
       f = FUNCTOR(u);
       if(ATOMIC(u))
          return 1;
     }
  switch(f)
     { case '^' :
          err = binomialtheorem(u,arg,&temp,reason);
          if(err)
             return 1;
          path[0] = INTEGRAL;
          path[1] = 1;
          path[2+flag] = 0;
          set_pathtail(path);
          if(!GetShowStepOperation())
             /* It may have been set by binomialtheorem */
             SetShowStepOperation(binomialtheorem);
          break;
       case '*' :
          n = ARITY(u);
          for(i=0;i<n;i++)
             { v = ARG(i,u);
               if(FUNCTOR(v) == '^' && FUNCTOR(ARG(0,v)) == '+' && INTEGERP(ARG(1,v)))
                    { err = binomialtheorem(v,arg,&temp2,reason);
                      if(err)
                         continue;
                      break;
                    }
             }
          if(i<n)  /* it worked */
             { temp = make_term('*',n);
               path[0] = INTEGRAL;
               path[1] = 1;
               path[2+flag] = '*';
               path[3+flag] = i+1;
               path[4+flag] = 0;
               set_pathtail(path);
               if(!GetShowStepOperation())
                  SetShowStepOperation(binomialtheorem);
               for(j=0;j<n;j++)
                  ARGREP(temp,j, j==i ? temp2 : ARG(j,u));
               break;  /* from the switch */
             }
          return 1;
       default:   /* functors other than '*' and '^' */
          return 1;  /* it failed */
     }
  if(flag)
     temp = make_fraction(temp,ARG(1,ARG(0,t)));
  *next = ARITY(t) == 2 ? integral(temp,ARG(1,t)) : definite_integral(temp,ARG(1,t),ARG(2,t),ARG(3,t));
  return 0;
}
/*____________________________________________________________________*/
MEXPORT_TRIGCALC int multiplyoutintegrand(term t, term arg, term *next, char *reason)

{ term u,temp;
  unsigned short f;
  unsigned short path[5];
  int err;
  int flag = 0;   /* whether the integrand is a fraction or not */
  if(FUNCTOR(t) != INTEGRAL)
     return 1;
  u = ARG(0,t);
  f = FUNCTOR(u);
  if(f == '/')
     { flag = 1;
       u = ARG(0,u);
       f = FUNCTOR(u);
     }
  if(f != '*')
     return 1;
  err = multiplyout(u,arg,&temp,reason);
  if(err)
     return 1;
  if(flag)
     temp = make_fraction(temp,ARG(1,ARG(0,t)));
  *next = ARITY(t) == 2 ? integral(temp,ARG(1,t)) : definite_integral(temp,ARG(1,t),ARG(2,t),ARG(3,t));
  path[0] = INTEGRAL;
  path[1] = 1;
  path[2] = 0;
  set_pathtail(path);
  SetShowStepOperation(multiplyout);
  return 0;
}

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