Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/algebra/
Upload File :
Current File : /usr/home/beeson/MathXpert/algebra/trighalf.c

/* double angle and half-angle trig operators
M. Beeson, for MathXpert
1.13.91 original date
2.26.98 last modified
5.31.13 eliminated the OEM character for theta
1.30.25 made doublesin work on sin x = 2 sin (x/2) cos(x/2)
1.31.25  corrected coshalf2 and sinhalf2, which had an incorrect condition passed to infer.
*/

#include <string.h>
#include <assert.h>
#include "globals.h"
#include "ops.h"
#include "trig.h"
#include "match.h"
#include "order.h"
#include "cancel.h"
#include "prover.h"
#include "trigsq.h"
#include "symbols.h"
#include "mathmode.h"   /* get_mathmode */
#include "errbuf.h"
#include "autosimp.h"   /* SetShowStepOperation */
#include "pstring.h"    /* log_term, for debugging */

static term expand_sin(int,term,term);
static term expand_cos(int,term,term);
/*__________________________________________________________________*/
int doublesin(term t, term arg, term *next, char *reason)
/* sin 2 theta = 2 sin theta cos theta */
{ int err;
  term cancelled, temp,u;
  if (FUNCTOR(t) != SIN)
     return 1;
  u = ARG(0,t);
  if(ISATOM(u))
     { temp = make_fraction(u,two);
     }
  else
     { if(FUNCTOR(u) != '*')
         return 1;
       err = cancel(u,two,&cancelled,&temp);
       if(err)
          return 1;
     }
  *next = product3(two,sin1(temp),cos1(temp));
  HIGHLIGHT(*next);
  strcpy(reason,"$sin 2\\theta=2 sin \\theta cos \\theta$");
  return 0;
}

/*__________________________________________________________________*/
int doublecos1(term t, term arg, term *next, char *reason)
/* cos 2\theta = cos^2 \theta - sin^2 \theta */
/* This operator is associated to COS; the same rule associated to
   '+' (for use when cos 2\theta is a summand) is called doublecos4.  */
{ int err;
  term cancelled, temp,u;
  if (FUNCTOR(t) != COS)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  err = cancel(u,two,&cancelled,&temp);
  if(err)
     return 1;
  *next = sum(make_power(cos1(temp),two),tnegate(make_power(sin1(temp),two)));
  HIGHLIGHT(*next);
  strcpy(reason,"$cos 2\\theta = cos^2\\theta-sin^2\\theta$");
  return 0;
}

/*__________________________________________________________________*/
int doublecos2(term t, term arg, term *next, char *reason)
/*cos 2 theta = 1 - 2 sin^2 \theta */
{ int err;
  term cancelled, temp,u;
  if(FUNCTOR(t) == '+')
     { // apply it to an arg if possible
       int n = ARITY(t);
       int i;
       term temp;
       for(i=0;i<n;i++)
          { if (FUNCTOR(ARG(i,t)) == COS)
               { err = doublecos2(ARG(i,t),arg,&temp,reason);
                 if(!err)
                   break;
               }
          }
       if(i< n)
          { // it worked
            *next = make_term('+',n+1);
            int j;
            for(j=0;j<n+1;j++)
               { if(j < i)
                   ARGREP(*next,j,ARG(j,t));
                 if(j == i)
                   ARGREP(*next,j,ARG(0,temp));
                 if(j == i+1)
                    ARGREP(*next,j,ARG(1,temp));
                 if(j > i+1)
                    ARGREP(*next,j,ARG(j-1,t));
               }
             SetShowStepArg(ARG(i,t));
            return 0;
          }
       return 1;
     }
  if (FUNCTOR(t) != COS)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  err = cancel(u,two,&cancelled,&temp);
  if(err)
     return 1;
  *next = sum(one,tnegate(product(two,make_power(sin1(temp),two))));
  HIGHLIGHT(*next);
  strcpy(reason,"$cos 2\\theta = 1-2 sin^2 \\theta$");
  return 0;
}

