Sindbad~EG File Manager

Current Path : /usr/home/beeson/Otter-Lambda/yyy/polyval/
Upload File :
Current File : /usr/home/beeson/Otter-Lambda/yyy/polyval/gcdsub.c

/* M. Beeson, for Mathpert */
/* 11.1.91 original date   */
/* 1.29.98 last modified   */

#include <assert.h>
#define POLYVAL_DLL
#include "globals.h"
#include "gcdsub.h"
#include "cancel.h"

static term exponent_gcd(term u, term v, term x);
static term gs_aux(term v, term x);
/*_______________________________________________________________________*/
MEXPORT_POLYVAL term get_gcdsub(term v, term x)

/* First remove any integer powers of x which are factors of v, or
if v is a fraction, which are factors of the num or denom.
Here roots are counted as fractional
powers.  Then return x raised to the naive_gcd of all exponents
of powers of x contained in the rest of v.  If no powers of x
are contained in the rest of v, return zero.
  Examples:  if v contains x^4 and x^6, return x^2.  If v contains
x^(1/2) and x^(1/3), return x^(1/6).
  However, if the powers 'removed' as factors of v involve a fractional
exponent, this power should also be thrown into the gcd calculation.
  Example:  sqrt(t) / (1 + root(3,t))  should yield u = t^(1/6).
*/

{  term temp, temp2, ans, left;
   unsigned short f = FUNCTOR(v);
   int flag = 0;
   if(ATOMIC(v))
      return zero;
   if(INEQUALITY(f) && ISATOM(x))
      { /* block certain useless substitutions, e.g. in 1/x^n = a don't
           substitute w = 1/x or 1/x^n  */
        if(!contains(ARG(1,v),FUNCTOR(x)))
           { left = ARG(0,v);
             flag = 1;
           }
        else if(!contains(ARG(0,v),FUNCTOR(x)))
           { left = ARG(1,v);
             flag = 2;
           }
        if(flag && (FRACTION(left) || FUNCTOR(left) == '*'))
           /* also in 5x^(1/3) = 1, don't substitute u = x^(1/3) */
           { term num = ARG(0,left);
             term denom = ARG(1,left);
             if(!contains(num,FUNCTOR(x)) &&
                (ISATOM(denom) || (FUNCTOR(denom) == '^' && ISATOM(ARG(0,denom)) && !contains(ARG(1,denom),FUNCTOR(x))))
               )
                return zero;
           }
      }
   if(FUNCTOR(v) == '/')
       { temp = get_gcdsub(ARG(0,v),x);
         temp2 = get_gcdsub(ARG(1,v),x);
         if(ZERO(temp) || ONE(temp))
            return temp2;
         if(ZERO(temp2) || ONE(temp2))
            return temp;
         if(equals(temp,temp2))
            ans = temp;
         else
            ans = exponent_gcd(temp,temp2,x);
       }
   else
      ans = gs_aux(remove_powers(v,x),x);
   /* If ans = x^(1/2) maybe it should be sqrt(x) instead */
   if(FUNCTOR(ans) == '^' && FUNCTOR(ARG(1,ans))=='/' &&
      ONE(ARG(0,ARG(1,ans))) && equals(ARG(1,ARG(1,ans)),two)
      && contains(v,SQRT)
     )
      ans = sqrt1(x);
   return ans;
}
/*_______________________________________________________________*/
MEXPORT_POLYVAL term remove_powers(term t,term x)
/* return t with all integer powers of x that are factors of t removed;
or if t is a fraction, remove integer powers of x in numerator and denom;
This function also deletes factors that don't contain x at all.  */

