This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl #126396 IRIX longdouble infinity issues
authorJarkko Hietaniemi <jhi@iki.fi>
Mon, 19 Oct 2015 02:30:43 +0000 (22:30 -0400)
committerJarkko Hietaniemi <jhi@iki.fi>
Mon, 19 Oct 2015 13:08:44 +0000 (09:08 -0400)
In IRIX longdouble (which uses the double-double format, bigendian)
multiplying with infinity introduces garbage bytes to the second double
of the double-double.

This garbage, in turn, seems to tickle another bug in long doubles,
in comparing infinities, where these garbage bytes errorneously matter
when they should not.

Workaround: zero these garbage bytes in multiplication.

The garbage bytes seem to appear only the multiplication, as far as
t/op/infnan.t can detect.

Even though we could place the multiplication result to a temporary NV
variable (for easier infiniteness inspection) for all the platforms and
depend on optimizer doing away with the temporary, let's be conservative.

pp.c

diff --git a/pp.c b/pp.c
index 6e9995a..b084d49 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1394,7 +1394,17 @@ PP(pp_multiply)
       NV right = SvNV_nomg(svr);
       NV left  = SvNV_nomg(svl);
       (void)POPs;
+#if defined(__sgi) && defined(USE_LONG_DOUBLE) && LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN && NVSIZE == 16
+      {
+          NV result = left * right;
+          if (Perl_isinf(result)) {
+              Zero((U8*)&result + 8, 8, U8);
+          }
+          SETn( result );
+      }
+#else
       SETn( left * right );
+#endif
       RETURN;
     }
 }