This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, libgcc, ARM] __gnu_f2h_internal inaccuracy
- From: John Tytgat <john at bass-software dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: ian at airs dot com, nickc at redhat dot com, richard dot earnshaw at arm dot com, paul at codesourcery dot com, ramana dot radhakrishnan at arm dot com
- Date: Tue, 27 Nov 2012 01:40:10 +0100
- Subject: [PATCH, libgcc, ARM] __gnu_f2h_internal inaccuracy
__gnu_f2h_internal in libgcc converts single-precision floating-point value
to half-precision value for ARM. I noticed there is a slight inaccuracy
for floating-point values 2^-25 + epsilon (with epsilon > 0 and < 2^-26).
Those should all be converted to 2^-24 in half-precision.
And this because the mask used to implement the even-odd rounding for
aexp = -25 is wrong. Currently we have:
/* Decimal point between bits 22 and 23. */
mantissa |= 0x00800000;
if (aexp < -14)
{
mask = 0x007fffff;
if (aexp < -25)
aexp = -26;
else if (aexp != -25)
mask >>= 24 + aexp;
}
else
mask = 0x00001fff;
But when aexp is 25 the mask should be 0xffffff instead of 0x7fffff as the
decimal dot in half-precision will be between bit 24 and 23 of the
above mentioned mantissa. Cfr. the even-odd rounding done:
/* Round. */
if (mantissa & mask)
{
increment = (mask + 1) >> 1;
if ((mantissa & mask) == increment)
increment = mantissa & (increment << 1);
mantissa += increment;
if (mantissa >= 0x01000000)
{
mantissa >>= 1;
aexp++;
}
}
Attached patch solves this problem. I've left out the clamping of
aexp to -26 for values less than -25 as this it not necessary. After
the even-odd rounding all aexp values less than -24 will result in +0. or
-0. anyway.
John Tytgat <John@bass-software.com>
* config/arm/fp16.c (__gnu_f2h_internal): Fix inaccuracy.
I've got a copyright assignment but no write access.
John Tytgat.
--
John Tytgat BASS
John@bass-software.com