Merged revisions 62420-62421,62423-62424 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r62420 | mark.dickinson | 2008-04-20 20:30:05 +0200 (Sun, 20 Apr 2008) | 3 lines

  Even more fixes for alpha Tru64, this time for
  the phase and polar methods.
........
  r62421 | mark.dickinson | 2008-04-20 22:38:48 +0200 (Sun, 20 Apr 2008) | 2 lines

  Add test for tanh(-0.) == -0. on IEEE 754 systems
........
  r62423 | amaury.forgeotdarc | 2008-04-20 23:02:21 +0200 (Sun, 20 Apr 2008) | 3 lines

  Correct an apparent refleak in test_pkgutil: zipimport._zip_directory_cache contains
  info for all processed zip files, even when they are no longer used.
........
  r62424 | mark.dickinson | 2008-04-20 23:39:04 +0200 (Sun, 20 Apr 2008) | 4 lines

  math.atan2 is misbehaving on Windows;  this patch
  should fix the problem in the same way that
  the cmath.phase problems were fixed.
........
This commit is contained in:
Christian Heimes 2008-04-21 13:08:03 +00:00
parent 1a3239e945
commit e57950fbfe
4 changed files with 108 additions and 2 deletions

View File

@ -124,6 +124,59 @@ class MathTests(unittest.TestCase):
self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
# math.atan2(0, x)
self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi)
self.ftest('atan2(0., -2.3)', math.atan2(0., -2.3), math.pi)
self.ftest('atan2(0., -0.)', math.atan2(0., -0.), math.pi)
self.assertEqual(math.atan2(0., 0.), 0.)
self.assertEqual(math.atan2(0., 2.3), 0.)
self.assertEqual(math.atan2(0., INF), 0.)
self.assert_(math.isnan(math.atan2(0., NAN)))
# math.atan2(-0, x)
self.ftest('atan2(-0., -inf)', math.atan2(-0., NINF), -math.pi)
self.ftest('atan2(-0., -2.3)', math.atan2(-0., -2.3), -math.pi)
self.ftest('atan2(-0., -0.)', math.atan2(-0., -0.), -math.pi)
self.assertEqual(math.atan2(-0., 0.), -0.)
self.assertEqual(math.atan2(-0., 2.3), -0.)
self.assertEqual(math.atan2(-0., INF), -0.)
self.assert_(math.isnan(math.atan2(-0., NAN)))
# math.atan2(INF, x)
self.ftest('atan2(inf, -inf)', math.atan2(INF, NINF), math.pi*3/4)
self.ftest('atan2(inf, -2.3)', math.atan2(INF, -2.3), math.pi/2)
self.ftest('atan2(inf, -0.)', math.atan2(INF, -0.0), math.pi/2)
self.ftest('atan2(inf, 0.)', math.atan2(INF, 0.0), math.pi/2)
self.ftest('atan2(inf, 2.3)', math.atan2(INF, 2.3), math.pi/2)
self.ftest('atan2(inf, inf)', math.atan2(INF, INF), math.pi/4)
self.assert_(math.isnan(math.atan2(INF, NAN)))
# math.atan2(NINF, x)
self.ftest('atan2(-inf, -inf)', math.atan2(NINF, NINF), -math.pi*3/4)
self.ftest('atan2(-inf, -2.3)', math.atan2(NINF, -2.3), -math.pi/2)
self.ftest('atan2(-inf, -0.)', math.atan2(NINF, -0.0), -math.pi/2)
self.ftest('atan2(-inf, 0.)', math.atan2(NINF, 0.0), -math.pi/2)
self.ftest('atan2(-inf, 2.3)', math.atan2(NINF, 2.3), -math.pi/2)
self.ftest('atan2(-inf, inf)', math.atan2(NINF, INF), -math.pi/4)
self.assert_(math.isnan(math.atan2(NINF, NAN)))
# math.atan2(+finite, x)
self.ftest('atan2(2.3, -inf)', math.atan2(2.3, NINF), math.pi)
self.ftest('atan2(2.3, -0.)', math.atan2(2.3, -0.), math.pi/2)
self.ftest('atan2(2.3, 0.)', math.atan2(2.3, 0.), math.pi/2)
self.assertEqual(math.atan2(2.3, INF), 0.)
self.assert_(math.isnan(math.atan2(2.3, NAN)))
# math.atan2(-finite, x)
self.ftest('atan2(-2.3, -inf)', math.atan2(-2.3, NINF), -math.pi)
self.ftest('atan2(-2.3, -0.)', math.atan2(-2.3, -0.), -math.pi/2)
self.ftest('atan2(-2.3, 0.)', math.atan2(-2.3, 0.), -math.pi/2)
self.assertEqual(math.atan2(-2.3, INF), -0.)
self.assert_(math.isnan(math.atan2(-2.3, NAN)))
# math.atan2(NAN, x)
self.assert_(math.isnan(math.atan2(NAN, NINF)))
self.assert_(math.isnan(math.atan2(NAN, -2.3)))
self.assert_(math.isnan(math.atan2(NAN, -0.)))
self.assert_(math.isnan(math.atan2(NAN, 0.)))
self.assert_(math.isnan(math.atan2(NAN, 2.3)))
self.assert_(math.isnan(math.atan2(NAN, INF)))
self.assert_(math.isnan(math.atan2(NAN, NAN)))
def testCeil(self):
self.assertRaises(TypeError, math.ceil)
self.assertEquals(int, type(math.ceil(0.5)))
@ -575,6 +628,11 @@ class MathTests(unittest.TestCase):
self.ftest('tanh(inf)', math.tanh(INF), 1)
self.ftest('tanh(-inf)', math.tanh(NINF), -1)
self.assert_(math.isnan(math.tanh(NAN)))
# check that tanh(-0.) == -0. on IEEE 754 systems
if float.__getformat__("double").startswith("IEEE"):
self.assertEqual(math.tanh(-0.), -0.)
self.assertEqual(math.copysign(1., math.tanh(-0.)),
math.copysign(1., -0.))
def test_trunc(self):
self.assertEqual(math.trunc(1), 1)

