Sindbad~EG File Manager

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

/* 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