Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/polyval/
Upload File :
Current File : /usr/home/beeson/MathXpert/polyval/polyquo.c

/* M. Beeson, for Mathpert
  Rational function arithmetic.
  Used for graph-range setting and singularities calculations.
*/
/* Original date 11.10.96
   Code last modified 4.18.97
   Last modified 1.29.98
   3.20.06  removed include heap.h as it's indirectly included from globals.h
*/

#include <assert.h>
#include <math.h>

#include "globals.h"
#include "ops.h"
#include "probtype.h"
#include "polynoms.h"
#include "order.h"
#include "cancel.h"
#include "algaux.h"
#include "simpsums.h"
#include "eqn.h"
#include "prover.h"   /* noccurs */
#include "reset.h"    /* save_and_reset */
#include "pvalaux.h"  /* content_factor */
#include "polyquo.h"

#define MAXEXP 12     /* maximum exponent to be expanded */
#define UNITPOLY(p)  (ARITY(p) == 1 && ONE(ARG(0,p)))

/*__________________________________________________________________________*/
int add_polyquos(POLYnomial p, POLYnomial q, POLYnomial r, POLYnomial s, POLYnomial *u, POLYnomial *v)
/* form the sum p/q + r/s and reduce it to form u/v where u and v are
POLYnomials with unit gcd.  Return 0 for success, 1 for failure.
*/
{ POLYnomial g = polynomial_gcd(q,s);
  POLYnomial trash,a,b,soverg,qoverg,gcd,z1,z2;
  term cc,dd;
  int err;
  /* answer is (p(s/g) + r(q/g))/ (qs/g) */
  /* unless that reduces further by cancelling out a common factor after
     the addition. */
  if(FUNCTOR(g) == ILLEGAL)
     { /* out of space in polynomial_gcd */
       return 1;
     }
  if(UNITPOLY(g))
     { soverg = s;
       cc = one;
     }
  else
     pseudodiv(s,g,&soverg,&trash,&cc);  /* soverg * g = s * cc */
  if(UNITPOLY(q))
     *v = soverg;
  else if(UNITPOLY(soverg))
     *v = q;
  else
     { err = polymult(q,soverg,v);
       if(err)
          return 1;
     }
  if(UNITPOLY(p))
     a = soverg;
  else if(UNITPOLY(soverg))
     a = p;
  else
     { err = polymult(p,soverg,&a);
       if(err)
          return 1;
     }
  if(UNITPOLY(g))
     { qoverg = q;
       dd = one;
     }
  else
     pseudodiv(q,g,&qoverg,&trash,&dd);
  err = polymult(r,qoverg,&b);
  if(err)
     return 1;
  /* Now b needs adjusting by a factor to account for cc and dd */
  /* This factor is  cc / dd */
  /* Instead though we multiply the denom and a by the dd factor
     and b by the cc factor */
  if(!ONE(cc))
     b = polymultscalar(cc,b);
  if(!ONE(dd))
     { a = polymultscalar(dd,a);
       *v = polymultscalar(dd,*v);
     }
  *u = polyadd(a,b);
  gcd = polynomial_gcd(*u,*v);
  if(ARITY(gcd) > 1)
     { pseudodiv(*u,gcd,&z1,&trash,&cc);
       pseudodiv(*v,gcd,&z2,&trash,&dd);
       /* Now adjust for cc and dd as above */
       if(!ONE(dd))
          *u = polymultscalar(dd,z1);
       else
          *u = z1;
       if(!ONE(cc))
          *v = polymultscalar(cc,z2);
       else
          *v = z2;
     }
  return 0;
}

/*__________________________________________________________________________*/
POLYnomial polymultscalar(term c, POLYnomial u)
/* return cu */
{ int i;
  unsigned short n = ARITY(u);
  term r;
  POLYnomial ans = make_term(POLY,n);
  for(i=0;i<n;i++)
     { polyval(product(c,ARG(i,u)),&r);
       ARGREP(ans,i,r);
     }
  return ans;
}

/*__________________________________________________________________________*/

int make_polyquo(term t, term x, POLYnomial *num, POLYnomial *denom)
/* Write t(x) as a quotient of polynomials, returning the
numerator and denominator in *num and *denom, in POLYnomial form,
and returning 0 for success.  Return 1 for failure, in which
case *num and *denom can be garbage.
*/

