@@ -139,6 +139,41 @@ cstring_to_quad_internal(const char *str, const char *start, QuadBackendType bac
139139 temp [len ] = '\0' ;
140140
141141 // Call Sleef_strtoq with the bounded string
142+ //
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.
142177 char * sleef_endptr ;
143178 out_value -> sleef_value = Sleef_strtoq (temp , & sleef_endptr );
144179 free (temp );
0 commit comments