Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include "fpi.h"

/*
 * the following routines depend on memory format, not the machine
 */

enum {
        Sign    = 1u << 31,
};

void
fpis2i(Internal *i, void *v)
{
        Single *s = v;

        i->s = (*s & Sign) ? 1: 0;
        if((*s & ~Sign) == 0){
                SetZero(i);
                return;
        }
        i->e = ((*s>>23) & 0x00FF) - SingleExpBias + ExpBias;
        i->h = (*s & 0x007FFFFF)<<(1+NGuardBits);
        i->l = 0;
        if(i->e)
                i->h |= HiddenBit;
        else
                i->e++;
}

void
fpid2i(Internal *i, void *v)
{
        Double *d = v;

        i->s = (d->h & Sign) ? 1: 0;
        i->e = (d->h>>20) & 0x07FF;
        i->h = ((d->h & 0x000FFFFF)<<(4+NGuardBits))|((d->l>>25) & 0x7F);
        i->l = (d->l & 0x01FFFFFF)<<NGuardBits;
        if(i->e)
                i->h |= HiddenBit;
        else
                i->e++;
}

void
fpiw2i(Internal *i, void *v)
{
        Word w, word = *(Word*)v;
        short e;

        if(word < 0){
                i->s = 1;
                word = -word;
        }
        else
                i->s = 0;
        if(word == 0){
                SetZero(i);
                return;
        }
        if(word > 0){
                for (e = 0, w = word; w; w >>= 1, e++)
                        ;
        } else
                e = 32;
        if(e > FractBits){
                i->h = word>>(e - FractBits);
                i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
        }
        else {
                i->h = word<<(FractBits - e);
                i->l = 0;
        }
        i->e = (e - 1) + ExpBias;
}

void
fpiv2i(Internal *i, void *v)
{
        Vlong w, word = *(Vlong*)v;
        short e;

        if(word < 0){
                i->s = 1;
                word = -word;
        }
        else
                i->s = 0;
        if(word == 0){
                SetZero(i);
                return;
        }
        if(word > 0){
                for (e = 0, w = word; w; w >>= 1, e++)
                        ;
        } else
                e = 64;
        if(e > FractBits){
                i->h = word>>(e - FractBits);
                i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
        }
        else {
                i->h = word<<(FractBits - e);
                i->l = 0;
        }
        i->e = (e - 1) + ExpBias;
}

/*
 * Note that all of these conversions from Internal format
 * potentially alter *i, so it should be a disposable copy
 * of the value to be converted.
 */

void
fpii2s(void *v, Internal *i)
{
        short e;
        Single *s = (Single*)v;

        fpiround(i);
        if(i->h & HiddenBit)
                i->h &= ~HiddenBit;
        else
                i->e--;
        *s = i->s ? Sign: 0;
        e = i->e;
        if(e < ExpBias){
                if(e <= (ExpBias - SingleExpBias))
                        return;
                e = SingleExpBias - (ExpBias - e);
        }
        else  if(e >= (ExpBias + (SingleExpMax-SingleExpBias))){
                *s |= SingleExpMax<<23;
                return;
        }
        else
                e = SingleExpBias + (e - ExpBias);
        *s |= (e<<23)|(i->h>>(1+NGuardBits));
}

void
fpii2d(void *v, Internal *i)
{
        Double *d = (Double*)v;

        fpiround(i);
        if(i->h & HiddenBit)
                i->h &= ~HiddenBit;
        else
                i->e--;
        i->l = ((i->h & GuardMask)<<25)|(i->l>>NGuardBits);
        i->h >>= NGuardBits;
        d->h = i->s ? Sign: 0;
        d->h |= (i->e<<20)|((i->h & 0x00FFFFFF)>>4);
        d->l = (i->h<<28)|i->l;
}

void
fpii2w(Word *word, Internal *i)
{
        Word w;
        short e;

        fpiround(i);
        e = (i->e - ExpBias) + 1;
        if(e <= 0)
                w = 0;
        else if(e > 31)
                w = 0x7FFFFFFF;
        else if(e > FractBits)
                w = (i->h<<(e - FractBits))|(i->l>>(2*FractBits - e));
        else
                w = i->h>>(FractBits-e);
        if(i->s)
                w = -w;
        *word = w;
}

void
fpii2v(Vlong *word, Internal *i)
{
        Vlong w;
        short e;

        fpiround(i);
        e = (i->e - ExpBias) + 1;
        if(e <= 0)
                w = 0;
        else if(e > 63)
                w = (1ull<<63) - 1;             /* maxlong */
        else if(e > FractBits)
                w = (Vlong)i->h<<(e - FractBits) | i->l>>(2*FractBits - e);
        else
                w = i->h>>(FractBits-e);
        if(i->s)
                w = -w;
        *word = w;
}