/* 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 mix_add(mixed_t *x, mixed_t *y)
{
    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;
}

