May be related to 1750. Plenty of details about how this was hit at : https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=247370 However on 32-bit Linux systems they all triggered a FE_INEXACT strangely for input 1 + 2^(-32) = 1.000000000232830643653869628906250 which is perfectly reasonable and all other reasonable ( and trivial ) test cases are fine. See test code in that FreeBSD bug report as well as a tarball with a test script. Here is a snippit from a Debian sid i686 server : . . . ---- 31 ---- 1.0000000004656612873077392578125000000000000000000000000000000000 ------------------------------------------------------------- system name = Linux node name = mars release = 5.8.0-rc1-genunix version = #1 SMP Mon Jun 15 04:57:18 UTC 2020 machine = i686 page size = 4096 avail memory = 782237696 = 763904 kB = 746 MB endian = little endian sizeof(unsigned long) = 4 sizeof(int) = 4 sizeof(void*) = 4 fp rounding mode is FE_TONEAREST ------------------------------------------------------------- INFO : seems like a decimal number +1.0000000004656612873077392578125 ---- 32 ---- 1.0000000002328306436538696289062500000000000000000000000000000000 ------------------------------------------------------------- system name = Linux node name = mars release = 5.8.0-rc1-genunix version = #1 SMP Mon Jun 15 04:57:18 UTC 2020 machine = i686 page size = 4096 avail memory = 782237696 = 763904 kB = 746 MB endian = little endian sizeof(unsigned long) = 4 sizeof(int) = 4 sizeof(void*) = 4 fp rounding mode is FE_TONEAREST ------------------------------------------------------------- INFO : FP Exception raised is FE_INEXACT WARN : FE_INEXACT returned by strtod() INFO : seems like a decimal number +1.00000000023283064365386962890625 ---- 33 ---- 1.0000000001164153218269348144531250000000000000000000000000000000 ------------------------------------------------------------- system name = Linux node name = mars release = 5.8.0-rc1-genunix version = #1 SMP Mon Jun 15 04:57:18 UTC 2020 machine = i686 page size = 4096 avail memory = 782237696 = 763904 kB = 746 MB endian = little endian sizeof(unsigned long) = 4 sizeof(int) = 4 sizeof(void*) = 4 fp rounding mode is FE_TONEAREST ------------------------------------------------------------- INFO : seems like a decimal number +1.000000000116415321826934814453125 . . . There you see that 1+2^(-31) is fine as well as 1+2^(-33) however the test in the middle for 1+2^(-32) triggers exception FE_INEXACT. Very strange. Same results on Kali Linux based on the armv7l architecture as well as even Debian sid on a VIA Eden Esther processor. Every reasonable variation of 1 + 2^( -n ) for n from 1 to 52 is perfect with the exception ( pun intended ) of n=32. Also for n>52 we see reasonable FE_INEXACT. I have not yet singled stepped may way through to see what is odd about n=32 but figured I could open a bug report. -- Dennis Clarke RISC-V/SPARC/PPC/ARM/CISC UNIX and Linux spoken GreyBeard and suspenders optional
The master branch has been updated by Joseph Myers <jsm28@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=09555b9721d090f7917f8221be2613a4d6a9b0f6 commit 09555b9721d090f7917f8221be2613a4d6a9b0f6 Author: Joseph Myers <joseph@codesourcery.com> Date: Tue Jun 30 23:04:06 2020 +0000 Fix strtod multiple-precision division bug (bug 26137). Bug 26137 reports spurious "inexact" exceptions from strtod, on 32-bit systems only, for a decimal argument that is exactly 1 + 2^-32. In fact the same issue also appears for 1 + 2^-64 and 1 + 2^-96 as arguments to strtof128 on 32-bit systems, and 1 + 2^-64 as an argument to strtof128 on 64-bit systems. In FE_DOWNWARD or FE_TOWARDZERO mode, the return value is also incorrect. The problem is in the multiple-precision division logic used in the case of dividing by a denominator that occupies at least three GMP limbs. There was a comment "The division does not work if the upper limb of the two-limb mumerator is greater than the denominator.", but in fact there were problems for the case of equality (that is, where the high limbs are equal, offset by some multiple of the GMP limb size) as well. In such cases, the code used "quot = ~(mp_limb_t) 0;" (with subsequent correction if that is an overestimate), because udiv_qrnnd does not support the case of equality, but it's possible for the shifted numerator to be greater than or equal to the denominator, in which case that is an underestimate. To avoid that, this patch changes the ">" condition to ">=", meaning the first division is done with a zero high word. The tests added are all 1 + 2^-n for n from 1 to 113 except for those that were already present in tst-strtod-round-data. Tested for x86_64 and x86.
Fixed for 2.32.
The master branch has been updated by Joseph Myers <jsm28@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c6aac3bf3663709cdefde5f5d5e9e875d607be5e commit c6aac3bf3663709cdefde5f5d5e9e875d607be5e Author: Joseph Myers <joseph@codesourcery.com> Date: Wed Jul 1 14:53:30 2020 +0000 Fix typo in comment in bug 26137 fix.