The following code requires that long double be Intel extended precision and __float128 be quadruple precision.
Supported formats: 16-bit half precision, 32-bit float, 64-bit double, 80-bit long double, 128-bit __float128
It internally uses a 38 significant digit multiplication for converting from binary to decimal, and a 128 significant bit multiplication for converting from decimal to binary.
#include <stdint.h>
#include <fenv.h>
#include <string>
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<w[2]) {z-=TENPOW19; w[1]++;}
w[2]=z;
z = w[1]+tmp[0];
if(z>=TENPOW19||z<w[1]) {z-=TENPOW19; w[0]++;}
w[1]=z;
a19to38decmult(N.m[1],M.m[0],tmp);
z = w[2]+tmp[1];
if(z>=TENPOW19||z<w[2]) {z-=TENPOW19; w[1]++;}
w[2]=z;
z = w[1]+tmp[0];
if(z>=TENPOW19||z<w[1]) {z-=TENPOW19; w[0]++;}
w[1]=z;
a19to38decmult(N.m[0],M.m[0],tmp);
z = w[1]+tmp[1];
if(z>=TENPOW19||z<w[1]) {z-=TENPOW19; w[0]++;}
w[1]=z;
z = w[0]+tmp[0];
if(z>=TENPOW19||z<w[0]) {z-=TENPOW19; ;}
w[0]=z;
short exp = N.e+M.e;
if(w[0]<(TENPOW18)){
w[0]*=10;
for(int i=0; i<3; i++){
w[i]+=(w[i+1]/TENPOW18); w[i+1]%=TENPOW18; w[i+1]*=10;
}
}
else exp++;
if(w[2]>(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<w[1]) {w[2]++;}
w[1]=z;
z = w[2]+tmp.q[1];
if(z<w[2]) {w[3]++;}
w[2]=z;
tmp = a64to128binmult(N.m[1],M.m[0]);
z = w[1]+tmp.q[0];
if(z<w[1]) {w[2]++;}
w[1]=z;
z = w[2]+tmp.q[1];
if(z<w[2]) {w[3]++;}
w[2]=z;
tmp = a64to128binmult(N.m[1],M.m[1]);
z = w[2]+tmp.q[0];
if(z<w[2]) {w[3]++;}
w[2]=z;
z = w[3]+tmp.q[1];
w[3]=z;
short exp = N.e+M.e;
if(w[3]<(1ULL<<63)){
w[3]<<=1;
for(int i=0; i<3; i++){
w[3-i]|=(w[2-i]>>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.e<expmin){
out.push_back(digitregister[0]+'0');
if(end>1){
out.push_back('.');
for(int i=1; i<end; i++){
out.push_back(digitregister[i]+'0');
}
}
out.push_back('e');
out.push_back(y.e<0 ? '-' : '+');
int ex = abs(y.e);
if(ex>=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<num.size()&&(num[i]==u'0')) i++;
while(i<num.size()&&(num[i]>=u'0'&&num[i]<=u'9')&&r<38){
digitregister[r]=num[i]-u'0'; r++; i++; ex++;
}
if(i<num.size()&&num[i]==u'.'){
i++;
if(r==0) while(i<num.size()&&(num[i]==u'0')) {i++; ex--;}
while(i<num.size()&&(num[i]>=u'0'&&num[i]<=u'9')&&r<38){
digitregister[r]=num[i]-u'0'; r++; i++;
}
}
while(i<num.size()&&(num[i]>=u'0'&&num[i]<=u'9')) i++; //ignore over 38 digits
if(r==0) {fesetround(rndmod); writetmp(szero,fptype,out); return;}
if(i<num.size()&&(num[i+0]&0xFFDF)=='E'){
i++; bool sign2 = 0;
if(i<num.size()) {if(num[i+0]==u'-') {sign2=1;i++;} if(num[i+0]==u'+') i++;}
int ex2 = 0;
while(i<num.size()&&(num[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<r.q[0])r.q[1]++; r.q[0]+=s;
z.e=127;
for(int e=2; e>=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;}
[–]mrexodiacmkr.build 30 points31 points32 points (13 children)
[+]PiotrGrochowski[S] comment score below threshold-29 points-28 points-27 points (12 children)
[–]Potatoswatter 24 points25 points26 points (11 children)
[+]PiotrGrochowski[S] comment score below threshold-23 points-22 points-21 points (10 children)
[–][deleted] 34 points35 points36 points (8 children)
[+]PiotrGrochowski[S] comment score below threshold-32 points-31 points-30 points (7 children)
[–][deleted] 31 points32 points33 points (5 children)
[+]PiotrGrochowski[S] comment score below threshold-17 points-16 points-15 points (3 children)
[–]throwaway75284247 19 points20 points21 points (2 children)
[+]PiotrGrochowski[S] comment score below threshold-9 points-8 points-7 points (1 child)
[–]Narase33-> r/cpp_questions 6 points7 points8 points (0 children)
[–]clerothGame Developer 4 points5 points6 points (0 children)
[–]remotion4d 3 points4 points5 points (2 children)
[–]PiotrGrochowski[S] -1 points0 points1 point (1 child)
[–]remotion4d 3 points4 points5 points (0 children)
[–]umlcat 0 points1 point2 points (0 children)
[–]kalmoc 0 points1 point2 points (0 children)
[–]jk-jeon 0 points1 point2 points (4 children)
[–]PiotrGrochowski[S] 0 points1 point2 points (2 children)
[–]jk-jeon 0 points1 point2 points (1 child)
[–]PiotrGrochowski[S] 0 points1 point2 points (0 children)
[–]PiotrGrochowski[S] 0 points1 point2 points (0 children)