/*__________________________________________________________________*/
int doublecos3(term t, term arg, term *next, char *reason)
/* cos 2\theta = 2 cos^2 \theta - 1*/
{ int err;
  term cancelled, temp,u;
  if (FUNCTOR(t) != COS)
      return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  err = cancel(u,two,&cancelled,&temp);
  if(err)
     return 1;
  *next = sum(product(two,make_power(cos1(temp),two)),minusone);
  HIGHLIGHT(*next);
  strcpy(reason,"$cos 2\\theta = 2 cos^2 \\theta-1$");
  return 0;
}
/*__________________________________________________________________*/
int doubletan(term t, term arg, term *next, char *reason)
/* tan(2\theta) = 2 tan \theta/(1 - tan^2 \theta) */
{ int err;
  term cancelled, temp,u, tan_theta;
  if (FUNCTOR(t) != TAN)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  err = cancel(u,two,&cancelled,&temp);
  if(err)
     return 1;
  tan_theta = tan1(temp);
  if(equals(temp,piover2) || check1(domain(tan_theta)))
      { errbuf(0,english(1126));
        /* That would result in an undefined value of tan. */
        return 1;
      }
  *next = make_fraction(product(two,tan_theta),sum(one,tnegate(make_power(tan_theta,two))));
  HIGHLIGHT(*next);
  strcpy(reason,"$$tan 2 theta = 2tan theta/(1-tan^2 theta)$$");
  return 0;
}

/*__________________________________________________________________*/
int doublecot(term t, term arg, term *next, char *reason)
/* cot(2\theta) = (cot^2 \theta -1) / (2 cot \theta) */
{ int err;
  term cancelled, temp,u,num,denom,cot_theta;
  if (FUNCTOR(t) != COT)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  err = cancel(u,two,&cancelled,&temp);
  if(err)
     return 1;
  cot_theta = cot1(temp);
  if(equals(temp,pi_term) || check1(domain(cot_theta)))
      { errbuf(0,english(1127));
        /* That would result in an undefined value of cot. */
        return 1;
      }
  num = sum(make_power(cot_theta,two),minusone);
  denom = product(two,cot_theta);
  *next = make_fraction(num,denom);
  HIGHLIGHT(*next);
  strcpy(reason,"$$cot 2 theta= (cot^2 theta-1)/(2 cot theta)$$");
  return 0;
}

/*__________________________________________________________________*/
int sinsqhalf(term t, term arg, term *next, char *reason)
/* sin^2(u/2) = (1-cos u)/2 */
/* but NOT sin^(2n)(u) = (1-cos(2u)/2)^n */
{ term u;
  if(FUNCTOR(t) != '^')
     return 1;
  if(FUNCTOR(ARG(0,t)) != SIN)
     return 1;
  u = ARG(0,ARG(0,t));
  if(FUNCTOR(u) != '/')
     return 1;
  return sinsqhalf2(t,arg,next,reason);
}
/*__________________________________________________________________*/
int cossqhalf(term t, term arg, term *next, char *reason)
/* cos^2(u/2) = (1+cos u)/2 */
/* but NOT cos^(2n)(u) = (1+cos(2u)/2)^n */
{ term u;
  if(FUNCTOR(t) != '^')
     return 1;
  if(FUNCTOR(ARG(0,t)) != COS)
     return 1;
  u = ARG(0,ARG(0,t));
  if(FUNCTOR(u) != '/')
     return 1;
  return cossqhalf2(t,arg,next,reason);
}
/*__________________________________________________________________*/
int sinsqhalf2(term t, term arg, term *next, char *reason)
/* sin^2(u/2) = (1-cos u)/2 */
/* sin^(2n)(u) = (1-cos(2u)/2)^n */
/* Also works on integral( f(x) sin^2 x,x), if f(x) does not
contain trig functions */

