Go to most recent revision | 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;
}