Sindbad~EG File Manager
/* 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
10.24.23 eliminated OEM for \int
5.13.24 moved some $ in reason strings
*/
#include <string.h>
#include <assert.h>
#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 */
/*_______________________________________________________________________*/
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,"$\\int 1 dt = t$");
return 0;
}
/*_______________________________________________________________________*/
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)); /* \\int c dt=ct (c constant) */
return 0;
}
/*_______________________________________________________________________*/
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;
}
/*_______________________________________________________________________*/
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, "$\\int t dt= t^2/2$");
return 0;
}
/*_______________________________________________________________________*/
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,"$\\int u c\\pm v dt=\\int u dt \\pm \\int v dt$");
else
strcpy(reason,"$\\int u+v dt=\\int u dt + \\int v dt$");
return 0;
}
/*_______________________________________________________________________*/
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,"$\\int u-v dt=\\int u dt - \\int v dt$");
/* else leave the reason in place that intsum produced (with the \pm sign) */
return 0;
}
/*_______________________________________________________________________*/
int intlinearity(term t, term arg, term *next, char *reason)
/* \\int au \pm bv dt = a\\int u dt \pm b\\int 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,"$\\int au \\pm bv dt=a\\int udt \\pm b\\int vdt$");
return 0;
}
/*_______________________________________________________________________*/
int intpower(term t, term arg, term *next, char *reason)
{ term u,x,n,m,temp;
int err;
char buffer[128];
char *r = "$\\int t^n 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 = check1(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;
}
/*_______________________________________________________________________*/
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 = "$\\int 1/t^(n+1) dt = -1/(nt^n)$";
char *r2 = "$\\int 1/(t+a)^(n+1) dt = -1/(n(t+a)^n)$";
char *r3= "$\\int 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 = check1(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;
}
/*_______________________________________________________________________*/
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,"$\\sqrt t = t^(1/2)$");
return 0;
}
/*_______________________________________________________________________*/
int intrecip(term t, term arg, term *next, char *reason)
/* \\int (1/t) dt = ln |t| */
/* also \\int 1/(t \pm a) dt = ln |t \pm 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,"$\\int (1/t) dt = ln |t|$");
else if(ZERO(a) && FUNCTOR(b)=='-')
strcpy(reason,"$\\int 1/(t-b)dt = ln|t-b|$");
else if(ZERO(a))
strcpy(reason,"$\\int 1/(t+b)dt = ln|t+b|$");
else if(ZERO(b))
strcpy(reason,"$\\int 1/(ct)dt=(1/c)ln|ct|$");
else if(FUNCTOR(b)== '-')
strcpy(reason,"$\\int 1/(ct-b) dt = (1/c)ln|ct-b|$");
else
strcpy(reason,"$\\int 1/(ct+b) dt =(1/c)ln|ct+b|$");
return 0;
}
/*_______________________________________________________________________*/
int intrecip2(term t, term arg, term *next, char *reason)
/* \\int 1/(t \pm a) dt = ln |t \pm a| */
/* also \\int (1/t) dt = ln |t| */
{ return intrecip(t,arg,next,reason);
}
/*_______________________________________________________________________*/
int intrecip3(term t, term arg, term *next, char *reason)
/* \\int 1/(at+b) dt = (1/a)ln|at+b| */
{ return intrecip(t,arg,next,reason);
}
/*____________________________________________________________________*/
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;
}
/*____________________________________________________________________*/
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