Beispiel #1
0
/* Division */
Rational bignum_div(Bignum _n, Bignum _m)
{
    mpz_t n, m, tmp;

    *n = *theBIGNUM(_n);
    *m = *theBIGNUM(_m);
    mpz_init(tmp);
    mpz_mod(tmp, n, m);
    /* Divided evenly */
    if (mpz_sgn(tmp) == 0) {
        mpz_cdiv_q(tmp, n, m);

        return make_bignum(tmp);
    } else {
        mpz_t q;
        ratio_t r;

        mpz_gcd(tmp, n, m);
        r = malloc(sizeof(struct ratio_t));
        mpz_cdiv_q(q, n, tmp);
        r->numerator = make_bignum(q);
        mpz_cdiv_q(q, m, tmp);
        r->denominator = make_bignum(q);

        return make_ratio(r);
    }
}
Beispiel #2
0
static Lisp_Object plusir(Lisp_Object a, Lisp_Object b)
/*
 * fixnum and ratio, but also valid for bignum and ratio.
 * Note that if the inputs were in lowest terms there is no need for
 * and GCD calculations here.
 */
{
    Lisp_Object nil;
    push(b);
    a = times2(a, denominator(b));
    nil = C_nil;
    if (!exception_pending()) a = plus2(a, numerator(stack[0]));
    pop(b);
    errexit();
    return make_ratio(a, denominator(b));
}
Beispiel #3
0
Ratio parse_ratio(char *token)
{
    int i;
    ratio_t ratio;

    for (i = 0; token[i] != '\0'; i++) {
        if ('/' == token[i]) {
            token[i] = '\0';
            break;
        }
    }
    ratio = malloc(sizeof(ratio_t));
    ratio->numerator = parse_input(token);
    ratio->denominator = parse_input(token + i + 1);
    free(token);

    return make_ratio(ratio);
}
Beispiel #4
0
Lisp_Object negate(Lisp_Object a)
{
#ifdef COMMON
    Lisp_Object nil;  /* needed for errexit() */
#endif
    switch ((int)a & TAG_BITS)
    {
case TAG_FIXNUM:
        {   int32_t aa = -int_of_fixnum(a);
/*
 * negating the number -#x8000000 (which is a fixnum) yields a value
 * which just fails to be a fixnum.
 */
            if (aa != 0x08000000) return fixnum_of_int(aa);
            else return make_one_word_bignum(aa);
        }
#ifdef COMMON
case TAG_SFLOAT:
        {   Float_union aa;
            aa.i = a - TAG_SFLOAT;
            aa.f = (float) (-aa.f);
            return (aa.i & ~(int32_t)0xf) + TAG_SFLOAT;
        }
#endif
case TAG_NUMBERS:
        {   int32_t ha = type_of_header(numhdr(a));
            switch (ha)
            {
    case TYPE_BIGNUM:
                return negateb(a);
#ifdef COMMON
    case TYPE_RATNUM:
                {   Lisp_Object n = numerator(a),
                                d = denominator(a);
                    push(d);
                    n = negate(n);
                    pop(d);
                    errexit();
                    return make_ratio(n, d);
                }
    case TYPE_COMPLEX_NUM:
                {   Lisp_Object r = real_part(a),
                                i = imag_part(a);
                    push(i);
                    r = negate(r);
                    pop(i);
                    errexit();
                    push(r);
                    i = negate(i);
                    pop(r);
                    errexit();
                    return make_complex(r, i);
                }
#endif
    default:
                return aerror1("bad arg for minus",  a);
            }
        }
case TAG_BOXFLOAT:
        {   double d = float_of_number(a);
            return make_boxfloat(-d, type_of_header(flthdr(a)));
        }
default:
        return aerror1("bad arg for minus",  a);
    }
}
Beispiel #5
0
static Lisp_Object plusrr(Lisp_Object a, Lisp_Object b)
/*
 * Adding two ratios involves some effort to keep the result in
 * lowest terms.
 */
{
    Lisp_Object nil = C_nil;
    Lisp_Object na = numerator(a), nb = numerator(b);
    Lisp_Object da = denominator(a), db = denominator(b);
    Lisp_Object w = nil;
    push5(na, nb, da, db, nil);
#define g   stack[0]
#define db  stack[-1]
#define da  stack[-2]
#define nb  stack[-3]
#define na  stack[-4]
    g = gcd(da, db);
    nil = C_nil;
    if (exception_pending()) goto fail;
/*
 * all the calls to quot2() in this procedure are expected - nay required -
 * to give exact integer quotients.
 */
    db = quot2(db, g);
    nil = C_nil;
    if (exception_pending()) goto fail;
    g = quot2(da, g);
    nil = C_nil;
    if (exception_pending()) goto fail;
    na = times2(na, db);
    nil = C_nil;
    if (exception_pending()) goto fail;
    nb = times2(nb, g);
    nil = C_nil;
    if (exception_pending()) goto fail;
    na = plus2(na, nb);
    nil = C_nil;
    if (exception_pending()) goto fail;
    da = times2(da, db);
    nil = C_nil;
    if (exception_pending()) goto fail;
    g = gcd(na, da);
    nil = C_nil;
    if (exception_pending()) goto fail;
    na = quot2(na, g);
    nil = C_nil;
    if (exception_pending()) goto fail;
    da = quot2(da, g);
    nil = C_nil;
    if (exception_pending()) goto fail;
    w = make_ratio(na, da);
/*
 * All the goto statements and the label seem a fair way of expressing
 * the common action that has to be taken if an error or interrupt is
 * detected during any of the intermediate steps here.  Anyone who
 * objects can change it if they really want...
 */
fail:
    popv(5);
    return w;
#undef na
#undef nb
#undef da
#undef db
#undef g
}