ref: a70379d7e4b822f532fb0a8ccdd1624a90b64a68
dir: /3rd/mp/mptod.c/
#include "platform.h" #include "mp.h" #include "nan.h" double mptod(mpint *a) { u64int v; mpdigit w, r; int sf, i, n; u32int m, s; FPdbleword x; if(a->top == 0) return 0.0; sf = (int)mpsignif(a); if(sf > 1024) return a->sign < 0 ? D_NINF : D_PINF; 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 & ((1ULL<<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; v = m < 64 ? (v<<m) : 0; s = (Dbits - m) & (Dbits - 1); v |= w >> s; r = w & ((1ULL<<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 a->sign < 0 ? D_NINF : D_PINF; } x.lo = v; x.hi = ((u32int)(v >> 32) & ((1<<20) - 1)) | (sf + 1022) << 20 | (a->sign & 1U<<31); return x.x; } mpint * dtomp(double d, mpint *a) { FPdbleword x; u64int 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 | (u64int)(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; }