{ int i,err;
  POLYnomial p,q,r,s,u,v,g1,g2,temp,trash;
  term cc,dd;
  long exp;
  unsigned short f = FUNCTOR(t);
  unsigned short n = ARITY(t);
  err = makepoly(t,x,num);
  if(!err)
     { *denom = make_term(POLY,1);
       ARGREP(*denom,0,one);
       return 0;  /* it was a polynomial */
     }
  switch(f)
     { case '-':
          err = make_polyquo(ARG(0,t),x,&p,&q);
          if(!err)
             { *num = polyneg(p);
               *denom = q;
               return 0;
             }
          return 1;
       case '*':
          err = make_polyquo(ARG(0,t),x,&p,&q);
          if(err)
             return 1;
          for(i=1;i<n;i++)
             { if(!contains(ARG(i,t),FUNCTOR(x)))
                  { p = polymultscalar(ARG(i,t),p);
                    continue;
                  }
               err = make_polyquo(ARG(i,t),x,&r,&s);
               if(err)
                  return 1;
               err = polymult(p,r,&u);
               if(err)
                  return 1;
               err = polymult(q,s,&v);
               if(err)
                  return 1;
               /* But now there may be cancellations to consider */
               g1 = polynomial_gcd(p,s);
               g2 = polynomial_gcd(q,r);
               if(UNITPOLY(g1) && UNITPOLY(g2))
                  { p = u;
                    q = v;
                    continue;
                  }
               if(!UNITPOLY(g1))
                  { /* replace p and s by p/g1 and s/g1 respectively */
                    pseudodiv(p,g1,&temp,&trash,&cc);
                    p = temp;
                    pseudodiv(s,g1,&temp,&trash,&dd);
                    s = temp;
                    if(!ONE(cc))
                       s = polymultscalar(make_power(cc,make_int(ARITY(p)-ARITY(g1)+1)),s);
                    if(!ONE(dd))
                       p = polymultscalar(make_power(dd,make_int(ARITY(s)-ARITY(g1)+1)),p);
                  }
               if(!UNITPOLY(g2))
                  { /* replace q and r by q/g2 and r/g2 respectively */
                    pseudodiv(q,g2,&temp,&trash,&cc);
                    q = temp;
                    pseudodiv(r,g2,&temp,&trash,&dd);
                    r = temp;
                    if(!ONE(cc))
                       r = polymultscalar(make_power(cc,make_int(ARITY(p)-ARITY(g1)+1)),r);
                    if(!ONE(dd))
                       q = polymultscalar(make_power(dd,make_int(ARITY(s)-ARITY(g1)+1)),q);
                  }
             }
          *num = p;
          *denom = q;
          return 0;
       case '+':
          err = make_polyquo(ARG(0,t),x,&p,&q);
          if(err)
             return 1;
          for(i=1;i<n;i++)
             { err = make_polyquo(ARG(i,t),x,&r,&s);
               if(err)
                  return 1;
               err = add_polyquos(p,q,r,s,&u,&v);
               if(err)
                  return 1;
               p = u;
               q = v;
             }
          *num = p;
          *denom = q;
          return 0;
       case '^':
          if(NEGATIVE(ARG(1,t)) && ISINTEGER(ARG(0,ARG(1,t))))
             { exp = INTDATA(ARG(0,ARG(1,t)));
               if(exp > MAXEXP)
                  return 1;
               err = make_polyquo(ARG(0,t),x,&p,&q);
               if(err)
                  return 1;
               if(exp == 1)
                  { *num = q;
                    *denom = p;
                    return 0;
                  }
               *num = polyexp(q,exp);
               *denom = polyexp(p,exp);
               return 0;
             }
          else if(ISINTEGER(ARG(1,t)))
             exp = INTDATA(ARG(1,t));
          else
             return 1;
          if(exp > MAXEXP)
             return 1;
          err = make_polyquo(ARG(0,t),x,&p,&q);
          if(err)
             return 1;
          *num = polyexp(p,exp);
          *denom = polyexp(q,exp);
          return 0;
       case '/':
          err = cancel(ARG(0,t),ARG(1,t),&p,&q);
          if(!err)  /* example: 6x^2y^6/6x^2y^4 */
             { if(FRACTION(q))
                  t = q;
               else
                  return make_polyquo(q,x,num,denom);
             }
          err = make_polyquo(ARG(0,t),x,&p,&q);
          if(err)
             return 1;
          err = make_polyquo(ARG(1,t),x,&r,&s);
          if(err)
             return 1;
          if(UNITPOLY(s))
             *num = p;
          else
             { err = polymult(p,s,num);
               if(err)
                  return 1;
             }
          if(UNITPOLY(q))
             *denom = r;
          else
             { err = polymult(q,r,denom);
               if(err)
                  return 1;
             }
          g1 = polynomial_gcd(*num,*denom);
          if(ARITY(g1) > 1)
             { /* cancel the gcd from num and denom */
               pseudodiv(*num,g1,&p,&r,&cc);
               if(ARITY(r) > 1 || !ZERO(ARG(0,r)))
                  assert(0);
               pseudodiv(*denom,g1,&q,&r,&dd);
               if(ARITY(r) > 1 || !ZERO(ARG(0,r)))
                  assert(0);
               if(ONE(cc))
                  *denom = q;
               else
                  *denom = polymultscalar(make_power(cc,make_int(ARITY(*num)-ARITY(g1)+1)),q);
               if(ONE(dd))
                  *num = p;
               else
                  *num = polymultscalar(make_power(dd,make_int(ARITY(*denom)-ARITY(g1)+1)),p);
             }
          return 0;
     }
  return 1;
}

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