{  int i;
   unsigned short n,k;
   unsigned short f = FUNCTOR(t);
   term u,ans,temp;
   if(ATOMIC(t))
      return one;
   if(f == '/')
      return make_fraction(remove_powers(ARG(0,t),x),remove_powers(ARG(1,t),x));
   if(f != '*')
      return t;
   n = ARITY(t);
   ans = make_term('*',n);
   k=0;
   for(i=0;i<n;i++)
      { u = ARG(i,t);
        if(!contains(u,FUNCTOR(x)))
           continue;
        if(equals(t,x))
           continue;
        f = FUNCTOR(u);
        if(f=='^' && INTEGERP(ARG(1,u)))
           continue;
        ARGREP(ans,k,u);
        ++k;
      }
  if(k==0)
      { RELEASE(ans);
        return one;
      }
  if(k==1)
      { temp = ARG(0,ans);
        RELEASE(ans);
        return temp;
      }
  SETFUNCTOR(ans,'*',k);
  return ans;
}
/*_______________________________________________________________*/
static term exponent_gcd(term u, term v, term x)
/* if u = x^a and v = x^b are powers of the same base x, return
x^gcd(a,b), where the gcd is naive_gcd; but if both a and b
are negative, return x^-gcd(a,b) instead.
x counts as x^1.  If one of u,v is a power of x but the other
is not, return the one that is.  Return zero if neither is.
   Also works on SQRT terms, treating them as fractional powers.
*/

{ term a,b,c;
  if(equals(u,x))
     a = one;
  else if(FUNCTOR(u) == '^' && equals(ARG(0,u),x))
     a = ARG(1,u);
  else if(FUNCTOR(u) == SQRT && equals(ARG(0,u),x))
     a = reciprocal(two);
  else if(FUNCTOR(u) == ROOT && equals(ARG(1,u),x))
     a = reciprocal(ARG(0,u));
  else
     SETFUNCTOR(a,ILLEGAL,0);
  if(equals(v,x))
     b = one;
  else if(FUNCTOR(v) == '^' && equals(ARG(0,v),x))
     b = ARG(1,v);
  else
     SETFUNCTOR(b,ILLEGAL,0);
  if(FUNCTOR(a) == ILLEGAL && FUNCTOR(b) == ILLEGAL)
     return zero;
  if(FUNCTOR(a) == ILLEGAL)
     return v;
  if(FUNCTOR(b) == ILLEGAL)
     return u;
  if(NEGATIVE(a) && NEGATIVE(b))
     { naive_gcd(ARG(0,a),ARG(0,b),&c);
       return make_power(x,tnegate(c));
     }
  naive_gcd(a,b,&c);
  return make_power(x,c);
}
/*_______________________________________________________________*/
static term gs_aux(term v, term x)
/* Return the exponent_gcd of all powers of x contained in v,
counting roots and square roots as fractional powers */
{  int i,err;
   unsigned short n;
   unsigned short f;
   term temp,ans,temp2,index,cancelled;
   if(equals(v,x))
      return x;
   else if(ATOMIC(v))
      return zero;
   f = FUNCTOR(v);
   n = ARITY(v);
   if(
      (f==SQRT  && equals(ARG(0,v),x)) ||
      (f==ROOT  && equals(ARG(1,v),x))
     )
      { if(f == SQRT)
           { index = two;
             temp = gs_aux(ARG(0,v),x);
           }
        else
           { index = ARG(0,v);
             temp = gs_aux(ARG(1,v),x);
           }
        if(equals(temp,x))
           return make_power(x,make_fraction(one,index));
        if(ZERO(temp) || ONE(temp))
           return zero;
        assert(FUNCTOR(temp) == '^' && equals(ARG(0,temp),x));
        err = cancel(ARG(1,temp),index,&cancelled,&temp2);
        if(err)
           temp2 = make_fraction(ARG(1,temp),index);
        return make_power(x,temp2);
      }
   if(f == '^' && equals(ARG(0,v),x))
      return v;
   ans = zero;
   for(i=0;i<n;i++)
      { temp2 = gs_aux(ARG(i,v),x);
        if(ZERO(ans) && ZERO(temp2))
           continue;
        if(ZERO(ans))
           ans = temp2;
        else if(! ZERO(temp2))
           { temp = exponent_gcd(ans,temp2,x);
             ans = temp;
           }
      }
   return ans;
}

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