[Python-checkins] r62396 - in python/trunk: Lib/test/test_math.py Modules/mathmodule.c

mark.dickinson python-checkins at python.org
Sat Apr 19 20:51:49 CEST 2008


Author: mark.dickinson
Date: Sat Apr 19 20:51:48 2008
New Revision: 62396

Log:
Additional tests for math.pow, and extra special-case
handling code in math.pow, in the hope of making all
tests pass on the alpha Tru64 buildbot.



Modified:
   python/trunk/Lib/test/test_math.py
   python/trunk/Modules/mathmodule.c

Modified: python/trunk/Lib/test/test_math.py
==============================================================================
--- python/trunk/Lib/test/test_math.py	(original)
+++ python/trunk/Lib/test/test_math.py	Sat Apr 19 20:51:48 2008
@@ -102,7 +102,7 @@
         self.ftest('atan(0)', math.atan(0), 0)
         self.ftest('atan(1)', math.atan(1), math.pi/4)
         self.ftest('atan(inf)', math.atan(INF), math.pi/2)
-        self.ftest('atan(-inf)', math.atan(-INF), -math.pi/2)
+        self.ftest('atan(-inf)', math.atan(NINF), -math.pi/2)
         self.assert_(math.isnan(math.atan(NAN)))
 
     def testAtanh(self):
@@ -387,14 +387,128 @@
         self.assert_(math.isnan(math.pow(2, NAN)))
         self.assert_(math.isnan(math.pow(0, NAN)))
         self.assertEqual(math.pow(1, NAN), 1)
-        self.assertEqual(1**NAN, 1)
-        self.assertEqual(1**INF, 1)
-        self.assertEqual(1**NINF, 1)
-        self.assertEqual(1**0, 1)
-        self.assertEqual(1.**NAN, 1)
-        self.assertEqual(1.**INF, 1)
-        self.assertEqual(1.**NINF, 1)
-        self.assertEqual(1.**0, 1)
+
+        # pow(0., x)
+        self.assertEqual(math.pow(0., INF), 0.)
+        self.assertEqual(math.pow(0., 3.), 0.)
+        self.assertEqual(math.pow(0., 2.3), 0.)
+        self.assertEqual(math.pow(0., 2.), 0.)
+        self.assertEqual(math.pow(0., 0.), 1.)
+        self.assertEqual(math.pow(0., -0.), 1.)
+        self.assertRaises(ValueError, math.pow, 0., -2.)
+        self.assertRaises(ValueError, math.pow, 0., -2.3)
+        self.assertRaises(ValueError, math.pow, 0., -3.)
+        self.assertRaises(ValueError, math.pow, 0., NINF)
+        self.assert_(math.isnan(math.pow(0., NAN)))
+
+        # pow(INF, x)
+        self.assertEqual(math.pow(INF, INF), INF)
+        self.assertEqual(math.pow(INF, 3.), INF)
+        self.assertEqual(math.pow(INF, 2.3), INF)
+        self.assertEqual(math.pow(INF, 2.), INF)
+        self.assertEqual(math.pow(INF, 0.), 1.)
+        self.assertEqual(math.pow(INF, -0.), 1.)
+        self.assertEqual(math.pow(INF, -2.), 0.)
+        self.assertEqual(math.pow(INF, -2.3), 0.)
+        self.assertEqual(math.pow(INF, -3.), 0.)
+        self.assertEqual(math.pow(INF, NINF), 0.)
+        self.assert_(math.isnan(math.pow(INF, NAN)))
+
+        # pow(-0., x)
+        self.assertEqual(math.pow(-0., INF), 0.)
+        self.assertEqual(math.pow(-0., 3.), -0.)
+        self.assertEqual(math.pow(-0., 2.3), 0.)
+        self.assertEqual(math.pow(-0., 2.), 0.)
+        self.assertEqual(math.pow(-0., 0.), 1.)
+        self.assertEqual(math.pow(-0., -0.), 1.)
+        self.assertRaises(ValueError, math.pow, -0., -2.)
+        self.assertRaises(ValueError, math.pow, -0., -2.3)
+        self.assertRaises(ValueError, math.pow, -0., -3.)
+        self.assertRaises(ValueError, math.pow, -0., NINF)
+        self.assert_(math.isnan(math.pow(-0., NAN)))
+
+        # pow(NINF, x)
+        self.assertEqual(math.pow(NINF, INF), INF)
+        self.assertEqual(math.pow(NINF, 3.), NINF)
+        self.assertEqual(math.pow(NINF, 2.3), INF)
+        self.assertEqual(math.pow(NINF, 2.), INF)
+        self.assertEqual(math.pow(NINF, 0.), 1.)
+        self.assertEqual(math.pow(NINF, -0.), 1.)
+        self.assertEqual(math.pow(NINF, -2.), 0.)
+        self.assertEqual(math.pow(NINF, -2.3), 0.)
+        self.assertEqual(math.pow(NINF, -3.), -0.)
+        self.assertEqual(math.pow(NINF, NINF), 0.)
+        self.assert_(math.isnan(math.pow(NINF, NAN)))
+
+        # pow(-1, x)
+        self.assertEqual(math.pow(-1., INF), 1.)
+        self.assertEqual(math.pow(-1., 3.), -1.)
+        self.assertRaises(ValueError, math.pow, -1., 2.3)
+        self.assertEqual(math.pow(-1., 2.), 1.)
+        self.assertEqual(math.pow(-1., 0.), 1.)
+        self.assertEqual(math.pow(-1., -0.), 1.)
+        self.assertEqual(math.pow(-1., -2.), 1.)
+        self.assertRaises(ValueError, math.pow, -1., -2.3)
+        self.assertEqual(math.pow(-1., -3.), -1.)
+        self.assertEqual(math.pow(-1., NINF), 1.)
+        self.assert_(math.isnan(math.pow(-1., NAN)))
+
+        # pow(1, x)
+        self.assertEqual(math.pow(1., INF), 1.)
+        self.assertEqual(math.pow(1., 3.), 1.)
+        self.assertEqual(math.pow(1., 2.3), 1.)
+        self.assertEqual(math.pow(1., 2.), 1.)
+        self.assertEqual(math.pow(1., 0.), 1.)
+        self.assertEqual(math.pow(1., -0.), 1.)
+        self.assertEqual(math.pow(1., -2.), 1.)
+        self.assertEqual(math.pow(1., -2.3), 1.)
+        self.assertEqual(math.pow(1., -3.), 1.)
+        self.assertEqual(math.pow(1., NINF), 1.)
+        self.assertEqual(math.pow(1., NAN), 1.)
+
+        # pow(x, 0) should be 1 for any x
+        self.assertEqual(math.pow(2.3, 0.), 1.)
+        self.assertEqual(math.pow(-2.3, 0.), 1.)
+        self.assertEqual(math.pow(NAN, 0.), 1.)
+        self.assertEqual(math.pow(2.3, -0.), 1.)
+        self.assertEqual(math.pow(-2.3, -0.), 1.)
+        self.assertEqual(math.pow(NAN, -0.), 1.)
+
+        # pow(x, y) is invalid if x is negative and y is not integral
+        self.assertRaises(ValueError, math.pow, -1., 2.3)
+        self.assertRaises(ValueError, math.pow, -15., -3.1)
+
+        # pow(x, NINF)
+        self.assertEqual(math.pow(1.9, NINF), 0.)
+        self.assertEqual(math.pow(1.1, NINF), 0.)
+        self.assertEqual(math.pow(0.9, NINF), INF)
+        self.assertEqual(math.pow(0.1, NINF), INF)
+        self.assertEqual(math.pow(-0.1, NINF), INF)
+        self.assertEqual(math.pow(-0.9, NINF), INF)
+        self.assertEqual(math.pow(-1.1, NINF), 0.)
+        self.assertEqual(math.pow(-1.9, NINF), 0.)
+
+        # pow(x, INF)
+        self.assertEqual(math.pow(1.9, INF), INF)
+        self.assertEqual(math.pow(1.1, INF), INF)
+        self.assertEqual(math.pow(0.9, INF), 0.)
+        self.assertEqual(math.pow(0.1, INF), 0.)
+        self.assertEqual(math.pow(-0.1, INF), 0.)
+        self.assertEqual(math.pow(-0.9, INF), 0.)
+        self.assertEqual(math.pow(-1.1, INF), INF)
+        self.assertEqual(math.pow(-1.9, INF), INF)
+
+        # the following tests have been commented out since they don't
+        # really belong here:  the implementation of ** for floats is
+        # independent of the implemention of math.pow
+        #self.assertEqual(1**NAN, 1)
+        #self.assertEqual(1**INF, 1)
+        #self.assertEqual(1**NINF, 1)
+        #self.assertEqual(1**0, 1)
+        #self.assertEqual(1.**NAN, 1)
+        #self.assertEqual(1.**INF, 1)
+        #self.assertEqual(1.**NINF, 1)
+        #self.assertEqual(1.**0, 1)
 
     def testRadians(self):
         self.assertRaises(TypeError, math.radians)
