Sindbad~EG File Manager

Current Path : /usr/home/beeson/Otter-Lambda/yyy/algebra/
Upload File :
Current File : /usr/home/beeson/Otter-Lambda/yyy/algebra/trigeqns.c

/* solve basic trig equations
M. Beeson
Original date 1.2.92
last modified 2.26.98
*/

#define ALGEBRA_DLL
#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,six);
             *q = make_fraction(product(five,pi),six);
           }
        else if(sign == -1 && ONE(num))
           { tneg(make_fraction(pi,six),p);
             tneg(make_fraction(product(five,pi),six),q);
           }
        else if(sign == 1 && FUNCTOR(num)==SQRT)
           { *p = make_fraction(pi,three);
             *q = make_fraction(product(two,pi),three);
           }
        else if(sign == -1 && FUNCTOR(num)==SQRT)
           { tneg(make_fraction(pi,three),p);
             tneg(make_fraction(product(two,pi),three),q);
           }
      }
  else if(FUNCTOR(den) == SQRT && ONE(num))
      {  *degrees = 45;
         if(sign == 1)
            { *p = make_fraction(pi,four);
              *q = make_fraction(product(three,pi),four);
            }
         else if(sign == -1)
            { *p = make_fraction(product(five,pi),four);
              *q = make_fraction(product(seven,pi),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,three);
             *q = tnegate(*p);
           }
        else if(sign == -1 && ONE(num))
           { *p = make_fraction(product(two,pi),three);
             *q = tnegate(*p);
           }
        else if(sign == 1 && FUNCTOR(num)==SQRT)
           { *p = make_fraction(pi,six);
             *q = tnegate(*p);
           }
        else if(sign == -1 && FUNCTOR(num)==SQRT)
           {  *p = make_fraction(product(five,pi),six);
              *q = tnegate(*p);
           }
      }
  else if(FUNCTOR(den) == SQRT && ONE(num))
      {  *degrees = 45;
         if(sign == 1)
            { *p = make_fraction(pi,four);
              *q = tnegate(*p);
            }
         else if(sign == -1)
            { *p = make_fraction(product(three,pi),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) = �num/den  producing the answer *next and justification string */
{ term left, right,u,n,twonpi,p,q;
  int i,degrees;
  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);
  if(sign == 0)
     { switch(f)
         { case TAN:   /* fall-through */
           case SIN:   *next = equation(u,product(n,pi));
                      break;
           case COT:   /* fall-through */
           case COS:   *next = equation(u,make_fraction(product(sum(product(two,n),one),pi),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,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),two),twonpi));
              break;
           case COS:
              *next = equation(u,product(sum(product(two,n),one),pi));
              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,six),product(n,pi)));
            degrees = 30;
          }
       else if(sign== -1 && ONE(num) && FUNCTOR(den)==SQRT && equals(ARG(0,den),three))
          { *next = equation(u,sum(tnegate(make_fraction(pi,six)),product(n,pi)));
            degrees = 30;
          }
       else if(sign == 1 && FUNCTOR(num) == SQRT && equals(ARG(0,num),three) && ONE(den))
          { *next = equation(u, sum(make_fraction(pi,three),product(n,pi)));
            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),three),product(n,pi)));
            degrees = 30;
          }
       else if(sign == 1 && ONE(num) && ONE(den))
          { *next = or(equation(u,sum(make_fraction(pi,four),twonpi)),
                       equation(u,sum(make_fraction(product(five,pi),four),twonpi))
                      );
            degrees = 45;
          }
       else if(sign == -1 && ONE(num) && ONE(den))
          { *next = or(equation(u, sum(make_fraction(product(three,pi),four),twonpi)),
                       equation(u, sum(make_fraction(product(seven,pi),four),twonpi))
                      );
            degrees = 45;
          }
     }
  else
     { if(f==SIN)
          sintable(sign,num,den,&p,&q,&degrees);
       else if(f==COS)
          costable(sign,num,den,&p,&q,&degrees);
       *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=�/2+2n� */
                      break;
                   case 0:
                      if(f==SIN)
                         strcpy(reason, english(1049));
                         /* sin u = 0 iff u = n� */
                      else
                         strcpy(reason, english(1134));
                         /* tan u = 0 iff u = n� */
                      break;
                   case -1:
                      strcpy(reason, english(1050));
                      /* sin u = -1 iff           u = 3�/2+2n� */
                      break;
                 }
            }
         else if(f==COS || f == COT)
            { switch(sign)
                 {  case 0:
                       strcpy(reason, english(1051));
                       /* cos u=0 iff          u=(2n+1)�/2 */
                       break;
                    case 1:
                       strcpy(reason, english(1052));
                       /* cos u = 1 iff u=2n� */
                       break;
                    case -1:
                       strcpy(reason, english(1053));
                       /* cos u = -1 iff       u = (2n+1)� */
                       break;
                  }
            }
    }
  if(FUNCTOR(*next) == '=' )
     { PROTECT(ARG(1,*next));  /* don't make �/6 + 2�k into (� + 12�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;
}

/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin30(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,1,one,two,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin330(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,-1,one,two,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin60(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,1,sqrt1(three),two,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin300(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,-1,sqrt1(three),two,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos30(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,1,sqrt1(three),two,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos150(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,-1,sqrt1(three),two,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos60(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,1,one,two,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos120(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,-1,one,two,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvetan30(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,1,one,sqrt1(three),next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvetan330(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,-1,one,sqrt1(three),next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvetan60(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,1,sqrt1(three),one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvetan120(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,-1,sqrt1(three),one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin45(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,1,one,sqrt1(two),next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin315(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,-1,one,sqrt1(two),next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos45(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,1,one,sqrt1(two),next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos135(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,-1,one,sqrt1(two),next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvetan45(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,1,one,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvetan135(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,-1,one,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin0(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,0,zero,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin90(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,1,one,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin270(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,SIN,-1,one,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos90(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,0,zero,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos0(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,1,one,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos180(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COS,-1,one,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvetan0(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,TAN,0,one,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecot90(term t, term arg, term *next, char *reason)
{ return trigeqn_aux(t,COT,0,one,one,next,reason);
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin(term t, term arg, term *next, char *reason)
/* sin u = c iff c = (-1)�arcsin u + n� */
{ 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 = check(le(abs1(right),one));
  if(err)
     { errbuf(0, english(1045));
          /* arcsin u defined only when |u|�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);
  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)�arcsin c + n� */
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvesin2(term t, term arg, term *next, char *reason)
/* sin u = c iff c = arcsin u + 2n� or -arcsin u + (2n+1)�*/
{ 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 = check(le(abs1(right),one));
  if(err)
     { errbuf(0, english(1045));
          /* arcsin u defined only when |u|�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));
  copy(right,&right2);
  copy(u,&u2);
  v2 = make_term('+',3);
  ARGREP(v2,0,product3(two,n,pi));
  ARGREP(v2,1,pi);
  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� or   u=-arcsin(c)+(2n+1)� */
  return 0;
}

/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvecos(term t, term arg, term *next, char *reason)
/* cos u=c iff u=�arccos c+2n� */
{ 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 = check(le(abs1(right),one));
  if(err)
     { errbuf(0, english(1055));
         /* arccos u defined only when |u|�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);
  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 = �arccos c + 2n� */
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int solvetan(term t, term arg, term *next, char *reason)
/* tan u = c iff u = arctan c + n� */
{ 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);
  *next = equation(u,sum(atan1(right),npi));
  HIGHLIGHT(*next);
  strcpy(reason, english(1057));
      /* tan u = c iff        u = arctan c + n� */
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA 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,two);
      strcat(reason,"$1 = �/2$");
      goto out;
    }
  if(equals(u,minusone))
    { tneg(make_fraction(pi,two),next);
      strcat(reason,"$-1 = -�/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,six),next);
            strcat(reason,"$-1/2 = -�/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,four),next);
            strcat(reason,"$-1/�2 = -�/4$");
            goto out;
          }
       if(equals(den,two) && FUNCTOR(num)==SQRT && equals(ARG(0,num),three))
          { tneg(make_fraction(pi,three),next);
            strcat(reason,"$-�3/2 = -�/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,six);
        strcat(reason,"$1/2 = �/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,four);
        strcat(reason,"$1/�2 = �/4$");
        goto out;
     }
  if(equals(den,two) && FUNCTOR(num)==SQRT && equals(ARG(0,num),three))
     { *next = make_fraction(pi,three);
       strcat(reason,"$�3/2 = �/3$");
       goto out;
     }
  return 1;
  out:
  HIGHLIGHT(*next);
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA 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,two);
      strcat(reason,"$0 = �/2$");
      goto out;
    }
  if(ONE(u))
    { *next = zero;
      strcat(reason,"1 = 0");
      goto out;
    }
  if(equals(u,minusone))
    { *next = pi;
      strcat(reason,"$-1 = �$");
      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),three);
           strcat(reason,"$-1/2 = 2�/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),four);
           strcat(reason,"$-1/�2 = 3�/4$");
           goto out;
         }
      if(equals(den,two) && FUNCTOR(num)==SQRT && equals(ARG(0,num),three))
         { *next = make_fraction(product(five,pi),six);
           strcat(reason,"$-�3/2 = 5�/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,three);
        strcat(reason,"$1/2 = �/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,four);
        strcat(reason,"$1/�2 = �/4$");
        goto out;
     }
  if(equals(den,two) && FUNCTOR(num)==SQRT && equals(ARG(0,num),three))
     { *next = make_fraction(pi,six);
       strcat(reason,"$�3/2 = �/6$");
       goto out;
     }
  return 1;
  out:
  HIGHLIGHT(*next);
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA 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,four);
      strcat(reason,"$1 = �/4$");
      goto out;
    }
  if(equals(u,minusone))
    { *next = tnegate(make_fraction(pi,four));
      strcat(reason,"$-1 = -�/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,three));
            strcat(reason,"$�3 = �/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,six));
            strcat(reason,"$-1/�3 = -�/6$");
            goto out;
          }
     }
  if(FUNCTOR(u) == SQRT && equals(ARG(0,u),three))
     { *next = make_fraction(pi,three);
       strcat(reason,"$�3 = �/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,three);
       strcat(reason,"$1/2 = �/3$");
       goto out;
     }
  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,six);
       strcat(reason,"$1/�3 = �/6$");
       goto out;
     }
  return 1;
  out:
  HIGHLIGHT(*next);
  return 0;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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 = false;
  HIGHLIGHT(*next);
  strcpy(reason,"$|sin u| � 1$");
  return 0;
}
/*__________________________________________________________________*/
MEXPORT_ALGEBRA 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 = false;
  HIGHLIGHT(*next);
  strcpy(reason,"$|cos u| � 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. */

MEXPORT_ALGEBRA 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;
}
/*___________________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*___________________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*___________________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA 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;
}
/*_______________________________________________________________*/
MEXPORT_ALGEBRA int arccosodd(term t, term arg, term *next, char *reason)
/* arccos(-x) = �-arcsin x */
{ if(FUNCTOR(t) != ACOS || !NEGATIVE(ARG(0,t)))
     return 1;
  *next = sum(pi,tnegate(acos1(ARG(0,ARG(0,t)))));
  HIGHLIGHT(*next);
  strcpy(reason, "$arccos(-x)=�-arccos x$");
  return 0;
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists