Sindbad~EG File Manager
/* operators for simplifying f(arcf(x)) and arcf(f(x)) */
/*
M. Beeson, for MathXpert
5.28.92 Original date
3.30.99 last modified
*/
#include <string.h>
#include <math.h>
#include <assert.h>
#define TRIGCALC_DLL
#include "globals.h"
#include "ops.h"
#include "trig.h"
#include "prover.h"
#include "symbols.h"
#include "mathmode.h" /* get_mathmode */
#include "match.h" /* matchstring */
#include "deval.h"
#include "pvalaux.h" /* topflatten */
#include "autosimp.h" /* SetShowStepArg */
#include "algaux.h" /* path_to_difference */
/*____________________________________________________________________*/
/* tan(arcsin x) = x/�(1-x^2) */
MEXPORT_TRIGCALC int tanasin(term t, term arg, term *next, char *reason)
{ term x;
if(FUNCTOR(t) != TAN)
return 1;
if(FUNCTOR(ARG(0,t)) != ASIN)
return 1;
x = ARG(0,ARG(0,t));
*next = make_fraction(x,sqrt1(sum(one,tnegate(make_power(x,two)))));
HIGHLIGHT(*next);
strcpy(reason,"tan(arcsin x) = $x/�(1-x^2)$");
return 0;
}
/*____________________________________________________________________*/
/* tan(arccos x) = �(1-x^2)/x */
MEXPORT_TRIGCALC int tanacos(term t, term arg, term *next, char *reason)
{ term x;
if(FUNCTOR(t) != TAN)
return 1;
if(FUNCTOR(ARG(0,t)) != ACOS)
return 1;
x = ARG(0,ARG(0,t));
*next = make_fraction(sqrt1(sum(one,tnegate(make_power(x,two)))),x);
HIGHLIGHT(*next);
strcpy(reason,"tan(arccos x) = $�(1-x^2)/x$");
return 0;
}
/*____________________________________________________________________*/
/* tan(arctan x) = x */
MEXPORT_TRIGCALC int tanatan(term t, term arg, term *next, char *reason)
{ if(FUNCTOR(t) != TAN)
return 1;
if(FUNCTOR(ARG(0,t)) != ATAN)
return 1;
*next = ARG(0,ARG(0,t));
HIGHLIGHT(*next);
strcpy(reason,"tan(arctan x) = x");
return 0;
}
/*____________________________________________________________________*/
/* sin(arcsin x) = x */
MEXPORT_TRIGCALC int sinasin(term t, term arg, term *next, char *reason)
{ if(FUNCTOR(t) != SIN)
return 1;
if(FUNCTOR(ARG(0,t)) != ASIN)
return 1;
*next = ARG(0,ARG(0,t));
HIGHLIGHT(*next);
strcpy(reason,"sin(arcsin x) = x");
return 0;
}
/*____________________________________________________________________*/
/* sin(arccos x) = �(1-x^2) */
MEXPORT_TRIGCALC int sinacos(term t, term arg, term *next, char *reason)
{ term x;
if(FUNCTOR(t) != SIN)
return 1;
if(FUNCTOR(ARG(0,t)) != ACOS)
return 1;
x = ARG(0,ARG(0,t));
*next = sqrt1(sum(one,tnegate(make_power(x,two))));
HIGHLIGHT(*next);
strcpy(reason,"$sin(arccos x)=�(1-x^2)$");
return 0;
}
/*____________________________________________________________________*/
/* sin(arctan x) = x/�(x^2+1) */
MEXPORT_TRIGCALC int sinatan(term t, term arg, term *next, char *reason)
{ term x;
if(FUNCTOR(t) != SIN)
return 1;
if(FUNCTOR(ARG(0,t)) != ATAN)
return 1;
x = ARG(0,ARG(0,t));
*next = make_fraction(x,sqrt1(sum(make_power(x,two),one)));
HIGHLIGHT(*next);
strcpy(reason,"sin(arctan x) = $x/�(x^2+1)$");
return 0;
}
/*____________________________________________________________________*/
/* cos(arcsin x) = �(1-x^2) */
MEXPORT_TRIGCALC int cosasin(term t, term arg, term *next, char *reason)
{ term x;
if(FUNCTOR(t) != COS)
return 1;
if(FUNCTOR(ARG(0,t)) != ASIN)
return 1;
x = ARG(0,ARG(0,t));
*next = sqrt1(sum(one,tnegate(make_power(x,two))));
HIGHLIGHT(*next);
strcpy(reason,"$cos(arcsin x)=�(1-x^2)$");
return 0;
}
/*____________________________________________________________________*/
/* cos(arccos x) = x */
MEXPORT_TRIGCALC int cosacos(term t, term arg, term *next, char *reason)
{ if(FUNCTOR(t) != COS)
return 1;
if(FUNCTOR(ARG(0,t)) != ACOS)
return 1;
*next = ARG(0,ARG(0,t));
HIGHLIGHT(*next);
strcpy(reason,"cos(arccos x) = x");
return 0;
}
/*____________________________________________________________________*/
/* cos(arctan x) = 1/�(x^2+1) */
MEXPORT_TRIGCALC int cosatan(term t, term arg, term *next, char *reason)
{ term x;
if(FUNCTOR(t) != COS)
return 1;
if(FUNCTOR(ARG(0,t)) != ATAN)
return 1;
x = ARG(0,ARG(0,t));
*next = make_fraction(one,sqrt1(sum(make_power(x,two),one)));
HIGHLIGHT(*next);
strcpy(reason,"cos(arctan x) = $1/�(x^2+1)$");
return 0;
}
/*____________________________________________________________________*/
/* sec(arcsin x) = 1/�(1-x^2) */
MEXPORT_TRIGCALC int secasin(term t, term arg, term *next, char *reason)
{ term x;
if(FUNCTOR(t) != SEC)
return 1;
if(FUNCTOR(ARG(0,t)) != ASIN)
return 1;
x = ARG(0,ARG(0,t));
*next = reciprocal(sqrt1(sum(one,tnegate(make_power(x,two)))));
HIGHLIGHT(*next);
strcpy(reason,"sec(arcsin x) = $1/�(1-x^2)$");
return 0;
}
/*____________________________________________________________________*/
/* sec(arccos x) = 1/x */
MEXPORT_TRIGCALC int secacos(term t, term arg, term *next, char *reason)
{ if(FUNCTOR(t) != SEC)
return 1;
if(FUNCTOR(ARG(0,t)) != ACOS)
return 1;
*next = reciprocal(ARG(0,ARG(0,t)));
HIGHLIGHT(*next);
strcpy(reason,"sec(arccos x) = 1/x");
return 0;
}
/*____________________________________________________________________*/
/* sec(arctan x) = �(x^2+1) */
MEXPORT_TRIGCALC int secatan(term t, term arg, term *next, char *reason)
{ term x;
if(FUNCTOR(t) != SEC)
return 1;
if(FUNCTOR(ARG(0,t)) != ATAN)
return 1;
x = ARG(0,ARG(0,t));
*next = sqrt1(sum(make_power(x,two),one));
HIGHLIGHT(*next);
strcpy(reason,"$sec(arctan x)=�(x^2+1)$");
return 0;
}
/*____________________________________________________________________*/
/* arctan(tan �) = � if */
MEXPORT_TRIGCALC int atantan(term t, term arg, term *next, char *reason)
{ int err;
term theta,p;
double z;
int sign = 1;
long kk;
if(FUNCTOR(t) != ATAN)
return 1;
if(FUNCTOR(ARG(0,t)) != TAN)
return 1;
theta = ARG(0,ARG(0,t));
if(seminumerical(theta))
{ deval(theta,&z);
if(z < 0)
{ z = -z;
sign = -1;
}
if(z < (double) 0xeffffffL)
{ kk = (long) (z / PI_DECIMAL + 0.5);
if(kk == 0)
*next = theta;
else if(sign < 0)
*next = sum(theta,make_fraction(product(make_int(kk),pi),two));
else
*next = sum(theta,tnegate(make_fraction(product(make_int(kk),pi),two)));
HIGHLIGHT(*next);
strcpy(reason, "$arctan(tan �)=�-n�/2$");
return 0;
}
}
/* Now theta is not seminumerical */
p = and(le(tnegate(make_fraction(pi,two)),theta),le(theta,make_fraction(pi,two)));
err = infer(p); /* Not 'check', else atantan2 never gets used */
if(err)
return 1;
*next = theta;
HIGHLIGHT(*next);
strcpy(reason,"$arctan(tan �) = �$ ");
strcat(reason,english(2179)); /* if -�/2����/2 */
return 0;
}
/*____________________________________________________________________*/
static int contains_int(term t)
/* t is a sum. Return 1 if one of the summands is a constant of
integration or an indefinite integral, or a product containing
such a thing as a factor.
*/
{ unsigned short n;
int i,j;
term u,v;
assert(FUNCTOR(t) == '+');
n = ARITY(t);
for(i=0;i<n;i++)
{ u = ARG(i,t);
if(NEGATIVE(u))
u = ARG(0,u);
if((FUNCTOR(u) == INTEGRAL && ARITY(u) == 2) ||
FUNCTOR(u) == CONSTANTOFINTEGRATION
)
break;
if(FUNCTOR(u) == '*')
{ for(j=0; j<ARITY(u); j++)
{ v = ARG(j,u);
if((FUNCTOR(v) == INTEGRAL && ARITY(v) == 2) ||
FUNCTOR(v) == CONSTANTOFINTEGRATION
)
break;
}
if(j < ARITY(u))
break;
}
}
return i<n ? 1 : 0;
}
/*____________________________________________________________________*/
/* arctan(tan �) = � + c1 */
MEXPORT_TRIGCALC int atantan2(term t, term arg, term *next, char *reason)
{ int i,j,k;
term u,v,a,newu,x,newc;
unsigned short n;
unsigned short path[MAXTAIL];
int sign = 1;
term denom = one;
char *r = "arctan(tan x) = x + c1";
int mathmode = get_mathmode();
if(mathmode == SELECTIONMODE)
{ if(FUNCTOR(t) != ATAN)
return 1;
if(FUNCTOR(ARG(0,t)) != TAN)
return 1;
*next = ARG(0,ARG(0,t));
HIGHLIGHT(*next);
strcpy(reason,r);
return 0;
}
/* Now we're in menu mode or auto mode. Apply it
only in a linear combination with an integral or
a constant of integration. It isn't called in automode
unless there is an ATAN occurring as a summand or
a factor of a summand; including the case where the
summand is negative.
*/
if(FUNCTOR(t) != '+')
return 1;
/* Check if there is an integral or constant of integration */
if(!contains_int(t))
return 1;
/* OK, you can go ahead and apply the operator to t */
n = ARITY(t);
/* x must be SOME variable to pass to matchstring */
x = var0;
for(i=0;i<n;i++)
{ u = ARG(i,t);
if(NEGATIVE(u))
{ sign = -1;
u = ARG(0,u);
}
if(FRACTION(u) && constant(ARG(1,u)))
{ u = ARG(0,u);
denom = ARG(1,u);
}
if(!matchstring(u,x,"arctan(tan(a))",&a))
{ newu = a;
HIGHLIGHT(newu);
break;
}
if(FUNCTOR(u)=='*')
{ for(j=0;j<ARITY(u);j++)
{ v = ARG(j,u);
if(!matchstring(v,x,"arctan(tan(a))",&a))
{ newu = make_term('*',ARITY(u));
HIGHLIGHT(a);
for(k=0;k<ARITY(u);k++)
ARGREP(newu,k, k==j ? a : ARG(k,u));
break;
}
}
if(j < ARITY(u))
break;
}
}
if(i==n)
return 1;
SetShowStepArg(atan1(tan1(a)));
if(!ONE(denom))
newu = make_fraction(newu,denom);
if(sign < 0)
newu = tnegate(newu);
*next = make_term('+',n);
for(j=0;j<n;j++)
{ if(j==i)
ARGREP(*next,j, newu);
else if(FUNCTOR(ARG(j,t)) == CONSTANTOFINTEGRATION)
{ newc = constant_of_integration(ARG(j,t),zero);
/* this makes it depend on the same variables as the old
constant of integration, but get a new subscript. */
HIGHLIGHT(newc);
ARGREP(*next,j,newc);
}
else
ARGREP(*next,j,ARG(j,t));
}
if(FUNCTOR(newu) == '+')
*next = topflatten(*next);
strcpy(reason,r);
path_to_difference(t,*next,path,1);
set_pathtail(path);
return 0;
}
/*____________________________________________________________________*/
/* arcsin(sin �) = � if -�/2����/2 */
MEXPORT_TRIGCALC int asinsin(term t, term arg, term *next, char *reason)
{ int err;
term theta,p;
if(FUNCTOR(t) != ASIN)
return 1;
if(FUNCTOR(ARG(0,t)) != SIN)
return 1;
theta = ARG(0,ARG(0,t));
p = and(le(tnegate(make_fraction(pi,two)),theta),le(theta,make_fraction(pi,two)));
err = check(p);
if(err)
return 1;
*next = theta;
HIGHLIGHT(*next);
strcpy(reason,"$arcsin(sin �) = �$ ");
strcat(reason, english(2179)); /* if -�/2����/2 */
return 0;
}
/*____________________________________________________________________*/
/* arccos(cos �) = � if 0���� */
MEXPORT_TRIGCALC int acoscos(term t, term arg, term *next, char *reason)
{ int err;
term theta,p;
if(FUNCTOR(t) != ACOS)
return 1;
if(FUNCTOR(ARG(0,t)) != COS)
return 1;
theta = ARG(0,ARG(0,t));
p = and(le(zero,theta),le(theta,pi));
err = check(p);
if(err)
return 1;
*next = theta;
HIGHLIGHT(*next);
strcpy(reason,"$arccos(cos �) = �$ ");
strcat(reason, english(2180)); /* if 0���� */
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists