Sindbad~EG File Manager
/* double angle and half-angle trig operators
M. Beeson, for MathXpert
1.13.91 original date
2.26.98 last modified
*/
#define ALGEBRA_DLL
#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 */
static term expand_sin(int,term,term);
static term expand_cos(int,term,term);
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int doublesin(term t, term arg, term *next, char *reason)
/* sin 2� = 2 sin � cos � */
{ int err;
term cancelled, temp,u;
if (FUNCTOR(t) != SIN)
return 1;
u = ARG(0,t);
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�=2 sin � cos �$");
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int doublecos1(term t, term arg, term *next, char *reason)
/* cos 2� = cos^2 � - sin^2 � */
/* This operator is associated to COS; the same rule associated to
'+' (for use when cos 2� 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� = cos^2�-sin^2�$");
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int doublecos2(term t, term arg, term *next, char *reason)
/*cos 2� = 1 - 2 sin^2 � */
{ 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(one,tnegate(product(two,make_power(sin1(temp),two))));
HIGHLIGHT(*next);
strcpy(reason,"$cos 2� = 1-2 sin^2 �$");
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int doublecos3(term t, term arg, term *next, char *reason)
/* cos 2� = 2 cos^2 � - 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� = 2 cos^2 �-1$");
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int doubletan(term t, term arg, term *next, char *reason)
/* tan(2�) = 2 tan �/(1 - tan^2 �) */
{ 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) || check(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�$ = $2tan �/(1-tan^2�)$");
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int doublecot(term t, term arg, term *next, char *reason)
/* cot(2�) = (cot^2 � -1) / (2 cot �) */
{ 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) || check(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�$ = $(cot^2�-1)/(2 cot �)$");
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int sinsqhalf(term t, term arg, term *next, char *reason)
/* sin^2(u/2) = (1-cos u)/2 */
/* but NOT sin^2�(u) = (1-cos(2u)/2)� */
{ 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);
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int cossqhalf(term t, term arg, term *next, char *reason)
/* cos^2(u/2) = (1+cos u)/2 */
/* but NOT cos^2�(u) = (1+cos(2u)/2)� */
{ 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);
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int sinsqhalf2(term t, term arg, term *next, char *reason)
/* sin^2(u/2) = (1-cos u)/2 */
/* sin^2�(u) = (1-cos(2u)/2)� */
/* 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;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int sinhalf1(term t, term arg, term *next, char *reason)
/* sin(u/2) = �((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) = $�((1-cos u)/2)$");
HIGHLIGHT(*next);
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int sinhalf2(term t, term arg, term *next, char *reason)
/* sin(u/2) = -�((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(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) = $-�((1-cos u)/2)$");
HIGHLIGHT(*next);
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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) = $�((1+cos u)/2)$");
HIGHLIGHT(*next);
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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(zero,t));
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) = $-�((1+cos u)/2)$");
HIGHLIGHT(*next);
return 0;
}
/*____________________________________________________________________*/
MEXPORT_ALGEBRA int twicehalf(term t, term arg, term *next, char *reason)
/* � = 2(�/2) on the menus, but really does
f(�) = f(2(�/2)) when f is a trig function and � 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,"$� = 2(�/2)$");
return 0;
}
/*______________________________________________________________*/
MEXPORT_ALGEBRA int decrementtrigarg(term t, term arg, term *next, char *reason)
/* n� = (n-1)� + � */
/* 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� = (n-1)� + �$");
return 0;
}
/*______________________________________________________________*/
MEXPORT_ALGEBRA int querytrigarg(term t, term arg, term *next, char *reason)
/* n� = ?�+(n-?)� */
{ 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� = ?� + (n-?)�$");
return 0;
}
/*______________________________________________________________*/
MEXPORT_ALGEBRA int triplesin(term t, term arg, term *next, char *reason)
/* sin 3� = 3 sin � - 4 sin^3 � */
{ 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 3�$ = $3 sin � - 4 sin^3 �$");
return 0;
}
/*______________________________________________________________*/
MEXPORT_ALGEBRA int triplecos(term t, term arg, term *next, char *reason)
/* cos 3� = 4 cos^3 � -3 cos � */
{ 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�$ = $4 cos^3 � - 3 cos �$");
return 0;
}
/*______________________________________________________________*/
#define MAXMULTIPLE 20
MEXPORT_ALGEBRA int expandsin(term t, term arg, term *next, char *reason)
/* expand sin n� in sin �, cos � */
{ 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;
}
/*______________________________________________________________*/
MEXPORT_ALGEBRA int expandcos(term t, term arg, term *next, char *reason)
/* expand cos n� in sin �, cos � */
{ 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