Sindbad~EG File Manager
/* csc and cot identities, for MathXpert
M. Beeson, 10.29.93
Last modified 2.26.98
This code is made from corresponding code for sec and tan
identities by global search-and-replace. If you change
the sec and tan identities code change this too.
*/
#include <string.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 "pathtail.h" /* set_pathtail */
#include "autosimp.h" /* SetShowStepOperation */
#include "pvalaux.h" /* ratpart2 */
/*__________________________________________________________________*/
int cscsqminuscotsq(term t, term arg, term *next, char *reason)
/* csc^2 a - cot^2 a = 1 */
{ term lhs,rhs,a;
int err;
lhs = sum(make_power(csc1(var0),two),tnegate(make_power(cot1(var0),two)));
rhs = one;
err = match(t,lhs,rhs,&a,next); /* instantiate a and *next */
if(err)
{ destroy_term(lhs);
return 1;
}
HIGHLIGHT(*next);
strcpy(reason,"csc^2 a - cot^2 a = 1");
return 0;
}
/*__________________________________________________________________*/
int cotsquare1(term t, term arg, term *next, char *reason)
/* cot^2 a + 1 = csc^2 a */
{ term lhs,rhs,a;
int err;
lhs = sum(make_power(cot1(var0),two),one);
rhs = make_power(csc1(var0),two);
err = match(t,lhs,rhs,&a,next); /* instantiate a and *next */
if(err)
{ destroy_term(lhs);
return 1;
}
HIGHLIGHT(*next);
strcpy(reason,"cot^2 a + 1 = csc^2 a");
return 0;
}
/*__________________________________________________________________*/
int cotsquare2(term t, term arg, term *next, char *reason)
/* csc^2 a - 1 = cot^2 a */
{ term lhs,rhs,a;
unsigned short i,j;
int err;
unsigned short path[11];
if(FRACTION(t) && get_mathmode() == AUTOMODE)
{ term x;
int whicharg;
term newnum,newdenom;;
err = sq_aux(ARG(1,t),COT,&x,&whicharg);
if(!err)
{ err = cotsquare2(ARG(0,t),arg,&newnum,reason);
if(err)
return 1;
*next = make_fraction(newnum,ARG(1,t));
path[0] = '/';
path[1] = 1;
path[2] = 0;
if(FUNCTOR(ARG(0,t)) == '*' || FUNCTOR(ARG(0,t)) == '^')
pathcat(path,get_pathtail());
set_pathtail(path);
return 0;
}
err = sq_aux(ARG(0,t),COT,&x,&whicharg);
if(!err)
{ err = cotsquare2(ARG(1,t),arg,&newdenom,reason);
if(err)
return 1;
*next = make_fraction(ARG(0,t),newdenom);;
path[0] = '/';
path[1] = 2;
path[2] = 0;
if(FUNCTOR(ARG(1,t)) == '*' || FUNCTOR(ARG(1,t)) == '^')
pathcat(path,get_pathtail());
set_pathtail(path);
return 0;
}
return 1;
}
if(FUNCTOR(t) == '^' && get_mathmode() == AUTOMODE)
{ term temp;
err = cotsquare2(ARG(0,t),arg,&temp,reason);
if(err)
return 1;
*next = make_power(temp,ARG(1,t));
path[0] = '^';
path[1] = 1;
path[2] = 0;
return 0;
}
if(FUNCTOR(t) == '*' && get_mathmode() == AUTOMODE)
{ unsigned short n = ARITY(t);
term u,temp;
for(i=0;i<n;i++)
{ u = ARG(i,t);
if(FUNCTOR(u) != '^' && FUNCTOR(u) != '+')
continue;
err = cotsquare2(u,arg,&temp,reason);
if(!err)
{ path[0] = '*';
path[1] = i+1;
path[2] = 0;
if(FUNCTOR(u) == '^')
pathcat(path, get_pathtail());
set_pathtail(path);
}
break;
}
if(i==n)
return 1;
*next = make_term('*',n);
for(j=0;j<n;j++)
{ if(j==i)
ARGREP(*next,j,temp);
else
ARGREP(*next,j,ARG(j,t));
}
return 0;
}
lhs = sum(make_power(csc1(var0),two),minusone);
rhs = make_power(cot1(var0),two);
err = match(t,lhs,rhs,&a,next); /* instantiate a and *next */
if(err)
{ destroy_term(lhs);
return 1;
}
HIGHLIGHT(*next);
strcpy(reason,"csc^2 a - 1 = cot^2 a");
return 0;
}
/*___________________________________________________________*/
int cotsqtocscsq(term t, term arg, term *next, char *reason)
/* cot^2 u = csc^2 u - 1. But it also works on a sum, applying
this identity wherever possible to summands, even if the
summands are multiplied by conscotts, and simplifying the result.
*/
{ term u,v,temp,c,s;
int i,j,err,powerflag;
unsigned short n;
int success = 0;
unsigned short path[11];
if(FUNCTOR(t) == '/' && get_mathmode() == AUTOMODE)
return sqinfract(t,COT,next,reason);
if(FUNCTOR(t) == '=')
{ if(FUNCTOR(ARG(0,t)) == '^' &&
FUNCTOR(ARG(0,ARG(0,t))) == COT &&
iseven(ARG(1,ARG(0,t)))
)
{ err = cotsqtocscsq(ARG(0,t),arg,&temp,reason);
if(err)
return 1;
*next = equation(temp,ARG(1,t));
path[0] = '=';
path[1] = 1;
path[2] = 0;
set_pathtail(path);
return 0;
}
else if(FUNCTOR(ARG(1,t)) == '^' &&
FUNCTOR(ARG(0,ARG(1,t))) == COT &&
iseven(ARG(1,ARG(1,t)))
)
{ err = cotsqtocscsq(ARG(1,t),arg,&temp,reason);
if(err)
return 1;
*next = equation(ARG(0,t),temp);
path[0] = '=';
path[1] = 2;
path[2] = 0;
set_pathtail(path);
return 0;
}
}
if(FUNCTOR(t)== '+' && contains(t,COT))
{ n = ARITY(t);
v = make_term((unsigned short)'+',n);
powerflag = 0;;
for(i=0;i<n;i++)
{ u = ARG(i,t);
if(FUNCTOR(u) == '^' && !equals(ARG(0,u),two))
powerflag = 1;
err = cotsqtocscsq(u,arg,&temp,reason);
if(!err)
{ ARGREP(v,i,temp);
success = 1;
path[0] = '+';
path[1] = i+1;
path[2] = 0;
if(FUNCTOR(u) == '*' || FUNCTOR(u) == '-')
pathcat(path,get_pathtail());
set_pathtail(path);
/* Now set powerflag if we don't want to call polyval on the result
because that will produce a too-large step for a student */
temp = NEGATIVE(u) ? ARG(0,u) : u;
if(FUNCTOR(temp) == '*')
{ ratpart2(temp,&c,&s);
temp = s;
}
if(FUNCTOR(temp) == '^' && !equals(ARG(1,temp),two))
powerflag = 1;
if(FUNCTOR(temp) == '*')
powerflag = 1;
PROTECT(ARG(i,v));
}
else
ARGREP(v,i,u);
}
if(success)
{ if(powerflag)
*next = v;
else
polyval(v,next);
return 0;
}
return 1;
}
if(FUNCTOR(t) == '*')
{ n = ARITY(t);
for(i=0;i<n;i++)
{ u = ARG(i,t);
if(FUNCTOR(u) == '^' && FUNCTOR(ARG(0,u)) == COT)
{ err = cotsqtocscsq(u,arg,&temp,reason);
if(!err)
{ path[0] = '*';
path[1] = i+1;
path[2] = 0;
set_pathtail(path);
break;
}
}
}
if(i==n)
return 1;
*next = make_term('*',n);
for(j=0;j<n;j++)
{ if(j==i)
ARGREP(*next,j,temp);
else
ARGREP(*next,j,ARG(j,t));
}
return 0;
}
if(FUNCTOR(t) == '-')
{ err = cotsqtocscsq(ARG(0,t),arg,&temp,reason);
if(err)
return 1;
*next = tnegate(temp);
path[0] = '-';
path[1] = 1;
path[2] = 0;
if(FUNCTOR(ARG(0,t)) == '*' || FUNCTOR(ARG(0,t)) == '+')
pathcat(path,get_pathtail());
set_pathtail(path);
return 0;
}
if(FUNCTOR(t) != '^')
return 1;
if(FUNCTOR(ARG(0,t)) != COT)
return 1;
u = ARG(0,ARG(0,t));
if(!equals(ARG(1,t),two))
{ err = cancel(ARG(1,t),two,&temp,&v);
if(err)
return 1;
*next = make_power(sum(make_power(csc1(u),two),minusone),v);
}
else /* exponentis two */
*next = sum(make_power(csc1(u),two),minusone);
HIGHLIGHT(*next);
strcpy(reason,"cot^2 u = csc^2 u - 1");
return 0;
}
/*___________________________________________________________*/
int cscsqtocotsq(term t, term arg, term *next, char *reason)
/* csc^2 u = cot^2 u + 1. But it also works on a sum, applying
this identity wherever possible to summands, even if the
summands are multiplied by conscotts, and simplifying the result.
*/
{ term u,v,temp,c,s;
int i,j,err,powerflag;
unsigned short n;
unsigned short path[11];
int success = 0;
if(FUNCTOR(t) == '/' && get_mathmode() == AUTOMODE)
return sqinfract(t,CSC,next,reason);
if(FUNCTOR(t) == '=')
{ if(FUNCTOR(ARG(0,t)) == '^' &&
FUNCTOR(ARG(0,ARG(0,t))) == CSC &&
iseven(ARG(1,ARG(0,t)))
)
{ err = cscsqtocotsq(ARG(0,t),arg,&temp,reason);
if(err)
return 1;
*next = equation(temp,ARG(1,t));
path[0] = '=';
path[1] = 1;
path[2] = 0;
set_pathtail(path);
return 0;
}
else if(FUNCTOR(ARG(1,t)) == '^' &&
FUNCTOR(ARG(0,ARG(1,t))) == CSC &&
iseven(ARG(1,ARG(1,t)))
)
{ err = cscsqtocotsq(ARG(1,t),arg,&temp,reason);
if(err)
return 1;
*next = equation(ARG(0,t),temp);
path[0] = '=';
path[1] = 2;
path[2] = 0;
set_pathtail(path);
return 0;
}
}
if(FUNCTOR(t)== '+' && contains(t,CSC))
{ n = ARITY(t);
v = make_term((unsigned short)'+',n);
powerflag = 0;
for(i=0;i<n;i++)
{ u = ARG(i,t);
if(FUNCTOR(u) == '^' && !equals(ARG(1,u),two))
powerflag = 1;
err = cscsqtocotsq(u,arg,&temp,reason);
if(!err)
{ ARGREP(v,i,temp);
success = 1;
path[0] = '+';
path[1] = i+1;
path[2] = 0;
if(FUNCTOR(u) == '*' || FUNCTOR(u) == '-')
pathcat(path,get_pathtail());
set_pathtail(path);
/* Now set powerflag if we don't want to call polyval on the result
because that will produce a too-large step for a student */
temp = NEGATIVE(u) ? ARG(0,u) : u;
if(FUNCTOR(temp) == '*')
{ ratpart2(temp,&c,&s);
temp = s;
}
if(FUNCTOR(temp) == '^' && !equals(ARG(1,temp),two))
powerflag = 1;
if(FUNCTOR(temp) == '*')
powerflag = 1;
PROTECT(ARG(i,v));
}
else
ARGREP(v,i,u);
}
if(success)
{ if(powerflag)
*next = v;
else
polyval(v,next);
return 0;
}
return 1;
}
if(FUNCTOR(t) == '*')
{ n = ARITY(t);
for(i=0;i<n;i++)
{ u = ARG(i,t);
if(FUNCTOR(u) == '^' && FUNCTOR(ARG(0,u)) == CSC)
{ err = cscsqtocotsq(u,arg,&temp,reason);
if(!err)
{ path[0] = '*';
path[1] = i+1;
path[2] = 0;
set_pathtail(path);
break;
}
}
}
if(i==n)
return 1;
*next = make_term('*',n);
for(j=0;j<n;j++)
{ if(j==i)
ARGREP(*next,j,temp);
else
ARGREP(*next,j,ARG(j,t));
}
return 0;
}
if(FUNCTOR(t) == '-')
{ err = cscsqtocotsq(ARG(0,t),arg,&temp,reason);
if(err)
return 1;
*next = tnegate(temp);
path[0] = '-';
path[1] = 1;
path[2] = 0;
if(FUNCTOR(ARG(0,t)) == '*' || FUNCTOR(ARG(0,t)) == '+')
pathcat(path,get_pathtail());
set_pathtail(path);
return 0;
}
if(FUNCTOR(t) != '^')
return 1;
if(FUNCTOR(ARG(0,t)) != CSC)
return 1;
u = ARG(0,ARG(0,t));
if(!equals(ARG(1,t),two))
{ err = cancel(ARG(1,t),two,&temp,&v);
if(err)
return 1;
*next = make_power(sum(make_power(cot1(u),two),one),v);
}
else /* exponentis two */
*next = sum(make_power(cot1(u),two),one);
HIGHLIGHT(*next);
strcpy(reason,"csc^2 u = cot^2 u + 1");
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists