Sindbad~EG File Manager
/* Evaluate trig functions menu operators for MathXpert */
/*
M. Beeson
Original date 11.19.91
Last modified 7.27.98
11.21.00 removed comments #pragma argsused
4.12.01 added two lines to combine3045
*/
#define ALGEBRA_DLL
#include <string.h>
#include <math.h>
#include <assert.h>
char *ltoa(long,char *,int);
#include "globals.h"
#include "ops.h"
#include "trig.h"
#include "cancel.h"
#include "prover.h"
#include "order.h" /* numerical */
#include "deval.h" /* nearint */
#include "polynoms.h"
#include "algaux.h"
#include "pvalaux.h"
#include "symbols.h"
#include "errbuf.h"
#include "dispfunc.h"
#include "mstring.h"
static term degrees_to_radians(term k);
static void trigreason(char *reason, unsigned short f, int flag, long k);
/*_________________________________________________________________________*/
#define RADIANS 0
#define DEGREES 1
static void trigreason(char *reason, unsigned short f, int flag, long k)
/* k is an angle in degrees between 0 and 359 which is a multiple
of 30 or 45 degrees. Return a reason string in *reason showing
its value. flag is either RADIANS or DEGREES; use this in generating
an appropriate reason string. */
{ int j;
functor_string(f,SCREEN,reason);
reason[3] = 32;
if(flag==DEGREES)
{ j = strlen(ltoa(k,reason+4,10)) + 4;
reason[j] = '$';
reason[j+1] = (char) 248; /* degree symbol */
reason[j+2] = '$';
reason[j+3] = '\0';
strcat(reason," = ");
}
else
{ mstring(degrees_to_radians(make_int(k)),reason+4);
strcat(reason," = ");
}
mstring(trig_aux(f,k),reason + strlen(reason));
}
/*_________________________________________________________________________*/
static term degrees_to_radians(term k)
/* convert degrees to radians */
{ term ans,u,v;
if(ZERO(k))
return zero;
u = product(pi,k);
v = make_int(180L);
polyval(make_fraction(u,v),&ans);
return ans;
}
/*_________________________________________________________________________*/
static term radians_to_degrees(term rad)
/* convert radians to degrees */
{ term ans,u;
if(ZERO(rad))
return zero;
u = product(make_int(180L),rad);
polyval(make_fraction(u,pi),&ans);
return ans;
}
/*_________________________________________________________________________*/
MEXPORT_ALGEBRA int mod360(term t, term arg, term *next, char *reason)
/* find coterminal angle < 360� */
{ unsigned short f = FUNCTOR(t);
term u,theta,val,three_sixty,temp;
char buffer[10];
int err;
if(ATOMIC(t) || !TRIGFUNCTOR(f))
return 1;
u = ARG(0,t);
if(FUNCTOR(u) != DEG)
{ errbuf(0, english(701));
/* Angle is not expressed in degrees. */
return 1;
}
theta = ARG(0,u);
if(!numerical(theta) && value(theta,&val))
/* nonzero return from value is nonnumerical value */
{ errbuf(0, english(702));
/* Can't do arithmetic with that angle */
return 1;
}
three_sixty = make_int(360L);
err = tmod(theta,three_sixty,&temp);
if(err || equals(theta,temp))
return 1;
*next = make_term(f,1);
ARGREP(*next,0,deg1(temp));
if(equals(t,*next))
return 1; /* angle already between 0 and 360 */
functor_string(f,SCREEN,buffer);
strcpy(reason,buffer);
strcat(reason,"(u) = ");
strcat(reason,buffer);
strcat(reason,"$(u+360�)$");
HIGHLIGHT(*next);
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int mod2pi(term t, term arg, term *next, char *reason)
/* find coterminal angle < 2� */
{ unsigned short f = FUNCTOR(t);
term theta,val,temp,u,cancelled,v;
double a;
char buffer[10];
int err;
if(ATOMIC(t) || !TRIGFUNCTOR(f))
return 1;
theta = ARG(0,t);
/* The next block of code deals with for example sin(x+2k�)
which has to go to sin(x); but in automode, this should
happen through operators sinperiodic etc, so that
sin(x+2�) is dealt with by sinsum and not by this
operator under the topic _trig_addition. */
if(get_mathmode() == MENUMODE &&
FUNCTOR(theta) == '+' &&
contains(theta,PI_ATOM)
)
{ err = periodic3(t,next,reason);
if(!err)
return 0;
}
err = polyval(make_fraction(theta,pi),&u);
if(!err)
{ if(POSNUMBER(u))
{ err = tmod(u,two,&temp);
if(err || equals(u,temp))
return 1;
}
else if(NEGATIVE(u) && POSNUMBER(ARG(0,u)))
{ err = tmod(ARG(0,u),two,&temp);
if(err || equals(ARG(0,u),temp))
return 1;
polyval(sum(product(two,pi),tnegate(temp)),&temp);
}
else /* u is symbolic */
{ err = cancel(u,product(two,pi),&cancelled, &v);
if(!err && isinteger(v))
temp = zero;
else
return 1;
}
*next = make_term(f,1);
polyval(product(temp,pi),ARGPTR(*next));
/* polyval used here to change (1/2) pi to pi/2 */
goto out;
}
/* Now pi doesn't cancel */
if(!numerical(theta) || value(theta,&val))
/* nonzero return from value is nonnumerical value */
{ badval:
errbuf(0, english(702));
/* Can't do arithmetic with that angle */
return 1;
}
u = make_term(MOD,2);
ARGREP(u,0,theta);
ARGREP(u,1,product(two,pi));
err = deval(u,&a);
if(err) goto badval;
*next = make_term(f,1);
ARGREP(*next,0,make_double(a));
out:
if(equals(*next,t))
return 1; /* angle already between 0 and 2� */
HIGHLIGHT(ARG(0,*next));
functor_string(f,SCREEN,buffer);
strcpy(reason,buffer);
strcat(reason,"(u) = ");
strcat(reason,buffer);
strcat(reason,"$(u+2�)$");
HIGHLIGHT(*next);
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int sin90(term t, term arg, term *next, char *reason)
/* angle is multiple of 90� */
/* calculate trig function of a multiple of pi/2, whether argument is
in degrees or radians */
{ term u,v,w,ninety,cancelled;
unsigned short f=FUNCTOR(t);
int err;
long k;
if(ATOMIC(t) || !TRIGFUNCTOR(f))
return 1;
if(FUNCTOR(ARG(0,t)) == DEG)
{ u = ARG(0,ARG(0,t));
if(ZERO(u))
v = zero;
else
{ ninety = make_int(90L);
err = cancel(u,ninety,&cancelled,&v);
if(err)
return 1;
}
}
else /* angle interpreted as radians */
{ u = ARG(0,t);
if(ZERO(u))
v = zero;
else
{ err = polyval(make_fraction(product(two,u),pi),&v);
if(err || !isinteger(v))
return 1;
}
}
err = tmod(v,four,&w);
if(!err && OBJECT(w) && TYPE(w)==INTEGER)
{ /* w is 0,1,2, or 3 */
k = INTDATA(w);
assert(k >=0 && k < 4);
*next = trig_aux(f,k*90);
goto out;
}
/* in case of sin(0.5 pi), v will now be 2 * 0.5 */
if(numerical(v))
{ double zz;
deval(v,&zz);
if(zz != BADVAL && nearint(zz,&k))
{k &= 0x0003; /* k = k%4 even for k negative */
*next = trig_aux(f,k*90);
goto out;
}
else
return 1;
}
/* Sometimes we can calculate the value even when tmod fails,
e.g. sin(n�) is always zero even though we don't know whether
n is even or odd */
k = 27; /* means we don't know its real value */
if(f == SIN || f == TAN || f == CSC)
{ err = cancel(v,two,&cancelled,&w); /* see if the angle is a multiple of pi */
if(!err)
{ err = infer(type(w,INTEGER));
if(err)
return 1;
/* yes, it's a multiple of pi */
*next = (f==CSC ? undefined : zero);
goto out;
}
return 1;
}
if(f == COS || f == COT || f == SEC)
{ err = cancel(sum(v,one),two,&cancelled,&w); /* is it an odd multiple of pi/2 ? */
if(!err)
{ err = infer(type(w,INTEGER));
if(err)
return 1;
*next = (f == SEC ? undefined : zero);
goto out;
}
}
return 1;
out:
HIGHLIGHT(*next);
if(k!=27)
trigreason(reason,f,(FUNCTOR(ARG(0,t))==DEG ? DEGREES: RADIANS), k*90);
else if(f==SIN || f == TAN || f == CSC)
{ strcpy(reason, english(703)); /* multiple of */
if(FUNCTOR(ARG(0,t))==DEG)
strcat(reason,"$180�$");
else
strcat(reason,"$�$");
}
else /* f == COS, SEC, or COT */
{ strcpy(reason, english(704)); /* odd multiple of */
if(FUNCTOR(ARG(0,t))==DEG)
strcat(reason, "$90�$");
else
strcat(reason, "$�/2$");
}
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int sin0(term t, term arg, term *next, char *reason)
/* sin 0 = 0 */
{ term u;
unsigned short f=FUNCTOR(t);
if(ATOMIC(t) || f != SIN)
return 1;
u = ARG(0,t);
if(ISZERO(u) || (FUNCTOR(u) == DEG && ISZERO(ARG(0,u))))
{ *next = zero;
strcpy(reason, "sin 0 = 0");
HIGHLIGHT(*next);
return 0;
}
return 1;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int cos0(term t, term arg, term *next, char *reason)
/* cos 0 = 1 */
{ term u;
unsigned short f=FUNCTOR(t);
if(ATOMIC(t) || f != COS)
return 1;
u = ARG(0,t);
if(ISZERO(u) || (FUNCTOR(u) == DEG && ISZERO(ARG(0,u))))
{ *next = one;
strcpy(reason, "cos 0 = 1");
HIGHLIGHT(*next);
return 0;
}
return 1;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int tan0(term t, term arg, term *next, char *reason)
/* tan 0 = 0 */
{ term u;
unsigned short f=FUNCTOR(t);
if(ATOMIC(t) || f != TAN)
return 1;
u = ARG(0,t);
if(ISZERO(u) || (FUNCTOR(u) == DEG && ISZERO(ARG(0,u))))
{ *next = zero;
strcpy(reason, "tan 0 = 0");
HIGHLIGHT(*next);
return 0;
}
return 1;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int sin30(term t, term arg, term *next, char *reason)
/* use 1-2-�3 triangle */
{ term u,v,w,thirty,cancelled;
unsigned short f = FUNCTOR(t);
int err;
long k;
if( ATOMIC(t) || !TRIGFUNCTOR(f) )
return 1;
if(FUNCTOR(ARG(0,t)) == DEG)
{ u = ARG(0,ARG(0,t));
if(ZERO(u))
v = zero;
else
{ thirty = make_int(30L);
err = cancel(u,thirty,&cancelled,&v);
if(err)
return 1;
}
}
else /* angle interpreted as radians */
{ u = ARG(0,t);
if(ZERO(u))
v = zero;
else
{ err = polyval(make_fraction(product(six,u),pi),&v);
if(err || !isinteger(v))
return 1;
}
}
err = tmod(v,make_int(12L),&w);
if(!err && OBJECT(w) && TYPE(w)==INTEGER)
{ /* w is 0,1,2,...11 */
k = INTDATA(w);
assert(k >=0 && k < 12);
if(k%3 == 0) /* angle is a multiple of �/2 */
{ if(!get_polyvalfunctionflag()) /* don't do this while using polyval */
errbuf(0, english(705));
/* Use \"angle is multiple of 90�\" instead. */
return 1;
}
*next = trig_aux(f,k*30);
goto out;
}
if(numerical(v))
{ double zz;
deval(v,&zz);
if(zz != BADVAL && nearint(zz,&k))
{ k = k %12;
if(k<0) k = 12-k;
*next = trig_aux(f,k*30);
goto out;
}
else
return 1;
}
return 1;
out:
HIGHLIGHT(*next);
trigreason(reason,f,(FUNCTOR(ARG(0,t))==DEG ? DEGREES: RADIANS), k*30);
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int sin45(term t, term arg, term *next, char *reason)
/* use 1-1-�2 triangle */
{ term u,v,w,fortyfive,cancelled;
unsigned short f = FUNCTOR(t);
int err;
long k;
if(ATOMIC(t) || !TRIGFUNCTOR(f) )
return 1;
if(FUNCTOR(ARG(0,t)) == DEG)
{ u = ARG(0,ARG(0,t));
if(ZERO(u)) v = zero;
else
{ fortyfive = make_int(45L);
err = cancel(u,fortyfive,&cancelled,&v);
if(err)
return 1;
}
}
else /* angle interpreted as radians */
{ u = ARG(0,t);
err = polyval(make_fraction(product(four,u),pi),&v);
/* cancel won't cancel pi out of 3pi/4, so we use polyval instead */
if(err || !isinteger(v))
return 1;
}
err = tmod(v,eight,&w);
if(!err && OBJECT(w) && TYPE(w) == INTEGER)
{ /* w is 0,1,2,...7 */
k = INTDATA(w);
assert(k >=0 && k < 8);
if(!(k&1)) /* k is even */
{ if(!get_polyvalfunctionflag())
errbuf(0, english(705));
/* Use \"angle is multiple of 90�\" instead. */
return 1;
}
*next = trig_aux(f,k*45);
goto out;
}
if(numerical(v))
{ double zz;
deval(v,&zz);
if(zz != BADVAL && nearint(zz,&k))
{ k = k % 8;
if(k<0) k = 8-k;
*next = trig_aux(f,k*45);
goto out;
}
else
return 1;
}
return 1;
out:
HIGHLIGHT(*next);
trigreason(reason,f,(FUNCTOR(ARG(0,t))==DEG ? DEGREES: RADIANS), k*45);
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int radtodeg(term t, term arg, term *next, char *reason)
/* change radians to degrees in arg of a trig functor */
{ unsigned short f = FUNCTOR(t);
term degrees;
int sign;
double z;
long kk;
term u;
if(ATOMIC(t) || !TRIGFUNCTOR(f))
return 1;
u = ARG(0,t);
if(FUNCTOR(u) == DEG)
{ errbuf(0,english(1364));
return 1; /* Angle is already in degrees. */
}
*next = make_term(f,1);
if(!seminumerical(ARG(0,t)))
{ errbuf(0, english(1856));
/* You can only convert a specific, numerical angle to degrees. */
return 1;
}
degrees = radians_to_degrees(ARG(0,t));
if(NEGATIVE(degrees))
{ sign = -1;
degrees = ARG(0,degrees);
}
else
sign = 1;
if(!OBJECT(degrees) && !NUMBER(degrees))
{ deval(degrees,&z);
if(z < 0)
{ sign *= -1;
z = -z;
}
if(nearint(z,&kk))
degrees = make_int(kk);
else
degrees = make_double(z);
}
if(sign == -1)
ARGREP(*next,0, tnegate(deg1(degrees)));
else
ARGREP(*next,0,deg1(degrees));
HIGHLIGHT(*next);
strcpy(reason, english(706)); /* radians to degrees */
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int degtorad(term t, term arg, term *next, char *reason)
/* change degrees to radians */
/* works either on deg(x) or f(deg(x)) where f is a trig functor */
{ unsigned short f = FUNCTOR(t);
if(TRIGFUNCTOR(f) && FUNCTOR(ARG(0,t)) == DEG)
{ *next = make_term(f,1);
ARGREP(*next,0,degrees_to_radians(ARG(0,ARG(0,t))));
strcpy(reason, english(707)); /* degrees = 180�rad/� */
HIGHLIGHT(ARG(0,*next));
return 0;
}
if (FUNCTOR(t) != DEG)
return 1;
*next = degrees_to_radians(ARG(0,t));
strcpy(reason, english(707)); /* degrees to radians */
HIGHLIGHT(*next);
return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA int combine3045(term t, term arg, term *next, char *reason)
/* angle = a 30� + b 45� etc. */
/* If t is a trig function of �, express � as a linear combination of
30 and 45 degrees */
{ long s,k,b;
unsigned short f = FUNCTOR(t);
term theta;
if(ATOMIC(t) || !TRIGFUNCTOR(f) )
return 1;
if(FUNCTOR(ARG(0,t)) != DEG)
{ errbuf(0, english(708));
/* First express the angle in degrees. */
return 1;
}
theta = ARG(0,ARG(0,t)); /* the angle in degrees */
if(FUNCTOR(theta) == '-')
{ errbuf(0, english(709));
/* This only works on positive angles. */
return 1;
}
if(! ISINTEGER(theta))
return 1;
s = INTDATA(theta);
if(s%15)
return 1; /* must be divisible by 15 for this to work */
if(s%45 == 0 || s%30 == 0)
return 1; /* don't work on multiples of 45 or 30 */
k = s/15;
b = k/3;
*next = make_term(f,1);
if( k-3*b == 2)
{
ARGREP(*next,0,
sum(deg1(make_int(30)),
product(make_int(b),deg1(make_int(45)))
)
);
strcpy(reason, english(710)); /* angle = 30� + b 45� */
}
else
{ --b;
ARGREP(*next,0,
sum(deg1(make_int(60)),
product(make_int(b),deg1(make_int(45)))
)
);
strcpy(reason, english(711)); /* angle = 60� + b 45� */
}
HIGHLIGHT(*next);
return 0;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int zeroesofsin(term t, term arg, term *next, char *reason)
/* sin(k�) = 0; does not work if argument is in degrees */
{ term u,cancelled,n;
int err;
if(FUNCTOR(t) != SIN)
return 1;
u = ARG(0,t);
if(ISZERO(u))
{ strcpy(reason,"sin 0 = 0");
*next = zero;
return 0;
}
if(equals(u,pi))
{ strcpy(reason,"$sin � = 0$");
*next = zero;
return 0;
}
if(NEGATIVE(u))
u = ARG(0,u);
if(FUNCTOR(u) != '*')
return 1;
err = cancel(u,pi,&cancelled,&n);
if(err)
return 1;
if(isinteger(n))
goto out;
if(contains(n,'/'))
return 1; /* it can't be an integer if it contains a fraction */
err = infer(type(n,INTEGER));
if(err)
return 1;
out:
strcpy(reason,"$sin k� = 0$");
*next = zero;
return 0;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int zeroesoftan(term t, term arg, term *next, char *reason)
/* tan(k�) = 0 */
{ term u,cancelled,n;
int err;
if(FUNCTOR(t) != TAN)
return 1;
u = ARG(0,t);
if(ZERO(u))
{ strcpy(reason,"tan 0 = 0");
*next = zero;
return 0;
}
if(equals(u,pi))
{ strcpy(reason,"$tan � = 0$");
*next = zero;
return 0;
}
if(NEGATIVE(u))
u = ARG(0,u);
if(FUNCTOR(u) != '*')
return 1;
err = cancel(u,pi,&cancelled,&n);
if(err)
return 1;
if(isinteger(n))
goto out;
if(contains(n,'/'))
return 1; /* it can't be an integer if it contains a fraction */
err = infer(type(n,INTEGER));
if(err)
return 1;
out:
strcpy(reason,"$tan k� = 0$");
*next = zero;
return 0;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int onesofcos(term t, term arg, term *next, char *reason)
/* cos(2k�) = 1 */
{ term u,cancelled,n,twopi;
int err;
if(FUNCTOR(t) != COS)
return 1;
u = ARG(0,t);
if(ZERO(u))
{ strcpy(reason,"cos 0 = 1");
*next = one;
return 0;
}
if(NEGATIVE(u))
u = ARG(0,u);
if(FUNCTOR(u) != '*')
return 1;
if(!contains(u,FUNCTOR(pi)))
return 1;
twopi = product(two,pi);
err = cancel(u,twopi,&cancelled,&n);
if(err)
{ RELEASE(twopi);
return 1;
}
if(isinteger(n))
goto out;
if(contains(n,'/'))
{ RELEASE(twopi);
return 1; /* it can't be an integer if it contains a fraction */
}
err = infer(type(n,INTEGER));
if(err)
{ RELEASE(twopi);
return 1;
}
out:
strcpy(reason,"$cos 2k� = 1$");
*next = one;
return 0;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int sinperiodic(term t, term arg, term *next, char *reason)
/* sin(u+2�) = sin u */
{ if(FUNCTOR(t) != SIN || ATOMIC(ARG(0,t)))
return 1;
return periodic3(t,next,reason);
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int cosperiodic(term t, term arg, term *next, char *reason)
/* cos(u+2�) = cos u */
{ if(FUNCTOR(t) != COS || ATOMIC(ARG(0,t)))
return 1;
return periodic3(t,next,reason);
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int tanperiodic(term t, term arg, term *next, char *reason)
/* tan(u+�) = tan u */
{ if(FUNCTOR(t) != TAN || ATOMIC(ARG(0,t)))
return 1;
return periodic3(t,next,reason);
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int sinsqperiodic(term t, term arg, term *next, char *reason)
/* sin^2(u+�) = sin^2 u */
{ term u,m;
int err;
if(FUNCTOR(t) != '^' || FUNCTOR(ARG(0,t)) != SIN)
return 1;
u = ARG(0,ARG(0,t));
m = ARG(1,t);
if(
(INTEGERP(m) && ISEVEN(m))
||
!infer(even(m))
)
{ err = periodic3(tan1(u),next,reason);
/* send a TAN term to periodic3 so it will use period pi */
if(err)
return 1;
/* Now convert the fake TAN answer in *next to a sinsq answer */
*next = make_power(sin1(ARG(0,*next)),m);
strcpy(reason,"$sin^2(u+�) = sin^2 u$");
return 0;
}
return 1;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int cossqperiodic(term t, term arg, term *next, char *reason)
/* cos^2(u+�) = cos^2 u */
{ term u,m;
int err;
if(FUNCTOR(t) != '^' || FUNCTOR(ARG(0,t)) != COS)
return 1;
u = ARG(0,ARG(0,t));
m = ARG(1,t);
if(
(INTEGERP(m) && ISEVEN(m))
||
!infer(even(m))
)
{ err = periodic3(tan1(u),next,reason);
/* send a TAN term to periodic3 so it will use period pi */
if(err)
return 1;
/* Now convert the fake TAN answer in *next to a cossq answer */
*next = make_power(cos1(ARG(0,*next)),m);
strcpy(reason,"$cos^2(u+�) = cos^2 u$");
return 0;
}
return 1;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int secsqperiodic(term t, term arg, term *next, char *reason)
/* sec^2(u+�) = sec^2 u */
{ term u,m;
int err;
if(FUNCTOR(t) != '^' || FUNCTOR(ARG(0,t)) != SEC)
return 1;
u = ARG(0,ARG(0,t));
m = ARG(1,t);
if(
(INTEGERP(m) && ISEVEN(m))
||
!infer(even(m))
)
{ err = periodic3(tan1(u),next,reason);
/* send a TAN term to periodic3 so it will use period pi */
if(err)
return 1;
/* Now convert the fake TAN answer in *next to a secsq answer */
*next = make_power(sec1(ARG(0,*next)),m);
strcpy(reason,"$sec^2(u+�) = sec^2 u$");
return 0;
}
return 1;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int cscsqperiodic(term t, term arg, term *next, char *reason)
/* csc^2(u+�) = csc^2 u */
{ term u,m;
int err;
if(FUNCTOR(t) != '^' || FUNCTOR(ARG(0,t)) != CSC)
return 1;
u = ARG(0,ARG(0,t));
m = ARG(1,t);
if(
(INTEGERP(m) && ISEVEN(m))
||
!infer(even(m))
)
{ err = periodic3(tan1(u),next,reason);
/* send a TAN term to periodic3 so it will use period pi */
if(err)
return 1;
/* Now convert the fake TAN answer in *next to a secsq answer */
*next = make_power(csc1(ARG(0,*next)),m);
strcpy(reason,"$csc^2(u+�) = csc^2 u$");
return 0;
}
return 1;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int cotperiodic(term t, term arg, term *next, char *reason)
/* cot(u+�) = cot u */
{ if(FUNCTOR(t) != COT || ATOMIC(ARG(0,t)))
return 1;
return periodic3(t,next,reason);
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int cscperiodic(term t, term arg, term *next, char *reason)
/* csc(u+2�) = csc u */
{ if(FUNCTOR(t) != CSC || ATOMIC(ARG(0,t)))
return 1;
return periodic3(t,next,reason);
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int secperiodic(term t, term arg, term *next, char *reason)
/* sec(u+2�) = sec u */
{ if(FUNCTOR(t) != SEC || ATOMIC(ARG(0,t)))
return 1;
return periodic3(t,next,reason);
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int sinhalfperiod1(term t, term arg, term *next, char *reason)
/* sin u = -sin(u-pi) */
{ term u,v,w;
int err;
double z;
if(FUNCTOR(t) != SIN)
return 1;
u = ARG(0,t);
if(FUNCTOR(u) == DEG)
{ v = ARG(0,u);
err = value(sum(v, tnegate(make_int(180))),&w);
if(err)
{ if(seminumerical(v))
{ deval(v,&z);
if(z != BADVAL)
w = make_double(z);
else
return 1;
}
else
return 1;
}
*next = tnegate(sin1(deg1(w)));
}
else
{ polyval(sum(u,tnegate(pi)),&w);
*next = tnegate(sin1(w));
}
strcpy(reason,"$sin u = -sin(u-�)$");
return 0;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int coshalfperiod1(term t, term arg, term *next, char *reason)
/* cos u = -cos(u-pi) */
{ term u,v,w;
int err;
double z;
if(FUNCTOR(t) != COS)
return 1;
u = ARG(0,t);
if(FUNCTOR(u) == DEG)
{ v = ARG(0,u);
err = value(sum(v, tnegate(make_int(180))),&w);
if(err)
{ if(seminumerical(v))
{ deval(v,&z);
if(z != BADVAL)
w = make_double(z);
else
return 1;
}
else
return 1;
}
*next = tnegate(cos1(deg1(w)));
}
else
{ polyval(sum(u,tnegate(pi)),&w);
*next = tnegate(cos1(w));
}
strcpy(reason,"$cos u = -cos(u-�)$");
return 0;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int sinhalfperiod2(term t, term arg, term *next, char *reason)
/* sin u = sin(pi-u) */
{ term u,v,w;
int err;
double z;
if(FUNCTOR(t) != SIN)
return 1;
u = ARG(0,t);
if(FUNCTOR(u) == DEG)
{ v = ARG(0,u);
err = value(sum(make_int(180),tnegate(v)),&w);
if(err)
{ if(seminumerical(v))
{ deval(v,&z);
if(z != BADVAL)
w = make_double(z);
else
return 1;
}
else
return 1;
}
*next = sin1(deg1(w));
}
else
{ polyval(sum(pi,tnegate(u)),&w);
*next = sin1(w);
}
strcpy(reason,"$sin u = sin(�-u)$");
return 0;
}
/*_____________________________________________________________________*/
MEXPORT_ALGEBRA int coshalfperiod2(term t, term arg, term *next, char *reason)
/* cos u = -cos(pi-u) */
{ term u,v,w;
int err;
double z;
if(FUNCTOR(t) != COS)
return 1;
u = ARG(0,t);
if(FUNCTOR(u) == DEG)
{ v = ARG(0,u);
err = value(sum(make_int(180),tnegate(v)),&w);
if(err)
{ if(seminumerical(v))
{ deval(v,&z);
if(z != BADVAL)
w = make_double(z);
else
return 1;
}
else
return 1;
}
*next = tnegate(cos1(deg1(w)));
}
else
{ polyval(sum(pi,tnegate(u)),&w);
*next = tnegate(cos1(w));
}
strcpy(reason,"$cos u = -cos(�-u)$");
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists