Subversion Repositories planix.SVN

Rev

Rev 33 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "os.h"
#include <mp.h>
#include "dat.h"

double
mptod(mpint *a)
{
        u64int v;
        mpdigit w, r;
        int sf, i, n, m, s;
        FPdbleword x;
        
        if(a->top == 0) return 0.0;
        sf = mpsignif(a);
        if(sf > 1024) return Inf(a->sign);
        i = a->top - 1;
        v = a->p[i];
        n = sf & Dbits - 1;
        n |= n - 1 & Dbits;
        r = 0;
        if(n > 54){
                s = n - 54;
                r = v & (1<<s) - 1;
                v >>= s;
        }
        while(n < 54){
                if(--i < 0)
                        w = 0;
                else
                        w = a->p[i];
                m = 54 - n;
                if(m > Dbits) m = Dbits;
                s = Dbits - m & Dbits - 1;
                v = v << m | w >> s;
                r = w & (1<<s) - 1;
                n += m;
        }
        if((v & 3) == 1){
                while(--i >= 0)
                        r |= a->p[i];
                if(r != 0)
                        v++;
        }else
                v++;
        v >>= 1;
        while((v >> 53) != 0){
                v >>= 1;
                if(++sf > 1024)
                        return Inf(a->sign);
        }
        x.lo = v;
        x.hi = (u32int)(v >> 32) & (1<<20) - 1 | sf + 1022 << 20 | a->sign & 1<<31;
        return x.x;
}

mpint *
dtomp(double d, mpint *a)
{
        FPdbleword x;
        uvlong v;
        int e;

        if(a == nil)
                a = mpnew(0);
        x.x = d;
        e = x.hi >> 20 & 2047;
        assert(e != 2047);
        if(e < 1022){
                mpassign(mpzero, a);
                return a;
        }
        v = x.lo | (uvlong)(x.hi & (1<<20) - 1) << 32 | 1ULL<<52;
        if(e < 1075){
                v += (1ULL<<1074 - e) - (~v >> 1075 - e & 1);
                v >>= 1075 - e;
        }
        uvtomp(v, a);
        if(e > 1075)
                mpleft(a, e - 1075, a);
        if((int)x.hi < 0)
                a->sign = -1;
        return a;
}