// Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // _[W]Sto[d f ld] common functionality // macros #define ACSIZE 4 // size of extended-precision accumulators #define D16TO7 FLIT(268435456.0) // 16^7 #define D10TO9 FLIT(1e9) // 10^9 #if FBITS == 24 #define NLONG 1 // 7 * NLONG == max hexadecimal digits #elif FBITS == 53 #define NLONG 3 #else // ^^^ FBITS == 53 / FBITS != 24 && FBITS != 53 vvv #error Unexpected value for FBITS #endif // ^^^ FBITS != 24 && FBITS != 53 ^^^ // FTYPE _Stodx(const CTYPE *s, CTYPE **endptr, long pten, int *perr) { // convert string to FTYPE, with checking FTYPE x; long lo[NLONG + 1]; const CTYPE* s0 = s; int code = CNAME(Stopfx)(&s, endptr); const int neg = code & FL_NEG; extern FTYPE FNAME(Dtento)(FTYPE*, long, int*); if (perr != nullptr) { *perr = 0; } if ((code &= ~FL_NEG) == FL_DEC) { // parse decimal format const int nlo = CNAME(Stoflt)(s0, s, endptr, lo, NLONG); _Analysis_assume_(nlo <= NLONG); FTYPE xpx[ACSIZE]; FTYPE xpf[ACSIZE]; int i; FNAME(Xp_setw)(xpf, ACSIZE, D10TO9); if (nlo == 0) { FNAME(Xp_setw)(xpx, ACSIZE, 0.0); } else { for (i = 1, FNAME(Xp_setn)(xpx, ACSIZE, lo[1]); i < nlo;) { // x = x * D10TO9 + (FTYPE)lo[++i] FTYPE xpa[ACSIZE]; FTYPE xpt[ACSIZE * 2]; FNAME(Xp_mulx)(xpx, ACSIZE, xpf, ACSIZE, xpt); FNAME(Xp_setn)(xpa, ACSIZE, lo[++i]); FNAME(Xp_addx)(xpx, ACSIZE, xpa, ACSIZE); } } pten += lo[0]; x = FNAME(Dtento)(xpx, pten, perr); } else if (code == FL_HEX) { // parse hexadecimal format const int nlo = CNAME(Stoxflt)(s0, s, endptr, lo, NLONG); _Analysis_assume_(nlo <= NLONG); FTYPE xpx[ACSIZE]; FTYPE xpf[ACSIZE]; int i; FNAME(Xp_setw)(xpf, ACSIZE, D16TO7); if (nlo == 0) { FNAME(Xp_setw)(xpx, ACSIZE, 0.0); } else { for (i = 1, FNAME(Xp_setn)(xpx, ACSIZE, lo[1]); i < nlo;) { // x = x * D16TO7 + (FTYPE)lo[++i] FTYPE xpa[ACSIZE]; FTYPE xpt[ACSIZE * 2]; FNAME(Xp_mulx)(xpx, ACSIZE, xpf, ACSIZE, xpt); FNAME(Xp_setn)(xpa, ACSIZE, lo[++i]); FNAME(Xp_addx)(xpx, ACSIZE, xpa, ACSIZE); } } x = FNAME(Dtento)(xpx, pten, perr); FNAME(Dscale)(&x, lo[0]); } else if (code == FL_INF) { x = FCONST(Inf); } else if (code == FL_NAN) { x = FCONST(Nan); } else { x = FLIT(0.0); // code == FL_ERR } if (neg) { FNEGATE(x); } return x; }