{ term u,newu,denom,num,cancelled,power,newpower,temp;
  int err;
  if(FUNCTOR(t) == INTEGRAL)
     { unsigned short path[5];
       u = ARG(0,t);
       if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
          !contains_trig(ARG(0,u)) &&
          FUNCTOR(ARG(1,u)) == '^' &&
          equals(ARG(1,ARG(1,u)),two) &&
          FUNCTOR(ARG(0,ARG(1,u))) == SIN &&
          !sinsqhalf2(ARG(1,u),arg,&temp,reason)
         )
          { path[0] = INTEGRAL;
            path[1] = 1;
            path[2] = '*';
            path[3] = 2;
            path[4] = 0;
            set_pathtail(path);
            if(ARITY(t) == 2)
               { *next = integral(product(ARG(0,u),temp),ARG(1,t));
                 return 0;
               }
            *next = definite_integral(product(ARG(0,u),temp),ARG(1,t),ARG(2,t),ARG(3,t));
            return 0;
          }
       return 1;
     }
  if(FUNCTOR(t) != '^')
     return 1;
  if(FUNCTOR(ARG(0,t)) != SIN)
     return 1;
  power = ARG(1,t);
  if(equals(power,two))
     newpower = one;
  else
     { err = cancel(power,two,&cancelled,&newpower);
       if(err)
          return 1;
     }
  u = ARG(0,ARG(0,t));
  if(FUNCTOR(u) != '/')
     newu = product(two,u);
  else
     { num  = ARG(0,u);
       denom = ARG(1,u);
       err = cancel(product(two,num),denom,&cancelled,&newu);
       if(err)
          newu = make_fraction(product(two,num),denom);
     }
  *next = make_power(make_fraction(sum(one,tnegate(cos1(newu))),two),newpower);
  HIGHLIGHT(*next);
  if(FUNCTOR(u) == '/')
     strcpy(reason,"$sin^2(u/2)=(1-cos u)/2$");
  else
     strcpy(reason,"$sin^2 u = (1-cos 2u)/2$");
  return 0;
}
/*__________________________________________________________________*/
int cossqhalf2(term t, term arg, term *next, char *reason)
/* cos^2(u/2) = (cos u + 1)/2 */
{ term u,newu,denom,num,cancelled,power,newpower;
  int err;
  if(FUNCTOR(t) != '^')
     return 1;
  if(FUNCTOR(ARG(0,t)) != COS)
     return 1;
  power = ARG(1,t);
  if(equals(power,two))
     newpower = one;
  else
     { err = cancel(power,two,&cancelled,&newpower);
       if(err)
          return 1;
     }
  u = ARG(0,ARG(0,t));
  if(FUNCTOR(u) != '/')
     newu = product(two,u);
  else
     { num  = ARG(0,u);
       denom = ARG(1,u);
       err = cancel(product(two,num),denom,&cancelled,&newu);
       if(err)
          newu = make_fraction(product(two,num),denom);
     }
  *next = make_power(make_fraction(sum(cos1(newu),one),two),newpower);
  HIGHLIGHT(*next);
  if(FUNCTOR(u) == '/')
     strcpy(reason,"$cos^2(u/2)=(1+cos u)/2$");
  else
     strcpy(reason,"$cos^2 u = (1+cos 2u)/2$");
  return 0;
}
/*__________________________________________________________________*/
int tanhalf1(term t, term arg, term *next, char *reason)
/* tan(u/2) = sin u/(1+cos u) */
{ term num,denom,u,v,cancelled,temp;
  int err;
  if(FUNCTOR(t) != TAN)
     return 1;
  v = ARG(0,t);
  if(FUNCTOR(v) == '*' && ONEHALF(ARG(0,v)))
     { denom = two;
       if(ARITY(v) == 2)
          num = ARG(1,v);
       else
          cancel(v,two,&cancelled,&denom);
     }
  else if(FUNCTOR(v) == '/')
     { denom = ARG(1,ARG(0,t));
       num = ARG(0,ARG(0,t));
     }
  else
     return 1;
  if(equals(denom,two))
     u = num;
  else
     { err = cancel(denom,two,&cancelled,&temp);
       if(err)
          return 1;
       u = make_fraction(num,temp);
     }
  *next = make_fraction(sin1(u),sum(one,cos1(u)));
  HIGHLIGHT(*next);
  strcpy(reason,"tan(u/2) =           sin u/(1+cos u)");
  return 0;
}
/*__________________________________________________________________*/
int tanhalf2(term t, term arg, term *next, char *reason)
/* tan(u/2) = (1-cos u)/sin u */
{ term num,denom,u,v, cancelled,temp;
  int err;
  if(FUNCTOR(t) != TAN)
     return 1;
  v = ARG(0,t);
  if(FUNCTOR(v) == '*' && ONEHALF(ARG(0,v)))
     { denom = two;
       if(ARITY(v) == 2)
          num = ARG(1,v);
       else
          cancel(v,two,&cancelled,&denom);
     }
  else if(FUNCTOR(v) == '/')
     { denom = ARG(1,ARG(0,t));
       num = ARG(0,ARG(0,t));
     }
  else
     return 1;
  if(equals(denom,two))
     u = num;
  else
     { err = cancel(denom,two,&cancelled,&temp);
       if(err)
          return 1;
       u = make_fraction(num,temp);
     }
  *next = make_fraction(sum(one,tnegate(cos1(u))),sin1(u));
  HIGHLIGHT(*next);
  strcpy(reason,"tan(u/2) =           (1-cos u)/sin u");
  return 0;
}
/*__________________________________________________________________*/
int cothalf1(term t, term arg, term *next, char *reason)
/* cot(u/2) = (1+cos u)/sin u */
{ term num,denom,u,v, cancelled,temp;
  int err;
  if(FUNCTOR(t) != COT)
     return 1;
  v = ARG(0,t);
  if(FUNCTOR(v) == '*' && ONEHALF(ARG(0,v)))
     { denom = two;
       if(ARITY(v) == 2)
          num = ARG(1,v);
       else
          cancel(v,two,&cancelled,&denom);
     }
  else if(FUNCTOR(v) == '/')
     { denom = ARG(1,ARG(0,t));
       num = ARG(0,ARG(0,t));
     }
  else
     return 1;
  if(equals(denom,two))
     u = num;
  else
     { err = cancel(denom,two,&cancelled,&temp);
       if(err)
          return 1;
       u = make_fraction(num,temp);
     }
  *next = make_fraction(sum(one,cos1(u)),sin1(u));
  HIGHLIGHT(*next);
  strcpy(reason,"cot(u/2) =           (1+cos u)/sin u");
  return 0;
}
/*__________________________________________________________________*/
int cothalf2(term t, term arg, term *next, char *reason)
/* cot(u/2) = (sin u)/(1-cos u)*/
{ term num,denom,u,v,cancelled,temp;
  int err;
  if(FUNCTOR(t) != COT)
     return 1;
  v = ARG(0,t);
  if(FUNCTOR(v) == '*' && ONEHALF(ARG(0,v)))
     { denom = two;
       if(ARITY(v) == 2)
          num  = ARG(1,v);
       else
          cancel(v,two,&cancelled,&denom);
     }
  else if(FUNCTOR(v) == '/')
     { denom = ARG(1,ARG(0,t));
       num = ARG(0,ARG(0,t));
     }
  else
     return 1;
  if(equals(denom,two))
     u = num;
  else
     { err = cancel(denom,two,&cancelled,&temp);
       if(err)
          return 1;
       u = make_fraction(num,temp);
     }
  *next = make_fraction(sin1(u),sum(one,tnegate(cos1(u))));
  HIGHLIGHT(*next);
  strcpy(reason,"cot(u/2) =           (sin u)/(1-cos u)");
  return 0;
}

