Fix wuffs_base__parse_number_f64 fast path comment
diff --git a/internal/cgen/base/floatconv-submodule-code.c b/internal/cgen/base/floatconv-submodule-code.c
index 05debab..68d390d 100644
--- a/internal/cgen/base/floatconv-submodule-code.c
+++ b/internal/cgen/base/floatconv-submodule-code.c
@@ -1578,9 +1578,8 @@
goto fallback;
}
- // If man and exp10 are small enough, all three of (man), (10 ** exp10) and
- // (man ** (10 ** exp10)) are exactly representable by a double. We don't
- // need to run the Eisel-Lemire algorithm.
+ // If both man and (10 ** exp10) are exactly representable by a double, we
+ // don't need to run the Eisel-Lemire algorithm.
if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) {
double d = (double)man;
if (exp10 >= 0) {
@@ -1596,7 +1595,7 @@
// The wuffs_base__private_implementation__parse_number_f64_eisel_lemire
// preconditions include that man is non-zero. Parsing "0" should be caught
- // by the "If man and exp10 are small enough" above, but "0e99" might not.
+ // by the "If both man and (10 ** exp10)" above, but "0e99" might not.
if (man == 0) {
goto fallback;
}
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index a23224a..1c13c3e 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -409,8 +409,8 @@
"ll correct for that later. The \"script/process-json-numbers.c with\n // -p\" benchmark is noticably slower if we try to correct for that now.\n uint32_t digit_count = (uint32_t)(p - start_of_digits_ptr);\n\n // Update exp10 for the optional exponent, starting with 'E' or 'e'.\n if ((*p | 0x20) == 'e') {\n p++;\n int32_t exp_sign = +1;\n if (*p == '-') {\n p++;\n exp_sign = -1;\n } else if (*p == '+') {\n p++;\n }\n if (!wuffs_base__private_implementation__is_decimal_digit(*p)) {\n goto fallback;\n }\n int32_t exp_num = ((uint8_t)(*p - '0'));\n p++;\n // The rest of the exp_num walking has a peculiar control flow but, once\n // again, the \"script/process-json-numbers.c with -p\" benchmark is\n // sensitive to alternative formulations.\n if (wuffs_base__private_implementation__is_decimal_digit(*p)) {\n exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));\n p++;\n }\n if (wuffs_base__private_implementation__is_decim" +
"al_digit(*p)) {\n exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));\n p++;\n }\n while (wuffs_base__private_implementation__is_decimal_digit(*p)) {\n if (exp_num > 0x1000000) {\n goto fallback;\n }\n exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));\n p++;\n }\n exp10 += exp_sign * exp_num;\n }\n\n // The Wuffs API is that the original slice has no trailing data. It also\n // allows underscores, which we don't catch here but the fallback should.\n if (p != &z[s.len]) {\n goto fallback;\n }\n\n // Check that the uint64_t typed man variable has not overflowed, based on\n // digit_count.\n //\n // For reference:\n // - (1 << 63) is 9223372036854775808, which has 19 decimal digits.\n // - (1 << 64) is 18446744073709551616, which has 20 decimal digits.\n // - 19 nines, 9999999999999999999, is 0x8AC7230489E7FFFF, which has 64\n // bits and 16 hexadecimal digits.\n // - 20 nines, 99999999999999999999, is 0x56BC75" +
"E2D630FFFFF, which has 67\n // bits and 17 hexadecimal digits.\n if (digit_count > 19) {\n // Even if we have more than 19 pseudo-digits, it's not yet definitely an\n // overflow. Recall that digit_count might be off-by-one (too large) if\n // there's a decimal separator. It will also over-report the number of\n // meaningful digits if the input looks something like \"0.000dddExxx\".\n //\n // We adjust by the number of leading '0's and '.'s and re-compare to 19.\n // Once again, technically, we could skip ','s too, but that perturbs the\n // \"script/process-json-numbers.c with -p\" benchmark.\n const uint8_t* q = start_of_digits_ptr;\n for (; (*q == '0') || (*q == '.'); q++) {\n }\n digit_count -= (uint32_t)(q - start_of_digits_ptr);\n if (digit_count > 19) {\n goto fallback;\n }\n }\n\n // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire\n // preconditions include that exp10 is in the range -326 ..= 310.\n if ((ex" +
- "p10 < -326) || (310 < exp10)) {\n goto fallback;\n }\n\n // If man and exp10 are small enough, all three of (man), (10 ** exp10) and\n // (man ** (10 ** exp10)) are exactly representable by a double. We don't\n // need to run the Eisel-Lemire algorithm.\n if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) {\n double d = (double)man;\n if (exp10 >= 0) {\n d *= wuffs_base__private_implementation__f64_powers_of_10[+exp10];\n } else {\n d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10];\n }\n wuffs_base__result_f64 ret;\n ret.status.repr = NULL;\n ret.value = negative ? -d : +d;\n return ret;\n }\n\n // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire\n // preconditions include that man is non-zero. Parsing \"0\" should be caught\n // by the \"If man and exp10 are small enough\" above, but \"0e99\" might not.\n if (man == 0) {\n goto fallback;\n }\n\n // Our man and exp10 are in range. Run the Eisel-Lem" +
- "ire algorithm.\n int64_t r =\n wuffs_base__private_implementation__parse_number_f64_eisel_lemire(\n man, exp10);\n if (r < 0) {\n goto fallback;\n }\n wuffs_base__result_f64 ret;\n ret.status.repr = NULL;\n ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n ((uint64_t)r) | (((uint64_t)negative) << 63));\n return ret;\n } while (0);\n\nfallback:\n do {\n wuffs_base__private_implementation__high_prec_dec h;\n wuffs_base__status status =\n wuffs_base__private_implementation__high_prec_dec__parse(&h, s,\n options);\n if (status.repr) {\n return wuffs_base__private_implementation__parse_number_f64_special(\n s, options);\n }\n return wuffs_base__private_implementation__high_prec_dec__to_f64(&h,\n options);\n } while (0);\n}\n\n" +
+ "p10 < -326) || (310 < exp10)) {\n goto fallback;\n }\n\n // If both man and (10 ** exp10) are exactly representable by a double, we\n // don't need to run the Eisel-Lemire algorithm.\n if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) {\n double d = (double)man;\n if (exp10 >= 0) {\n d *= wuffs_base__private_implementation__f64_powers_of_10[+exp10];\n } else {\n d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10];\n }\n wuffs_base__result_f64 ret;\n ret.status.repr = NULL;\n ret.value = negative ? -d : +d;\n return ret;\n }\n\n // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire\n // preconditions include that man is non-zero. Parsing \"0\" should be caught\n // by the \"If both man and (10 ** exp10)\" above, but \"0e99\" might not.\n if (man == 0) {\n goto fallback;\n }\n\n // Our man and exp10 are in range. Run the Eisel-Lemire algorithm.\n int64_t r =\n wuffs_base__private_implementation__pa" +
+ "rse_number_f64_eisel_lemire(\n man, exp10);\n if (r < 0) {\n goto fallback;\n }\n wuffs_base__result_f64 ret;\n ret.status.repr = NULL;\n ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n ((uint64_t)r) | (((uint64_t)negative) << 63));\n return ret;\n } while (0);\n\nfallback:\n do {\n wuffs_base__private_implementation__high_prec_dec h;\n wuffs_base__status status =\n wuffs_base__private_implementation__high_prec_dec__parse(&h, s,\n options);\n if (status.repr) {\n return wuffs_base__private_implementation__parse_number_f64_special(\n s, options);\n }\n return wuffs_base__private_implementation__high_prec_dec__to_f64(&h,\n options);\n } while (0);\n}\n\n" +
"" +
"// --------\n\nstatic inline size_t //\nwuffs_base__private_implementation__render_inf(wuffs_base__slice_u8 dst,\n bool neg,\n uint32_t options) {\n if (neg) {\n if (dst.len < 4) {\n return 0;\n }\n wuffs_base__store_u32le__no_bounds_check(dst.ptr, 0x666E492D); // '-Inf'le.\n return 4;\n }\n\n if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {\n if (dst.len < 4) {\n return 0;\n }\n wuffs_base__store_u32le__no_bounds_check(dst.ptr, 0x666E492B); // '+Inf'le.\n return 4;\n }\n\n if (dst.len < 3) {\n return 0;\n }\n wuffs_base__store_u24le__no_bounds_check(dst.ptr, 0x666E49); // 'Inf'le.\n return 3;\n}\n\nstatic inline size_t //\nwuffs_base__private_implementation__render_nan(wuffs_base__slice_u8 dst) {\n if (dst.len < 3) {\n return 0;\n }\n wuffs_base__store_u24le__no_bounds_check(dst.ptr, 0x4E614E); // 'NaN'le.\n return 3;\n}\n\nstatic size_t //\nwuffs_base__private_implementation__high" +
"_prec_dec__render_exponent_absent(\n wuffs_base__slice_u8 dst,\n wuffs_base__private_implementation__high_prec_dec* h,\n uint32_t precision,\n uint32_t options) {\n size_t n = (h->negative ||\n (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN))\n ? 1\n : 0;\n if (h->decimal_point <= 0) {\n n += 1;\n } else {\n n += (size_t)(h->decimal_point);\n }\n if (precision > 0) {\n n += precision + 1; // +1 for the '.'.\n }\n\n // Don't modify dst if the formatted number won't fit.\n if (n > dst.len) {\n return 0;\n }\n\n // Align-left or align-right.\n uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)\n ? &dst.ptr[dst.len - n]\n : &dst.ptr[0];\n\n // Leading \"±\".\n if (h->negative) {\n *ptr++ = '-';\n } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {\n *ptr++ = '+';\n }\n\n // Integral digits.\n if (h->decimal_point <= 0) {\n *ptr++ = '0';\n } else {\n uint32_t m =\n" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 5c4395d..bd069d6 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -12221,9 +12221,8 @@
goto fallback;
}
- // If man and exp10 are small enough, all three of (man), (10 ** exp10) and
- // (man ** (10 ** exp10)) are exactly representable by a double. We don't
- // need to run the Eisel-Lemire algorithm.
+ // If both man and (10 ** exp10) are exactly representable by a double, we
+ // don't need to run the Eisel-Lemire algorithm.
if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) {
double d = (double)man;
if (exp10 >= 0) {
@@ -12239,7 +12238,7 @@
// The wuffs_base__private_implementation__parse_number_f64_eisel_lemire
// preconditions include that man is non-zero. Parsing "0" should be caught
- // by the "If man and exp10 are small enough" above, but "0e99" might not.
+ // by the "If both man and (10 ** exp10)" above, but "0e99" might not.
if (man == 0) {
goto fallback;
}