Issue15477
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2012-07-28 10:03 by ned.deily, last changed 2022-04-11 14:57 by admin. This issue is now closed.
Files | ||||
---|---|---|---|---|
File name | Uploaded | Description | Edit | |
issue15477.patch | trent, 2012-08-17 19:39 | review | ||
log1p_sign_workaround.patch | mark.dickinson, 2012-08-18 09:21 | review |
Messages (21) | |||
---|---|---|---|
msg166642 - (view) | Author: Ned Deily (ned.deily) * | Date: 2012-07-28 10:03 | |
====================================================================== FAIL: testAtanSign (test.test_cmath.CMathTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/test/test_cmath.py", line 526, in testAtanSign self.assertComplexIdentical(cmath.atan(z), z) File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/test/test_cmath.py", line 96, in assertComplexIdentical self.assertFloatIdentical(x.imag, y.imag) File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/test/test_cmath.py", line 86, in assertFloatIdentical self.fail(msg.format(x, y)) AssertionError: floats -0.0 and 0.0 are not identical: zeros have different signs ====================================================================== FAIL: testAtanhSign (test.test_cmath.CMathTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/test/test_cmath.py", line 533, in testAtanhSign self.assertComplexIdentical(cmath.atanh(z), z) File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/test/test_cmath.py", line 95, in assertComplexIdentical self.assertFloatIdentical(x.real, y.real) File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/test/test_cmath.py", line 86, in assertFloatIdentical self.fail(msg.format(x, y)) AssertionError: floats 0.0 and -0.0 are not identical: zeros have different signs ====================================================================== FAIL: test_specific_values (test.test_cmath.CMathTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/test/test_cmath.py", line 382, in test_specific_values msg=error_message) File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/test/test_cmath.py", line 128, in rAssertAlmostEqual 'got {!r}'.format(a, b)) AssertionError: atan1000: atan(complex(-0.0, 0.0)) Expected: complex(-0.0, 0.0) Received: complex(-0.0, -0.0) Received value insufficiently close to expected value. ---------------------------------------------------------------------- Failures seen across various compilers and deployment targets and running the tests with the same binaries on earlier OS X versions do not fail. FWIW, the Apple-supplied Python 2.7.2 in 10.8 (that's the most recent version supplied) also has a test_cmath failure: ====================================================================== FAIL: test_specific_values (test.test_cmath.CMathTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/test/test_cmath.py", line 352, in test_specific_values msg=error_message) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/test/test_cmath.py", line 94, in rAssertAlmostEqual 'got {!r}'.format(a, b)) AssertionError: atan0000: atan(complex(0.0, 0.0)) Expected: complex(0.0, 0.0) Received: complex(0.0, -0.0) Received value insufficiently close to expected value. ---------------------------------------------------------------------- Is there any reason to not consider this a platform bug? If it is, what should the bug report be? |
|||
msg166648 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-07-28 11:49 | |
Judging by previous reports of this type, it's probably either a bug in the platform math library or a compiler optimization bug (or possibly a combination of the two: one previous OS X bug involved calls to sin / cos being 'optimized' to a badly implemented single call to cexp). I assume the failure still happens in debug mode? If so, a math library bug seems more likely. Are there any math module failures? It's not immediately obvious what the bug is, since the cmath module functions are not just simple wrappers around library functions. In this case it looks like either atan2 or log1p is doing the wrong thing with signs of zeros. What do math.log1p(0.0) and math.log1p(-0.0) give? (Answers *should* be 0.0 and -0.0 respectively.) |
|||
msg166649 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-07-28 11:51 | |
Also: what's HAVE_LOG1P for this build? |
|||
msg166691 - (view) | Author: Ned Deily (ned.deily) * | Date: 2012-07-28 21:01 | |
> I assume the failure still happens in debug mode? Yes > Are there any math module failures? No > What do math.log1p(0.0) and math.log1p(-0.0) give? (Answers *should* be 0.0 and -0.0 respectively.) >>> math.log1p(0.0) 0.0 >>> math.log1p(-0.0) 0.0 >>> sysconfig.get_config_var('HAVE_LOG1P') 1 |
|||
msg166698 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-07-28 22:17 | |
>>> math.log1p(0.0) 0.0 >>> math.log1p(-0.0) 0.0 Ah, that would do it, then. It looks as though the system's log1p function is buggy, in the sense that it doesn't follow C99 Annex F (F.9.3.9). It also doesn't agree with what 'man log1p' says on my OS X 10.6 Macbook: under 'SPECIAL VALUES', it says: 'log1p(+-0) returns +-0.' I'm puzzled about one thing, though: there's a test for this problem in the configure script, and LOG1P_DROPS_ZERO_SIGN should be defined in this case---in that case, the two testAtanSign and testAtanhSign tests are skipped. So it looks as though LOG1P_DROPS_ZERO_SIGN isn't being defined on this machine; I'm not sure why---there may be a compiler optimization kicking in in the configure test. (Is this clang or gcc, BTW?) So definitely worth a bug report, I'd say, though perhaps it's too much to hope for a fix within the lifetime of 10.8. |
|||
msg166700 - (view) | Author: Ned Deily (ned.deily) * | Date: 2012-07-28 23:18 | |
>>It also doesn't agree with what 'man log1p' says on my OS X 10.6 >>Macbook: under 'SPECIAL VALUES', it says: 'log1p(+-0) returns +-0.' That manpage is unchanged for 10.8. >>I'm puzzled about one thing, though: there's a test for this problem >>in the configure script, and LOG1P_DROPS_ZERO_SIGN should be defined in >>this case---in that case, the two testAtanSign and testAtanhSign tests >>are skipped. So it looks as though LOG1P_DROPS_ZERO_SIGN isn't being >>defined on this machine; I'm not sure why---there may be a compiler >>optimization kicking in in the configure test. Ah, this rings a bell and points out yet another issue: 1. The configure test is working properly: when run on 10.8, LOG1P_DROPS_ZERO_SIGN is set to 1. However, something I just ran into recently, the unittest skip idiom using sysconfig.get_config_vars results - as is being used here in test_cmath - doesn't seem to work properly. I see it is used in test_math and test_subprocess as well. I'll look into that. 2. These types of run-time tests based on configure-time tests are problematic for binary installations of Python, like the OS X installers. For example, the OS X installers are built on earlier versions of OS X where a configuration test (like this one) may have one result but not necessarily the same result on all supported target configurations where the binary Pythons may be installed. And, in general, multiple-architecture builds, in particular, OS X universal builds may have different configuration values per architecture embedded in one executable (i386 vs x86_64 or i386 vs ppc or i386 vs x86_64 vs ppc) that are not reflected in the single architecture ./configure results. I guess it's time to open an issue on that can of worms. >>(Is this clang or gcc, BTW?) It's clang which is now the only supported option with Xcode 4.4 on either 10.7 or 10.8. More importantly, 10.8 is the first OS X release which itself was built with clang; 10.7 was built with the transitional llvm-gcc compiler. |
|||
msg166729 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-07-29 09:04 | |
> These types of run-time tests based on configure-time tests are problematic > for binary installations of Python, like the OS X installers. Understood. I'm wondering how to fix this for Python, given that we're unlikely to see an OS-level fix for a while. There's an easy workaround, namely to add an "if (x == 0.0) return x;" before any use of the system log1p; the issue is how and when to apply this workaround. One option is always to apply the workaround, but this feels to me as though it's unnecessarily penalising those OSs that get it right; maybe just always apply the workaround on OS X? |
|||
msg168445 - (view) | Author: Martin v. Löwis (loewis) * | Date: 2012-08-17 14:03 | |
Without looking into the details of the issue: conditionalizing a work-around on OSX sounds right. On the one hand, it may penalize OSX releases which get it right. OTOH, it's all Apple's fault (IIUC), so they deserve it :-) Further, using a build-time check for the OS release is inappropriate, since the binary should work on other releases as well; a run-time check is probably more costly than the work-around. |
|||
msg168470 - (view) | Author: Trent Nelson (trent) * | Date: 2012-08-17 19:39 | |
I ran into this last night and posted to python-dev before realizing this bug had been raised: http://mail.python.org/pipermail/python-dev/2012-August/121359.html I'll reproduce it here as I made a few observations that haven't yet been mentioned in this issue: The Mountain Lion build slave I set up earlier this evening fails on test_cmath: ====================================================================== FAIL: test_specific_values (test.test_cmath.CMathTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Volumes/bay2/buildslave/cpython/2.7.snakebite-mountainlion-amd64/build/Lib/test/test_cmath.py", line 352, in test_specific_values msg=error_message) File "/Volumes/bay2/buildslave/cpython/2.7.snakebite-mountainlion-amd64/build/Lib/test/test_cmath.py", line 94, in rAssertAlmostEqual 'got {!r}'.format(a, b)) AssertionError: atan0000: atan(complex(0.0, 0.0)) Expected: complex(0.0, 0.0) Received: complex(0.0, -0.0) Received value insufficiently close to expected value. Mountain Lion's atan/log1p appear to drop the negative sign when passed in -0.0, whereas previous versions of OS X didn't: Mountain Lion: % ~/log1p-viper log1p_drops_zero_sign_test: atan2(log1p(-0.), -1.) != atan2(-0., -1.) 3.14159 vs -3.14159 atan_drops_zero_sign_test: atan2(-0., 0.): -0.00000 atan2( 0., -0.): 3.14159 atan2(-0., -0.): -3.14159 atan2( 0., 0.): 0.00000 log1p(-0.): 0.00000 log1p( 0.): 0.00000 Lion: % ./log1p log1p_drops_zero_sign_test: atan2(log1p(-0.), -1.) == atan2(-0., -1.) -3.14159 vs -3.14159 atan_drops_zero_sign_test: atan2(-0., 0.): -0.00000 atan2( 0., -0.): 3.14159 atan2(-0., -0.): -3.14159 atan2( 0., 0.): 0.00000 log1p(-0.): -0.00000 log1p( 0.): 0.00000 (The C code for that is below.) configure.ac already has a test for this (it makes mention of AIX having similar behaviour), and the corresponding sysconfig entry named 'LOG1P_DROPS_ZERO_SIGN' is already being used on a few tests, i.e.: # The algorithm used for atan and atanh makes use of the system # log1p function; If that system function doesn't respect the sign # of zero, then atan and atanh will also have difficulties with # the sign of complex zeros. @requires_IEEE_754 @unittest.skipIf(sysconfig.get_config_var('LOG1P_DROPS_ZERO_SIGN'), "system log1p() function doesn't preserve the sign") def testAtanSign(self): for z in complex_zeros: self.assertComplexIdentical(cmath.atan(z), z) @requires_IEEE_754 @unittest.skipIf(sysconfig.get_config_var('LOG1P_DROPS_ZERO_SIGN'), "system log1p() function doesn't preserve the sign") def testAtanhSign(self): for z in complex_zeros: self.assertComplexIdentical(cmath.atanh(z), z) Taking a look at cmath_testcases.txt, and we can see this: -- These are tested in testAtanSign in test_cmath.py -- atan0000 atan 0.0 0.0 -> 0.0 0.0 -- atan0001 atan 0.0 -0.0 -> 0.0 -0.0 -- atan0002 atan -0.0 0.0 -> -0.0 0.0 -- atan0003 atan -0.0 -0.0 -> -0.0 -0.0 However, a few lines down, those tests crop up again: -- special values atan1000 atan -0.0 0.0 -> -0.0 0.0 <snip> atan1014 atan 0.0 0.0 -> 0.0 0.0 ....which is what causes the current test failures. I hacked test_cmath.py a bit to spit out all the errors it finds after it's finished parsing the test file (instead of bombing out on the first one), and it yielded this: FAIL: test_specific_values (test.test_cmath.CMathTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Volumes/bay2/buildslave/cpython/3.2.snakebite-mountainlion-amd64/build/Lib/test/test_cmath.py", line 446, in test_specific_values self.fail("\n".join(failures)) AssertionError: atan1000: atan(complex(-0.0, 0.0)) Expected: complex(-0.0, 0.0) Received: complex(-0.0, -0.0) Received value insufficiently close to expected value. atan1014: atan(complex(0.0, 0.0)) Expected: complex(0.0, 0.0) Received: complex(0.0, -0.0) Received value insufficiently close to expected value. atanh0225: atanh(complex(-0.0, 5.6067e-320)) Expected: complex(-0.0, 5.6067e-320) Received: complex(0.0, 5.6067e-320) Received value insufficiently close to expected value. atanh0227: atanh(complex(-0.0, -3.0861101e-316)) Expected: complex(-0.0, -3.0861101e-316) Received: complex(0.0, -3.0861101e-316) Received value insufficiently close to expected value. atanh1024: atanh(complex(-0.0, -0.0)) Expected: complex(-0.0, -0.0) Received: complex(0.0, -0.0) Received value insufficiently close to expected value. atanh1034: atanh(complex(-0.0, 0.0)) Expected: complex(-0.0, 0.0) Received: complex(0.0, 0.0) Received value insufficiently close to expected value. This is the patch I came up with against test_cmath.py: xenon% hg diff Lib/test/test_cmath.py diff -r ce49599b9fdf Lib/test/test_cmath.py --- a/Lib/test/test_cmath.py Thu Aug 16 22:14:43 2012 +0200 +++ b/Lib/test/test_cmath.py Fri Aug 17 07:54:05 2012 +0000 @@ -121,8 +121,10 @@ # if both a and b are zero, check whether they have the same sign # (in theory there are examples where it would be legitimate for a # and b to have opposite signs; in practice these hardly ever - # occur). - if not a and not b: + # occur) -- the exception to this is if we're on a system that drops + # the sign on zeros. + drops_zero_sign = sysconfig.get_config_var('LOG1P_DROPS_ZERO_SIGN') + if not drops_zero_sign and not a and not b: if math.copysign(1., a) != math.copysign(1., b): self.fail(msg or 'zero has wrong sign: expected {!r}, ' 'got {!r}'.format(a, b)) With that applied, all the test_cmath tests pass again (without any changes to the test file). Thoughts? Trent. -- C code for the example earlier: #include <math.h> #include <stdlib.h> int main(int argc, char **argv) { printf("\nlog1p_drops_zero_sign_test:\n"); if (atan2(log1p(-0.), -1.) == atan2(-0., -1.)) printf(" atan2(log1p(-0.), -1.) == atan2(-0., -1.)\n"); else printf(" atan2(log1p(-0.), -1.) != atan2(-0., -1.)\n"); printf( " %.5f vs %.5f\n", atan2(log1p(-0.), -1.), atan2(-0., -1.) ); printf("\natan_drops_zero_sign_test:\n"); printf(" atan2(-0., 0.): %0.5f\n", atan2(-0., 0.)); printf(" atan2( 0., -0.): %0.5f\n", atan2( 0., -0.)); printf(" atan2(-0., -0.): %0.5f\n", atan2(-0., -0.)); printf(" atan2( 0., 0.): %0.5f\n", atan2( 0., 0.)); printf(" log1p(-0.): %0.5f\n", log1p(-0.)); printf(" log1p( 0.): %0.5f\n", log1p( 0.)); } /* vim:set ts=8 sw=4 sts=4 tw=78 et: */ After thinking about it a bit longer, I think patching rAssertAlmostEqual is unnecessarily hacky. The problem is that the 'special value' atan tests in the cmath test file shouldn't have any zero tests -- these are handled in testAtanSign, which is what cmath_testcase.txt states: --------------------------- -- atan: Inverse tangent -- --------------------------- -- zeros -- These are tested in testAtanSign in test_cmath.py -- atan0000 atan 0.0 0.0 -> 0.0 0.0 -- atan0001 atan 0.0 -0.0 -> 0.0 -0.0 -- atan0002 atan -0.0 0.0 -> -0.0 0.0 -- atan0003 atan -0.0 -0.0 -> -0.0 -0.0 So, given, that, let's review the affected tests further down in cmath_testcase.txt: AssertionError: atan1000: atan(complex(-0.0, 0.0)) Expected: complex(-0.0, 0.0) Received: complex(-0.0, -0.0) Received value insufficiently close to expected value. atan1014: atan(complex(0.0, 0.0)) Expected: complex(0.0, 0.0) Received: complex(0.0, -0.0) Received value insufficiently close to expected value. atanh0225: atanh(complex(-0.0, 5.6067e-320)) Expected: complex(-0.0, 5.6067e-320) Received: complex(0.0, 5.6067e-320) Received value insufficiently close to expected value. atanh0227: atanh(complex(-0.0, -3.0861101e-316)) Expected: complex(-0.0, -3.0861101e-316) Received: complex(0.0, -3.0861101e-316) Received value insufficiently close to expected value. atanh1024: atanh(complex(-0.0, -0.0)) Expected: complex(-0.0, -0.0) Received: complex(0.0, -0.0) Received value insufficiently close to expected value. atanh1034: atanh(complex(-0.0, 0.0)) Expected: complex(-0.0, 0.0) Received: complex(0.0, 0.0) Received value insufficiently close to expected value. I propose we remove the faulty zero tests as follows: % hg diff diff -r 05274ab06182 Lib/test/cmath_testcases.txt --- a/Lib/test/cmath_testcases.txt Sat May 05 21:57:17 2012 -0700 +++ b/Lib/test/cmath_testcases.txt Fri Aug 17 18:58:03 2012 +0000 @@ -849,7 +849,6 @@ atan0304 atan -9.9998886718268301e-321 -1.0 -> -0.78539816339744828 -368.76019403576692 -- special values -atan1000 atan -0.0 0.0 -> -0.0 0.0 atan1001 atan nan 0.0 -> nan 0.0 atan1002 atan -0.0 1.0 -> -0.0 inf divide-by-zero atan1003 atan -inf 0.0 -> -1.5707963267948966 0.0 @@ -863,7 +862,6 @@ atan1011 atan -2.2999999999999998 nan -> nan nan atan1012 atan -inf nan -> -1.5707963267948966 0.0 ignore-imag-sign atan1013 atan nan nan -> nan nan -atan1014 atan 0.0 0.0 -> 0.0 0.0 atan1015 atan 0.0 1.0 -> 0.0 inf divide-by-zero atan1016 atan inf 0.0 -> 1.5707963267948966 0.0 atan1017 atan inf 2.2999999999999998 -> 1.5707963267948966 0.0 @@ -873,7 +871,6 @@ atan1021 atan 0.0 nan -> nan nan atan1022 atan 2.2999999999999998 nan -> nan nan atan1023 atan inf nan -> 1.5707963267948966 0.0 ignore-imag-sign -atan1024 atan 0.0 -0.0 -> 0.0 -0.0 atan1025 atan nan -0.0 -> nan -0.0 atan1026 atan 0.0 -1.0 -> 0.0 -inf divide-by-zero atan1027 atan inf -0.0 -> 1.5707963267948966 -0.0 @@ -883,7 +880,6 @@ atan1031 atan 2.2999999999999998 -inf -> 1.5707963267948966 -0.0 atan1032 atan inf -inf -> 1.5707963267948966 -0.0 atan1033 atan nan -inf -> nan -0.0 -atan1034 atan -0.0 -0.0 -> -0.0 -0.0 atan1035 atan -0.0 -1.0 -> -0.0 -inf divide-by-zero atan1036 atan -inf -0.0 -> -1.5707963267948966 -0.0 atan1037 atan -inf -2.2999999999999998 -> -1.5707963267948966 -0.0 That leaves us with: atanh0225: atanh(complex(-0.0, 5.6067e-320)) Expected: complex(-0.0, 5.6067e-320) Received: complex(0.0, 5.6067e-320) Received value insufficiently close to expected value. atanh0227: atanh(complex(-0.0, -3.0861101e-316)) Expected: complex(-0.0, -3.0861101e-316) Received: complex(0.0, -3.0861101e-316) Received value insufficiently close to expected value. Those aren't duplicate tests like the 0.0 -> -0.0 ones, so, how should they be handled? The proposed patch to rAssertAlmostEqual will skip these ones, but perhaps something like this would be more appropriate: diff -r 12c062dbe746 Lib/test/cmath_testcases.txt --- a/Lib/test/cmath_testcases.txt Thu Aug 16 22:18:37 2012 +0200 +++ b/Lib/test/cmath_testcases.txt Fri Aug 17 15:37:11 2012 -0400 @@ -849,7 +849,6 @@ atan0304 atan -9.9998886718268301e-321 -1.0 -> -0.78539816339744828 -368.76019403576692 -- special values -atan1000 atan -0.0 0.0 -> -0.0 0.0 atan1001 atan nan 0.0 -> nan 0.0 atan1002 atan -0.0 1.0 -> -0.0 inf divide-by-zero atan1003 atan -inf 0.0 -> -1.5707963267948966 0.0 @@ -863,7 +862,6 @@ atan1011 atan -2.2999999999999998 nan -> nan nan atan1012 atan -inf nan -> -1.5707963267948966 0.0 ignore-imag-sign atan1013 atan nan nan -> nan nan -atan1014 atan 0.0 0.0 -> 0.0 0.0 atan1015 atan 0.0 1.0 -> 0.0 inf divide-by-zero atan1016 atan inf 0.0 -> 1.5707963267948966 0.0 atan1017 atan inf 2.2999999999999998 -> 1.5707963267948966 0.0 @@ -873,7 +871,6 @@ atan1021 atan 0.0 nan -> nan nan atan1022 atan 2.2999999999999998 nan -> nan nan atan1023 atan inf nan -> 1.5707963267948966 0.0 ignore-imag-sign -atan1024 atan 0.0 -0.0 -> 0.0 -0.0 atan1025 atan nan -0.0 -> nan -0.0 atan1026 atan 0.0 -1.0 -> 0.0 -inf divide-by-zero atan1027 atan inf -0.0 -> 1.5707963267948966 -0.0 @@ -883,7 +880,6 @@ atan1031 atan 2.2999999999999998 -inf -> 1.5707963267948966 -0.0 atan1032 atan inf -inf -> 1.5707963267948966 -0.0 atan1033 atan nan -inf -> nan -0.0 -atan1034 atan -0.0 -0.0 -> -0.0 -0.0 atan1035 atan -0.0 -1.0 -> -0.0 -inf divide-by-zero atan1036 atan -inf -0.0 -> -1.5707963267948966 -0.0 atan1037 atan -inf -2.2999999999999998 -> -1.5707963267948966 -0.0 @@ -1011,9 +1007,7 @@ atanh0222 atanh -5.9656816081325078e-317 9.9692253555416263e-313 -> -5.9656816081325078e-317 9.9692253555416263e-313 atanh0223 atanh -6.5606671178400239e-313 -2.1680936406357335e-309 -> -6.5606671178400239e-313 -2.1680936406357335e-309 atanh0224 atanh 0.0 2.5230944401820779e-319 -> 0.0 2.5230944401820779e-319 -atanh0225 atanh -0.0 5.6066569490064658e-320 -> -0.0 5.6066569490064658e-320 atanh0226 atanh 0.0 -2.4222487249468377e-317 -> 0.0 -2.4222487249468377e-317 -atanh0227 atanh -0.0 -3.0861101089206037e-316 -> -0.0 -3.0861101089206037e-316 atanh0228 atanh 3.1219222884393986e-310 0.0 -> 3.1219222884393986e-310 0.0 atanh0229 atanh 9.8926337564976196e-309 -0.0 -> 9.8926337564976196e-309 -0.0 atanh0230 atanh -1.5462535092918154e-312 0.0 -> -1.5462535092918154e-312 0.0 @@ -1051,7 +1045,6 @@ atanh1021 atanh nan -0.0 -> nan nan atanh1022 atanh nan -2.3 -> nan nan atanh1023 atanh nan -inf -> 0.0 -1.5707963267948966 ignore-real-sign -atanh1024 atanh -0.0 -0.0 -> -0.0 -0.0 atanh1025 atanh -0.0 nan -> -0.0 nan atanh1026 atanh -1.0 -0.0 -> -inf -0.0 divide-by-zero atanh1027 atanh -0.0 -inf -> -0.0 -1.5707963267948966 @@ -1061,7 +1054,6 @@ atanh1031 atanh -inf -2.3 -> -0.0 -1.5707963267948966 atanh1032 atanh -inf -inf -> -0.0 -1.5707963267948966 atanh1033 atanh -inf nan -> -0.0 nan -atanh1034 atanh -0.0 0.0 -> -0.0 0.0 atanh1035 atanh -1.0 0.0 -> -inf 0.0 divide-by-zero atanh1036 atanh -0.0 inf -> -0.0 1.5707963267948966 atanh1037 atanh -2.3 inf -> -0.0 1.5707963267948966 diff -r 12c062dbe746 Lib/test/test_cmath.py --- a/Lib/test/test_cmath.py Thu Aug 16 22:18:37 2012 +0200 +++ b/Lib/test/test_cmath.py Fri Aug 17 15:37:11 2012 -0400 @@ -532,6 +532,36 @@ for z in complex_zeros: self.assertComplexIdentical(cmath.atanh(z), z) + @requires_IEEE_754 + @unittest.skipIf(sysconfig.get_config_var('LOG1P_DROPS_ZERO_SIGN'), + "system log1p() function doesn't preserve the sign") + def testAtanhSignNearZero(self): + for z in (-30861101e-316, 5.6067e-320): + expected = complex(-0.0, z) + actual = cmath.atanh(complex(-0.0, z)) + error_message = ( + 'Expected: complex({!r}, {!r})\n' + 'Received: complex({!r}, {!r})\n' + 'Received value insufficiently close to expected value.' + ).format( + expected.real, + expected.imag, + actual.real, + actual.imag + ) + + self.rAssertAlmostEqual( + expected.real, + actual.real, + abs_err=5e-323, + msg=error_message, + ) + + self.rAssertAlmostEqual( + expected.imag, + actual.imag, + msg=error_message, + ) def test_main(): run_unittest(CMathTests) With this patch applied, test_cmath passes on both Mountain Lion and Lion. I've attached this patch as issue15477.patch. Thoughts? |
|||
msg168498 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-08-18 09:17 | |
Trent, many thanks for the report and analysis. The LOG1P_DROPS_ZERO_SIGN hackery was a result of a previous attempt to 'fix' the tests on another platform whose log1p didn't preserve zero signs. But now that this behaviour has emerged on OS X too, I think it might be time to fix this in the Python core code (i.e., add a workaround for the buggy OS behaviour) instead of trying to make the tests pass again. Attached is a patch that adds a workaround for this on all platforms that have a system log1p. I was originally thinking of adding this workaround only on OS X (so as not to unnecessarily punish those platforms that get it right), but after running some timings (see below) it seems that the workaround is insignificant performance-wise, so we might as well keep things simple and add it on all platforms. Trent, if you have time, please could you try this patch on OS X 10.8 and see if it fixes all the test_cmath and test_math failures? Some timings on OS X 10.6. Current default branch (pass value directly onto system log1p): iwasawa:cpython mdickinson$ ./python.exe -m timeit -s 'from math import log1p; x = 2.3' 'log1p(x)' 10000000 loops, best of 3: 0.0685 usec per loop With the attached patch (do zero check, then pass value directly onto system log1p): iwasawa:cpython mdickinson$ ./python.exe -m timeit -s 'from math import log1p; x = 2.3' 'log1p(x)' 10000000 loops, best of 3: 0.0686 usec per loop |
|||
msg168499 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-08-18 09:21 | |
Updated patch that also removes the sysconfig checks from the cmath tests. |
|||
msg168500 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-08-18 09:32 | |
See also http://bugs.python.org/issue9920; the patch here *should* fix that issue, too. |
|||
msg168501 - (view) | Author: Trent Nelson (trent) * | Date: 2012-08-18 09:33 | |
Happy to report your patch does the trick Mark. test_cmath passes on 10.7 and 10.8 with it applied. |
|||
msg168503 - (view) | Author: Martin v. Löwis (loewis) * | Date: 2012-08-18 10:27 | |
BTW, did anybody file a bug report with Apple? Even to my untrained eye, that looks like a clear violation of the POSIX standard: If x is ±0, or +Inf, x shall be returned. http://pubs.opengroup.org/onlinepubs/009604599/functions/log1p.html C seems to make it implementation-defined, unless the implementation defines __STDC_IEC_559__, in which case log1p also needs to return ±0 (C99 F.9.3.9, C11 F.10.3.9). |
|||
msg168506 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-08-18 10:59 | |
> BTW, did anybody file a bug report with Apple? I'll file one. |
|||
msg168507 - (view) | Author: Roundup Robot (python-dev) | Date: 2012-08-18 11:24 | |
New changeset 08418369da7b by Mark Dickinson in branch '3.2': Issue #15477: Add workaround for log1p(-0.0) on platforms where it's broken. http://hg.python.org/cpython/rev/08418369da7b |
|||
msg168508 - (view) | Author: Roundup Robot (python-dev) | Date: 2012-08-18 11:26 | |
New changeset 336653319112 by Mark Dickinson in branch 'default': Issue #15477: Merge fix from 3.2 http://hg.python.org/cpython/rev/336653319112 |
|||
msg168509 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2012-08-18 11:32 | |
Apple bug report filed: Bug ID# 12128251. Closing the issue. |
|||
msg201148 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2013-10-24 16:00 | |
Update: I just received this from Apple, for bug #12128251. """ We believe this issue has been addressed in OS X Mavericks GM build 13A603. Please verify with this release, and update this report with your results. """ |
|||
msg201185 - (view) | Author: Ned Deily (ned.deily) * | Date: 2013-10-24 20:54 | |
I built Python at 3fba718e46e5 on both 10.8 and 10.9 which was just before your changes for this issue went in, Mark. On 10.8: test_cmath fails and: >>> math.log1p(-0.0) 0.0 And, indeed, on 10.9, it passes and: >>> math.log1p(-0.0) -0.0 |
|||
msg201262 - (view) | Author: Mark Dickinson (mark.dickinson) * | Date: 2013-10-25 17:22 | |
Perfect. Thanks, Ned! I'll update the Apple issue. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:57:33 | admin | set | github: 59682 |
2013-10-25 17:22:35 | mark.dickinson | set | messages: + msg201262 |
2013-10-24 20:54:18 | ned.deily | set | messages: + msg201185 |
2013-10-24 16:00:11 | mark.dickinson | set | messages: + msg201148 |
2013-03-14 13:44:00 | alef | set | nosy:
- alef |
2013-03-14 13:43:24 | alef | set | nosy:
+ alef |
2012-08-18 11:32:35 | mark.dickinson | set | status: open -> closed resolution: fixed messages: + msg168509 |
2012-08-18 11:26:27 | python-dev | set | messages: + msg168508 |
2012-08-18 11:24:51 | python-dev | set | nosy:
+ python-dev messages: + msg168507 |
2012-08-18 10:59:08 | mark.dickinson | set | messages: + msg168506 |
2012-08-18 10:27:01 | loewis | set | messages: + msg168503 |
2012-08-18 09:33:09 | trent | set | messages: + msg168501 |
2012-08-18 09:32:24 | mark.dickinson | set | messages: + msg168500 |
2012-08-18 09:25:50 | mark.dickinson | set | stage: patch review type: behavior components: + Extension Modules versions: + Python 2.7, Python 3.2 |
2012-08-18 09:22:01 | mark.dickinson | set | files: - log1p_sign_workaround.patch |
2012-08-18 09:21:40 | mark.dickinson | set | files:
+ log1p_sign_workaround.patch messages: + msg168499 |
2012-08-18 09:17:14 | mark.dickinson | set | files:
+ log1p_sign_workaround.patch messages: + msg168498 |
2012-08-18 08:43:12 | mark.dickinson | set | assignee: mark.dickinson |
2012-08-17 19:39:24 | trent | set | files:
+ issue15477.patch nosy: + trent messages: + msg168470 keywords: + patch |
2012-08-17 14:03:20 | loewis | set | nosy:
+ loewis messages: + msg168445 |
2012-07-29 09:04:49 | mark.dickinson | set | messages: + msg166729 |
2012-07-28 23:18:29 | ned.deily | set | messages: + msg166700 |
2012-07-28 22:17:23 | mark.dickinson | set | messages: + msg166698 |
2012-07-28 21:01:43 | ned.deily | set | messages: + msg166691 |
2012-07-28 11:51:57 | mark.dickinson | set | messages: + msg166649 |
2012-07-28 11:49:11 | mark.dickinson | set | messages: + msg166648 |
2012-07-28 10:03:57 | ned.deily | create |