Sindbad~EG File Manager
/* 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