diff options
author | John L. Allen <allen@grumman.com> | 2006-03-30 12:53:13 -0500 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2006-04-03 08:50:28 +0000 |
commit | 3aaeb62467c14b38d6daaf18225526b68f56ae59 (patch) | |
tree | 085eef8dfc8b18c2cddca19c1b944f65d1e32642 /pp.c | |
parent | 8988a1bb3fb8fac6b97385be1a1d8b9945b1e29e (diff) | |
download | perl-3aaeb62467c14b38d6daaf18225526b68f56ae59.tar.gz |
revisited: pow.t test failures on AIX 5.1 perl588 with -Duselongdouble
From: "John L. Allen" <allen@grumman.com>
Message-ID: <Pine.GSO.4.53.0603301710140.24672@gateway.northropgrumman.com>
p4raw-id: //depot/perl@27698
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 40 |
1 files changed, 40 insertions, 0 deletions
@@ -998,7 +998,47 @@ PP(pp_pow) #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); |