/*__________________________________________________________________*/
int sinhalf1(term t, term arg, term *next, char *reason)
/* sin(u/2) =  \pm \\sqrt ((1-cos u)/2) if sin(u/2) >= 0*/
{ term u,v,temp,cancelled,num,denom;
  int err;
  if(FUNCTOR(t)!= SIN)
     return 1;
  v = ARG(0,t);
  if(FUNCTOR(v) == '*' && ONEHALF(ARG(0,v)))
     { denom = two;
       if(ARITY(v) == 2)
          num = ARG(1,v);
       else
          cancel(v,two,&cancelled,&denom);
     }
  else if(FUNCTOR(v) == '/')
     { denom = ARG(1,ARG(0,t));
       num = ARG(0,ARG(0,t));
     }
  else
     return 1;
  if(equals(denom,two))
     u = num;
  else
     { err = cancel(denom,two,&cancelled,&temp);
       if(err)
          return 1;
       u = make_fraction(num,temp);
     }
  if(get_mathmode() == AUTOMODE)
     { err = infer(le(zero,t));
       if(err)
          return 1;
     }
  else /* menu mode */
     { err = infer(le(zero,t));
       if(err)
          { err = infer(lessthan(t,zero));
            if(!err)
               return 1;
            assume(le(zero,t));
            commentbuf(0,english(1984));
            commentbuf(1,english(1985));
            commentbuf(2,english(1986));
/* MathXpert is assuming that what is under the square root is nonnegative.
   It is possible to make contradictory assumptions and arrive at wrong answers.
   Therefore, keep an eye on your assumptions.
*/
          }
     }
  *next = sqrt1(make_fraction(sum(one,tnegate(cos1(u))),two));
  strcpy(reason,"sin(u/2) =            $\\sqrt ((1-cos u)/2)$");
  HIGHLIGHT(*next);
  return 0;
}
/*__________________________________________________________________*/
int sinhalf2(term t, term arg, term *next, char *reason)
/* sin(u/2) = -\\sqrt ((1-cos u)/2) if sin(u/2) <= 0*/
{ term u,v,temp,cancelled,num,denom;
  int err;
  if(FUNCTOR(t)!= SIN)
     return 1;
  v = ARG(0,t);
  if(FUNCTOR(v) == '*' && ONEHALF(ARG(0,v)))
     { denom = two;
       if(ARITY(v) == 2)
          num = ARG(1,v);
       else
          cancel(v,two,&cancelled,&denom);
     }
  else if(FUNCTOR(v) == '/')
     { denom = ARG(1,ARG(0,t));
       num = ARG(0,ARG(0,t));
     }
  else
     return 1;
  if(equals(denom,two))
     u = num;
  else
     { err = cancel(denom,two,&cancelled,&temp);
       if(err)
          return 1;
       u = make_fraction(num,temp);
     }
  if(get_mathmode() == AUTOMODE)
     { err = infer(le(t,zero));
       if(err)
          return 1;
     }
  else /* menu mode */
     { err = infer(le(t,zero));
       if(err)
          { err = infer(lessthan(zero,t));
            if(!err)
               return 1;
            assume(le(t,zero));
            commentbuf(0,english(1984));
            commentbuf(1,english(1985));
            commentbuf(2,english(1986));
/* MathXpert is assuming that what is under the square root is nonnegative.
   It is possible to make contradictory assumptions and arrive at wrong answers.
   Therefore, keep an eye on your assumptions.
*/
          }
     }
  *next = tnegate(sqrt1(make_fraction(sum(one,tnegate(cos1(u))),two)));
   strcpy(reason,"sin(u/2) =            $-\\sqrt ((1-cos u)/2)$");
  HIGHLIGHT(*next);
  return 0;
}

