Sindbad~EG File Manager
/* solve basic trig equations
M. Beeson
Original date 1.2.92
last modified 2.26.98
11.18.10 corrected evalarctan
3.19.23 added else return 1 line 221
*/
#include <string.h>
#include <math.h>
#include <assert.h>
#include "globals.h"
#include "ops.h"
#include "trig.h"
#include "cancel.h"
#include "prover.h"
#include "probtype.h"
#include "symbols.h"
#include "errbuf.h"
static int eliminatesq_aux(unsigned short ,term,term *);
/*_______________________________________________________________*/
static void sintable(int sign,term num,term den,term *p,term *q,int *degrees)
/* sign is 1 or -1
return the two basic solutions p and q of sin u = sign * num/den,
and return *degrees = 30 or 45 according as which triangle was used.
*/
{ if(equals(den,two))
{ *degrees = 30;
if(sign == 1 && ONE(num))
{ *p = make_fraction(pi_term,six);
*q = make_fraction(product(five,pi_term),six);
}
else if(sign == -1 && ONE(num))
{ tneg(make_fraction(pi_term,six),p);
tneg(make_fraction(product(five,pi_term),six),q);
}
else if(sign == 1 && FUNCTOR(num)==SQRT)
{ *p = make_fraction(pi_term,three);
*q = make_fraction(product(two,pi_term),three);
}
else if(sign == -1 && FUNCTOR(num)==SQRT)
{ tneg(make_fraction(pi_term,three),p);
tneg(make_fraction(product(two,pi_term),three),q);
}
}
else if(FUNCTOR(den) == SQRT && ONE(num))
{ *degrees = 45;
if(sign == 1)
{ *p = make_fraction(pi_term,four);
*q = make_fraction(product(three,pi_term),four);
}
else if(sign == -1)
{ *p = make_fraction(product(five,pi_term),four);
*q = make_fraction(product(seven,pi_term),four);
}
}
}
/*_______________________________________________________________*/
static void costable(int sign,term num,term den,term *p,term *q,int *degrees)
/* sign is 1 or -1
return the two basic solutions p and q of cos u = sign * num/den,
and return *degrees = 30 or 45 according as which triangle was used.
*/
{ if(equals(den,two))
{ *degrees = 30;
if(sign == 1 && ONE(num))
{ *p = make_fraction(pi_term,three);
*q = tnegate(*p);
}
else if(sign == -1 && ONE(num))
{ *p = make_fraction(product(two,pi_term),three);
*q = tnegate(*p);
}
else if(sign == 1 && FUNCTOR(num)==SQRT)
{ *p = make_fraction(pi_term,six);
*q = tnegate(*p);
}
else if(sign == -1 && FUNCTOR(num)==SQRT)
{ *p = make_fraction(product(five,pi_term),six);
*q = tnegate(*p);
}
}
else if(FUNCTOR(den) == SQRT && ONE(num))
{ *degrees = 45;
if(sign == 1)
{ *p = make_fraction(pi_term,four);
*q = tnegate(*p);
}
else if(sign == -1)
{ *p = make_fraction(product(three,pi_term),four);
*q = tnegate(*p);
}
}
SETORDERED(*p);
SETORDERED(*q); /* don't rearrange the order later on */
}
/*_______________________________________________________________*/
static int trigeqn_aux(term t, unsigned short f, int sign, term num, term den, term *next, char *reason)
/* solve f(u) = plus or minus num/den producing the answer *next and justification string */
{ term left, right,u,n,twonpi,p,q;
int i,degrees=0; // initialization to silence warning message
if(FUNCTOR(t) != '=')
return 1;
if(FUNCTOR(num) == SQRT && equals(den,ARG(0,num)))
/* treat sqrt(2)/2 as 1/sqrt 2 so that arcsin(sqrt(2)/2)
and arcsin(1/sqrt(2)) can both be evaluated. */
{ den = num;
num = one;
}
left = ARG(0,t);
u = ARG(0,left);
right = ARG(1,t);
if(FUNCTOR(left)!= f)
return 1;
if(sign < 0)
{ if(FUNCTOR(right) != '-')
return 1;
if(FUNCTOR(ARG(0,right))=='/')
{ if(!equals(num,ARG(0,ARG(0,right))))
return 1;
if(!equals(den,ARG(1,ARG(0,right))))
return 1;
}
else if(!ONE(ARG(0,right)) || !ONE(den) || !ONE(num))
return 1;
}
else if (sign==0)
{ if(!ZERO(right))
return 1;
}
else if(ONE(right))
{ if(!ONE(num) || !ONE(den))
return 1;
}
else if(FUNCTOR(right)!= '/')
{ if(!ONE(den) || !equals(right,num))
return 1;
}
else if(!equals(num,ARG(0,right)))
return 1;
else if(!equals(den,ARG(1,right)))
return 1;
n = getnewintvar1(t,"nmkjpq");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more */
return 1;
}
twonpi = product3(two,n,pi_term);
if(sign == 0)
{ switch(f)
{ case TAN: /* fall-through */
case SIN: *next = equation(u,product(n,pi_term));
break;
case COT: /* fall-through */
case COS: *next = equation(u,make_fraction(product(sum(product(two,n),one),pi_term),two));
break;
}
degrees = 90; /* signal to get the right reason string below */
}
else if(sign > 0 && ONE(right) && f != TAN)
{ switch(f)
{ case SIN:
*next = equation(u,sum(make_fraction(pi_term,two),twonpi));
break;
case COS:
*next = equation(u,twonpi);
break;
}
degrees = 90;
}
else if(sign < 0 && ONE(num) && ONE(den) && f != TAN)
{ switch(f)
{ case SIN:
*next = equation(u,sum(make_fraction(product(three,pi_term),two),twonpi));
break;
case COS:
*next = equation(u,product(sum(product(two,n),one),pi_term));
break;
}
degrees = 90;
}
else if(f==TAN)
{ if(sign==1 && FUNCTOR(den)==SQRT && equals(ARG(0,den),three))
{ *next = equation(u,sum(make_fraction(pi_term,six),product(n,pi_term)));
degrees = 30;
}
else if(sign== -1 && ONE(num) && FUNCTOR(den)==SQRT && equals(ARG(0,den),three))
{ *next = equation(u,sum(tnegate(make_fraction(pi_term,six)),product(n,pi_term)));
degrees = 30;
}
else if(sign == 1 && FUNCTOR(num) == SQRT && equals(ARG(0,num),three) && ONE(den))
{ *next = equation(u, sum(make_fraction(pi_term,three),product(n,pi_term)));
degrees = 30;
}
else if(sign == -1 && FUNCTOR(num) == SQRT && equals(ARG(0,num),three) && ONE(den))
{ *next = equation(u,sum(make_fraction(product(two,pi_term),three),product(n,pi_term)));
degrees = 30;
}
else if(sign == 1 && ONE(num) && ONE(den))
{ *next = or(equation(u,sum(make_fraction(pi_term,four),twonpi)),
equation(u,sum(make_fraction(product(five,pi_term),four),twonpi))
);
degrees = 45;
}
else if(sign == -1 && ONE(num) && ONE(den))
{ *next = or(equation(u, sum(make_fraction(product(three,pi_term),four),twonpi)),
equation(u, sum(make_fraction(product(seven,pi_term),four),twonpi))
);
degrees = 45;
}
}
else
{ if(f==SIN)
sintable(sign,num,den,&p,&q,°rees);
else if(f==COS)
costable(sign,num,den,&p,&q,°rees);
else
return 1;
*next = or(equation(u,sum(p,twonpi)),equation(u,sum(q,twonpi)));
}
HIGHLIGHT(*next);
switch(degrees)
{ case 30:
strcpy(reason, english(1046)); /* 30-60-90 triangle */
break;
case 45:
strcpy(reason, english(1047)); /* 45-45-90 triangle */
break;
case 90:
if(f==SIN || f == TAN)
{ switch(sign)
{ case 1:
strcpy(reason, english(1048));
/* sin u=1 iff u=\\pi /2+2n\\pi */
break;
case 0:
if(f==SIN)
strcpy(reason, english(1049));
/* sin u = 0 iff u = n\\pi */
else
strcpy(reason, english(1134));
/* tan u = 0 iff u = n\\pi */
break;
case -1:
strcpy(reason, english(1050));
/* sin u = -1 iff u = 3\\pi /2+2n\\pi */
break;
}
}
else if(f==COS || f == COT)
{ switch(sign)
{ case 0:
strcpy(reason, english(1051));
/* cos u=0 iff u=(2n+1)\\pi /2 */
break;
case 1:
strcpy(reason, english(1052));
/* cos u = 1 iff u=2n\\pi */
break;
case -1:
strcpy(reason, english(1053));
/* cos u = -1 iff u = (2n+1)\\pi */
break;
}
}
}
if(FUNCTOR(*next) == '=' )
{ PROTECT(ARG(1,*next)); /* don't make \\pi /6 + 2\\pi k into (\\pi + 12\\pi k)/12 */
SETORDERED(ARG(1,*next));
if(ATOMIC(u) && get_problemtype() != MINMAX)
/* in MINMAX this would block eliminateparameter */
PROTECT(*next);
}
else if(FUNCTOR(*next) == OR)
{ for(i=0;i<ARITY(*next);i++)
{ if(FUNCTOR(ARG(i,*next)) == '=')
{ PROTECT(ARG(1,ARG(i,*next)));
SETORDERED(ARG(1,ARG(i,*next)));
if(ATOMIC(u) && get_problemtype() != MINMAX)
/* in MINMAX this would block eliminateparameter */
PROTECT(ARG(i,*next));
}
}
}
return 0;
}
/*_______________________________________________________________*/
int solvesin30(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,1,one,two,next,reason);
}
/*_______________________________________________________________*/
int solvesin330(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,-1,one,two,next,reason);
}
/*_______________________________________________________________*/
int solvesin60(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,1,sqrt1(three),two,next,reason);
}
/*_______________________________________________________________*/
int solvesin300(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,-1,sqrt1(three),two,next,reason);
}
/*_______________________________________________________________*/
int solvecos30(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,1,sqrt1(three),two,next,reason);
}
/*_______________________________________________________________*/
int solvecos150(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,-1,sqrt1(three),two,next,reason);
}
/*_______________________________________________________________*/
int solvecos60(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,1,one,two,next,reason);
}
/*_______________________________________________________________*/
int solvecos120(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,-1,one,two,next,reason);
}
/*_______________________________________________________________*/
int solvetan30(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,1,one,sqrt1(three),next,reason);
}
/*_______________________________________________________________*/
int solvetan330(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,-1,one,sqrt1(three),next,reason);
}
/*_______________________________________________________________*/
int solvetan60(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,1,sqrt1(three),one,next,reason);
}
/*_______________________________________________________________*/
int solvetan120(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,-1,sqrt1(three),one,next,reason);
}
/*_______________________________________________________________*/
int solvesin45(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,1,one,sqrt1(two),next,reason);
}
/*_______________________________________________________________*/
int solvesin315(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,-1,one,sqrt1(two),next,reason);
}
/*_______________________________________________________________*/
int solvecos45(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,1,one,sqrt1(two),next,reason);
}
/*_______________________________________________________________*/
int solvecos135(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,-1,one,sqrt1(two),next,reason);
}
/*_______________________________________________________________*/
int solvetan45(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,1,one,one,next,reason);
}
/*_______________________________________________________________*/
int solvetan135(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,-1,one,one,next,reason);
}
/*_______________________________________________________________*/
int solvesin0(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,0,zero,one,next,reason);
}
/*_______________________________________________________________*/
int solvesin90(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,1,one,one,next,reason);
}
/*_______________________________________________________________*/
int solvesin270(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,-1,one,one,next,reason);
}
/*_______________________________________________________________*/
int solvecos90(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,0,zero,one,next,reason);
}
/*_______________________________________________________________*/
int solvecos0(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,1,one,one,next,reason);
}
/*_______________________________________________________________*/
int solvecos180(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,-1,one,one,next,reason);
}
/*_______________________________________________________________*/
int solvetan0(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,0,one,one,next,reason);
}
/*_______________________________________________________________*/
int solvecot90(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COT,0,one,one,next,reason);
}
/*_______________________________________________________________*/
int solvesin(term t, term arg, term *next, char *reason)
/* sin u = c iff c = (-1)^n arcsin u + n\\pi */
{ term left,right,npi,u,v,n;
int err;
if(FUNCTOR(t) != '=')
return 1;
left = ARG(0,t);
right = ARG(1,t);
if(FUNCTOR(left)!= SIN)
return 1;
u = ARG(0,left);
err = check1(le(abs1(right),one));
if(err)
{ errbuf(0, english(1045));
/* arcsin u defined only when |u| \le 1 */
return 1;
}
n = getnewintvar1(t,"nmkjpq");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more */
return 1;
}
npi = product(n,pi_term);
v = product(make_power(minusone,n),asin1(right));
*next = equation(u,sum(v,npi));
HIGHLIGHT(*next);
strcpy(reason, english(1054));
/* sin u = c iff u=(-1)^n arcsin c + n\\pi */
return 0;
}
/*_______________________________________________________________*/
int solvesin2(term t, term arg, term *next, char *reason)
/* sin u = c iff c = arcsin u + 2n\\pi or -arcsin u + (2n+1)\\pi */
{ term left,right,right2,u2,u,v,v2,n;
int err;
if(FUNCTOR(t) != '=')
return 1;
left = ARG(0,t);
right = ARG(1,t);
if(FUNCTOR(left)!= SIN)
return 1;
u = ARG(0,left);
err = check1(le(abs1(right),one));
if(err)
{ errbuf(0, english(1045));
/* arcsin u defined only when |u| \le 1 */
return 1;
}
n = getnewintvar1(t,"nmkjpq");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more */
return 1;
}
v = sum(asin1(right),product3(two,n,pi_term));
copy(right,&right2);
copy(u,&u2);
v2 = make_term('+',3);
ARGREP(v2,0,product3(two,n,pi_term));
ARGREP(v2,1,pi_term);
ARGREP(v2,2,tnegate(asin1(right2)));
*next = or(equation(u,v),equation(u2,v2));
HIGHLIGHT(*next);
strcpy(reason, english(1656));
/* sin u = c iff u=arcsin(c)+2n\\pi or u=-arcsin(c)+(2n+1)\\pi */
return 0;
}
/*_______________________________________________________________*/
int solvecos(term t, term arg, term *next, char *reason)
/* cos u=c iff u= \pm arccos c+2n pi */
{ term left,right,twonpi,u,v,n;
int err;
if(FUNCTOR(t) != '=')
return 1;
left = ARG(0,t);
right = ARG(1,t);
if(FUNCTOR(left)!= COS)
return 1;
u = ARG(0,left);
err = check1(le(abs1(right),one));
if(err)
{ errbuf(0, english(1055));
/* arccos u defined only when |u| \le 1 */
return 1;
}
n = getnewintvar1(t,"nmkjpq");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more */
return 1;
}
twonpi = product3(two,n,pi_term);
v = acos1(right);
*next = or(equation(u,sum(v,twonpi)),equation(u,sum(twonpi,tnegate(v))));
HIGHLIGHT(*next);
strcpy(reason, english(1056));
/* cos u = c iff u = \ pm arccos c + 2n pi */
return 0;
}
/*_______________________________________________________________*/
int solvetan(term t, term arg, term *next, char *reason)
/* tan u = c iff u = arctan c + n\\pi */
{ term left,right,npi,u,n;
if(FUNCTOR(t) != '=')
return 1;
left = ARG(0,t);
right = ARG(1,t);
if(FUNCTOR(left)!= TAN)
return 1;
u = ARG(0,left);
n = getnewintvar1(t,"nmkjpq");
if(FUNCTOR(n) == ILLEGAL)
{ errbuf(0, english(1448));
/* Too many subscripted variables, can't make more */
return 1;
}
npi = product(n,pi_term);
*next = equation(u,sum(atan1(right),npi));
HIGHLIGHT(*next);
strcpy(reason, english(1057));
/* tan u = c iff u = arctan c + n\\pi */
return 0;
}
/*_______________________________________________________________*/
int evalarcsin(term t, term arg, term *next, char *reason)
/* evaluate arcsin exactly */
{ term u,num,den;
if(FUNCTOR(t)!=ASIN)
return 1;
u = ARG(0,t);
strcpy(reason,"arcsin ");
if(ZERO(u))
{ *next = zero;
strcat(reason,"0 = 0");
goto out;
}
if(ONE(u))
{ *next = make_fraction(pi_term,two);
strcat(reason,"$1 = \\pi /2$");
goto out;
}
if(equals(u,minusone))
{ tneg(make_fraction(pi_term,two),next);
strcat(reason,"$-1 = -\\pi /2$");
goto out;
}
if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
FUNCTOR(ARG(1,u)) == SQRT && FRACTION(ARG(0,u)) &&
ONE(ARG(0,ARG(0,u)))
)
u = make_fraction(ARG(1,u),ARG(1,ARG(0,u)));
if(FUNCTOR(u) == '-')
{ u = ARG(0,u);
if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
FUNCTOR(ARG(1,u)) == SQRT && FRACTION(ARG(0,u)) &&
ONE(ARG(0,ARG(0,u)))
)
u = make_fraction(ARG(1,u),ARG(1,ARG(0,u)));
if(FUNCTOR(u) != '/')
return 1;
num = ARG(0,u);
den = ARG(1,u);
if(ONE(num) && equals(den,two))
{ tneg(make_fraction(pi_term,six),next);
strcat(reason,"$-1/2 = -\\pi /6$");
goto out;
}
if(
(ONE(num) && FUNCTOR(den) == SQRT && equals(ARG(0,den),two)) ||
(equals(den,two) && FUNCTOR(num)== SQRT && equals(ARG(0,num),two))
)
{ tneg(make_fraction(pi_term,four),next);
strcat(reason,"$-1/\\sqrt 2 = -\\pi /4$");
goto out;
}
if(equals(den,two) && FUNCTOR(num)==SQRT && equals(ARG(0,num),three))
{ tneg(make_fraction(pi_term,three),next);
strcat(reason,"$-\\sqrt 3/2 = -\\pi /3$");
goto out;
}
}
if(FUNCTOR(u) != '/')
return 1;
num = ARG(0,u);
den = ARG(1,u);
if(ONE(num) && equals(den,two))
{ *next = make_fraction(pi_term,six);
strcat(reason,"$1/2 = \\pi /6$");
goto out;
}
if(
(ONE(num) && FUNCTOR(den) == SQRT && equals(ARG(0,den),two)) ||
(equals(den,two) && FUNCTOR(num)== SQRT && equals(ARG(0,num),two))
)
{ *next = make_fraction(pi_term,four);
strcat(reason,"$1/\\sqrt 2 = \\pi /4$");
goto out;
}
if(equals(den,two) && FUNCTOR(num)==SQRT && equals(ARG(0,num),three))
{ *next = make_fraction(pi_term,three);
strcat(reason,"$\\sqrt 3/2 = \\pi /3$");
goto out;
}
return 1;
out:
HIGHLIGHT(*next);
return 0;
}
/*_______________________________________________________________*/
int evalarccos(term t, term arg, term *next, char *reason)
/* evaluate arccos exactly */
{ term u,num,den;
if(FUNCTOR(t)!=ACOS)
return 1;
u = ARG(0,t);
strcpy(reason,"arccos ");
if(ZERO(u))
{ *next = make_fraction(pi_term,two);
strcat(reason,"$0 = \\pi /2$");
goto out;
}
if(ONE(u))
{ *next = zero;
strcat(reason,"1 = 0");
goto out;
}
if(equals(u,minusone))
{ *next = pi_term;
strcat(reason,"$-1 = \\pi $");
goto out;
}
if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
FUNCTOR(ARG(1,u)) == SQRT && FRACTION(ARG(0,u)) &&
ONE(ARG(0,ARG(0,u)))
)
u = make_fraction(ARG(1,u),ARG(1,ARG(0,u)));
if(FUNCTOR(u) == '-')
{ u = ARG(0,u);
/* if u is (1/2) sqrt n, convert it to sqrt(n)/2 */
if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
FUNCTOR(ARG(1,u)) == SQRT && FRACTION(ARG(0,u)) &&
ONE(ARG(0,ARG(0,u)))
)
u = make_fraction(ARG(1,u),ARG(1,ARG(0,u)));
if(FUNCTOR(u) != '/')
return 1;
num = ARG(0,u);
den = ARG(1,u);
if(ONE(num) && equals(den,two))
{ *next = make_fraction(product(two,pi_term),three);
strcat(reason,"$-1/2 = 2\\pi /3$");
goto out;
}
if(
(ONE(num) && FUNCTOR(den) == SQRT && equals(ARG(0,den),two)) ||
(equals(den,two) && FUNCTOR(num)== SQRT && equals(ARG(0,num),two))
)
{ *next = make_fraction(product(three,pi_term),four);
strcat(reason,"$-1/\\sqrt 2 = 3\\pi /4$");
goto out;
}
if(equals(den,two) && FUNCTOR(num)==SQRT && equals(ARG(0,num),three))
{ *next = make_fraction(product(five,pi_term),six);
strcat(reason,"$-\\sqrt 3/2 = 5\\pi /6$");
goto out;
}
}
if(FUNCTOR(u) != '/')
return 1;
num = ARG(0,u);
den = ARG(1,u);
if(ONE(num) && equals(den,two))
{ *next = make_fraction(pi_term,three);
strcat(reason,"$1/2 = \\pi /3$");
goto out;
}
if(
(ONE(num) && FUNCTOR(den) == SQRT && equals(ARG(0,den),two)) ||
(equals(den,two) && FUNCTOR(num)== SQRT && equals(ARG(0,num),two))
)
{ *next = make_fraction(pi_term,four);
strcat(reason,"$1/\\sqrt 2 = \\pi /4$");
goto out;
}
if(equals(den,two) && FUNCTOR(num)==SQRT && equals(ARG(0,num),three))
{ *next = make_fraction(pi_term,six);
strcat(reason,"$\\sqrt 3/2 = \\pi /6$");
goto out;
}
return 1;
out:
HIGHLIGHT(*next);
return 0;
}
/*_______________________________________________________________*/
int evalarctan(term t, term arg, term *next, char *reason)
/* evaluate arctan exactly */
{ term u,num,den;
if(FUNCTOR(t)!=ATAN)
return 1;
u = ARG(0,t);
strcpy(reason,"arctan ");
if(ZERO(u))
{ *next = zero;
strcat(reason,"0 = 0");
goto out;
}
if(ONE(u))
{ *next = make_fraction(pi_term,four);
strcat(reason,"$1 = \\pi /4$");
goto out;
}
if(equals(u,minusone))
{ *next = tnegate(make_fraction(pi_term,four));
strcat(reason,"$-1 = -\\pi /4$");
goto out;
}
if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
FUNCTOR(ARG(1,u)) == SQRT && FRACTION(ARG(0,u)) &&
ONE(ARG(0,ARG(0,u)))
)
u = make_fraction(ARG(1,u),ARG(1,ARG(0,u)));
if(FUNCTOR(u) == '-')
{ u = ARG(0,u);
if(FUNCTOR(u) == '*' && ARITY(u) == 2 &&
FUNCTOR(ARG(1,u)) == SQRT && FRACTION(ARG(0,u)) &&
ONE(ARG(0,ARG(0,u)))
)
u = make_fraction(ARG(1,u),ARG(1,ARG(0,u)));
if(FUNCTOR(u) == SQRT && equals(ARG(0,u),three))
{ *next = tnegate(make_fraction(pi_term,three));
strcpy(reason,"$$arctan(- sqrt(3) = -pi /3$$");
goto out;
}
if(FUNCTOR(u) != '/')
return 1;
num = ARG(0,u);
den = ARG(1,u);
if(
(ONE(num) && FUNCTOR(den) == SQRT && equals(ARG(0,den),three)) ||
(equals(den,three) && FUNCTOR(num) == SQRT && equals(ARG(0,num),three))
)
{ *next = tnegate(make_fraction(pi_term,six));
strcpy(reason,"$$arctan(-1/sqrt 3) = -pi /6$$");
goto out;
}
}
if(FUNCTOR(u) == SQRT && equals(ARG(0,u),three))
{ *next = make_fraction(pi_term,three);
strcat(reason,"$\\sqrt 3 = \\pi /3$");
goto out;
}
if(FUNCTOR(u) != '/')
return 1;
num = ARG(0,u);
den = ARG(1,u);
if(
(ONE(num) && FUNCTOR(den) == SQRT && equals(ARG(0,den),three)) ||
(FUNCTOR(num) == SQRT && equals(ARG(0,num),three) && equals(den,three))
)
{ *next = make_fraction(pi_term,six);
strcat(reason,"$1/\\sqrt 3 = \\pi /6$");
goto out;
}
return 1;
out:
HIGHLIGHT(*next);
return 0;
}
/*_______________________________________________________________*/
int evalarccot(term t, term arg, term *next, char *reason)
{ if(FUNCTOR(t)!=ACOT)
return 1;
*next = atan1(reciprocal(ARG(0,t)));
strcpy(reason,"arccot x =arctan(1/x)");
return 0;
}
/*_______________________________________________________________*/
int evalarcsec(term t, term arg, term *next, char *reason)
{ if(FUNCTOR(t)!=ASEC)
return 1;
*next = acos1(reciprocal(ARG(0,t)));
strcpy(reason,"arcsec x =arccos(1/x)");
return 0;
}
/*_______________________________________________________________*/
int evalarccsc(term t, term arg, term *next, char *reason)
{ if(FUNCTOR(t)!=ACSC)
return 1;
*next = asin1(reciprocal(ARG(0,t)));
strcpy(reason,"arccsc x =arcsin(1/x)");
return 0;
}
/*__________________________________________________________________*/
int rejectimpossiblesin(term t, term arg, term *next, char *reason)
/* reject sin u = c if |c|>1 */
{ term left,right;
int err;
if(FUNCTOR(t) != '=')
return 1;
left = ARG(0,t);
right = ARG(1,t);
if(FUNCTOR(left)!= SIN)
return 1;
err = infer(lessthan(one,abs1(right)));
if(err)
return 1;
*next = falseterm;
HIGHLIGHT(*next);
strcpy(reason,"$|sin u| \\le 1$");
return 0;
}
/*__________________________________________________________________*/
int rejectimpossiblecos(term t, term arg, term *next, char *reason)
/* reject cos u = c if |c|>1 */
{ term left,right;
int err;
if(FUNCTOR(t) != '=')
return 1;
left = ARG(0,t);
right = ARG(1,t);
if(FUNCTOR(left)!= COS)
return 1;
err = infer(lessthan(one,abs1(right)));
if(err)
return 1;
*next = falseterm;
HIGHLIGHT(*next);
strcpy(reason,"$|cos u| \\le 1$");
return 0;
}
/*___________________________________________________________________*/
/* When only sin and cos are left, and one of them does not occur to
an odd power, that one must be eliminated. This is done in automode
only-- in menu mode you just use cossqtosinsq or sinsqtocossq.
You get here from autoeqn only when you know there are no trig
functors but sin and cos present and they all have the same arg. */
int eliminatesinsq(term t, term arg, term *next, char *reason)
{ int err;
if(FUNCTOR(t) != '=')
return 1;
if(!contains(t,COS) || !contains(t,SIN))
return 1;
err = eliminatesq_aux(SIN,t,next);
if(err)
return 1; /* SIN occurred to an odd power */
strcpy(reason,"$sin^2 u = 1 - cos^2 u$");
HIGHLIGHT(*next);
inhibit(sinsquare3); /* so 1-cos^2 doesn't re-introduce sin^2 */
return 0;
}
/*___________________________________________________________________*/
int eliminatecossq(term t, term arg, term *next, char *reason)
{ int err;
if(FUNCTOR(t) != '=')
return 1;
if(!contains(t,COS) || !contains(t,SIN))
return 1;
err = eliminatesq_aux(COS,t,next);
if(err)
return 1; /* COS occurred to an odd power */
strcpy(reason,"$cos^2 u = 1 - sin^2 u$");
HIGHLIGHT(*next);
inhibit(sinsquare2); /* so 1-sin^2 doesn't reintroduce cos^2 */
return 0;
}
/*___________________________________________________________________*/
int eliminatesecsq(term t, term arg, term *next, char *reason)
{ int err;
if(FUNCTOR(t) != '=')
return 1;
if(!contains(t,TAN) || !contains(t,SEC))
return 1;
err = eliminatesq_aux(SEC,t,next);
if(err)
return 1; /* SEC occurred to an odd power */
strcpy(reason,"$sec^2 u = tan^2 u + 1$");
HIGHLIGHT(*next);
inhibit(tansquare1); /* so tan^2 + 1 doesn't reintroduce sec^2 */
return 0;
}
/*___________________________________________________________________*/
int eliminatetansq(term t, term arg, term *next, char *reason)
{ int err;
if(FUNCTOR(t) != '=')
return 1;
if(!contains(t,TAN) || !contains(t,SEC))
return 1;
err = eliminatesq_aux(TAN,t,next);
if(err)
return 1; /* TAN occurred to an odd power */
strcpy(reason,"$tan^2 u = sec^2 u - 1$");
HIGHLIGHT(*next);
inhibit(tansquare2); /* so sec^2 - 1 doesn't reintroduce tan^2 */
return 0;
}
/*___________________________________________________________________*/
static int eliminatesq_aux(unsigned short h,term t,term *next)
/* apply sin^2 u = 1 - cos^2 u etc., where h = SIN, COS, SEC, or TAN
is the functor to be eliminated throughout t using the power laws */
/* Zero return is success; but it can succeed without doing anything
if there were no occurrences of the functor to be eliminated. This
however can't happen because it is only called when there ARE such
occurrences */
{ term power,newpower,cancelled;
int i,err;
unsigned short f,n;
if(ATOMIC(t))
{ *next = t;
return 0;
}
if(FUNCTOR(t) == '^' && FUNCTOR(ARG(0,t))==h)
{ power = ARG(1,t);
err = infer(even(power));
if(err)
return 1;
err = cancel(power,two,&cancelled,&newpower);
if(err)
return 1;
switch(h)
{ case SIN: *next = make_power(sum(one,tnegate(make_power(cos1(ARG(0,ARG(0,t))),two))),newpower);
break;
case COS: *next = make_power(sum(one,tnegate(make_power(sin1(ARG(0,ARG(0,t))),two))),newpower);
break;
case SEC: *next = make_power(sum(make_power(tan1(ARG(0,ARG(0,t))),two),one),newpower);
break;
case TAN: *next = make_power(sum(make_power(sec1(ARG(0,ARG(0,t))),two),minusone),newpower);
break;
default: assert(0);
}
return 0;
}
if(FUNCTOR(t)==h)
return 1;
f = FUNCTOR(t);
n = ARITY(t);
*next = make_term(f,n);
for(i=0;i<n;i++)
{ err = eliminatesq_aux(h,ARG(i,t),ARGPTR(*next)+i);
if(err)
return 1;
}
return 0;
}
/*_______________________________________________________________*/
int arctanodd(term t, term arg, term *next, char *reason)
/* arctan(-x) = -arctan x */
{ if(FUNCTOR(t) != ATAN || !NEGATIVE(ARG(0,t)))
return 1;
*next = tnegate(atan1(ARG(0,ARG(0,t))));
HIGHLIGHT(*next);
strcpy(reason, "arctan(-x)= -arctan x");
return 0;
}
/*_______________________________________________________________*/
int arcsinodd(term t, term arg, term *next, char *reason)
/* arcsin(-x) = -arcsin x */
{ if(FUNCTOR(t) != ASIN || !NEGATIVE(ARG(0,t)))
return 1;
*next = tnegate(asin1(ARG(0,ARG(0,t))));
HIGHLIGHT(*next);
strcpy(reason, "arcsin(-x)= -arcsin x");
return 0;
}
/*_______________________________________________________________*/
int arccosodd(term t, term arg, term *next, char *reason)
/* arccos(-x) = \\pi -arcsin x */
{ if(FUNCTOR(t) != ACOS || !NEGATIVE(ARG(0,t)))
return 1;
*next = sum(pi_term,tnegate(acos1(ARG(0,ARG(0,t)))));
HIGHLIGHT(*next);
strcpy(reason, "$arccos(-x)=\\pi -arccos x$");
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists