Algorithm Search⌘K

Proofs: Clinger's correct decimal input

These are the human proofs of Clinger's correct decimal input, at full length.

Clinger's fast path and AlgorithmM return the correctly rounded binary64 number full

This proof shows: correctness.

Setting. Binary64: precision P=53P = 53, the smallest subnormal 2Kmin⁡2^{K_{\min}} with Kmin⁡=−1074K_{\min} = -1074, the largest finite number (2P−1) 2Kmax⁡(2^{P} - 1)\,2^{K_{\max}} with Kmax⁡=971K_{\max} = 971. RN\mathrm{RN} is rounding to nearest, ties to even, with the overflow rule of IEEE 754-2019 (Clause 7.4): the result is ∞\infty when the value rounded with an unbounded exponent range is at least 210242^{1024}. The input is a pair of integers f>0f > 0 and ee; the goal is RN(f⋅10e)\mathrm{RN}(f \cdot 10^{e}). Two facts about the format are used. (F1) If k≥Kmin⁡k \ge K_{\min}, then the floats in [2k+P−1,2k+P][2^{k + P - 1}, 2^{k + P}] are exactly the integer multiples of 2k2^{k} in that interval (for k+P−1≥−1022k + P - 1 \ge -1022 this is the binade of exponent k+P−1k + P - 1 and its upper end). (F2) The floats in [0,2−1022][0, 2^{-1022}] are exactly the integer multiples of 2Kmin⁡2^{K_{\min}} in that interval (the subnormals, zero and the smallest normal).

Lemma 1 (fast path, lines L2 and L3). If f<253f < 2^{53} and ∣e∣≤22|e| \le 22, then L3 returns RN(f⋅10e)\mathrm{RN}(f \cdot 10^{e}).

Proof. ff is an integer below 2532^{53}, so float(f)=f\mathrm{float}(f) = f exactly. For 0≤j≤220 \le j \le 22, 10j=5j2j10^{j} = 5^{j} 2^{j} and 5j≤522<2535^{j} \le 5^{22} < 2^{53}, so 10j10^{j} is a binary64 number and the table entry is exact. IEEE 754 multiplication and division return the correctly rounded value of the exact product or quotient of their operands (Clause 5.4.1), so the single operation returns RN(f⋅10j)\mathrm{RN}(f \cdot 10^{j}) or RN(f/10j)\mathrm{RN}(f / 10^{j}). No overflow or underflow occurs: f⋅1022<253⋅1022<2127f \cdot 10^{22} < 2^{53} \cdot 10^{22} < 2^{127} and f/1022≥10−22>2−74f / 10^{22} \ge 10^{-22} > 2^{-74}. □\square

Lemma 2 (scale, lines L5 and L6). Let u>0u > 0 and v>0v > 0 be integers, ℓu\ell_u and ℓv\ell_v their lengths in binary, and x=u/vx = u/v. After L6, 2P−1≤x/2k<2P2^{P - 1} \le x / 2^{k} < 2^{P}.

Proof. From 2ℓu−1≤u<2ℓu2^{\ell_u - 1} \le u < 2^{\ell_u} and 2ℓv−1≤v<2ℓv2^{\ell_v - 1} \le v < 2^{\ell_v} we get 2ℓu−ℓv−1<x<2ℓu−ℓv+12^{\ell_u - \ell_v - 1} < x < 2^{\ell_u - \ell_v + 1}, so with k=ℓu−ℓv−Pk = \ell_u - \ell_v - P (L5), 2P−1<x/2k<2P+12^{P - 1} < x/2^{k} < 2^{P + 1}. L6 computes ⌊x/2k⌋\lfloor x / 2^{k} \rfloor. If it is at least 2P2^{P}, then x/2k≥2Px / 2^{k} \ge 2^{P} and after k←k+1k \leftarrow k + 1 we have 2P−1≤x/2k<2P2^{P - 1} \le x / 2^{k} < 2^{P}. Otherwise x/2k<2Px / 2^{k} < 2^{P} already, since x/2k<⌊x/2k⌋+1≤2Px/2^k < \lfloor x/2^k \rfloor + 1 \le 2^{P}. □\square

Lemma 3 (the neighbors of xx). After L7, set q0=⌊x/2k⌋q_0 = \lfloor x / 2^{k} \rfloor. Then q02kq_0 2^{k} and (q0+1)2k(q_0 + 1) 2^{k} are consecutive numbers of the binary64 grid with an unbounded exponent range, and q02k≤x<(q0+1)2kq_0 2^{k} \le x < (q_0 + 1) 2^{k}.