/*__________________________________________________________________*/
int coshalf1(term t, term arg, term *next, char *reason)
{ term u,v,temp,cancelled,num,denom;
  int err;
  if(FUNCTOR(t)!= COS)
     return 1;
  v = ARG(0,t);
  if(FUNCTOR(v) == '*' && ONEHALF(ARG(0,v)))
     { denom = two;
       if(ARITY(v) == 2)
          num = ARG(1,v);
       else
          cancel(v,two,&cancelled,&denom);
     }
  else if(FUNCTOR(v) == '/')
     { denom = ARG(1,ARG(0,t));
       num = ARG(0,ARG(0,t));
     }
  else
     return 1;
  if(equals(denom,two))
     u = num;
  else
     { err = cancel(denom,two,&cancelled,&temp);
       if(err)
          return 1;
       u = make_fraction(num,temp);
     }
  if(get_mathmode() == AUTOMODE)
     { err = infer(le(zero,t));
       if(err)
          return 1;
     }
  else /* menu mode */
     { err = infer(le(zero,t));
       if(err)
          { err = infer(lessthan(t,zero));
            if(!err)
               return 1;
            assume(le(zero,t));
            commentbuf(0,english(1984));
            commentbuf(1,english(1985));
            commentbuf(2,english(1986));
/* MathXpert is assuming that what is under the square root is nonnegative.
   It is possible to make contradictory assumptions and arrive at wrong answers.
   Therefore, keep an eye on your assumptions.
*/
          }
     }
  *next = sqrt1(make_fraction(sum(one,cos1(u)),two));
  strcpy(reason,"cos(u/2) =            $\\sqrt ((1+cos u)/2)$");
  HIGHLIGHT(*next);
  return 0;
}
/*__________________________________________________________________*/
int coshalf2(term t, term arg, term *next, char *reason)
{ term u,v,temp,cancelled,num,denom;
  int err;
  if(FUNCTOR(t)!= COS)
     return 1;
  v = ARG(0,t);
  if(FUNCTOR(v) == '*' && ONEHALF(ARG(0,v)))
     { denom = two;
       if(ARITY(v) == 2)
          num = ARG(1,v);
       else
          cancel(v,two,&cancelled,&denom);
     }
  else if(FUNCTOR(v) == '/')
     { denom = ARG(1,ARG(0,t));
       num = ARG(0,ARG(0,t));
     }
  else
     return 1;
  if(equals(denom,two))
     u = num;
  else
     { err = cancel(denom,two,&cancelled,&temp);
       if(err)
          return 1;
       u = make_fraction(num,temp);
     }
  if(get_mathmode() == AUTOMODE)
     { err = infer(le(t,zero));
       if(err)
          return 1;
     }
  else /* menu mode */
     { err = infer(le(t,zero));
       if(err)
          { err = infer(lessthan(zero,t));
            if(!err)
               return 1;
            assume(le(zero,t));
            commentbuf(0,english(1984));
            commentbuf(1,english(1985));
            commentbuf(2,english(1986));
/* MathXpert is assuming that what is under the square root is nonnegative.
   It is possible to make contradictory assumptions and arrive at wrong answers.
   Therefore, keep an eye on your assumptions.
*/
          }
     }
  *next = tnegate(sqrt1(make_fraction(sum(one,cos1(u)),two)));
  strcpy(reason,"cos(u/2) =            $-\\sqrt ((1+cos u)/2)$");
  HIGHLIGHT(*next);
  return 0;
}
/*____________________________________________________________________*/
int twicehalf(term t, term arg, term *next, char *reason)
/* \theta = 2(\theta/2) on the menus, but really  does
f(\theta) = f(2(\theta/2))  when f is a trig function and \theta is not
a fraction. */
/* This operator is only used in menu mode, for example to
give one proof of tan(x/2) = (1-cos x)/sin x, by writing the
right side as a function of x/2  */

