This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
bz1311954 - multilib variations in LC_COLLATE files, with fixes
- From: DJ Delorie <dj at redhat dot com>
- To: libc-alpha at sourceware dot org
- Date: Wed, 20 Mar 2019 14:25:40 -0400
- Subject: bz1311954 - multilib variations in LC_COLLATE files, with fixes
https://bugzilla.redhat.com/show_bug.cgi?id=1311954
Fedora BZ 1311954 saw that the locale archives were not the same
across all builds; partly that was due to big vs little endian, but
there were differences between 32 and 64-bit on both s390 and x86.
In locale/programs/ld-collate.c we see this:
/* Add 40% and find the next prime number. */
elem_size = next_prime (elem_size * 1.4);
After debugging this for a week, it turned out that when elem_size is
120, "elem_size * 1.4" is 168 - but not exactly 168. Since 1.4 isn't
exactly representable in IEEE, the result was either 168.00000001 or
167.9999999 - and it turns out that 167 *is prime* so the next_prime()
call returned completely different results depending on the FPU and
rounding.
The solution is to avoid floating point math.
Since elem_size is limited by locale limits, overflow isn't much of a
problem. There are a couple of simple changes, but which to choose?
/* Same value as before, but "/10" isn't exact */
elem_size = next_prime (elem_size * 14/10);
/* Slightly different value (37.5%) but now it's exact */
elem_size = next_prime (elem_size * 11/8);
/* Same as above, but without extra chance of overflow */
elem_size = next_prime (elem_size + (elem_size>>2) + (elem_size>>3));
Note this math also happens in ./iconv/iconvconfig.c:
hash_size = next_prime (nnames * 1.4);