@@ -421,7 +535,7 @@
         self.ftest('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1)
         self.ftest('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0)
         self.assertEquals(math.sinh(INF), INF)
-        self.assertEquals(math.sinh(-INF), -INF)
+        self.assertEquals(math.sinh(NINF), NINF)
         self.assert_(math.isnan(math.sinh(NAN)))
 
     def testSqrt(self):

Modified: python/trunk/Modules/mathmodule.c
==============================================================================
--- python/trunk/Modules/mathmodule.c	(original)
+++ python/trunk/Modules/mathmodule.c	Sat Apr 19 20:51:48 2008
@@ -513,6 +513,7 @@
 {
 	PyObject *ox, *oy;
 	double r, x, y;
+	int y_is_odd;
 
 	if (! PyArg_UnpackTuple(args, "pow", 2, 2, &ox, &oy))
 		return NULL;
@@ -523,6 +524,16 @@
 	/* 1**x and x**0 return 1., even if x is a NaN or infinity. */
 	if (x == 1.0 || y == 0.0)
 	        return PyFloat_FromDouble(1.);
+	/* inf ** (nonzero, non-NaN) is one of +-0, +-infinity */
+	if (Py_IS_INFINITY(x) && !Py_IS_NAN(y)) {
+		y_is_odd = Py_IS_FINITE(y) && fmod(fabs(y), 2.0) == 1.0;
+		if (y > 0.)
+			r = y_is_odd ? x : fabs(x);
+		else
+			r = y_is_odd ? copysign(0., x) : 0.;
+		return PyFloat_FromDouble(r);
+	}
+
 	errno = 0;
 	PyFPE_START_PROTECT("in math_pow", return 0);
 	r = pow(x, y);


More information about the Python-checkins mailing list