Converting between floating point and string

The following code requires long double be Intel extended precision. Having double precision in long double makes this code fail due to the 64-to-128-bit multiplication subroutine.

It supports 16/32/64/80/128-bit floats. Floating point to string embeds the (11, 24, 53, 64, 113) significant bits in 38 decimal significant digits then multiplies by powers of 2. String to floating point reads up to 38 significant digits, embeds them in binary, multiplied by powers of 10 then rounds to target precision.


 * 1) include 
 * 2) include 
 * 3) include

struct decimal38tmp{ uint64_t m[2]; // 19 digits in each integer short e; };

struct binary128tmp{ uint64_t m[2]; // 64 bits in each integer short e; };

struct int128tmp{ uint64_t q[2];

operator uint64_t(void){ return q[0]; }

operator long double(void){ return q[1]*0x1.p64l+q[0]; } };

int128tmp toint128tmp(uint64_t a){ return {a, 0}; }

int128tmp operator*(int128tmp z, int128tmp x){ // rounding mode toward zero at this point int128tmp w;   w.q[0]=z.q[0]*x.q[0]; w.q[1]=((long double)z.q[0]*x.q[0])*0x1.p-64l; w.q[1]+=z.q[1]*x.q[0]+z.q[0]*x.q[1]; return w; }

int128tmp operator-(int128tmp z, int128tmp x){ int128tmp w = z; w.q[0]-=x.q[0]; if(w.q[0]>z.q[0]) w.q[1]--; w.q[1]-=x.q[1]; return w; }

const uint64_t TENPOW19 = 10000000000000000000ULL; const uint64_t TENPOW18 = 1000000000000000000;

int128tmp a64to128binmult(uint64_t a, uint64_t b){ int128tmp w;   w.q[0]=a*b; w.q[1]=((long double)a*b)*0x1.p-64l; return w; }

//base 10^19 multiplications void a19to38decmult(uint64_t a, uint64_t b, uint64_t* out){ int128tmp z = a64to128binmult(a,b); uint64_t q = (uint64_t)((long double)z*1.e-19l); int128tmp z2 = z-a64to128binmult(q,TENPOW19); if((long double)(z2)>=TENPOW19) q++; if((long double)(z2)<0) q--; z2 = z-a64to128binmult(q,TENPOW19); out[0]=q; out[1]=z2; }

decimal38tmp powpow2p[] = { {{2000000000000000000,0000000000000000000},  0}, {{4000000000000000000,0000000000000000000},   0}, {{1600000000000000000,0000000000000000000},   1}, {{2560000000000000000,0000000000000000000},   2}, {{6553600000000000000,0000000000000000000},   4}, {{4294967296000000000,0000000000000000000},   9}, {{1844674407370955161,6000000000000000000},  19}, {{3402823669209384634,6337460743176821146},  38}, {{1157920892373161954,2357098500868790785},  77}, {{1340780792994259709,9574024998205846127ULL}, 154}, {{1797693134862315907,7293051907890247336}, 308}, {{3231700607131100730, 714876688669951960}, 616}, {{1044388881413152506,6917527107166243826},1233}, {{1090748135619415929,4629842447337828624},2466}, };

decimal38tmp powpow2m[] = { {{5000000000000000000,0000000000000000000},-  1}, {{2500000000000000000,0000000000000000000},-   1}, {{6250000000000000000,0000000000000000000},-   2}, {{3906250000000000000,0000000000000000000},-   3}, {{1525878906250000000,0000000000000000000},-   5}, {{2328306436538696289, 625000000000000000},-  10}, {{5421010862427522170, 372640043497085571},-  20}, {{2938735877055718769,9218413430556141945},-  39}, {{8636168555094444625,3863518628003995711},-  78}, {{7458340731200206743,2909653154629338374},- 155}, {{5562684646268003457,7255817933310101605},- 309}, {{3094346047382578275,4801833699711978539},- 617}, {{9574977460952185357ULL,9467310122804202421ULL},-1234}, {{9168019337774235828,1070619602424158298},-2467}, {{8405257857780233765,6566945433043815065},-4933}, };

binary128tmp powpow10p[] = { {{0x0000000000000000,0xa000000000000000,},   3,}, {{0x0000000000000000,0xc800000000000000,},   6,}, {{0x0000000000000000,0x9c40000000000000,},  13,}, {{0x0000000000000000,0xbebc200000000000,},  26,}, {{0x0000000000000000,0x8e1bc9bf04000000,},  53,}, {{0xf020000000000000,0x9dc5ada82b70b59d,}, 106,}, {{0x3cbf6b71c76b25fb,0xc2781f49ffcfa6d5,}, 212,}, {{0xc66f336c36b10137,0x93ba47c980e98cdf,}, 425,}, {{0xddbb901b98feeab8,0xaa7eebfb9df9de8d,}, 850,}, {{0xcc655c54bc5058fa,0xe319a0aea60e91c6,}, 1700,}, {{0x650d3d28f18b50d1,0xc976758681750c17,}, 3401,}, {{0xa74d28ce329ace57,0x9e8b3b5dc53d5de4,}, 6803,}, {{0xc94c153f804a4a9e,0xc46052028a20979a,},13606,}, };

binary128tmp powpow10m[] = { {{0xcccccccccccccccd,0xcccccccccccccccc,},-   4,}, {{0x3d70a3d70a3d70a4,0xa3d70a3d70a3d70a,},-   7,}, {{0xd3c36113404ea4a9,0xd1b71758e219652b,},-  14,}, {{0xfdc20d2b36ba7c3e,0xabcc77118461cefc,},-  27,}, {{0x4c2ebe687989a9b6,0xe69594bec44de15b,},-  54,}, {{0x67de18eda5814af6,0xcfb11ead453994ba,},- 107,}, {{0x3f2398d747b3622b,0xa87fea27a539e9a5,},- 213,}, {{0xac7cb3f6d05ddbf1,0xddd0467c64bce4a0,},- 426,}, {{0xfa911155fefb5328,0xc0314325637a1939,},- 851,}, {{0x7132d332e3f20504,0x9049ee32db23d21c,},- 1701,}, {{0x87a601586bd3f703,0xa2a682a5da57c0bd,},- 3402,}, {{0x492512d4f2ead3d9,0xceae534f34362de4,},- 6804,}, {{0x2de38123a1c3d1af,0xa6dd04c8d2ce9fde,},-13607,}, };

decimal38tmp operator*(decimal38tmp N, decimal38tmp M){ uint64_t w[4] = {0,0,0,0,}; a19to38decmult(N.m[1],M.m[1],w+2); uint64_t tmp[2]; uint64_t z;   a19to38decmult(N.m[0],M.m[1],tmp); z = w[2]+tmp[1]; if(z>=TENPOW19||z=TENPOW19||z=TENPOW19||z=TENPOW19||z=TENPOW19||z=TENPOW19||z(TENPOW19/2)||(w[2]==TENPOW19/2&&(w[3]>0||(w[1]%2)))){ w[1]++; if(w[1]==TENPOW19) {w[1]=0; w[0]++; if(w[0]==TENPOW19){ w[0]=TENPOW18; w[1]=0; exp++; }}   }    decimal38tmp out = {{w[0],w[1],},exp,}; return out; }

binary128tmp operator*(binary128tmp N, binary128tmp M){ uint64_t w[4] = {0,0,0,0,}; int128tmp tmp = a64to128binmult(N.m[0],M.m[0]); w[0]=tmp.q[0]; w[1]=tmp.q[1]; uint64_t z;   tmp = a64to128binmult(N.m[0],M.m[1]); z = w[1]+tmp.q[0]; if(z>63); w[2-i]<<=1; }   }    else exp++; if(w[1]>(1ULL<<63)||(w[1]==(1ULL<<63)&&(w[0]>0||(w[2]%2)))){ w[2]++; if(w[2]==0) {w[2]=0; w[3]++; if(w[3]==0){ w[3]=1ULL<<63; w[2]=0; exp++; }}   }    binary128tmp out = {{w[2],w[3],},exp,}; return out; }

std::u16string fptostring(void* num, int fptype){ uint64_t mantissa; short exponent; bool sign; int128tmp mantissa128; int mbits; int ebits; switch(fptype){ case 16: mantissa = ((*(uint16_t*)num)&0x3FF)|0x400; mbits = 11; exponent = (((*(uint16_t*)num)>>10)&0x1F)-15; ebits = 5; sign = (*(uint16_t*)num)>>15; if(exponent==-15) mantissa&=0x3FF; break; case 32: mantissa = ((*(uint32_t*)num)&0x7FFFFF)|0x800000; mbits = 24; exponent = (((*(uint32_t*)num)>>23)&0xFF)-127; ebits = 8; sign = (*(uint32_t*)num)>>31; if(exponent==-127) mantissa&=0x7FFFFF; break; case 64: mantissa = ((*(uint64_t*)num)&0xFFFFFFFFFFFFF)|0x10000000000000; mbits = 53; exponent = (((*(uint64_t*)num)>>52)&0x7FF)-1023; ebits = 11; sign = (*(uint64_t*)num)>>63; if(exponent==-1023) mantissa&=0xFFFFFFFFFFFFF; break; case 80: mantissa = *(uint64_t*)num; mbits = 64; exponent = ((*((short*)num+4))&0x7FFF)-16383; ebits = 15; sign = ((*((short*)num+4))&0x8000); break; case 128: mantissa128 = *(int128tmp*)num; mantissa128.q[1]=(mantissa128.q[1]&0xFFFFFFFFFFFF)|0x1000000000000; mbits = 113; exponent = ((*((short*)num+7))&0x7FFF)-16383; ebits = 15; sign = ((*((short*)num+7))&0x8000); if(exponent==-16383) mantissa128.q[1]&=0xFFFFFFFFFFFF; break; } std::u16string out = sign ? u"-" : u""; if(exponent==1<<(ebits-1)){ if(fptype==128 ? mantissa128.q[0]||(mantissa128.q[1]&((1ULL<<48)-1)) : mantissa&((1ULL<<(mbits-1))-1)) return u"NaN"; out.append(u"Infinity"); return out; } if(fptype==128 ? mantissa128.q[0]==0&&mantissa128.q[1]==0 : mantissa==0) {out.append(u"0"); return out;} int rndmod = fegetround; fesetround(FE_TOWARDZERO); if(exponent==-((1<<(ebits-1))-1)) exponent++; decimal38tmp x = {{1000000000000000000,0000000000000000000,},0,}; exponent-=mbits-1; if(exponent>0) for(int i=13; i>=0; i--){if(((+exponent)>>i)&1)x=x*powpow2p[i];} if(exponent<0) for(int i=14; i>=0; i--){if(((-exponent)>>i)&1)x=x*powpow2m[i];} decimal38tmp p,q,r; // q is the value, and halfway toward preceding (p) and following (r) floating points switch(fptype){ case 128:{ uint64_t q2 = (uint64_t)((long double)mantissa128*1.e-19l); int128tmp z2 = mantissa128-a64to128binmult(q2,TENPOW19); if((long double)(z2)>=TENPOW19) q2++; if((long double)(z2)<0) q2--; z2 = mantissa128-a64to128binmult(q2,TENPOW19); q = {{q2,z2,},35,}; q.m[0]*=100; q.m[0]+=(q.m[1]/(TENPOW19/100)); q.m[1]%=(TENPOW19/100); q.m[1]*=100; break; } case 80: q = {{mantissa/(TENPOW19/100),mantissa%(TENPOW19/100)*100,},35,}; break; case 16: case 32: case 64: default: q = {{0,mantissa*100,},35,}; break; } p = q; r = q; p.m[1] -= ((fptype==128?*(uint64_t*)num==0&&*((uint64_t*)num+1)<<16==0:mantissa==(1ULL<<(mbits-1)))&&exponent>-((1<<(ebits-1))+mbits-3)) ? 25 : 50; if(p.m[1]>TENPOW19) {p.m[1]+=TENPOW19; p.m[0]--;} r.m[1] += 50; if(r.m[1]>TENPOW19) {r.m[1]-=TENPOW19; r.m[0]++;} decimal38tmp* pqr[3] = {&p,&q,&r,}; for(int j=0; j<3; j++){ for(int i=0; i<38; i++){ if(pqr[j]->m[0]>=TENPOW18) break; pqr[j]->m[0]*=10; pqr[j]->m[0]+=pqr[j]->m[1]/TENPOW18; pqr[j]->m[1]%=TENPOW18; pqr[j]->m[1]*=10; pqr[j]->e--; } } decimal38tmp w = x*p; decimal38tmp y = x*r; x = x*q; decimal38tmp* wxy[3] = {&w,&x,&y,}; if(y.e>x.e){ w.m[1]/=10; w.m[1]+=w.m[0]%10*TENPOW18; w.m[0]/=10; w.e++; x.m[1]/=10; x.m[1]+=x.m[0]%10*TENPOW18; x.m[0]/=10; x.e++; } if(x.e>w.e){ w.m[1]/=10; w.m[1]+=w.m[0]%10*TENPOW18; w.m[0]/=10; w.e++; } char digitregister[38]; for(int i=0; i<38; i++) digitregister[i]=0; bool flag = 0; for(int i=0; i<38; i++){ int s[3]; // digits for(int j=0; j<3; j++){ s[j] = wxy[j]->m[0]/TENPOW18; } int d[3]; // rounded digits for(int j=0; j<3; j++){ d[j] = s[j]+(wxy[j]->m[0]%TENPOW18>TENPOW18/2 || (wxy[j]->m[0]%TENPOW18==TENPOW18/2&&(wxy[j]->m[1]||(s[j]&2)))); } if(flag){digitregister[i]=d[1]; break;} if(s[0]==s[2]){ digitregister[i]=s[1]; } else if(s[0]!=s[2]&&(d[1]>s[0]&&d[1]<=s[2])){ digitregister[i]=d[1]; break; } else if(s[0]!=s[2]&&(d[1]+1>s[0]&&d[1]+1<=s[2])){ //rare power of two case digitregister[i]=d[1]+1; break; } else digitregister[i]=s[1]; for(int j=0; j<3; j++){ wxy[j]->m[0]-=s[1]*TENPOW18; wxy[j]->m[0]*=10; wxy[j]->m[0]+=wxy[j]->m[1]/TENPOW18; wxy[j]->m[1]%=TENPOW18; wxy[j]->m[1]*=10; } } if(digitregister[0]==0){for(int i=0; i<37; i++)digitregister[i]=digitregister[i+1]; digitregister[37]=0;y.e--;} int end = 38; for(int i=37; i>0; i--){if(digitregister[i]==0)end--; else break;} int expmin = -2; int expmax = 10; switch(fptype){ case 16: expmin=- 5; expmax= 5; break; case 32: expmin=- 6; expmax=10; break; case 64: expmin=-10; expmax=17; break; case 80: expmin=-13; expmax=21; break; case 128: expmin=-15; expmax=35; break; } if(y.e>=expmax||y.e1){ out.push_back('.'); for(int i=1; i=1000) out.push_back(ex/1000+'0'); if(ex>=100) out.push_back(ex/100%10+'0'); if(ex>=10) out.push_back(ex/10%10+'0'); out.push_back(ex%10+'0'); } else{ if(y.e<0){ out.append(u"0."); for(int i=1; i<-y.e; i++) out.push_back('0'); for(int i=0; i<end; i++) out.push_back(digitregister[i]+'0'); } else{ if(y.e+1<end){ for(int i=0; i<y.e+1; i++) out.push_back(digitregister[i]+'0'); out.push_back('.'); for(int i=y.e+1; i<end; i++) out.push_back(digitregister[i]+'0'); }  else{ for(int i=0; i<end; i++) out.push_back(digitregister[i]+'0'); for(int i=end; i<y.e+1; i++) out.push_back('0'); } } } fesetround(rndmod); return out; }

std::u16string      halftostring(   uint16_t num){return fptostring(&num, 16);} std::u16string     floattostring(      float num){return fptostring(&num, 32);} std::u16string    doubletostring(     double num){return fptostring(&num, 64);} std::u16string longdoubletostring(long double num){return fptostring(&num, 80);} std::u16string  float128tostring( __float128 num){return fptostring(&num,128);}

void writetmp(long double num, int fptype, void* out){ switch(fptype){ case 16: { uint16_t x = ((*((short*)&num+4))&0x8000); if(num!=num) x|=0x7C01; if(1.0l/num==0) x|=0x7C00; *(uint16_t*)out = x; break;} case 32: *(float*)out = num; break; case 64: *(double*)out = num; break; case 80: *(long double*)out = num; break; case 128: { __float128 x = 0; (*((short*)&x+7)) = ((*((short*)&num+4))&0x8000); if(num!=num) (*((uint32_t*)&x+3))|=0x7FFF8000; if(1.0l/num==0) (*((uint32_t*)&x+3))|=0x7FFF0000; *(__float128*)out = x; break;} } }

void stringtofp(std::u16string num, int fptype, void* out){ int i = 0; bool sign = 0; if(num.size==0) {writetmp(0.l,fptype,out); return;} if(num[0]==u'-') {sign=1;i++;} if(num[0]==u'+') i++; long double szero = sign ? -0.0l : 0.0l; if(num.size-i>=3&&(num[i+0]&0xFFDF)=='I'&&(num[i+1]&0xFFDF)=='N'&&(num[i+2]&0xFFDF)=='F') {writetmp(1.l/szero,fptype,out); return;} if(num.size-i>=3&&(num[i+0]&0xFFDF)=='N'&&(num[i+1]&0xFFDF)=='A'&&(num[i+2]&0xFFDF)=='N') {writetmp(0.l/szero,fptype,out); return;} int rndmod = fegetround; fesetround(FE_TOWARDZERO); char digitregister[38]; for(int i=0; i<38; i++) digitregister[i]=0; int r = 0; int ex = -1; while(i=u'0'&&num[i]<=u'9')&&r<38){ digitregister[r]=num[i]-u'0'; r++; i++; ex++; } if(i=u'0'&&num[i]<=u'9')&&r<38){ digitregister[r]=num[i]-u'0'; r++; i++; } } while(i=u'0'&&num[i]<=u'9')) i++; //ignore over 38 digits if(r==0) {fesetround(rndmod); writetmp(szero,fptype,out); return;} if(i=u'0'&&num[i]<=u'9')) {ex2*=10; ex2+=num[i]-u'0'; i++;} if(sign2) ex2=-ex2; ex+=ex2; } binary128tmp z; { uint64_t s = 0; for(int j=0; j<19; j++) {s*=10; s+=digitregister[j];} int128tmp r = a64to128binmult(s,TENPOW19); s=0; for(int j=19; j<38; j++) {s*=10; s+=digitregister[j];} if(r.q[0]+s=0; e--) if(!(r.q[1]>>(64-(1<<e)))){r.q[1]<<=(1<<e);r.q[1]|=(r.q[0]>>(64-(1<<e)));r.q[0]<<=(1<<e); z.e-=(1<<e);} z.m[0]=r.q[0]; z.m[1]=r.q[1]; } binary128tmp x = {{0,1ULL<<63,},0,}; ex-=37; if(ex>0) for(int i=13; i>=0; i--){if(((+ex)>>i)&1)x=x*powpow10p[i];} if(ex<0) for(int i=13; i>=0; i--){if(((-ex)>>i)&1)x=x*powpow10m[i];} x=x*z; fesetround(rndmod); switch(fptype){ case 16:{ if(x.e<-25) {*(uint16_t*)out = sign<<15; return;} if(x.e<-14) { uint64_t y = -14-x.e;  bool flag = 0; if((x.m[0]&((1ULL<<y)-1))&&!((x.m[0]>>y)&1)) flag = 1; x.m[0]>>=y; x.m[0]|=x.m[1]<<(64-y); x.m[1]>>=y; if(flag) {uint64_t p = x.m[0]+1; if(p<x.m[0])x.m[1]++; x.m[0]=p;} } if((x.m[1]<<11)>(1ULL<<63)||((x.m[1]<<11)==(1ULL<<63)&&(x.m[0]||((x.m[1]>>53)&1)))) {x.m[1]+=1ULL<<53; if((x.m[1]>>53)==0) {x.m[1]=1ULL<<63; x.e++;}} if(x.e<-14) x.e=-15; if(x.e>15) {*(uint16_t*)out = (sign<<15)|0x7C00; return;} uint16_t out_; *(uint16_t*)&out_ = ((x.m[1]>>53)&0x3FF)|((x.e+15)<<10)|((uint64_t)sign<<15); *(uint16_t*)out = out_; break;} case 32:{ if(x.e<-150) {*(float*)out = szero; return;} if(x.e<-126) { uint64_t y = -126-x.e;  bool flag = 0; if((x.m[0]&((1ULL<<y)-1))&&!((x.m[0]>>y)&1)) flag = 1; x.m[0]>>=y; x.m[0]|=x.m[1]<<(64-y); x.m[1]>>=y; if(flag) {uint64_t p = x.m[0]+1; if(p<x.m[0])x.m[1]++; x.m[0]=p;} } if((x.m[1]<<24)>(1ULL<<63)||((x.m[1]<<24)==(1ULL<<63)&&(x.m[0]||((x.m[1]>>40)&1)))) {x.m[1]+=1ULL<<40; if((x.m[1]>>40)==0) {x.m[1]=1ULL<<63; x.e++;}} if(x.e<-126) x.e=-127; if(x.e>127) {*(float*)out = 1.0/szero; return;} float out_; *(uint32_t*)&out_ = ((x.m[1]>>40)&0x7FFFFF)|((x.e+127)<<23)|((uint64_t)sign<<31); *(float*)out = out_; break;} case 64:{ if(x.e<-1075) {*(double*)out = szero; return;} if(x.e<-1022) { uint64_t y = -1022-x.e;  bool flag = 0; if((x.m[0]&((1ULL<<y)-1))&&!((x.m[0]>>y)&1)) flag = 1; x.m[0]>>=y; x.m[0]|=x.m[1]<<(64-y); x.m[1]>>=y; if(flag) {uint64_t p = x.m[0]+1; if(p<x.m[0])x.m[1]++; x.m[0]=p;} } if((x.m[1]<<53)>(1ULL<<63)||((x.m[1]<<53)==(1ULL<<63)&&(x.m[0]||((x.m[1]>>11)&1)))) {x.m[1]+=1ULL<<11; if((x.m[1]>>11)==0) {x.m[1]=1ULL<<63; x.e++;}} if(x.e<-1022) x.e=-1023; if(x.e>1023) {*(double*)out = 1.0/szero; return;} double out_; *(uint64_t*)&out_ = ((x.m[1]>>11)&0xFFFFFFFFFFFFF)|((uint64_t)(x.e+1023)<<52)|((uint64_t)sign<<63); *(double*)out = out_; break;} case 80:{ if(x.e<-16446) {*(long double*)out = szero; return;} if(x.e==-16446){if(x.m[0]&&!(x.m[1]&1)) x.m[1]++; x.m[0]=x.m[1]; x.m[1]=0; if(x.m[0]==0)x.m[1]=1;} if(x.e<-16382&&x.e>-16446) { uint64_t y = -16382-x.e;  bool flag = 0; if((x.m[0]&((1ULL<<y)-1))&&!((x.m[0]>>y)&1)) flag = 1; x.m[0]>>=y; x.m[0]|=x.m[1]<<(64-y); x.m[1]>>=y; if(flag) {uint64_t p = x.m[0]+1; if(p<x.m[0])x.m[1]++; x.m[0]=p;} } if(x.m[0]>(1ULL<<63)||(x.m[0]==(1ULL<<63)&&(x.m[1]&1))) {x.m[1]++; if(x.m[1]==0) {x.m[1]=1ULL<63; x.e++;}} if(x.e<-16382) x.e=-16383; if(x.e>16383) {*(long double*)out = 1.0l/szero; return;} long double out_; *(uint64_t*)&out_ = x.m[1]; *((short*)&out_+4) = (x.e+16383)|((int)sign<<15); *(long double*)out = out_; break;} case 128:{ if(x.e<-16495) {*(__float128*)out = szero; return;} if(x.e<-16382) { uint64_t y = -16382-x.e;  if(y==65) {if(x.m[0]&& (x.m[1]&1)) x.m[1]++; x.m[0]=x.m[1]; x.m[1]=0; if(x.m[0]==0)x.m[1]=1; y=-64;} if(y>=64) {if(x.m[0]&&!(x.m[1]&1)) x.m[1]++; x.m[0]=x.m[1]; x.m[1]=0; if(x.m[0]==0)x.m[1]=1; y-=64;} bool flag = 0; if((x.m[0]&((1ULL<<y)-1))&&!((x.m[0]>>y)&1)) flag = 1; x.m[0]>>=y; x.m[0]|=x.m[1]<<(64-y); x.m[1]>>=y; if(flag) {uint64_t p = x.m[0]+1; if(p<x.m[0])x.m[1]++; x.m[0]=p;} } if((x.m[0]<<48)>(1ULL<<63)||((x.m[0]<<48)==(1ULL<<63)&&((x.m[0]>>16)&1))) {x.m[0]+=1ULL<<16; if((x.m[0]>>16)==0) {x.m[1]++; if(x.m[1]==0) {x.m[1]=1ULL<<63; x.m[0]=0; x.e++;}}} if(x.e<-16382) x.e=-16383; if(x.e>16383) {*(__float128*)out = 1.0/szero; return;} __float128 out_; *(uint64_t*)&out_ = x.m[0]>>15|x.m[1]<<49; *((uint64_t*)&out_+1) = ((x.m[1]>>15)&0xFFFFFFFFFFFF)|((uint64_t)(x.e+16383)<<48)|((uint64_t)sign<<63); *(__float128*)out = out_; break;} } }

uint16_t stringtohalf(std::u16string num){uint16_t x; stringtofp(num,16,&x); return x;} float stringtofloat(std::u16string num){float x; stringtofp(num,32,&x); return x;} double stringtodouble(std::u16string num){double x; stringtofp(num,64,&x); return x;} long double stringtolongdouble(std::u16string num){long double x; stringtofp(num,80,&x); return x;} __float128 stringtofloat128(std::u16string num){__float128 x; stringtofp(num,128,&x); return x;}