View File

@ -122,6 +122,9 @@ class PkgutilPEP302Tests(unittest.TestCase):
def test_main():
run_unittest(PkgutilTests, PkgutilPEP302Tests)
# this is necessary if test is run repeated (like when finding leaks)
import zipimport
zipimport._zip_directory_cache.clear()
if __name__ == '__main__':
test_main()

View File

@ -264,7 +264,8 @@ c_atan(Py_complex z)
return r;
}
/* Windows screws up atan2 for inf and nan */
/* Windows screws up atan2 for inf and nan, and alpha Tru64 5.1 doesn't follow
C99 for atan2(0., 0.). */
static double
c_atan2(Py_complex z)
{
@ -282,6 +283,14 @@ c_atan2(Py_complex z)
/* atan2(+-inf, x) == +-pi/2 for finite x */
return copysign(0.5*Py_MATH_PI, z.imag);
}
if (Py_IS_INFINITY(z.real) || z.imag == 0.) {
if (copysign(1., z.real) == 1.)
/* atan2(+-y, +inf) = atan2(+-0, +x) = +-0. */
return copysign(0., z.imag);
else
/* atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. */
return copysign(Py_MATH_PI, z.imag);
}
return atan2(z.imag, z.real);
}

View File

@ -95,6 +95,42 @@ is_error(double x)
return result;
}
/*
wrapper for atan2 that deals directly with special cases before
delegating to the platform libm for the remaining cases. This
is necessary to get consistent behaviour across platforms.
Windows, FreeBSD and alpha Tru64 are amongst platforms that don't
always follow C99.
*/
static double
m_atan2(double y, double x)
{
if (Py_IS_NAN(x) || Py_IS_NAN(y))
return Py_NAN;
if (Py_IS_INFINITY(y)) {
if (Py_IS_INFINITY(x)) {
if (copysign(1., x) == 1.)
/* atan2(+-inf, +inf) == +-pi/4 */
return copysign(0.25*Py_MATH_PI, y);
else
/* atan2(+-inf, -inf) == +-pi*3/4 */
return copysign(0.75*Py_MATH_PI, y);
}
/* atan2(+-inf, x) == +-pi/2 for finite x */
return copysign(0.5*Py_MATH_PI, y);
}
if (Py_IS_INFINITY(x) || y == 0.) {
if (copysign(1., x) == 1.)
/* atan2(+-y, +inf) = atan2(+-0, +x) = +-0. */
return copysign(0., y);
else
/* atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. */
return copysign(Py_MATH_PI, y);
}
return atan2(y, x);
}
/*
math_1 is used to wrap a libm function f that takes a double
arguments and returns a double.
@ -250,7 +286,7 @@ FUNC1(asinh, asinh, 0,
"asinh(x)\n\nReturn the hyperbolic arc sine (measured in radians) of x.")
FUNC1(atan, atan, 0,
"atan(x)\n\nReturn the arc tangent (measured in radians) of x.")
FUNC2(atan2, atan2,
FUNC2(atan2, m_atan2,
"atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
"Unlike atan(y/x), the signs of both x and y are considered.")
FUNC1(atanh, atanh, 0,