Front page | perl.perl5.porters |
Postings from March 2006
revisited: pow.t test failures on AIX 5.1 perl588 with -Duselongdouble
Thread Next
From:
John L. Allen
Date:
March 30, 2006 14:53
Subject:
revisited: pow.t test failures on AIX 5.1 perl588 with -Duselongdouble
Message ID:
Pine.GSO.4.53.0603301710140.24672@gateway.northropgrumman.com
Well, it's three+ weeks since I reported the powl() bug to IBM, and of
course they have not provided a fix yet, so I was forced to write the
following patch to pp.c. Hopefully it conforms to everyone's patching
standards - I did my best. The extra code to make powl() work correctly
is only compiled in when both USE_LONG_DOUBLE and
HAS_AIX_POWL_NEG_BASE_BUG are set. Nicholas Clark's intent was to
provide a Configure probe to look for the problem and set
HAS_AIX_POWL_NEG_BASE_BUG if found. I wrote a short C program to evince
the bug in a prior thread. I hope it can still be integrated into
Configure. I'll be happy to test it.
As for this patch to pp.c, my only regret is that I call fmod() to
determine if the exponent is an odd/even integer. If someone knows a
better way, please chime in, but be aware that it has to work for
long double "integers" too large to fit in a long long integer.
There is one other change I'd like to make: that is, to t/op/pow.t. In
order for it to be a able to uncover this problem, it needs to raise -3 to
a power higher than 32. Currently it tops out at -3**29 because of not
wanting to produce a result greater than 2**48 for Cray's benefit. What
is the best way to skip such higher power tests on a Cray?
Here's the gdiff -u patch:
--- pp.c.orig Sun Jan 8 15:58:55 2006
+++ pp.c Thu Mar 30 16:35:36 2006
@@ -1014,7 +1014,47 @@
#endif
{
dPOPTOPnnrl;
+
+#if defined(USE_LONG_DOUBLE) && defined(HAS_AIX_POWL_NEG_BASE_BUG)
+ /*
+ We are building perl with long double support and are on an AIX OS
+ afflicted with a powl() function that wrongly returns NaNQ for any
+ negative base. This was reported to IBM as PMR #23047-379 on
+ 03/06/2006. The problem exists in at least the following versions
+ of AIX and the libm fileset, and no doubt others as well:
+
+ AIX 4.3.3-ML10 bos.adt.libm 4.3.3.50
+ AIX 5.1.0-ML04 bos.adt.libm 5.1.0.29
+ AIX 5.2.0 bos.adt.libm 5.2.0.85
+
+ So, until IBM fixes powl(), we provide the following workaround to
+ handle the problem ourselves. Our logic is as follows: for
+ negative bases (left), we use fmod(right, 2) to check if the
+ exponent is an odd or even integer:
+
+ - if odd, powl(left, right) == -powl(-left, right)
+ - if even, powl(left, right) == powl(-left, right)
+
+ If the exponent is not an integer, the result is rightly NaNQ, so
+ we just return that (as NV_NAN).
+ */
+
+ if (left < 0.0) {
+ NV mod2 = Perl_fmod( right, 2.0 );
+ if (mod2 == 1.0 || mod2 == -1.0) { /* odd integer */
+ SETn( -Perl_pow( -left, right) );
+ } else if (mod2 == 0.0) { /* even integer */
+ SETn( Perl_pow( -left, right) );
+ } else { /* fractional power */
+ SETn( NV_NAN );
+ }
+ } else {
+ SETn( Perl_pow( left, right) );
+ }
+#else
SETn( Perl_pow( left, right) );
+#endif /* HAS_AIX_POWL_NEG_BASE_BUG */
+
#ifdef PERL_PRESERVE_IVUV
if (is_int)
SvIV_please(TOPs);
Thread Next
-
revisited: pow.t test failures on AIX 5.1 perl588 with -Duselongdouble
by John L. Allen