Proof. The inequality holds by the definition of the floor. If L7 did not change kk, then k≥Kmin⁡k \ge K_{\min} and 2P−1≤q0<2P2^{P - 1} \le q_0 < 2^{P} by Lemma 2, so both points lie in [2k+P−1,2k+P][2^{k + P - 1}, 2^{k + P}], and by (F1), applied to the format without an upper exponent limit, the grid points there are exactly the multiples of 2k2^{k}. If L7 raised kk to Kmin⁡K_{\min}, then by Lemma 2 the old scale k′<Kmin⁡k' < K_{\min} gives x<2k′+P≤2Kmin⁡−1+P=2−1022x < 2^{k' + P} \le 2^{K_{\min} - 1 + P} = 2^{-1022}, so q0<2P−1q_0 < 2^{P - 1} and both points lie in [0,2−1022][0, 2^{-1022}], where by (F2) the floats are exactly the multiples of 2Kmin⁡2^{K_{\min}}. In both cases there is no grid point strictly between them. □\square

Lemma 4 (rounding, lines L8 and L9). After L9, q2kq 2^{k} is the grid point nearest to xx, with ties broken to the even significand.

Proof. L8 divides the integers num\mathit{num} and den\mathit{den} with num/den=x/2k\mathit{num}/\mathit{den} = x / 2^{k}, so q0q_0 is the quotient and x/2k=q0+r/denx / 2^{k} = q_0 + r/\mathit{den} with 0≤r<den0 \le r < \mathit{den}. By Lemma 3 the nearest grid point is q02kq_0 2^{k} if r/den<1/2r/\mathit{den} < 1/2, that is 2r<den2r < \mathit{den}, and (q0+1)2k(q_0 + 1) 2^{k} if 2r>den2r > \mathit{den}. If 2r=den2r = \mathit{den}, then xx is the midpoint, and IEEE ties to even picks the neighbor whose integral significand is even. For q0≥2P−1q_0 \ge 2^{P - 1} (normal case) and for q0<2P−1q_0 < 2^{P - 1} (subnormal case) the integral significand of q02kq_0 2^{k} is q0q_0 itself; if q0+1=2Pq_0 + 1 = 2^{P}, the upper neighbor is the power of two 2P−1⋅2k+12^{P - 1} \cdot 2^{k + 1} with even significand 2P−12^{P - 1}, and q0=2P−1q_0 = 2^P - 1 is odd; if q0+1=2P−1q_0 + 1 = 2^{P - 1} in the subnormal case, the upper neighbor is 2−10222^{-1022}, whose significand 2P−12^{P-1} is even, and q0q_0 is odd. In every case "the even one" is q0q_0 when q0q_0 is even and q0+1q_0 + 1 otherwise, which is the test of L9. The carry step rewrites 2P⋅2k2^{P} \cdot 2^{k} as 2P−1⋅2k+12^{P - 1} \cdot 2^{k + 1} without changing the value. □\square

Theorem. For integers f>0f > 0 and ee, clinger_read(f, e) returns RN(f⋅10e)\mathrm{RN}(f \cdot 10^{e}), including +∞+\infty on overflow and subnormal or zero results on underflow. With the sign applied afterwards, read_float returns the correctly rounded value of any decimal string it accepts, since RN(−y)=−RN(y)\mathrm{RN}(-y) = -\mathrm{RN}(y).

Proof. If L2 holds, Lemma 1 applies. Otherwise L4 forms uu and vv with u/v=f⋅10eu / v = f \cdot 10^{e} exactly: u=f⋅10eu = f \cdot 10^{e} and v=1v = 1 for e≥0e \ge 0, u=fu = f and v=10−ev = 10^{-e} for e<0e < 0. By Lemma 4, after L9 the value q2kq 2^{k} is the rounding of xx to the binary64 grid with an unbounded exponent range, with q≤2P−1q \le 2^{P} - 1 after the carry step and k≥Kmin⁡k \ge K_{\min}. If k≤Kmax⁡k \le K_{\max}, then q2k≤(2P−1)2Kmax⁡q 2^{k} \le (2^{P} - 1) 2^{K_{\max}} is a finite float, and ldexp returns it exactly. If k>Kmax⁡k > K_{\max}, then q≥2P−1q \ge 2^{P - 1} (the case q<2P−1q < 2^{P-1} occurs only with k=Kmin⁡k = K_{\min}), so q2k≥2P−1+Kmax⁡+1=21024q 2^{k} \ge 2^{P - 1 + K_{\max} + 1} = 2^{1024}, and the IEEE overflow rule for rounding to nearest gives +∞+\infty, which L10 returns. ■\blacksquare

Remarks. The proof uses only exact integer arithmetic in AlgorithmM, so it holds for any number of digits and any exponent; the cost, not the correctness, grows with them. Lemma 1 is the only place where floating-point operations are used, and it needs the processor to round binary64 operations once, to binary64 precision; on x87 hardware with 64-bit internal precision the fast path can round twice (double rounding).

Back to Clinger's correct decimal input