/* mix_num2.c */
/* Copyright 1992 by P.J. LaBrocca */

#include "mixed.h"

mixed_t mix_sub(mixed_t *x, mixed_t *y)
{
mixed_t sum, xt, yt;

mix_clear( &sum );
mix_make_improper(x);
mix_make_improper(y);

xt.num = x->num * y->den;
xt.den = x->den * y->den;
yt.num = y->num * x->den;
yt.den = y->den * x->den;

sum.num = x->sign * xt.num - y->sign * yt.num;

if(sum.num < 0) {
sum.num = abs(sum.num);
sum.sign = NEGATIVE;
}
sum.den = xt.den; /*xt.den == yt.den at this point*/
if(sum.num == 0) {
sum.den = 1;
if(sum.whole == 0)
sum.sign = POSITIVE;
}
return sum;
}

{
mixed_t sum, t, xt, yt;

mix_clear( &sum );

mix_make_improper(x);
mix_make_improper(y);

xt.num = x->num * y->den;
xt.den = x->den * y->den;
yt.num = y->num * x->den;
yt.den = y->den * x->den;

sum.num = x->sign * xt.num + y->sign * yt.num;

if(sum.num < 0) {
sum.num = abs(sum.num);
sum.sign = NEGATIVE;
}
sum.den = xt.den; /*xt.den == yt.den at this point*/

if(sum.num == 0) {
sum.den = 1;
if(sum.whole == 0)
sum.sign = POSITIVE;
}
return sum;
}

mixed_t mix_mul(mixed_t *x, mixed_t *y)
{
mixed_t product;
Integer xn, yn;

mix_clear( &product );

xn = x->sign * (x->whole * x->den + x->num);
yn = y->sign * (y->whole * y->den + y->num);

product.num = xn * yn;
product.den = x->den * y->den;
if(product.num < 0) {
product.num = abs(product.num);
product.sign = NEGATIVE;
}
if(product.num == 0) {
product.den = 1;
if(product.whole == 0)
product.sign = POSITIVE;
}
return product;
}

mixed_t mix_recip(mixed_t f) /*reciprocal*/
{ /* does not alter f*/
Integer tmp;

mix_make_improper( &f );
if(f.num == 0) {
mix_error("denominator will become zero");
return f;
}

tmp = f.num;
f.num = f.den;
f.den = tmp;
return f;
}

mixed_t mix_divide(mixed_t *f, mixed_t *g)
{
mixed_t rec = mix_recip( *g );

return mix_mul( f, &rec );
}

Integer mix_lcd(mixed_t *f, mixed_t *g)
{
int i = 0, j = 0;
Integer low[30];
Integer *l = low;
Integer t;

mix_factor(g);
mix_factor(f);
while(1) {
if(f->factors[1][i] == 1) {
while(g->factors[1][j] != 1)
*l++ = g->factors[1][j++];
break;
}
else if(g->factors[1][j] == 1) {
while(f->factors[1][i] != 1)
*l++ = f->factors[1][i++];
break;
}
else if(f->factors[1][i] == g->factors[1][j]) {
*l++ = f->factors[1][i];
++i;
++j;
}
else if(f->factors[1][i] > g->factors[1][j]) {
*l++ = g->factors[1][j];
++j;
}
else if(f->factors[1][i] < g->factors[1][j]) {
*l++ = f->factors[1][i];
++i;
}
}
*l = 1;
t = 1;
i = 0;
while(low[i] != 1)
t *= low[i++];
return t;
}

void mix_neg(mixed_t *f)
{
if(f->sign == NEGATIVE)
f->sign = POSITIVE;
else
f->sign = NEGATIVE;
}