{ unsigned short f = FUNCTOR(t);
  term theta,u;
  if(!TRIGFUNCTOR(f))
     return 1;
  theta = ARG(0,t);
  if(FRACTION(theta))
     { errbuf(0,english(1128));
       /* Trig arguments already are fractions. */
       return 1;
     }
  u = product(two,make_fraction(theta,two));
  PROTECT(u);
  HIGHLIGHT(u);
  *next = make_term(f,1);
  ARGREP(*next,0,u);
  strcpy(reason,"$\\theta = 2(\\theta/2)$");
  return 0;
}
/*______________________________________________________________*/
int decrementtrigarg(term t, term arg, term *next, char *reason)
/* n\theta = (n-1)\theta + \theta */
/* Not used in auto mode */
{ term a,n,theta;
  if(FUNCTOR(t) != '*' || !INTEGERP(ARG(0,t)))
     return 1;
  n = ARG(0,t);
  if(ONE(n) || ZERO(n))
     return 1;
  if(ARITY(t) == 2)
     theta = ARG(1,t);
  else
     cancel(t,n,&a,&theta);
  value(sum(n,minusone),&a);
  assert(INTEGERP(a));
  *next = sum(product(a,theta),theta);
  PROTECT(*next);
  HIGHLIGHT(*next);
  strcpy(reason, "$n\\theta = (n-1)\\theta + \\theta$");
  return 0;
}

