Sindbad~EG File Manager

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

/* 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
*/

#include <string.h>
#include <assert.h>
#define TRIGCALC_DLL
#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 "getprob.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 */

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 �x instead of x^�. */
        return;
      }
   /* More cases can be explained here if required. */
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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));
  }
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC int difpower(term t, term arg, term *next, char *reason)
/* works on x� and on ax�, 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;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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;
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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,"dx/dx = 1");
  SETCOLOR(*next,YELLOW);
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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, english(600));  /* dc/dx=0 (c constant) */
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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");
  else if (flag)
     strcpy(reason,"$(d/dx)(u�v)$ =        $du/dx�dv/dx$");
  else
     strcpy(reason,"(d/dx)(u+v) =        du/dx+dv/dx");
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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,"d(-y)/dx = -dy/dx");
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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");
       *next = tnegate(make_fraction(one,make_power(x,two)));
     }
  else if(ONE(c))
     { strcpy(reason,"(d/dx)(1/v) =        -(dv/dx)/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) */
       *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) */
       *next = tnegate(make_fraction(c,make_power(v,two)));
     }
  else
     return 1;
  SETCOLOR(*next,YELLOW);
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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,"$��x = x^(1/n)$");
  return 0;
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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,"$(d/dx) �x = 1/(2�x)$");
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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,"$(d/dx) �x = 1/(2�x)$");
     }
  else
     { num = diff(p,x);
       strcpy(reason,"$(d/dx)�u$ =           $(du/dx)/(2�u)$");
     }
  *next = make_fraction(num,product(two,u));
  SETCOLOR(*next,YELLOW);
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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;
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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 = check(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;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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;
}
 /*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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,"d/dx (cu) = c du/dx");
  twoparts(u,x,&c,&v);
  if(ONE(c))
     return 1;
  if(equals(v,x))
     { *next = c;
       strcpy(reason,"d/dx (cx) = c");
     }
  else
     *next = product(c,diff(v,x));
  SETCOLOR(*next,YELLOW);
  return 0;
}

 /*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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");
  else
     strcpy(reason,"d/dx (cu) = c du/dx");
  SETCOLOR(*next,YELLOW);
  return 0;
}

/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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,"d/dx c/x^n=-nc/x^(n+1)");
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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)) != ABS)
     return 1;
  if(!equals(x,ARG(0,ARG(0,t))))
      return 1;
  *next = make_fraction(x,abs1(x));
  SETCOLOR(*next,YELLOW);
  strcpy(reason,"d/dx |x| = x/|x|");
  return 0;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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)) != ABS)
     return 1;
  u = ARG(0,ARG(0,t));
  *next = make_fraction(product(u,diff(u,x)),abs1(u));
  HIGHLIGHT(*next);
  strcpy(reason,"d/dx |u|=u du/dx/|u|");
  return 0;
}
/*__________________________________________________________________*/
MEXPORT_TRIGCALC 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,"u=v => du/dt = dv/dt");
  if(isascii(FUNCTOR(arg)))
     { char c = (char) FUNCTOR(arg);
       reason[11] = reason[19] = c;
     }
  if(problemtype == RELATED_RATES)
     { copy(t,&temp);
       PROTECT(temp);
       *next = and(temp, *next);  /* Keep the original equation too */
     }
  return 0;
}

/*__________________________________________________________________*/
MEXPORT_TRIGCALC 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,"$d^2u/dx^2 = (d/dx)(du/dx)$");
  SETCOLOR(*next,YELLOW);
  return 0;
}
/*__________________________________________________________________*/
MEXPORT_TRIGCALC 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 = check(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�u/dx� */
  return 0;
}

/*__________________________________________________________________*/
MEXPORT_TRIGCALC 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;
}
/*_______________________________________________________________________*/
MEXPORT_TRIGCALC 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);
}
/*_______________________________________________________________*/
MEXPORT_TRIGCALC 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,"d/dx ln(cos x)=-tan x");
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_TRIGCALC 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,"d/dx ln(sin x)=cot x");
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_TRIGCALC 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,"d/dx ln(cosh x)=-tanh x");
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_TRIGCALC 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,"d/dx ln(sinh x)=coth x");
  return 0;
}

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