Skip to content

Commit a574c02

Browse files
committed
trim devnote
1 parent ee40e6d commit a574c02

1 file changed

Lines changed: 9 additions & 35 deletions

File tree

src/csrc/utilities.c

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -138,42 +138,16 @@ cstring_to_quad_internal(const char *str, const char *start, QuadBackendType bac
138138
memcpy(temp, str, len);
139139
temp[len] = '\0';
140140

141-
// Call Sleef_strtoq with the bounded string
141+
// Call Sleef_strtoq with the bounded string.
142142
//
143-
// DEVELOPER NOTE - Sleef_strtoq decimal precision limit.
144-
// The decimal branch of Sleef_strtoq is NOT correctly-rounded. It
145-
// accumulates digits (n = n*10 + d) into SLEEF's triple-double "tdx"
146-
// format (a 64-bit exponent + vdouble3 mantissa, ~159 mantissa bits),
147-
// scales by exp10i() and rounds via cast_vq_tdx(). Only the hex (0x...)
148-
// branch is exact bit-manipulation.
149-
//
150-
// Three different digit counts are involved - do NOT conflate them:
151-
// * ~34 = a quad's actual precision (113 * log10(2))
152-
// * 36 = digits that GUARANTEE any quad round-trips; this is
153-
// SLEEF_QUAD_DECIMAL_DIG and the most Dragon4 (str/repr) emits
154-
// * ~48 = the tdx mantissa's raw capacity (159 bits / log2(10))
155-
// * ~45 = the EFFECTIVE window this parser resolves correctly - a few
156-
// digits below 48 because the tdx add/mul/div/exp10i are not
157-
// perfectly rounded. Property of the parser, not of quads.
158-
//
159-
// ~45 is NOT a hard/coded limit: it is a soft, build-dependent threshold,
160-
// and it is measured (empirical), not read from a constant. Sweeping
161-
// genuine quads across the exponent range, the smallest k at which
162-
// nudging a half-ULP midpoint by 10^-k gets silently dropped (rounds the
163-
// wrong way) was 45 (some values tolerate 46-48). Inputs longer than the
164-
// window are still read - the extra digits just stop reliably affecting
165-
// the result. So if the digit that decides rounding sits at position
166-
// >= ~46 - e.g. a value just above a midpoint - the result can be 1 ULP
167-
// off. Concrete repro
168-
// (SLEEF 3.9.0, x86): the ~46-digit-deep value near
169-
// "1.99999...9997111...e0" parses to ...ffffe, not the correct ...fffff.
170-
//
171-
// Practical impact on quad<->string round-trips: none here. Every quad
172-
// is captured by <= 36 digits, ~9 below the ~45 window, so Dragon4
173-
// output re-parses exactly. BUT that ~45 is FMA-/codegen-dependent (the
174-
// tdx arithmetic can lose a guard bit on some toolchains, e.g. macOS)
175-
// and can shrink toward 36 - so do not rely on string parsing for
176-
// exactness. Binary paths (raw bytes) are always exact.
143+
// NOTE: SLEEF's decimal strtoq is only non-correctly-rounded for inputs
144+
// whose *significant* digits exceed what a quad can hold (>~45); there it
145+
// may be <= 1 ULP off. This is unreachable for quad<->string round-trips:
146+
// every quad is exact within SLEEF_QUAD_DECIMAL_DIG (36) significant
147+
// digits and Dragon4 (str/repr) emits <= 36, so re-parsing is exact. Only
148+
// significant digits count - magnitude/exponent (e.g. 1e4932) is scaled
149+
// separately and is fine. Pickling uses raw bytes (from_raw_bytes), which
150+
// never goes through this path.
177151
char *sleef_endptr;
178152
out_value->sleef_value = Sleef_strtoq(temp, &sleef_endptr);
179153
free(temp);

0 commit comments

Comments
 (0)