/*______________________________________________________________*/
int querytrigarg(term t, term arg, term *next, char *reason)
/* n\theta = ?\theta+(n-?)\theta */
{ term a,b,n,theta;
  if(FUNCTOR(t) != '*' || !INTEGERP(ARG(0,t)))
     return 1;
  n = ARG(0,t);
  if(ONE(n) || ZERO(n))
     return 1;
  if(ARITY(t) == 2)
     theta = ARG(1,t);
  else
     cancel(t,n,&a,&theta);
  if(!INTEGERP(arg))
     return 1;
  a = arg;
  value(sum(n,tnegate(a)),&b);
  if(NEGATIVE(b))
     { errbuf(0, english(1422));
       /* Number entered is too large */
       return 1;
     }
  *next = sum(product(a,theta),product(b,theta));
  PROTECT(*next);
  HIGHLIGHT(*next);
  strcpy(reason, "$n\\theta = ?\\theta + (n-?)\\theta$");
  return 0;
}
/*______________________________________________________________*/
int triplesin(term t, term arg, term *next, char *reason)
/* sin 3\theta = 3 sin \theta - 4 sin^3 \theta */
{ int err;
  term cancelled, temp,u;
  if (FUNCTOR(t) != SIN)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  err = cancel(u,three,&cancelled,&temp);
  if(err)
     return 1;
  *next = sum(product(three,sin1(temp)), tnegate(product(four, make_power(sin1(temp),three))));
  HIGHLIGHT(*next);
  strcpy(reason,"$$sin 3theta = 3 sin theta - 4 sin^3 theta$$");
  return 0;
}

/*______________________________________________________________*/
int triplecos(term t, term arg, term *next, char *reason)
/* cos 3\theta = 4 cos^3 \theta -3 cos \theta  */
{ int err;
  term cancelled, temp,u;
  if (FUNCTOR(t) != COS)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  err = cancel(u,three,&cancelled,&temp);
  if(err)
     return 1;
  *next = sum(product(four,make_power(cos1(temp),three)),tnegate(product(three, cos1(temp))));
  HIGHLIGHT(*next);
  strcpy(reason,"$$cos 3 theta =  4 cos^3 theta - 3 cos theta$$");
  return 0;
}

