in include/yyjson/yyjson.c [7296:7354]
static_inline void f64_bin_to_dec(u64 sig_raw, u32 exp_raw,
u64 sig_bin, i32 exp_bin,
u64 *sig_dec, i32 *exp_dec) {
bool is_even, regular_spacing, u_inside, w_inside, round_up;
u64 s, sp, cb, cbl, cbr, vb, vbl, vbr, pow10hi, pow10lo, upper, lower, mid;
i32 k, h, exp10;
is_even = !(sig_bin & 1);
regular_spacing = (sig_raw == 0 && exp_raw > 1);
cbl = 4 * sig_bin - 2 + regular_spacing;
cb = 4 * sig_bin;
cbr = 4 * sig_bin + 2;
/* exp_bin: [-1074, 971] */
/* k = regular_spacing ? floor(log10(pow(2, exp_bin))) */
/* : floor(log10(pow(2, exp_bin) * 3.0 / 4.0)) */
/* = regular_spacing ? floor(exp_bin * log10(2)) */
/* : floor(exp_bin * log10(2) + log10(3.0 / 4.0)) */
k = (i32)(exp_bin * 315653 - (regular_spacing ? 131237 : 0)) >> 20;
/* k: [-324, 292] */
/* h = exp_bin + floor(log2(pow(10, e))) */
/* = exp_bin + floor(log2(10) * e) */
exp10 = -k;
h = exp_bin + ((exp10 * 217707) >> 16) + 1;
pow10_table_get_sig(exp10, &pow10hi, &pow10lo);
pow10lo += (exp10 < POW10_SIG_TABLE_MIN_EXACT_EXP ||
exp10 > POW10_SIG_TABLE_MAX_EXACT_EXP);
vbl = round_to_odd(pow10hi, pow10lo, cbl << h);
vb = round_to_odd(pow10hi, pow10lo, cb << h);
vbr = round_to_odd(pow10hi, pow10lo, cbr << h);
lower = vbl + !is_even;
upper = vbr - !is_even;
s = vb / 4;
if (s >= 10) {
sp = s / 10;
u_inside = (lower <= 40 * sp);
w_inside = (upper >= 40 * sp + 40);
if (u_inside != w_inside) {
*sig_dec = sp + w_inside;
*exp_dec = k + 1;
return;
}
}
u_inside = (lower <= 4 * s);
w_inside = (upper >= 4 * s + 4);
mid = 4 * s + 2;
round_up = (vb > mid) || (vb == mid && (s & 1) != 0);
*sig_dec = s + ((u_inside != w_inside) ? w_inside : round_up);
*exp_dec = k;
}