Jarkko Hietaniemi via RT wrote:
>
http://perl5.git.perl.org/perl.git/commit/b6d9b423fab1963346eb79e83b356114396b1f2e
When I first reviewed this, before Jarkko merged it to blead, I thought
it fixed the problem, and declared it good. Actually it's not correct:
it's changed the problem into a different form. Sorry for not spotting
it first time.
With IEEE double:
$ perl -lwe 'printf "%a\n", 0x1.fffffffffffffp-1022'
0x1.fffffffffffffp-1022
$ perl -lwe 'printf "%a\n", 0x0.fffffffffffffp-1022'
0x1.fffffffffffffp-1023
$ perl -lwe 'printf "%a\n", 0x0.7ffffffffffffp-1022'
0x1.7ffffffffffffp-1024
$ perl -lwe 'printf "%a\n", 0x0.3ffffffffffffp-1022'
0x1.3ffffffffffffp-1025
$ perl -lwe 'printf "%a\n", 0x0.1ffffffffffffp-1022'
0x1.1ffffffffffffp-1026
$ perl -lwe 'printf "%a\n", 0x0.0ffffffffffffp-1022'
0x1.fffffffffffep-1027
The first one here (which is normalised) is OK, but the subnormals
have gone awry. The second should be "0x1.ffffffffffffep-1023",
the third should be "0x1.ffffffffffffcp-1024", the fourth
should be "0x1.ffffffffffff8p-1025", and the fifth should be
"0x1.ffffffffffffp-1026". The sixth output, also subnormal, is correct.
Smaller subnormals of the same pattern are all correct, down to the
smallest positive value.
All of the incorrect ones have the pattern of showing a normalised-style
integer part and exponent but the fractional part from subnormal style.
That's precisely what was wrong originally for all subnormals.
As far as I can see, the problem arises with any magnitude in the range
[2**-1026, 2**-1022), and not for anything outside that range. I expect
that the reason for exactly four binary orders of magnitude being affected
is down to that being a single order of magnitude of the output radix.
With x86 80-bit long double, the behaviour is stranger:
$ perl -lwe 'printf "%a\n", 0x1.fffffffffffffffep0 * 2**-16382'
Hexadecimal float: mantissa overflow at -e line 1.
0xf.fffffffffffffffp-16385
$ perl -lwe 'printf "%a\n", 0x0.fffffffffffffffep0 * 2**-16382'
0x7.fffffffffffffffp-16386
$ perl -lwe 'printf "%a\n", 0x0.7ffffffffffffffep0 * 2**-16382'
0x3.fffffffffffffffp-16387
$ perl -lwe 'printf "%a\n", 0x0.3ffffffffffffffep0 * 2**-16382'
0x1.fffffffffffffffp-16388
$ perl -lwe 'printf "%a\n", 0x0.1ffffffffffffffep0 * 2**-16382'
0x0.fffffffffffffffp-16389
$ perl -lwe 'printf "%a\n", 0x0.0ffffffffffffffep0 * 2**-16382'
0x0.7ffffffffffffffp-16390
$ perl -lwe 'printf "%a\n", 0x0.07fffffffffffffep0 * 2**-16382'
0x0.3ffffffffffffffp-16391
$ perl -lwe 'printf "%a\n", 0x0.03fffffffffffffep0 * 2**-16382'
0x0.1ffffffffffffffp-16392
$ perl -lwe 'printf "%a\n", 0x0.01fffffffffffffep0 * 2**-16382'
0x0.0ffffffffffffffp-16393
$ perl -lwe 'printf "%a\n", 0x0.00fffffffffffffep0 * 2**-16382'
0x0.07fffffffffffffp-16394
Subnormals here are consistently showing the integer and fractional
part from subnormal style but the exponent of normalised style. This is
different from the manifestation that was seen with IEEE double. 5.24.0
shows the same behaviour as blead here. Thus the manifestation of the
subnormal problem was always different depending on the NV format, and
Jarkko's patch hasn't affected the behaviour on x86 80-bit long double.
Things get even weirder for certain subnormals in this format:
$ perl -lwe 'printf "%a\n", 0x0.1000000000000000p0 * 2**-16382'
0x08p-16389
$ perl -lwe 'printf "%a\n", 0x0.1e00000000000000p0 * 2**-16382'
0x0fp-16389
$ perl -lwe 'printf "%a\n", 0x0.0000000000000040p0 * 2**-16382'
0x000000000000002p-16443
$ perl -lwe 'printf "%a\n", 0x0.0000000000000020p0 * 2**-16382'
0x000000000000001p-16444
$ perl -lwe 'printf "%a\n", 0x0.000000000000001ep0 * 2**-16382'
0x000000000000000fp-16445
Where only one output hex digit is non-zero, in addition to the initial
subnormal bug the output is missing its radix point. This too hasn't
changed between 5.24.0 and blead. This is presumably because if the
values were output correctly normalised these ones would not require a
radix point.
-zefram