/*______________________________________________________________*/
#define MAXMULTIPLE 20
int expandsin(term t, term arg, term *next, char *reason)
/* expand sin n\theta in sin \theta, cos \theta */
{ term u,n,s,c,p,theta;
  long kk;
  if(FUNCTOR(t) != SIN)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  n = ARG(0,u);
  if(!INTEGERP(n))
     return 1;
  if(!ISINTEGER(n) || INTDATA(n) > MAXMULTIPLE)
     { errbuf(0, english(1423));
       /* Expansion would be too long */
       return 1;
     }
  if(ARITY(u) == 2)
     theta = ARG(1,u);
  else
     cancel(u,n,&p,&theta);
  kk = INTDATA(n);
  if(kk == 2)
     { SetShowStepOperation(doublesin);
       return doublesin(t,arg,next,reason);
     }
  if(kk==3)
     { SetShowStepOperation(triplesin);
       return triplesin(t,arg,next,reason);
     }
  s = sin1(theta);
  c = cos1(theta);
  *next = expand_sin((int) kk,s,c);
  SETORDERED(*next);
  HIGHLIGHT(*next);
  strcpy(reason, english(362));  /* expand sin */
  return 0;
}
/*______________________________________________________________*/
int expandcos(term t, term arg, term *next, char *reason)
/* expand cos n\theta in sin \theta, cos \theta */
{ term u,n,s,c,p,theta;
  long kk;
  if(FUNCTOR(t) != COS)
     return 1;
  u = ARG(0,t);
  if(FUNCTOR(u) != '*')
     return 1;
  n = ARG(0,u);
  if(!INTEGERP(n))
     return 1;
  if(!ISINTEGER(n) || INTDATA(n) > MAXMULTIPLE)
     { errbuf(0, english(1423));
       /* Expansion would be too long */
       return 1;
     }
  if(ARITY(u) == 2)
     theta = ARG(1,u);
  else
     cancel(u,n,&p,&theta);
  kk = INTDATA(n);
  if(kk == 2)
     { SetShowStepOperation(doublecos1);
       return doublecos1(t,arg,next,reason);
     }
  if(kk==3)
     { SetShowStepOperation(triplecos);
       return triplecos(t,arg,next,reason);
     }
  s = sin1(theta);
  c = cos1(theta);
  *next = expand_cos((int) kk,s,c);
  SETORDERED(*next);
  HIGHLIGHT(*next);
  strcpy(reason, english(829)); /* expand cos */
  return 0;
}
/*______________________________________________________________*/
static term expand_sin(int n, term s, term c)
/* return a polynomial f(s,c) which expresses sin(n x) in terms
of s = sin x and c = cos x.  Such a polynomial is obtained from
the imaginary part of the binomial expansion of e^(i n x) = (cos(x) + i sin x)^n
*/
{ int k;
  term ans,u,coef,p,q;
  term nn = make_int(n);
  int m = (n-1)/2;  /* upper limit of sum index */
  ans = make_term('+',(unsigned short)(m+1));
  for(k=0;k<=m;k++)
     { binomial(nn,make_int(2*k+1),&coef);
       p = n == 2*k+1 ? one : make_power(c,make_int(n-2*k-1));
       q = make_power(s,make_int(2*k+1));
       if(ONE(coef))
          u = (k&1) ? tnegate(product(p,q)) : product(p,q);
       else
          u = (k&1) ? tnegate(product3(coef,p,q)) : product3(coef,p,q);
       ARGREP(ans,k,u);
     }
  return ans;
}


/*______________________________________________________________*/
static term expand_cos(int n, term s, term c)
/* return a polynomial f(s,c) which expresses cos(n x) in terms
of s = sin x and c = cos x.  Such a polynomial is obtained from
the real part of the binomial expansion of e^(i n x)
*/
{ int k;
  term ans,u,coef,nn,p,q;
  int m = n/2;  /* upper limit of sum index */
  ans = make_term('+',(unsigned short)(m+1));
  nn = make_int(n);
  for(k=0;k<=m;k++)
     { binomial(nn,make_int(2*k),&coef);
       p = n == 2*k ? one : make_power(c,make_int(n-2*k));
       q = k == 0 ? one : make_power(s,make_int(2*k));
       if(ONE(coef))
          u = (k&1) ? tnegate(product(p,q)) : product(p,q);
       else
          u = (k&1) ? tnegate(product3(coef,p,q)) : product3(coef,p,q);
       ARGREP(ans,k,u);
     }
  return ans;
}

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