Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/algebra/
Upload File :
Current File : /usr/home/beeson/MathXpert/algebra/precanc.c

/* M. Beeson, for MathXpert
   'precancel', a/b (b/c) => a/c
   9.13.93 cut out of fraction.c
   12.21.96 last modified
*/
#include <string.h>
#include "globals.h"
#include "cancel.h"
#include "precanc.h"

/*________________________________________________________________*/
int precancel(term t, term *next, term *cancelled)
/* t must be a product containing at least one fraction.  Cancel
denominator of a fraction with another factor. (But don't do it
if the denominator itself is a fraction, unless the other factor
is a fraction with the same denominator; thus (1/4) (3/(1/4)) would cancel
the 1/4 but 2 (3/(5/4))  will not cancel 1/4.)

Put the cancelled term in *cancelled.  Return 0 for success. */

{ unsigned short n = ARITY(t);
  int i,j,k,m,err;
  term u,v,num,denom,newnum,newdenom,p;
  if(FUNCTOR(t) != '*')
     return 1;
  for(i=0;i<n;i++)
     { u = ARG(i,t);
       if(ATOMIC(u) || FUNCTOR(u) != '/')
          continue;
       denom = ARG(1,u);
       for(j=0;j<n;j++)
          { if(j==i)
               continue;
            v = ARG(j,t);
            if(FRACTION(denom) && !(FRACTION(v) && equals(ARG(1,v),ARG(1,denom))))
               continue;  /* see specs of this function */
            num = FRACTION(v) ? ARG(0,v) : v;
            err = cancel(num,denom,cancelled,&p);
            if(err)
               continue;
            break; /* something cancelled */
          }
       if(j<n)
          break;   /* something cancelled */
     }
  if(i==n)
     return 1;   /* there was no cancellation */
  cancel(denom,*cancelled,&p,&newdenom);  /* newdenom of the i-th arg */
  cancel(num, *cancelled,&p,&newnum);     /* newnum of the j-th arg   */
  HIGHLIGHT(newnum);
  HIGHLIGHT(newdenom);
  if(equals(denom,*cancelled) && ONE(ARG(0,u)) &&
     equals(v,num) && equals(v, *cancelled)
    )
     /* both i-th and j-th factor will disappear */
     /* example,  (1/4) 4x  */
     { if(n==2)
          { *next = one;
            HIGHLIGHT(*next);
            return 0;
          }
       else if(n==3)
          { *next = ARG(i && j ? 0 : i!= 1 && j != 1 ? 1 : 2, t);
            HIGHLIGHT(*next);
            return 0;
          }
       else  /* answer will be product of the remaining terms */
          { *next = make_term('*',(unsigned short)(n-2));
             k=0;
             for(m=0;m<n;m++)
                { if(m==i || m==j)
                     continue;
                  ARGREP(*next,k,ARG(m,t));
                  ++k;
                }
             HIGHLIGHT(*next);
             return 0;
           }
     }
  if(equals(denom,*cancelled) && ONE(ARG(0,u)))
     /* i-th  factor will disappear */
     /* j-th  factor will be replaced by newnum/ old denom of j-th arg */
     /* example,  1/4 4/pi ; the 1/4 will disappear leaving 1/pi  */
       { if(n==2)
          { v = ARG(i ? 0 : 1,t);
            if(FRACTION(v))
               *next = make_fraction(newnum,ARG(1,v));
            else
               *next = newnum;
            HIGHLIGHT(*next);
            return 0;
          }
       else  /* answer will be product of the remaining terms */
          { *next = make_term('*',(unsigned short)(n-1));
             k=0;
             for(m=0;m<n;m++)
                { if(m==i)
                     continue;
                  if(m==j && FRACTION(ARG(j,t)))
                     ARGREP(*next,k, make_fraction(newnum,ARG(1,ARG(j,t))));
                  else if(m==j)  /* and not FRACTION(ARG(j,t)) */
                     ARGREP(*next,k, newnum);
                  else
                     ARGREP(*next,k,ARG(m,t));
                  ++k;
                }
             HIGHLIGHT(*next);
             return 0;
           }
     }
  if(equals(v,*cancelled))
     /* j-th factor will disappear */
     /* i-th factor will become (old num of i-th factor)/newdenom */
     { if(n==2)
          { *next = make_fraction(ARG(0,u),newdenom);
            HIGHLIGHT(*next);
            return 0;
          }
       else  /* answer will be product of the remaining terms */
          { *next = make_term('*',(unsigned short)(n-1));
             k=0;
             for(m=0;m<n;m++)
                { if(m==j)
                     continue;
                  if(m==i)
                     ARGREP(*next,k, make_fraction(ARG(0,u),newdenom));
                  else
                     ARGREP(*next,k,ARG(m,t));
                  ++k;
                }
             HIGHLIGHT(*next);
             return 0;
           }
     }
  /* Now the i-th and j-th factors will both remain after cancellation */
  *next = make_term('*',n);
  for(k=0;k<n;k++)
     { if(k==i)
          ARGREP(*next,k,make_fraction(ARG(0,u),newdenom));
       else if(k==j && FRACTION(ARG(j,t)))
          ARGREP(*next,k,make_fraction(newnum,ARG(1,ARG(j,t))));
       else if(k==j)  /* and ARG(j,t) is not a fraction */
          ARGREP(*next,k,newnum);
       else
          ARGREP(*next,k,ARG(k,t));
     }
  return 0;
}

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