Example #1
0
Lisp_Object difference2(Lisp_Object a, Lisp_Object b)
{
    Lisp_Object nil;
    switch ((int)b & TAG_BITS)
    {
case TAG_FIXNUM:
        if (is_fixnum(a))
        {
            int32_t r = int_of_fixnum(a) - int_of_fixnum(b);
            int32_t t = r & fix_mask;
            if (t == 0 || t == fix_mask) return fixnum_of_int(r);
            else return make_one_word_bignum(r);
        }
        else if (b != ~0x7ffffffe) return plus2(a, 2*TAG_FIXNUM-b);
        else
        {   push(a);
            b = make_one_word_bignum(-int_of_fixnum(b));
            break;
        }
case TAG_NUMBERS:
        push(a);
        if (type_of_header(numhdr(b)) == TYPE_BIGNUM) b = negateb(b);
        else b = negate(b);
        break;
case TAG_BOXFLOAT:
default:
        push(a);
        b = negate(b);
        break;
    }
    pop(a);
    errexit();
    return plus2(a, b);
}
Example #2
0
int64_t sixty_four_bits(Lisp_Object a)
{
    switch ((int)a & TAG_BITS)
    {
case TAG_FIXNUM:
        return int_of_fixnum(a);
case TAG_NUMBERS:
        if (is_bignum(a))
        {   int len = bignum_length(a);
            switch (len)
            {
        case CELL+4:
                return (int64_t)bignum_digits(a)[0]; /* One word bignum */
        case CELL+8:
                return bignum_digits(a)[0] |
                       ((int64_t)bignum_digits(a)[1] << 31);
        default:
                return bignum_digits(a)[0] |
                       ((int64_t)bignum_digits(a)[1] << 31) |
                       ((int64_t)bignum_digits(a)[2] << 62);
            }
        }
        /* else drop through */
case TAG_BOXFLOAT:
default:
/*
 * return 0 for all non-fixnums
 */
        return 0;
    }
}
Example #3
0
int32_t thirty_two_bits(Lisp_Object a)
/*
 * return a 32 bit integer value for the Lisp integer (fixnum or bignum)
 * passed down - ignore any higher order bits and return 0 if the arg was
 * floating, rational etc or not a number at all.  Only really wanted where
 * links between C-specific code (that might really want 32-bit values)
 * and Lisp are being coded.
 */
{
    switch ((int)a & TAG_BITS)
    {
case TAG_FIXNUM:
        return int_of_fixnum(a);
case TAG_NUMBERS:
        if (is_bignum(a))
        {   int len = bignum_length(a);
/*
 * Note that I keep 31 bits per word and use a 2s complement representation.
 * thus if I have a one-word bignum I just want its contents but in all
 * other cases I need just one bit from the next word up.
 */
            if (len == CELL+4) return bignum_digits(a)[0]; /* One word bignum */
            return bignum_digits(a)[0] | (bignum_digits(a)[1] << 31);
        }
        /* else drop through */
case TAG_BOXFLOAT:
default:
/*
 * return 0 for all non-fixnums
 */
        return 0;
    }
}
Example #4
0
static Lisp_Object plusis(Lisp_Object a, Lisp_Object b)
{
    Float_union bb;
    bb.i = b - TAG_SFLOAT;
    bb.f = (float)((float)int_of_fixnum(a) + bb.f);
    return (bb.i & ~(int32_t)0xf) + TAG_SFLOAT;
}
Example #5
0
static Lisp_Object plusif(Lisp_Object a, Lisp_Object b)
/*
 * Fixnum plus boxed-float.
 */
{
    double d = (double)int_of_fixnum(a) + float_of_number(b);
    return make_boxfloat(d, type_of_header(flthdr(b)));
}
Example #6
0
Lisp_Object sub1(Lisp_Object p)
/*
 * Decrement a number.  Short cut when the number is a fixnum, otherwise
 * just hand over to the general addition code.
 */
{
    if (is_fixnum(p))
    {   if (p == ~0x7ffffffe)     /* The ONLY possible overflow case here  */
            return make_one_word_bignum(int_of_fixnum(p) - 1);
        else return (Lisp_Object)(p - 0x10);
    }
    else return plus2(p, fixnum_of_int(-1));
}
Example #7
0
static Lisp_Object Lscale_float(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
{
    double d = float_of_number(a);
    CSL_IGNORE(nil);
    if (!is_fixnum(b)) return aerror("scale-float");
    d = ldexp(d, int_of_fixnum(b));
#ifdef COMMON
    if (is_sfloat(a)) return onevalue(make_sfloat(d));
    else
#endif
    if (!is_bfloat(a)) return aerror1("bad arg for scale-float",  a);
    else return onevalue(make_boxfloat(d, type_of_header(flthdr(a))));
}
Example #8
0
Lisp_Object rembi(Lisp_Object a, Lisp_Object b)
{
    Lisp_Object nil;
    if (b == fixnum_of_int(0)) return aerror2("bad arg for remainder", a, b);
    else if (b == fixnum_of_int(1) ||
             b == fixnum_of_int(-1)) return fixnum_of_int(0);
    quotbn1(a, int_of_fixnum(b));
    /*
     * If the divisor was a fixnum then the remainder will be a fixnum too.
     */
    errexit();
    return fixnum_of_int(nwork);
}
Example #9
0
static Lisp_Object modbi(Lisp_Object a, Lisp_Object b)
{
    Lisp_Object nil = C_nil;
    int32_t bb = int_of_fixnum(b);
    if (b == fixnum_of_int(0)) return aerror2("bad arg for mod", a, b);
    if (bb == 1 || bb == -1) nwork = 0;
    else quotbn1(a, bb);
    /*
     * If the divisor was a fixnum then the remainder will be a fixnum too.
     */
    errexit();
    if (bb < 0)
    {   if (nwork > 0) nwork += bb;
    }
    else if (nwork < 0) nwork += bb;
    return fixnum_of_int(nwork);
}
Example #10
0
Lisp_Object plus2(Lisp_Object a, Lisp_Object b)
/*
 * I probably want to change the specification of plus2 so that the fixnum +
 * fixnum case is always expected to be done before the main body of the code
 * is entered.  Well maybe even if I do that it then costs very little to
 * include the fixnum code here as well, so I will not delete it.
 */
{
    switch ((int)a & TAG_BITS)
    {
case TAG_FIXNUM:
        switch ((int)b & TAG_BITS)
        {
    case TAG_FIXNUM:
/*
 * This is where fixnum + fixnum arithmetic happens - the case I most want to
 * make efficient. Note that even if this becomes a bignum it can only be a
 * one word one.
 */
            {   int32_t r = int_of_fixnum(a) + int_of_fixnum(b);
                int32_t t = r & fix_mask;
                if (t == 0 || t == fix_mask) return fixnum_of_int(r);
                else return make_one_word_bignum(r);
            }
#ifdef COMMON
    case TAG_SFLOAT:
            return plusis(a, b);
#endif
    case TAG_NUMBERS:
            {   int32_t hb = type_of_header(numhdr(b));
                switch (hb)
                {
        case TYPE_BIGNUM:
                return plusib(a, b);
#ifdef COMMON
        case TYPE_RATNUM:
                return plusir(a, b);
        case TYPE_COMPLEX_NUM:
                return plusic(a, b);
#endif
        default:
                return aerror1("bad arg for plus", b);
                }
            }
    case TAG_BOXFLOAT:
            return plusif(a, b);
    default:
            return aerror1("bad arg for plus",  b);
        }
#ifdef COMMON
case TAG_SFLOAT:
        switch (b & TAG_BITS)
        {
    case TAG_FIXNUM:
            return plussi(a, b);
    case TAG_SFLOAT:
            {   Float_union aa, bb;
                aa.i = a - TAG_SFLOAT;
                bb.i = b - TAG_SFLOAT;
                aa.f = (float)(aa.f + bb.f);
                return (aa.i & ~(int32_t)0xf) + TAG_SFLOAT;
            }
    case TAG_NUMBERS:
            {   int32_t hb = type_of_header(numhdr(b));
                switch (hb)
                {
        case TYPE_BIGNUM:
                return plussb(a, b);
        case TYPE_RATNUM:
                return plussr(a, b);
        case TYPE_COMPLEX_NUM:
                return plussc(a, b);
        default:
                return aerror1("bad arg for plus",  b);
                }
            }
    case TAG_BOXFLOAT:
            return plussf(a, b);
    default:
            return aerror1("bad arg for plus",  b);
        }
#endif
case TAG_NUMBERS:
        {   int32_t ha = type_of_header(numhdr(a));
            switch (ha)
            {
    case TYPE_BIGNUM:
                switch ((int)b & TAG_BITS)
                {
            case TAG_FIXNUM:
                    return plusbi(a, b);
#ifdef COMMON
            case TAG_SFLOAT:
                    return plusbs(a, b);
#endif
            case TAG_NUMBERS:
                    {   int32_t hb = type_of_header(numhdr(b));
                        switch (hb)
                        {
                case TYPE_BIGNUM:
                        return plusbb(a, b);
#ifdef COMMON
                case TYPE_RATNUM:
                        return plusbr(a, b);
                case TYPE_COMPLEX_NUM:
                        return plusbc(a, b);
#endif
                default:
                        return aerror1("bad arg for plus",  b);
                        }
                    }
            case TAG_BOXFLOAT:
                    return plusbf(a, b);
            default:
                    return aerror1("bad arg for plus",  b);
                }
#ifdef COMMON
    case TYPE_RATNUM:
                switch (b & TAG_BITS)
                {
            case TAG_FIXNUM:
                    return plusri(a, b);
            case TAG_SFLOAT:
                    return plusrs(a, b);
            case TAG_NUMBERS:
                    {   int32_t hb = type_of_header(numhdr(b));
                        switch (hb)
                        {
                case TYPE_BIGNUM:
                        return plusrb(a, b);
                case TYPE_RATNUM:
                        return plusrr(a, b);
                case TYPE_COMPLEX_NUM:
                        return plusrc(a, b);
                default:
                        return aerror1("bad arg for plus",  b);
                        }
                    }
            case TAG_BOXFLOAT:
                    return plusrf(a, b);
            default:
                    return aerror1("bad arg for plus",  b);
                }
    case TYPE_COMPLEX_NUM:
                switch (b & TAG_BITS)
                {
            case TAG_FIXNUM:
                    return plusci(a, b);
            case TAG_SFLOAT:
                    return pluscs(a, b);
            case TAG_NUMBERS:
                    {   int32_t hb = type_of_header(numhdr(b));
                        switch (hb)
                        {
                case TYPE_BIGNUM:
                        return pluscb(a, b);
                case TYPE_RATNUM:
                        return pluscr(a, b);
                case TYPE_COMPLEX_NUM:
                        return pluscc(a, b);
                default:
                        return aerror1("bad arg for plus",  b);
                        }
                    }
            case TAG_BOXFLOAT:
                    return pluscf(a, b);
            default:
                    return aerror1("bad arg for plus",  b);
                }
#endif
    default:    return aerror1("bad arg for plus",  a);
            }
        }
case TAG_BOXFLOAT:
        switch ((int)b & TAG_BITS)
        {
    case TAG_FIXNUM:
            return plusfi(a, b);
#ifdef COMMON
    case TAG_SFLOAT:
            return plusfs(a, b);
#endif
    case TAG_NUMBERS:
            {   int32_t hb = type_of_header(numhdr(b));
                switch (hb)
                {
        case TYPE_BIGNUM:
                return plusfb(a, b);
#ifdef COMMON
        case TYPE_RATNUM:
                return plusfr(a, b);
        case TYPE_COMPLEX_NUM:
                return plusfc(a, b);
#endif
        default:
                return aerror1("bad arg for plus",  b);
                }
            }
    case TAG_BOXFLOAT:
            return plusff(a, b);
    default:
            return aerror1("bad arg for plus",  b);
        }
default:
        return aerror1("bad arg for plus",  a);
    }
}
Example #11
0
static CSLbool numeqsr(Lisp_Object a, Lisp_Object b)
/*
 * Here I will rely somewhat on the use of IEEE floating point values
 * (an in particular the weaker supposition that I have floating point
 * with a binary radix).  Then for equality the denominator of b must
 * be a power of 2, which I can test for and then account for.
 */
{
    Lisp_Object nb = numerator(b), db = denominator(b);
    double d = float_of_number(a), d1;
    int x;
    int32_t dx, w, len;
    uint32_t u, bit;
    /*
     * first I will check that db (which will be positive) is a power of 2,
     * and set dx to indicate what power of two it is.
     * Note that db != 0 and that one of the top two words of a bignum
     * must be nonzero (for normalisation) so I end up with a nonzero
     * value in the variable 'bit'
     */
    if (is_fixnum(db))
    {   bit = int_of_fixnum(db);
        w = bit;
        if (w != (w & (-w))) return NO;   /* not a power of 2 */
        dx = 0;
    }
    else if (is_numbers(db) && is_bignum(db))
    {   int32_t lenb = (bignum_length(db)-CELL-4)/4;
        bit = bignum_digits(db)[lenb];
        /*
         * I need to cope with bignums where the leading digits is zero because
         * the 0x80000000 bit of the next word down is 1.  To do this I treat
         * the number as having one fewer digits.
         */
        if (bit == 0) bit = bignum_digits(db)[--lenb];
        w = bit;
        if (w != (w & (-w))) return NO;   /* not a power of 2 */
        dx = 31*lenb;
        while (--lenb >= 0)     /* check that the rest of db is zero */
            if (bignum_digits(db)[lenb] != 0) return NO;
    }
    else return NO; /* Odd - what type IS db here?  Maybe error. */
    if ((bit & 0xffffU) == 0) dx += 16, bit = bit >> 16;
    if ((bit & 0xff) == 0) dx += 8, bit = bit >> 8;
    if ((bit & 0xf) == 0) dx += 4, bit = bit >> 4;
    if ((bit & 0x3) == 0) dx += 2, bit = bit >> 2;
    if ((bit & 0x1) == 0) dx += 1;
    if (is_fixnum(nb))
    {   double d1 = (double)int_of_fixnum(nb);
        /*
         * The ldexp on the next line could potentially underflow.  In that case C
         * defines that the result 0.0 be returned.  To avoid trouble I put in a
         * special test the relies on that fact that a value represented as a rational
         * would not have been zero.
         */
        if (dx > 10000) return NO;  /* Avoid gross underflow */
        d1 = ldexp(d1, (int)-dx);
        return (d == d1 && d != 0.0);
    }
    len = (bignum_length(nb)-CELL-4)/4;
    if (len == 0)   /* One word bignums can be treated specially */
    {   int32_t v = bignum_digits(nb)[0];
        double d1;
        if (dx > 10000) return NO;  /* Avoid gross underflow */
        d1 = ldexp((double)v, (int)-dx);
        return (d == d1 && d != 0.0);
    }
    d1 = frexp(d, &x);    /* separate exponent from mantissa */
    if (d1 == 1.0) d1 = 0.5, x++; /* For Zortech */
    dx += x;              /* adjust to allow for the denominator */
    d1 = ldexp(d1, (int)(dx % 31));
    /* can neither underflow nor overflow here */
    /*
     * At most 3 words in the bignum may contain nonzero data - I subtract
     * the (double) value of those bits off and check that (a) the floating
     * result left is zero and (b) there are no more bits left.
     */
    dx = dx / 31;
    if (dx != len) return NO;
    w = bignum_digits(nb)[len];
    d1 = (d1 - (double)w) * TWO_31;
    u = bignum_digits(nb)[--len];
    d1 = (d1 - (double)u) * TWO_31;
    if (len > 0)
    {   u = bignum_digits(nb)[--len];
        d1 = d1 - (double)u;
    }
    if (d1 != 0.0) return NO;
    while (--len >= 0)
        if (bignum_digits(nb)[len] != 0) return NO;
    return YES;
}
Example #12
0
static CSLbool numeqis(Lisp_Object a, Lisp_Object b)
{
    Float_union bb;
    bb.i = b - TAG_SFLOAT;
    return ((double)int_of_fixnum(a) == (double)bb.f);
}
Example #13
0
Lisp_Object modulus(Lisp_Object a, Lisp_Object b)
{
    switch ((int)a & TAG_BITS)
    {
    case TAG_FIXNUM:
        switch ((int)b & TAG_BITS)
        {
        case TAG_FIXNUM:
            /*
             * This is where fixnum % fixnum arithmetic happens - the case I most want to
             * make efficient.
             */
        {   int32_t p = int_of_fixnum(a);
            int32_t q = int_of_fixnum(b);
            if (q == 0) return aerror2("bad arg for mod", a, b);
            p = p % q;
            if (q < 0)
            {   if (p > 0) p += q;
            }
            else if (p < 0) p += q;
            /* No overflow is possible in a modulus operation */
            return fixnum_of_int(p);
        }
        /*
         * Common Lisp defines a meaning for the modulus function when applied
         * to floating point values - so there is a whole pile of mess here to
         * support that.  Standard Lisp is only concerned with fixnums and
         * bignums.
         */
        case TAG_SFLOAT:
            return modis(a, b);
        case TAG_NUMBERS:
        {   int32_t hb = type_of_header(numhdr(b));
            switch (hb)
            {
            case TYPE_BIGNUM:
                return modib(a, b);
            case TYPE_RATNUM:
                return modir(a, b);
            default:
                return aerror1("Bad arg for mod",  b);
            }
        }
        case TAG_BOXFLOAT:
            return modif(a, b);
        default:
            return aerror1("Bad arg for mod",  b);
        }
    case TAG_SFLOAT:
        switch ((int)b & TAG_BITS)
        {
        case TAG_FIXNUM:
            return modsi(a, b);
        case TAG_SFLOAT:
        {   Float_union aa, bb;
            aa.i = a - TAG_SFLOAT;
            bb.i = b - TAG_SFLOAT;
            aa.f = (float) (aa.f + bb.f);
            return (aa.i & ~(int32_t)0xf) + TAG_SFLOAT;
        }
        case TAG_NUMBERS:
        {   int32_t hb = type_of_header(numhdr(b));
            switch (hb)
            {
            case TYPE_BIGNUM:
                return modsb(a, b);
            case TYPE_RATNUM:
                return modsr(a, b);
            default:
                return aerror1("Bad arg for mod",  b);
            }
        }
        case TAG_BOXFLOAT:
            return modsf(a, b);
        default:
            return aerror1("Bad arg for mod",  b);
        }
    case TAG_NUMBERS:
    {   int32_t ha = type_of_header(numhdr(a));
        switch (ha)
        {
        case TYPE_BIGNUM:
            switch ((int)b & TAG_BITS)
            {
            case TAG_FIXNUM:
                return modbi(a, b);
            case TAG_SFLOAT:
                return modbs(a, b);
            case TAG_NUMBERS:
            {   int32_t hb = type_of_header(numhdr(b));
                switch (hb)
                {
                case TYPE_BIGNUM:
                    return modbb(a, b);
                case TYPE_RATNUM:
                    return modbr(a, b);
                default:
                    return aerror1("Bad arg for mod",  b);
                }
            }
            case TAG_BOXFLOAT:
                return modbf(a, b);
            default:
                return aerror1("Bad arg for mod",  b);
            }
        case TYPE_RATNUM:
            switch ((int)b & TAG_BITS)
            {
            case TAG_FIXNUM:
                return modri(a, b);
            case TAG_SFLOAT:
                return modrs(a, b);
            case TAG_NUMBERS:
            {   int32_t hb = type_of_header(numhdr(b));
                switch (hb)
                {
                case TYPE_BIGNUM:
                    return modrb(a, b);
                case TYPE_RATNUM:
                    return modrr(a, b);
                default:
                    return aerror1("Bad arg for mod",  b);
                }
            }
            case TAG_BOXFLOAT:
                return modrf(a, b);
            default:
                return aerror1("Bad arg for mod",  b);
            }
        default:
            return aerror1("Bad arg for mod",  a);
        }
    }
    case TAG_BOXFLOAT:
        switch ((int)b & TAG_BITS)
        {
        case TAG_FIXNUM:
            return modfi(a, b);
        case TAG_SFLOAT:
            return modfs(a, b);
        case TAG_NUMBERS:
        {   int32_t hb = type_of_header(numhdr(b));
            switch (hb)
            {
            case TYPE_BIGNUM:
                return modfb(a, b);
            case TYPE_RATNUM:
                return modfr(a, b);
            default:
                return aerror1("Bad arg for mod",  b);
            }
        }
        case TAG_BOXFLOAT:
            return ccl_modff(a, b);
        default:
            return aerror1("Bad arg for mod",  b);
        }
    default:
        return aerror1("Bad arg for mod",  a);
    }
}
Example #14
0
Lisp_Object Cremainder(Lisp_Object a, Lisp_Object b)
{
    int32_t c;
    switch ((int)a & TAG_BITS)
    {
    case TAG_FIXNUM:
        switch ((int)b & TAG_BITS)
        {
        case TAG_FIXNUM:
            /*
             * This is where fixnum % fixnum arithmetic happens - the case I most want to
             * make efficient.
             */
            if (b == fixnum_of_int(0))
                return aerror2("bad arg for remainder", a, b);
            /* No overflow is possible in a remaindering operation */
            {   int32_t aa = int_of_fixnum(a);
                int32_t bb = int_of_fixnum(b);
                c = aa % bb;
                /*
                 * C does not specify just what happens when % is used with negative
                 * operands (except maybe if the division went exactly), so here I do
                 * some adjusting, assuming that the quotient returned was one of the
                 * integral values surrounding the exact result.
                 */
                if (aa < 0)
                {   if (c > 0) c -= bb;
                }
                else if (c < 0) c += bb;
                return fixnum_of_int(c);
            }
        /*
         * Common Lisp defines a meaning for the remainder function when applied
         * to floating point values - so there is a whole pile of mess here to
         * support that.  Standard Lisp is only concerned with fixnums and
         * bignums, but can tolerate the extra generality.
         */
        case TAG_SFLOAT:
            return remis(a, b);
        case TAG_NUMBERS:
        {   int32_t hb = type_of_header(numhdr(b));
            switch (hb)
            {
            case TYPE_BIGNUM:
                /*
                 * When I divide a fixnum a by a bignum b the remainder is a except in
                 * the case that a = 0xf8000000 and b = 0x08000000 in which case the
                 * answer is zero.
                 */
                if (int_of_fixnum(a) == fix_mask &&
                        bignum_length(b) == CELL+4 &&
                        bignum_digits(b)[0] == 0x08000000)
                    return fixnum_of_int(0);
                else return a;
            case TYPE_RATNUM:
                return remir(a, b);
            default:
                return aerror1("Bad arg for remainder",  b);
            }
        }
        case TAG_BOXFLOAT:
            return remif(a, b);
        /*
            case TAG_BOXFLOAT:
                {   double v = (double) int_of_fixnum(a);
                    double u = float_of_number(b);
                    v = v - (v/u)*u;
                    return make_boxfloat(v, TYPE_DOUBLE_FLOAT);
                }
         */
        default:
            return aerror1("Bad arg for remainder",  b);
        }
    case TAG_SFLOAT:
        switch ((int)b & TAG_BITS)
        {
        case TAG_FIXNUM:
            return remsi(a, b);
        case TAG_SFLOAT:
        {   Float_union aa, bb;
            aa.i = a - TAG_SFLOAT;
            bb.i = b - TAG_SFLOAT;
            aa.f = (float) (aa.f + bb.f);
            return (aa.i & ~(int32_t)0xf) + TAG_SFLOAT;
        }
        case TAG_NUMBERS:
        {   int32_t hb = type_of_header(numhdr(b));
            switch (hb)
            {
            case TYPE_BIGNUM:
                return remsb(a, b);
            case TYPE_RATNUM:
                return remsr(a, b);
            default:
                return aerror1("Bad arg for remainder",  b);
            }
        }
        case TAG_BOXFLOAT:
            return remsf(a, b);
        default:
            return aerror1("Bad arg for remainder",  b);
        }
    case TAG_NUMBERS:
    {   int32_t ha = type_of_header(numhdr(a));
        switch (ha)
        {
        case TYPE_BIGNUM:
            switch ((int)b & TAG_BITS)
            {
            case TAG_FIXNUM:
                return rembi(a, b);
            case TAG_SFLOAT:
                return rembs(a, b);
            case TAG_NUMBERS:
            {   int32_t hb = type_of_header(numhdr(b));
                switch (hb)
                {
                case TYPE_BIGNUM:
                    return rembb(a, b);
                case TYPE_RATNUM:
                    return rembr(a, b);
                default:
                    return aerror1("Bad arg for remainder",  b);
                }
            }
            case TAG_BOXFLOAT:
                return rembf(a, b);
            default:
                return aerror1("Bad arg for remainder",  b);
            }
        case TYPE_RATNUM:
            switch ((int)b & TAG_BITS)
            {
            case TAG_FIXNUM:
                return remri(a, b);
            case TAG_SFLOAT:
                return remrs(a, b);
            case TAG_NUMBERS:
            {   int32_t hb = type_of_header(numhdr(b));
                switch (hb)
                {
                case TYPE_BIGNUM:
                    return remrb(a, b);
                case TYPE_RATNUM:
                    return remrr(a, b);
                default:
                    return aerror1("Bad arg for remainder",  b);
                }
            }
            case TAG_BOXFLOAT:
                return remrf(a, b);
            default:
                return aerror1("Bad arg for remainder",  b);
            }
        default:
            return aerror1("Bad arg for remainder",  a);
        }
    }
    case TAG_BOXFLOAT:
        switch ((int)b & TAG_BITS)
        {
        /*
            case TAG_FIXNUM:
                    {   double u = (double) int_of_fixnum(b);
                        double v = float_of_number(a);
                        v = v - (v/u)*u;
                        return make_boxfloat(v, TYPE_DOUBLE_FLOAT);
                    }
            case TAG_BOXFLOAT:
                    {   double u = float_of_number(b);
                        double v = float_of_number(a);
                        v = v - (v/u)*u;
                        return make_boxfloat(v, TYPE_DOUBLE_FLOAT);
                    }
         */
        case TAG_FIXNUM:
            return remfi(a, b);
        case TAG_SFLOAT:
            return remfs(a, b);
        case TAG_NUMBERS:
        {   int32_t hb = type_of_header(numhdr(b));
            switch (hb)
            {
            case TYPE_BIGNUM:
                return remfb(a, b);
            case TYPE_RATNUM:
                return remfr(a, b);
            default:
                return aerror1("Bad arg for remainder",  b);
            }
        }
        case TAG_BOXFLOAT:
            return remff(a, b);
        default:
            return aerror1("Bad arg for remainder",  b);
        }
    default:
        return aerror1("Bad arg for remainder",  a);
    }
}
Example #15
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);
    }
}
Example #16
0
double float_of_number(Lisp_Object a)
/*
 * Return a (double precision) floating point value for the given Lisp
 * number, or 0.0 in case of trouble.  This is often called in circumstances
 * where I already know the type of its argument and so its type-dispatch
 * is unnecessary - in doing so I am trading off performance against
 * code repetition.
 */
{
    if (is_fixnum(a)) return (double)int_of_fixnum(a);
#ifdef COMMON
    else if (is_sfloat(a))
    {   Float_union w;
        w.i = a - TAG_SFLOAT;
        return (double)w.f;
    }
#endif
    else if (is_bfloat(a))
    {   int32_t h = type_of_header(flthdr(a));
        switch (h)
        {
#ifdef COMMON
    case TYPE_SINGLE_FLOAT:
            return (double)single_float_val(a);
#endif
    case TYPE_DOUBLE_FLOAT:
            return double_float_val(a);
#ifdef COMMON
    case TYPE_LONG_FLOAT:
            return (double)long_float_val(a);
#endif
    default:
            return 0.0;
        }
    }
    else
    {   Header h = numhdr(a);
        int x1;
        double r1;
        switch (type_of_header(h))
        {
    case TYPE_BIGNUM:
            r1 = bignum_to_float(a, length_of_header(h), &x1);
            return ldexp(r1, x1);
#ifdef COMMON
    case TYPE_RATNUM:
            {   int x2;
                Lisp_Object na = numerator(a);
                a = denominator(a);
                if (is_fixnum(na)) r1 = float_of_number(na), x1 = 0;
                else r1 = bignum_to_float(na,
                              length_of_header(numhdr(na)), &x1);
                if (is_fixnum(a)) r1 = r1 / float_of_number(a), x2 = 0;
                else r1 = r1 / bignum_to_float(a,
                                   length_of_header(numhdr(a)), &x2);
/* Floating point overflow can only arise in this ldexp() */
                return ldexp(r1, x1 - x2);
            }
#endif
    default:
/*
 * If the value was non-numeric or a complex number I hand back 0.0,
 * and since I am supposed to have checked the object type already
 * this OUGHT not to arrive - bit raising an exception seems over-keen.
 */
            return 0.0;
        }
    }
}
Example #17
0
static Lisp_Object plusib(Lisp_Object a, Lisp_Object b)
/*
 * Add a fixnum to a bignum, returning a result as a fixnum or bignum
 * depending on its size.  This seems much nastier than one would have
 * hoped.
 */
{
    int32_t len = bignum_length(b)-CELL, i, sign = int_of_fixnum(a), s;
    Lisp_Object c, nil;
    len = len/4;         /* This is always 4 because even on a 64-bit */
                         /* machine where CELL=8 I use 4-byte B-digits */
    if (len == 1)
    {   int32_t t;
/*
 * Partly because it will be a common case and partly because it has
 * various special cases I have special purpose code to cope with
 * adding a fixnum to a one-word bignum.
 */
        s = (int32_t)bignum_digits(b)[0] + sign;
        t = s + s;
        if (top_bit_set(s ^ t))  /* needs to turn into two-word bignum */
        {   if (s < 0) return make_two_word_bignum(-1, clear_top_bit(s));
            else return make_two_word_bignum(0, s);
        }
        t = s & fix_mask;    /* Will it fit as a fixnum? */
        if (t == 0 || t == fix_mask) return fixnum_of_int(s);
        /* here the result is a one-word bignum */
        return make_one_word_bignum(s);
    }
/*
 * Now, after all the silly cases have been handled, I have a calculation
 * which seems set to give a multi-word result.  The result here can at
 * least never shrink to a fixnum since subtracting a fixnum can at
 * most shrink the length of a number by one word.  I omit the stack-
 * check here in the hope that code here never nests enough for trouble.
 */
    push(b);
    c = getvector(TAG_NUMBERS, TYPE_BIGNUM, CELL+4*len);
    pop(b);
    errexit();
    s = bignum_digits(b)[0] + clear_top_bit(sign);
    bignum_digits(c)[0] = clear_top_bit(s);
    if (sign >= 0) sign = 0; else sign = 0x7fffffff; /* extend the sign */

    len--;
    for (i=1; i<len; i++)
    {   s = bignum_digits(b)[i] + sign + top_bit(s);
        bignum_digits(c)[i] = clear_top_bit(s);
    }
    /* Now just the most significant digit remains to be processed  */
    if (sign != 0) sign = -1;
    {   s = bignum_digits(b)[i] + sign + top_bit(s);
        if (!signed_overflow(s))         /* did it overflow? */
        {
/*
 * Here the most significant digit did not produce an overflow, but maybe
 * what we actually had was some cancellation and the MSD is now zero
 * or -1, so that the number should shrink...
 */
            if ((s == 0 && (bignum_digits(c)[i-1] & 0x40000000) == 0) ||
                (s == -1 && (bignum_digits(c)[i-1] & 0x40000000) != 0))
            {   /* shrink the number */
                numhdr(c) -= pack_hdrlength(1L);
                if (s == -1) bignum_digits(c)[i-1] |= ~0x7fffffff;
/*
 * Now sometimes the shrinkage will leave a padding word, sometimes it
 * will really allow me to save space. As a jolly joke with a 64-bit
 * system I need padding if there have been an odd number of (32-bit)
 * words of bignum data while with a 32-bit system the header word is
 * 32-bits wide and I need padding if there are ar even number of additional
 * data words.
 */
                if ((SIXTY_FOUR_BIT && ((i & 1) != 0)) ||
                    (!SIXTY_FOUR_BIT && ((i & 1) == 0)))
                {   bignum_digits(c)[i] = 0;   /* leave the unused word tidy */
                    return c;
                }
/*
 * Having shrunk the number I am leaving a doubleword of unallocated space
 * in the heap.  Dump a header word into it to make it look like an
 * 8-byte bignum since that will allow the garbage collector to handle it.
 * It I left it containing arbitrary junk I could wreck myself. The
 * make_bighdr(2L) makes a header for a number that fills 2 32-bit words
 * in all.
 */
                *(Header *)&bignum_digits(c)[i] = make_bighdr(2L);
                return c;
            }
            bignum_digits(c)[i] = s;  /* length unchanged */
            return c;
        }
/*
 * Here the result is one word longer than the input-bignum.
 * Once again SOMTIMES this will not involve allocating more store,
 * but just encroaching into the previously unused word that was padding
 * things out to a multiple of 8 bytes.
 */
        if ((SIXTY_FOUR_BIT && ((i & 1) == 0)) ||
            (!SIXTY_FOUR_BIT && ((i & 1) == 1)))
        {   bignum_digits(c)[i++] = clear_top_bit(s);
            bignum_digits(c)[i] = top_bit_set(s) ? -1 : 0;
            numhdr(c) += pack_hdrlength(1L);
            return c;
        }
        push(c);
/*
 * NB on the next line there is a +8. One +4 is because I had gone len--
 * somewhere earlier. The other +4 is to increase the length of the number
 * by one word.
 */
        b = getvector(TAG_NUMBERS, TYPE_BIGNUM, CELL+8+4*len);
        pop(c);
        errexit();
        for (i=0; i<len; i++)
            bignum_digits(b)[i] = bignum_digits(c)[i];
/*
 * I move the top digit across by hand since if the number is negative
 * I must lost its top bit
 */
        bignum_digits(b)[i++] = clear_top_bit(s);
/* Now the one-word extension to the number */
        bignum_digits(b)[i++] = top_bit_set(s) ? -1 : 0;
/*
 * Finally because I know that I expanded into a new doubleword I should
 * tidy up the second word of the newly allocated pair.
 */
        bignum_digits(b)[i] = 0;
        return b;
    }
}