Sindbad~EG File Manager
/* M. Beeson, simple differentiation operators for MathXpert */
/*
1.14.91 original date
2.27.98 last modified
3.10.99 corrected difabs2
11.16.00 corrected fundamentaltheorem2 on indefinite integrals
6.3.05 corrected typo at line 902
10.12.10 corrected difrecip ad line 418
5.6.13 include diff.h
5.20.13 removed include getprob.h
8.24.23 eliminated OEM for \pm and \sqrt
2.5.24 $$ reasons throughout
2.7.24 removed $$ from difeqn, as parser can't handle "implies"
4.25.24 put x^(1/n) in display math
10.1.24 added english(1253)
*/
#include <string.h>
#include <assert.h>
#include "globals.h"
#include "ops.h"
#include "calc.h"
#include "polynoms.h"
#include "probtype.h"
#include "deriv.h"
#include "cancel.h"
#include "order.h"
#include "factor.h"
#include "algaux.h"
#include "prover.h"
#include "symbols.h"
#include "errbuf.h"
#include "relrates.h"
#include "autosimp.h" /* SetShowStepOperation */
#include "dispfunc.h"
#include "deval.h"
#include "pvalaux.h" /* twoparts */
#include "diff.h"
static term dif_aux2(term u, term x);
/*_______________________________________________________________________*/
static void difdef_warning(term t)
/* If a user tries to differentiate e.g. x^(1/2) from definition,
they will get a comment about the difficulty of the resulting limit. */
{ if(FUNCTOR(t) == '^' && FRACTION(ARG(1,t)) && equals(ARG(1,ARG(1,t)),two))
{ commentbuf(0, english(1034));
/* You might do better to work with sqrt x instead of x^(1/2). */
return;
}
/* More cases can be explained here if required. */
}
/*_______________________________________________________________________*/
int defnofderivative(term t, term arg, term *next, char *reason)
{ term h; /* for the limit variable */
term x,u,a,q;
int nvariables;
varinf *varinfo = get_varinfo();
term *varlist = get_varlist();
int i;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
if(!ISATOM(x)) /* supposedly such terms can't ever be created anyway */
{ errbuf(0, english(591));
/* In du/dx, x must be a variable. */
return 1;
}
u = ARG(0,t);
h = getnewvar(t,"hpqrst"); /* already adds it to the varlist */
if(FUNCTOR(h)==ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more. */
return 1;
}
nvariables = get_nvariables();
SETORDERED(h); /* we'll make its dependency information in varinfo
show it dependent on x; order.c uses this to ensure
that xh won't get re-ordered to hx. But, we don't
mark it with SETDEPENDENT, as that screws up
stdpart, which then thinks it is dealing with a
limit at infinity. */
SETORDERED(varlist[nvariables-1]);
assert(FUNCTOR(varlist[nvariables-1]) == FUNCTOR(h)); /* it was just added */
set_eigenvariable(nvariables-1); /* make h the new eigenvariable */
/* This will make factoroutconstant treat expressions not
involving h as constant; without it automode can't differentiate
e^x from the definition of derivative */
varinfo[nvariables-1].scope = BOUND; /* specify that the new variable is
a bound variable; this will be used by actual_condition in axioms.c */
varinfo[nvariables-1].multorder = 1; /* used by multcompare1 to control
ordering of factors */
/* find out which varlist[i] is x */
for(i=0;i<nvariables;i++)
{ if(equals(varlist[i],x))
break;
}
assert(i<nvariables);
varinfo[nvariables-1].dp |= (1 << i); /* set bit i of the depends info for h */
subst(sum(x,h),x,u,&a);
q = make_term(ARROW,2);
ARGREP(q,0,h);
ARGREP(q,1,zero);
*next = limit(q,make_fraction(sum(a,tnegate(u)),h));
SETCOLOR(*next,YELLOW);
strcpy(reason, english(592)); /* defn of derivative */
difdef_warning(t);
return 0;
}
/*______________________________________________________________________*/
void set_chainrule_errmsg(void)
/*
That operation won't work here because the
expression inside the function isn't exactly
the same as the independent variable. Try the
chain rule version of the operation instead.
*/
{ errbuf(0, english(593));
errbuf(1, english(594));
errbuf(2, english(595));
errbuf(3, english(596));
}
/*_______________________________________________________________________*/
int difpower(term t, term arg, term *next, char *reason)
/* works on x^n and on ax^n, on which it yields nax^(n-1) */
{ term a,x,u,n,p,nminusone,cancelled;
int i,err,flag;
char buffer[128];
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u) != '^' && FUNCTOR(u) != '*')
return 1;
if(FUNCTOR(u)== '^')
{ a= one;
p = ARG(0,u);
n = ARG(1,u);
if(!equals(p,x))
{ set_chainrule_errmsg();
return 1;
}
}
if(FUNCTOR(u)=='*')
{ for(i=0;i<ARITY(u);i++)
{ if(FUNCTOR(ARG(i,u))=='^')
{ flag=1; /* consider (3x)^2 x^2 for example;
flag gets set at (3x)^2 but we don't want to break */
if(equals(ARG(0,ARG(i,u)),x)) break;
}
}
if(i==ARITY(u))
{ if(flag)
set_chainrule_errmsg();
return 1;
}
n = ARG(1,ARG(i,u));
p = ARG(0,ARG(i,u));
cancel(u,ARG(i,u),&cancelled,&a);
}
if(depends(n,x)) /* don't use this on x^x for example */
{ strcpy(buffer, english(597)); /* The exponent depends on */
strcat(buffer,atom_string(x));
strcat(buffer,",");
errbuf(0,buffer);
errbuf(1, english(598));
/* so you can't use that operation. */
return 1;
}
strcpy(reason, english(599)); /* power rule */
if(equals(n,two))
{ *next = (FUNCTOR(u) == '^' ? product(two,x) : product3(two,a,x));
SETCOLOR(*next,YELLOW);
return 0;
}
else if (status(difpower) >= KNOWN)
{ err = value(sum(n,minusone),&nminusone);
if(err!=0 && err!=2)
nminusone = sum(n,minusone);
}
else nminusone = sum(n,minusone);
*next = (FUNCTOR(u) == '^' ? product(n,make_power(x,nminusone)) :
product3(n,a,make_power(x,nminusone))
);
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int difpower2(term t, term arg, term *next, char *reason)
/* chain rule version of power rule */
{ term a,x,u,n,p,nminusone,cancelled,extra,temp;
int i;
char buffer[128];
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u) != '^' && FUNCTOR(u) != '*')
return 1;
if(FUNCTOR(u)== '^')
{ a= one;
p = ARG(0,u);
n = ARG(1,u);
extra = (equals(p,x) ? one : diff(p,x));
}
if(FUNCTOR(u)=='*')
{ for(i=0;i<ARITY(u);i++)
{ if(FUNCTOR(ARG(i,u))=='^' && depends(ARG(i,u),x))
break;
}
if(i==ARITY(u))
return 1;
n = ARG(1,ARG(i,u));
p = ARG(0,ARG(i,u));
extra = (equals(p,x) ? one : diff(p,x));
cancel(u,ARG(i,u),&cancelled,&a);
if(depends(a,x))
return 1; /* non-power terms must be constant */
}
if(depends(n,x)) /* don't use this on x^x for example */
{ strcpy(buffer, english(597)); /* The exponent depends on */
strcat(buffer,atom_string(x));
strcat(buffer,",");
errbuf(0,buffer);
errbuf(1, english(598));
/* so you can't use that operation. */
return 1;
}
strcpy(reason, english(599)); /* power rule */
if(equals(n,two))
{ temp = (FUNCTOR(u) == '^' ? product(two,p) : product3(two,a,p));
if(ONE(extra))
*next = temp;
else
{ *next = product(temp,extra);
RELEASE(temp);
}
SETCOLOR(*next,YELLOW);
return 0;
}
else if (status(difpower) >= KNOWN)
polyval(sum(n,minusone),&nminusone);
else nminusone = sum(n,minusone);
temp = (FUNCTOR(u) == '^' ? product(n,make_power(p,nminusone)) :
product3(n,a,make_power(p,nminusone))
);
if(ONE(extra))
*next = temp;
else
{ *next = product(temp,extra);
if(!ONE(n))
RELEASE(temp);
}
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int difidentity(term t, term arg, term *next, char *reason)
{ term x,u;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(!equals(x,u))
return 1;
*next = one;
strcpy(reason,"$$diff(x,x) = 1$$");
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int difconstant(term t, term arg, term *next, char *reason)
{ term x,u;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(depends(u,x))
return 1;
*next = zero;
SETCOLOR(*next,YELLOW);
strcpy(reason, "$$diff(a,x) = 0$$");
strcat(reason, english(883)); /* (a constant) */
return 0;
}
/*_______________________________________________________________________*/
int difsum(term t, term arg, term *next, char *reason)
{ term x,u;
unsigned short n;
int i;
int flag = 0; /* set when we encounter minus sign */
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u) != '+')
return 1;
n = ARITY(u);
*next = make_term('+',n);
for(i=0;i<n;i++)
{ if(FUNCTOR(ARG(i,u)) == '-')
{ ARGREP(*next,i,tnegate(diff(ARG(0,ARG(i,u)),x)));
flag = 1;
}
else
ARGREP(*next,i,diff(ARG(i,u),x));
}
SETCOLOR(*next,YELLOW);
if(n==2 && FUNCTOR(ARG(1,u))=='-')
// strcpy(reason,"(d/dx)(u-v) = du/dx-dv/dx");
strcpy(reason, "$$ diff(u-v,x) = diff(u,x)-diff(v,x)$$");
else if (flag)
strcpy(reason,"$(d/dx)(u \\pm v)$ = $du/dx \\pm dv/dx$");
// can't use 2d display since MathXpert can't parse \pm
else
strcpy(reason, "$$ diff(u+v,x) = diff(u,x)+diff(v,x)$$");
return 0;
}
/*_______________________________________________________________________*/
int difminus(term t, term arg, term *next, char *reason)
{ term x,u;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u) != '-')
return 1;
*next = tnegate(diff(ARG(0,u),x));
SETCOLOR(*next,YELLOW);
strcpy(reason,"$$diff(-y,x) = -diff(y,x)$$");
return 0;
}
/*_______________________________________________________________________*/
int difproduct(term t, term arg, term *next, char *reason)
{ term x,u,temp,temp2;
unsigned short n;
int i,j;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(ATOMIC(u) || FUNCTOR(u) != '*')
return 1;
n = ARITY(u);
*next = make_term('+',n);
if(status(difproduct) <= LEARNING && n > 2)
/* then don't do more than two at a time */
{ term v = make_term('*',(unsigned short)(n-1));
for(i=1;i<n;i++)
ARGREP(v,i,ARG(i,u));
temp = make_term('*',2);
ARGREP(temp,0,ARG(0,u));
ARGREP(temp,1,v);
return difproduct(temp,arg,next,reason);
}
for(i=0;i<n;++i)
{ temp2 = make_term('*',n);
/* this term will have the n-i-1'th arg of the product differentiated
and put at the end */
for(j=0;j<n;j++)
{ arg = ARG(j,u);
if(j<n-i-1)
ARGREP(temp2,j,arg);
else if(j==n-i-1)
ARGREP(temp2,n-1,diff(arg,x));
else
ARGREP(temp2,j-1,arg);
}
sortargs(temp2);
ARGREP(*next,i,temp2);
}
if(n > 2)
additive_sortargs(*next);
/* to save a useless-looking 'order terms' step */
SETCOLOR(*next,YELLOW);
strcpy(reason, english(601)); /* product rule */
return 0;
}
/*_______________________________________________________________________*/
int difrecip(term t, term arg, term *next, char *reason)
{ term x,u,c,v;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u) != '/')
return 1;
v = ARG(1,u);
c = ARG(0,u);
if(ONE(c) && equals(v,x))
{ // strcpy(reason, "(d/dx)(1/x) = -1/x^2");
strcpy(reason,"$$diff(1/x,x) = - 1/x^2$$");
*next = tnegate(make_fraction(one,make_power(x,two)));
}
else if(ONE(c))
{ // strcpy(reason,"(d/dx)(1/v) = -(dv/dx)/v^2");
strcpy(reason,"$$diff(1/v,x) = - (diff(v,x)/v^2)$$");
*next = tnegate(make_fraction(diff(v,x),make_power(v,two)));
}
else if(equals(v,x) && !depends(c,x))
{ // strcpy(reason, english(602)); /* (d/dx)(c/v) = -c/v^2 (c constant) */
strcpy(reason,"$$diff(a/v,x) = -a/v^2$$");
strcat(reason, english(883)); // "if $a\\ge 0$",
*next = tnegate(make_fraction(c,make_power(v,two)));
}
else if(!depends(c,x))
{// strcpy(reason, english(603));
/* (d/dx)(c/v) = -c(dv/dx)/v^2 (c constant) */
strcpy(reason,"$$ diff(a/v,x) = - a (diff(v,x) / v^2))$$");
strcat(reason, english(883)); // "if $a\\ge 0$",
*next = tnegate(make_fraction(product(c,diff(v,x)),make_power(v,two)));
}
else
return 1;
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int difquotient(term t, term arg, term *next, char *reason)
{ term x,u,a,b;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u) != '/')
return 1;
a = ARG(0,u);
b = ARG(1,u);
*next = make_fraction(
sum(product(b,diff(a,x)), tnegate(product(a,diff(b,x)))),
make_power(b,two)
);
SETCOLOR(*next,YELLOW);
strcpy(reason, english(604)); /* quotient rule */
return 0;
}
/*_______________________________________________________________________*/
int difroots(term t, term arg, term *next, char *reason)
{ term x,u,n,p;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u)!= ROOT)
return 1;
p = ARG(1,u);
n = ARG(0,u);
*next = diff(make_power(p,make_fraction(one,n)),x);
SETCOLOR(*next,YELLOW);
strcpy(reason,"$$root(n,x) = x^(1/n)$$");
return 0;
}
/*_______________________________________________________________________*/
int difsqrt(term t, term arg, term *next, char *reason)
{ term x,u,p;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u)!= SQRT)
return 1;
p = ARG(0,u);
if(!equals(p,x))
{ set_chainrule_errmsg();
return 1;
}
*next = make_fraction(one,product(two,u));
SETCOLOR(*next,YELLOW);
strcpy(reason,"$$diff(sqrt(x),x) = 1/(2 sqrt x)$$");
return 0;
}
/*_______________________________________________________________________*/
int difsqrt2(term t, term arg, term *next, char *reason)
/* chain rule version */
{ term x,u,p,num;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u)!= SQRT)
return 1;
p = ARG(0,u);
if(equals(p,x))
{ num = one;
strcpy(reason,"$$diff(sqrt(x),x) = 1/(2 sqrt x)$$");
}
else
{ num = diff(p,x);
strcpy(reason,"$(d/dx)\\sqrt u$ = $(du/dx)/(2\\sqrt u)$");
}
*next = make_fraction(num,product(two,u));
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int chainrule(term t, term arg, term *next, char *reason)
/* d/dx(f(u))=f'(u)du/dx */
{ term x,u,v,p;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(ATOMIC(u))
return 1;
if(ARITY(u) != 1)
return 1;
v = ARG(0,u);
if(ATOMIC(v))
return 1;
if(ARITY(v) != 1)
return 1;
/* so u = f(v(y)) */
p = make_term(PR,2);
ARGREP(p,0, MAKE_ATOM(FUNCTOR(u)));
ARGREP(p,1,one);
*next = product(p,diff(v,x));
strcpy(reason,"d/dx(f(u))=f'(u)du/dx");
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int primerule(term t, term arg, term *next, char *reason)
/* f'(x)= d/dx f(x) */
{ term x,u;
int err;
if(FUNCTOR(t) != PR)
return 1;
u = ARG(0,t); /* u is f(x) hopefully */
if(ATOMIC(u))
return 1;
if(ARITY(u) != 1)
return 1;
x = ARG(0,u);
if(!ATOMIC(x))
{ errbuf(0, english(605));
/* in d/dx, x must be a variable. */
return 1;
}
if(ONE(ARG(1,t)))
*next = diff(u,x);
else
{ err = check1(and(type(ARG(1,t),INTEGER),positive(ARG(1,t))));
if(err)
{ errbuf(0, english(606));
/* Can't take derivatives of non-integer order */
return 1;
}
*next = diff3(u,x,ARG(1,t));
}
strcpy(reason,"f'(x)= d/dx f(x)");
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int fundamentaltheorem2(term t, term arg, term *next, char *reason)
{ term x,u;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u) != INTEGRAL)
return 1;
strcpy(reason, english(607)); /* fundamental theorem of calculus */
if(ARITY(u)==2) /* differentiate an indefinite integral */
{ if(!equals(x,ARG(1,u)))
return 1;
*next = ARG(0,u);
SETCOLOR(*next,YELLOW);
return 0;
}
if(ARITY(u)==4) /* differentiate a definite integral */
{ term lo,hi,t,temp,temp2,a,b;
t = ARG(1,u); /* variable of integration */
lo = ARG(2,u);
hi = ARG(3,u);
if(!depends(lo,x))
{ if(equals(x,hi))
subst(x,t,ARG(0,u),next);
else if(!depends(hi,x))
return 1;
else
{ subst(hi,t,ARG(0,u),&temp);
*next = product(temp, diff(hi,x));
}
}
else if(!depends(hi,x))
{ if(equals(x,lo))
{ subst(x,t,ARG(0,u),&temp);
tneg(temp,next);
}
else
{ subst(lo,t,ARG(0,u),&temp);
*next = tnegate(product(temp,diff(lo,x)));
}
}
else
{ subst(hi,t,ARG(0,u),&temp);
subst(lo,t,ARG(0,u),&temp2);
a = equals(hi,x) ? temp : product(temp,diff(hi,x));
b = equals(lo,x) ? temp2 : product(temp2,diff(lo,x));
*next = sum(a,tnegate(b));
}
SETCOLOR(*next,YELLOW);
return 0;
}
return 1;
}
/*_______________________________________________________________________*/
int diflinear(term t, term arg, term *next, char *reason)
/* d(cu)/dx = c du/dx */
/* d/dx (u/c) = (1/c) du/dx */
{ term x,u,c,v;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FRACTION(u))
return diflinear2(t,arg,next,reason);
if(FUNCTOR(u) != '*')
return 1;
strcpy(reason,"$$diff(cu,x) = c diff(u,x)$$");
twoparts(u,x,&c,&v);
if(ONE(c))
return 1;
if(equals(v,x))
{ *next = c;
strcpy(reason,"$$diff(cx,x) = c$$");
}
else
*next = product(c,diff(v,x));
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int diflinear2(term t, term arg, term *next, char *reason)
/* d/dx (u/c) = (1/c) du/dx */
{ term x,u,c,v,num,denom,c1,c2,v2;
if(FUNCTOR(t) != DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(FUNCTOR(u) != '/')
return 1;
num = ARG(0,u);
denom = ARG(1,u);
twoparts(num,x,&c1,&v);
twoparts(denom,x,&c2,&v2);
if(ONE(c1) && ONE(c2))
return 1;
c = make_fraction(c1,c2);
*next = product(c,diff(make_fraction(v,v2),x));
if(ONE(c))
// strcpy(reason,"d/dx (u/c)=(1/c)du/dx");
strcpy(reason,"$$ diff(u/c,x) = (1/c) diff(u,x)$$");
else
strcpy(reason,"$$diff(cu,x) = c diff(u,x)$$");
SETCOLOR(*next,YELLOW);
return 0;
}
/*_______________________________________________________________________*/
int difinversepower(term t, term arg, term *next, char *reason)
/* d/dx (c/x�) = -nc/x^(n+1) */
{ term x,c,n,m,u;
if(FUNCTOR(t) != DIFF || ARITY(t) != 2)
return 1;
x = ARG(1,t);
if(FUNCTOR(ARG(0,t)) != '/')
return 1;
c = ARG(0,ARG(0,t));
if(!constant(c))
return 1;
u = ARG(1,ARG(0,t)); /* the denominator */
if(FUNCTOR(u) != '^')
return 1;
n = ARG(1,u);
if(!equals(ARG(0,u),x))
return 1;
polyval(sum(n,one),&m);
*next = tnegate(make_fraction(product(n,c),make_power(x,m)));
SETCOLOR(*next,YELLOW);
strcpy(reason,"$$ diff(c/x^n,x) =-nc/x^(n+1)$$");
return 0;
}
/*_______________________________________________________________________*/
int difabs(term t, term arg, term *next, char *reason)
/* d/dx |x| = x / |x| */
{ term x;
if(FUNCTOR(t) != DIFF || ARITY(t) != 2)
return 1;
x = ARG(1,t);
if(FUNCTOR(ARG(0,t)) != ABSFUNCTOR)
return 1;
if(!equals(x,ARG(0,ARG(0,t))))
return 1;
*next = make_fraction(x,abs1(x));
SETCOLOR(*next,YELLOW);
strcpy(reason,"$$diff(abs(x),x) = x/abs(x)$$");
return 0;
}
/*_______________________________________________________________________*/
int difabs2(term t, term arg, term *next, char *reason)
/* d/dx |u|=u du/dx/|u| */
{ term x,u;
if(FUNCTOR(t) != DIFF || ARITY(t) != 2)
return 1;
x = ARG(1,t);
if(FUNCTOR(ARG(0,t)) != ABSFUNCTOR)
return 1;
u = ARG(0,ARG(0,t));
*next = make_fraction(product(u,diff(u,x)),abs1(u));
HIGHLIGHT(*next);
strcpy(reason,"$$ diff(abs(u),x) = diff(u,x)/abs(u)$$");
// strcpy(reason,"d/dx |u|=u du/dx/|u|");
return 0;
}
/*__________________________________________________________________*/
int difeqn(term t, term arg, term *next, char *reason)
/* take derivative of equation with respect to varlist[eigenvariable] */
/* get f'(x) from f(x), but dV/dt from V */
{ term left,right,temp;
int problemtype = get_problemtype();
if(FUNCTOR(t) != '=')
return 1;
if(SOLVETYPE(problemtype) &&
problemtype != IMPLICIT_DIFF &&
problemtype != RELATED_RATES
)
{ errbuf(0, english(608));
/* Can't differentiate while solving equations. */
errbuf(1, english(609));
/* Example: solve x = 1; dx/dx = 1 = d1/dx = 0 */
/* but: it's ok in IMPLICIT_DIFF because the equation is
still universal with respect to x */
}
if(problemtype == RELATED_RATES && contains(t,DIFF))
{ errbuf(0, english(1922));
/* You have already differentiated the equation. */
return 1;
}
left = ARG(0,t);
right = ARG(1,t);
arg = get_eigenvariable();
*next = equation(dif_aux2(left,arg),dif_aux2(right,arg));
HIGHLIGHT(*next);
strcpy(reason,english(1253)); /* "$$diff(u,t) = diff(v,t)$$ if $u=v$" */
if(problemtype == RELATED_RATES)
{ copy(t,&temp);
PROTECT(temp);
*next = and(temp, *next); /* Keep the original equation too */
}
return 0;
}
/*__________________________________________________________________*/
int difdif(term t, term arg, term *next, char *reason)
/* d^2u/dx^2 = (d/dx)(du/dx) etc. */
{ term u,x,n;
if(FUNCTOR(t) != DIFF || ARITY(t) != 3)
return 1;
u = ARG(0,t);
n = ARG(2,t);
x = ARG(1,t);
if(!equals(n,two))
return 1;
*next = diff(diff(u,x),x);
strcpy(reason,"$$diff(u,x,2) = diff(diff(u,x),x)$$");
SETCOLOR(*next,YELLOW);
return 0;
}
/*__________________________________________________________________*/
int difdifn(term t, term arg, term *next, char *reason)
/* d^2u/dx^2 = (d/dx)(du/dx) etc. */
{ term u,x,n,v;
int err;
int mathmode = get_mathmode();
if(FUNCTOR(t) != DIFF || ARITY(t) != 3)
return 1;
u = ARG(0,t);
n = ARG(2,t);
x = ARG(1,t);
if(equals(n,two))
return difdif(t,arg,next,reason);
err = value(n,&v);
if(err && mathmode == AUTOMODE)
return 1;
if(err && mathmode == MENUMODE)
{ err = check1(lessthan(one,n));
if(!err)
v = sum(n,minusone);
else
return 1;
}
*next = diff(diff3(u,x,v),x);
SETCOLOR(*next,YELLOW);
strcpy(reason, english(610)); /* definition of d^nu/dx^n*/
return 0;
}
/*__________________________________________________________________*/
int derivop(term t, term arg, term *next, char *reason)
/* take derivative in one step */
{ if(FUNCTOR(t)!= DIFF)
return 1;
if(ARITY(t) != 2)
return 1;
if(equals(ARG(0,t),ARG(1,t)))
{ SetShowStepOperation(difidentity);
return difidentity(t,arg,next,reason);
}
if(!depends(ARG(0,t),ARG(1,t)))
{ SetShowStepOperation(difconstant);
return difconstant(t,arg,next,reason);
}
*next = derivative(ARG(0,t),ARG(1,t));
if(equals(*next,t))
return 1; /* dy/dx in, dy/dx out; nothing done */
SETCOLOR(*next,YELLOW);
strcpy(reason, english(611)); /* calculate derivative */
return 0;
}
/*_______________________________________________________________________*/
int difpoly(term t, term arg, term *next, char *reason)
/* Differentiate a polynomial all at once */
/* Also differentiate all monomials in a sum such as x + 3x^2 + sin x + x^4 */
{ term x,u,v,c,s;
unsigned short n;
int i;
if(FUNCTOR(t) != DIFF)
return 1;
x = ARG(1,t);
u = ARG(0,t);
if(equals(u,x))
{ SetShowStepOperation(difidentity);
return difidentity(t,arg,next,reason);
}
if(!depends(u,x))
{ SetShowStepOperation(difconstant);
return difconstant(t,arg,next,reason);
}
if((FUNCTOR(u) == '*' || FRACTION(u)) && !monomial(u))
{ /* it still should work on cx */
twoparts(u,x,&c,&s);
if(equals(s,x))
{ *next = c;
HIGHLIGHT(*next);
strcpy(reason, english(657));
return 0;
}
if(monomial(s))
{ *next = product(c,derivative(s,x));
HIGHLIGHT(*next);
strcpy(reason,english(657));
return 0;
}
return 1;
}
if(mvpoly(u))
*next = derivative(u,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++)
{ v = ARG(i,u);
if(monomial(v))
ARGREP(*next,i,derivative(v,x));
else if(FRACTION(v) || FUNCTOR(v) == '*')
{ twoparts(v,x,&c,&s);
if(equals(s,x))
ARGREP(*next,i,c);
else if(monomial(s))
ARGREP(*next,i,product(c,derivative(s,x)));
else
ARGREP(*next,i,product(c,diff(s,x)));
}
else
ARGREP(*next,i,diff(v,x));
}
}
HIGHLIGHT(*next);
strcpy(reason, english(657));
/* differentiate polynomial */
/* so they can see what menu operator was used */
return 0;
}
/*_____________________________________________________________*/
static term dif_aux2(term u, term x)
/* x is an atom. Return diff(u,x) unless u is already a derivative
and then return a higher-derivative term, one higher derivative than u.
However, unlike dif_aux in maketerm.c, if u is a number or an
atom not depending on x, return zero.
*/
{ term v,index,ans;
int err;
unsigned f = FUNCTOR(u);
if(f == PR && equals(x,get_eigenvariable()))
{ v = sum(ARG(1,u),one);
err = value(v,&index);
if(err==1)
index = v;
ans = make_term(PR,2);
ARGREP(ans,0,ARG(0,u));
ARGREP(ans,1,index);
return ans;
}
if(!ATOMIC(u) && !PREDEFINED_FUNCTOR(f))
{ /* differentiate f(x) to f'(x) */
ans = make_term(PR,2);
ARGREP(ans,0,u);
ARGREP(ans,1,one);
return ans;
}
if(f != DIFF)
{ if(ISATOM(u) && !depends(u,x))
return zero;
if(seminumerical(u))
return zero;
return diff(u,x);
}
if(!equals(x,ARITY(u)==2 ? ARG(1,u) : ARG(2,u)))
return diff(u,x);
if(ARITY(u) == 2)
return diff3(ARG(0,u),x,two);
v = sum(ARG(1,u),one);
err = value(v,&index);
if(err==1)
index = v;
return diff3(ARG(0,u),x,index);
}
/*_______________________________________________________________*/
int diflncos(term t, term arg, term *next, char *reason)
/* d/dx ln(cos x) = -tan x */
{ term u,x;
if(FUNCTOR(t) != DIFF || ARITY(t) != 2)
return 1;
if(FUNCTOR(ARG(0,t)) != LN)
return 1;
if(FUNCTOR(ARG(0,ARG(0,t))) != COS)
return 1;
x = ARG(1,t);
u = ARG(0,ARG(0,ARG(0,t)));
if(equals(u,x))
*next = tnegate(tan1(x));
else
*next = tnegate(product(tan1(u), diff(u,x)));
HIGHLIGHT(*next);
strcpy(reason,"$$ diff(ln(cos x),x) = -tan x$$");
return 0;
}
/*_______________________________________________________________*/
int diflnsin(term t, term arg, term *next, char *reason)
/* d/dx ln(sin x) = cot x */
{ term u,x;
if(FUNCTOR(t) != DIFF || ARITY(t) != 2)
return 1;
if(FUNCTOR(ARG(0,t)) != LN)
return 1;
if(FUNCTOR(ARG(0,ARG(0,t))) != SIN)
return 1;
x = ARG(1,t);
u = ARG(0,ARG(0,ARG(0,t)));
if(equals(u,x))
*next = cot1(x);
else
*next = product(cot1(u), diff(u,x));
HIGHLIGHT(*next);
strcpy(reason,"$$diff( ln(sin x),x) =cot x$$");
return 0;
}
/*_______________________________________________________________*/
int diflncosh(term t, term arg, term *next, char *reason)
/* d/dx ln(cosh x) = tanh x */
{ term u,x;
if(FUNCTOR(t) != DIFF || ARITY(t) != 2)
return 1;
if(FUNCTOR(ARG(0,t)) != LN)
return 1;
if(FUNCTOR(ARG(0,ARG(0,t))) != COSH)
return 1;
x = ARG(1,t);
u = ARG(0,ARG(0,ARG(0,t)));
if(equals(u,x))
*next = tanh1(x);
else
*next = product(tanh1(u), diff(u,x));
HIGHLIGHT(*next);
strcpy(reason,"$$ diff( ln(cosh x),x)= -tanh x$$");
return 0;
}
/*_______________________________________________________________*/
int diflnsinh(term t, term arg, term *next, char *reason)
/* d/dx ln(sinh x) = coth x */
{ term u,x;
if(FUNCTOR(t) != DIFF || ARITY(t) != 2)
return 1;
if(FUNCTOR(ARG(0,t)) != LN)
return 1;
if(FUNCTOR(ARG(0,ARG(0,t))) != SINH)
return 1;
x = ARG(1,t);
u = ARG(0,ARG(0,ARG(0,t)));
if(equals(u,x))
*next = coth1(x);
else
*next = product(coth1(u), diff(u,x));
HIGHLIGHT(*next);
strcpy(reason,"$$diff(ln(sinh x),x) = coth x$$");
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists