[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] pgreloaded patches



Hi,

I did a review of the math module in the pgreloaded branch and compiled some patches.
The patches address the following problems:
 * consistently use degrees and not radians
 * raise a ValueError rather than a ZeroDivisionError in case the div zero occurs during an internal calculation.
 * SLERP implementation is more robust. check for special cases like angle=0,180,360 degrees.
 * fixed a bug in LERP. t must be in range [0,1]
 * in the rotation methods: check if the rotation axis is zero and raise a ValueError in case it is.
 * check for div zero for div, idiv, floor_div
 * also check for div zero in the angleto method
 * a wrong function signature in basemod.c

I tried to seperate these issues in different patches. The "00_all.patch" is a combination of the others.

Hope you find this usefull.

cheers
//Lorenz
diff -r fb31d86448f9 -r 8eafbb955d09 src/base/basemod.c
--- a/src/base/basemod.c	Mon Apr 12 15:51:01 2010 +0200
+++ b/src/base/basemod.c	Mon Apr 12 17:44:30 2010 +0200
@@ -109,8 +109,8 @@
     return 0;
 }
 
-unsigned long
-UlongFromObj (PyObject* obj, long* val)
+int
+UlongFromObj (PyObject* obj, unsigned long* val)
 {
     PyObject* longobj;
     unsigned long tmp;
diff -r fb31d86448f9 -r 8eafbb955d09 src/base/internals.h
--- a/src/base/internals.h	Mon Apr 12 15:51:01 2010 +0200
+++ b/src/base/internals.h	Mon Apr 12 17:44:30 2010 +0200
@@ -60,7 +60,7 @@
 int ASCIIFromObj (PyObject *obj, char **text, PyObject **freeme);
 int UTF8FromObj (PyObject *obj, char **text, PyObject **freeme);
 int LongFromObj (PyObject* obj, long* val);
-unsigned long UlongFromObj (PyObject* obj, long* val);
+int UlongFromObj (PyObject* obj, unsigned long* val);
 int ColorFromObj (PyObject *obj, pguint32 *val);
 
 extern PyTypeObject PyColor_Type;
diff -r fb31d86448f9 -r 8eafbb955d09 src/math/mathmod.c
--- a/src/math/mathmod.c	Mon Apr 12 15:51:01 2010 +0200
+++ b/src/math/mathmod.c	Mon Apr 12 17:44:30 2010 +0200
@@ -42,6 +42,7 @@
 
     if (!PyArg_ParseTuple (args, "dd:vector_from_polar", &r, &phi))
         return NULL;
+    phi = DEG2RAD(phi);
     c1 = r * cos (phi);
     c2 = r * sin (phi);
     return PyVector2_New (c1, c2);
@@ -54,7 +55,8 @@
 
     if (!PyArg_ParseTuple (args, "ddd:vector_from_spherical", &r, &theta, &phi))
         return NULL;
-
+    phi = DEG2RAD(phi);
+    theta = DEG2RAD(theta);
     c1 = r * sin (theta) * cos (phi);
     c2 = r * sin (theta) * sin (phi);
     c3 = r * cos (theta);
diff -r fb31d86448f9 -r 8eafbb955d09 src/math/vector.c
--- a/src/math/vector.c	Mon Apr 12 15:51:01 2010 +0200
+++ b/src/math/vector.c	Mon Apr 12 17:44:30 2010 +0200
@@ -538,12 +538,18 @@
     PyVector *v = (PyVector *) self;
     Py_ssize_t i;
     
-    PyObject *tuple = PyTuple_New (v->dim);
+    PyObject *tmp, *tuple = PyTuple_New (v->dim);
     if (!tuple)
         return NULL;
     for (i = 0; i < v->dim; i++)
     {
-        PyTuple_SET_ITEM (tuple, i, PyFloat_FromDouble (v->coords[i]));
+        tmp = PyFloat_FromDouble (v->coords[i]);
+        if (!tmp)
+        {
+            Py_DECREF (tuple);
+            return NULL;
+        }
+        PyTuple_SET_ITEM (tuple, i, tmp);
     }
     return tuple;
 }
@@ -632,7 +638,7 @@
     length = sqrt (_ScalarProduct(self->coords, self->coords, self->dim));
     if (length == 0)
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "can not normalize vector of length 0");
         return NULL;
     }
@@ -652,7 +658,7 @@
     length = sqrt (_ScalarProduct (self->coords, self->coords, self->dim));
     if (length == 0)
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "can not normalize vector of length 0");
         return NULL;
     }
@@ -669,7 +675,7 @@
     PyObject *other;
     PyVector *ret;
     double *othercoords;
-    double angle, t, length1, length2, f0, f1, f2;
+    double angle, t, length1, length2, f0, f1, f2, tmp;
 
     if (!PyArg_ParseTuple(args, "Od:slerp", &other, &t))
         return NULL;
@@ -703,13 +709,16 @@
 
     if ((length1 < self->epsilon) || (length2 < self->epsilon))
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "can not use slerp with zero-Vector");
         PyMem_Free (othercoords);
         return NULL;
     }
-    angle = acos (_ScalarProduct (self->coords, othercoords, self->dim) /
-        (length1 * length2));
+    tmp = _ScalarProduct (self->coords, othercoords, self->dim) /
+        (length1 * length2);
+    /* make sure tmp is in the range [-1:1] so acos won't return NaN */
+    tmp = (tmp < -1 ? -1 : (tmp > 1 ? 1 : tmp));
+    angle = acos (tmp);
 
     if (t < 0)
     {
@@ -726,12 +735,28 @@
         PyMem_Free (othercoords);
         return NULL;
     }
-    f0 = ((length2 - length1) * t + length1) / sin (angle);
-    f1 = sin (angle * (1 - t)) / length1;
-    f2 = sin (angle * t) / length2;
-    for (i = 0; i < self->dim; ++i)
-        ret->coords[i] = (self->coords[i] * f1 + othercoords[i] * f2) * f0;
-
+    /* special case angle==0 and angle==360 */
+    if ((fabs(angle) < self->epsilon) || 
+        (fabs(fabs(angle) - 2 * M_PI) < self->epsilon)) {
+        /* approximate with lerp, because slerp diverges with 1/sin(angle) */
+        for (i = 0; i < self->dim; ++i)
+            ret->coords[i] = self->coords[i] * (1 - t) + othercoords[i] * t;
+    }
+    /* special case angle==180 and angle==-180 */
+    else if (fabs(fabs(angle) - M_PI) < self->epsilon) {
+        PyErr_SetString(PyExc_ValueError, 
+                        "SLERP with 180 degrees is undefined.");
+        Py_DECREF(ret);
+        PyMem_Free (othercoords);
+        return NULL;
+    }
+    else {
+        f0 = ((length2 - length1) * t + length1) / sin (angle);
+        f1 = sin (angle * (1 - t)) / length1;
+        f2 = sin (angle * t) / length2;
+        for (i = 0; i < self->dim; ++i)
+            ret->coords[i] = (self->coords[i] * f1 + othercoords[i] * f2) * f0;
+    }
     PyMem_Free (othercoords);
     return (PyObject*) ret;
 }
@@ -765,9 +790,9 @@
         return NULL;
     }
 
-    if (fabs (t) > 1)
+    if (t < 0 || t > 1)
     {
-        PyErr_SetString (PyExc_ValueError, "t must be in range [-1, 1]");
+        PyErr_SetString (PyExc_ValueError, "t must be in range [0, 1]");
         PyMem_Free (othercoords);
         return NULL;
     }
@@ -822,13 +847,11 @@
     if (!DoubleFromObj (args, &newlength))
         return NULL;
 
-    for (i = 0; i < self->dim; ++i)
-        oldlength += self->coords[i] * self->coords[i];
-    oldlength = sqrt (oldlength);
+    oldlength = sqrt (_ScalarProduct (self->coords, self->coords, self->dim));
 
     if (oldlength < self->epsilon)
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "cannot scale a vector with zero length");
         return NULL;
     }
@@ -869,12 +892,10 @@
     }
 
     /* Normalize the normal */
-    nlength = 0;
-    for (i = 0; i < ndim; i++)
-        nlength += ncoords[i] * ncoords[i];
+    nlength = _ScalarProduct(ncoords, ncoords, ndim);
     if (nlength < eps)
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "normal must not be a zero-length vector");
         goto ret;
     }
@@ -887,9 +908,7 @@
     }
 
     /* Calculate the dot product for the projection. */
-    dotprod = 0;
-    for (i = 0; i < dim; i++)
-        dotprod += srccoords[i] * ncoords[i];
+    dotprod = _ScalarProduct(srccoords, ncoords, dim);
         
     dstcoords = PyMem_New (double, dim);
     if (!dstcoords)
@@ -935,68 +954,54 @@
     Py_RETURN_NONE;
 }
 
-static PyObject*
-_vector_distance (PyVector *self, PyObject *args)
+static double
+_vector_distance_squared_as_double(PyVector *self, PyObject *args)
 {
     Py_ssize_t otherdim, i;
-    double *othercoords, distance, tmp;
+    double *othercoords, distance_squared, tmp;
 
     if (!IsVectorCompatible (args))
     {
         PyErr_SetString (PyExc_TypeError, "other must be a vector compatible");
-        return NULL;
+        return -1;
     }
 
     othercoords = VectorCoordsFromObj (args, &otherdim);
     if (!othercoords)
-        return NULL;
+        return -1;
     if (otherdim != self->dim)
     {
         PyErr_SetString (PyExc_ValueError,
             "must have same the same dimension as vector");
         PyMem_Free (othercoords);
-        return NULL;
+        return -1;
     }
-    distance = 0;
+    distance_squared = 0;
     for (i = 0; i < self->dim; i++)
     {
         tmp = othercoords[i] - self->coords[i];
-        distance += tmp * tmp;
+        distance_squared += tmp * tmp;
     }
     PyMem_Free (othercoords);
-    return PyFloat_FromDouble (sqrt (distance));
+    return distance_squared;
+ }
+
+static PyObject*
+_vector_distance (PyVector *self, PyObject *args)
+{
+    double distance_squared = _vector_distance_squared_as_double (self, args);
+    if (distance_squared == -1 && PyErr_Occurred())
+        return NULL;
+    return PyFloat_FromDouble (sqrt (distance_squared));
 }
 
 static PyObject*
 _vector_distance_squared (PyVector *self, PyObject *args)
 {
-    Py_ssize_t otherdim, i;
-    double *othercoords, distance, tmp;
-
-    if (!IsVectorCompatible (args))
-    {
-        PyErr_SetString (PyExc_TypeError, "other must be a vector compatible");
+    double distance_squared = _vector_distance_squared_as_double (self, args);
+    if (distance_squared == -1 && PyErr_Occurred())
         return NULL;
-    }
-
-    othercoords = VectorCoordsFromObj (args, &otherdim);
-    if (!othercoords)
-        return NULL;
-    if (otherdim != self->dim)
-    {
-        PyErr_SetString (PyExc_ValueError,
-            "must have same the same dimension as vector");
-        PyMem_Free (othercoords);
-        return NULL;
-    }
-    distance = 0;
-    for (i = 0; i < self->dim; i++)
-    {
-        tmp = othercoords[i] - self->coords[i];
-        distance += tmp * tmp;
-    }
-    PyMem_Free (othercoords);
-    return PyFloat_FromDouble (distance);
+    return PyFloat_FromDouble (distance_squared);
 }
 
 static PyObject*
@@ -1139,6 +1144,11 @@
         double tmp;
         if (!DoubleFromObj (other, &tmp))
             break;
+        if (tmp == 0.f)
+        {
+            PyErr_SetString (PyExc_ZeroDivisionError, "division by zero");
+            return NULL;
+        }
         tmp = 1.f / tmp;
         retval = PyVector_NewSpecialized (dim);
         if (!retval)
@@ -1152,6 +1162,11 @@
         double tmp;
         if (!DoubleFromObj (other, &tmp))
             break;
+        if (tmp == 0.f)
+        {
+            PyErr_SetString (PyExc_ZeroDivisionError, "division by zero");
+            return NULL;
+        }
         tmp = 1. / tmp;
         for (i = 0; i < dim; i++)
             vcoords[i] *= tmp;
@@ -1164,6 +1179,11 @@
         double tmp;
         if (!DoubleFromObj (other, &tmp))
             break;
+        if (tmp == 0.f)
+        {
+            PyErr_SetString (PyExc_ZeroDivisionError, "division by zero");
+            return NULL;
+        }
         tmp = 1. / tmp;
         retval = PyVector_NewSpecialized(dim);
         if (!retval)
@@ -1177,6 +1197,11 @@
         double tmp;
         if (!DoubleFromObj (other, &tmp))
             break;
+        if (tmp == 0.f)
+        {
+            PyErr_SetString (PyExc_ZeroDivisionError, "division by zero");
+            return NULL;
+        }
         tmp = 1. / tmp;
         for (i = 0; i < dim; i++)
             v->coords[i] = floor (vcoords[i] * tmp);
@@ -1287,7 +1312,7 @@
 }
 
 /**
- * -vector1, ~vector1
+ * -vector1, +vector1
  */
 static PyObject*
 _vector_neg (PyVector *self)
@@ -1317,7 +1342,7 @@
     Py_ssize_t i;
     for (i = 0; i < self->dim; i++)
     {
-        if (fabs (self->coords[i]) > self->epsilon)
+        if (self->coords[i] != 0.f)
             return 1;
     }
     return 0;
@@ -1597,7 +1622,7 @@
     double diff;
     PyVector *v = NULL, *v2 = NULL;
     PyObject *other = NULL;
-    int swap = 0, retval = 1;
+    int retval = 1;
     
     if (PyVector_Check (o1))
     {
@@ -1606,7 +1631,6 @@
     }
     else if (PyVector_Check (o2))
     {
-        swap = 1;
         v = (PyVector *) o2;
         other = o1;
     }
@@ -1647,13 +1671,6 @@
             }
         }
     }
-    if (swap == 1)
-    {
-        if (retval == 0)
-            retval = 1;
-        else
-            retval = 0;
-    }
 
     switch (op)
     {
diff -r fb31d86448f9 -r 8eafbb955d09 src/math/vector2.c
--- a/src/math/vector2.c	Mon Apr 12 15:51:01 2010 +0200
+++ b/src/math/vector2.c	Mon Apr 12 17:44:30 2010 +0200
@@ -360,7 +360,7 @@
     double r, phi;
     r = sqrt(_ScalarProduct (self->coords, self->coords, self->dim));
     phi = atan2 (self->coords[1], self->coords[0]);
-    return Py_BuildValue ("(dd)", r, phi);
+    return Py_BuildValue ("(dd)", r, RAD2DEG(phi));
 }
 
 /* C API */
diff -r fb31d86448f9 -r 8eafbb955d09 src/math/vector3.c
--- a/src/math/vector3.c	Mon Apr 12 15:51:01 2010 +0200
+++ b/src/math/vector3.c	Mon Apr 12 17:44:30 2010 +0200
@@ -34,7 +34,7 @@
 static PyObject* _vector3_get_z (PyObject *self, void *closure);
 static int _vector3_set_z (PyObject *self, PyObject *value, void *closure);
 
-static void _do_rotate (double *dst_coords, const double *src_coords,
+static int _do_rotate (double *dst_coords, const double *src_coords,
     const double* axis_coords, double angle, double epsilon);
 
 static PyObject* _vector3_rotate (PyObject *self, PyObject *args);
@@ -261,7 +261,7 @@
 }
 
 /* Vector3 methods */
-static void
+static int
 _do_rotate (double *dst_coords, const double *src_coords,
     const double* axis_coords, double angle, double epsilon)
 {
@@ -282,8 +282,15 @@
         axis[i] = axis_coords[i];
     }
 
+    if (axislen < epsilon)
+    {
+        PyErr_SetString (PyExc_ValueError,
+            "rotation axis is too close to zero.");
+        return 0;
+    }
+ 
     /* normalize the axis */
-    if (axislen - 1 > epsilon)
+    if (fabs(axislen - 1) > epsilon)
     {
         nfactor = 1. / sqrt (axislen);
         for (i = 0; i < 3; ++i)
@@ -353,6 +360,7 @@
              src_coords[1] * (axis[1] * axis[2] * coscompl + axis[0] * sinv) +
              src_coords[2] * (cosv + axis[2] * axis[2] * coscompl));
     }
+    return 1;
 }
 
 static PyObject*
@@ -384,7 +392,12 @@
         return NULL;
     }
     ret = (PyVector*) PyVector3_New (0.f, 0.f, 0.f);
-    _do_rotate (ret->coords, v->coords, axiscoords, angle, v->epsilon);
+    if (!ret || 
+        !_do_rotate (ret->coords, v->coords, axiscoords, angle, v->epsilon))
+    {
+        Py_XDECREF(ret);
+        ret = NULL;
+    }
     PyMem_Free (axiscoords);
     return (PyObject*) ret;
 }
@@ -418,7 +431,11 @@
     }
 
     memcpy (tmp, v->coords, sizeof (double) * 3);
-    _do_rotate (v->coords, tmp, axiscoords, angle, v->epsilon);
+    if (!_do_rotate (v->coords, tmp, axiscoords, angle, v->epsilon))
+    {
+        PyMem_Free (axiscoords);
+        return NULL;
+    }
     PyMem_Free (axiscoords);
     Py_RETURN_NONE;
 }
@@ -606,7 +623,7 @@
 static PyObject*
 _vector3_angleto (PyObject *self, PyObject *args)
 {
-    double angle, tmp1, tmp2;
+    double angle, tmp, squared_length1, squared_length2;
     double *othercoords;
     Py_ssize_t otherdim;
     PyVector* v = (PyVector*)self;
@@ -628,10 +645,17 @@
         return NULL;
     }
     
-    tmp1 = _ScalarProduct (v->coords, v->coords, v->dim);
-    tmp2 = _ScalarProduct (othercoords, othercoords, otherdim);
-    angle = acos (_ScalarProduct (v->coords, othercoords, v->dim) /
-        sqrt (tmp1 * tmp2));
+    squared_length1 = _ScalarProduct (v->coords, v->coords, v->dim);
+    squared_length2 = _ScalarProduct (othercoords, othercoords, otherdim);
+    tmp = sqrt(squared_length1 * squared_length2);
+    if (tmp == 0.f)
+    {
+        PyErr_SetString (PyExc_ValueError, "angle to zero vector is undefined");
+        PyMem_Free (othercoords);
+        return NULL;
+    }
+
+    angle = acos (_ScalarProduct (v->coords, othercoords, v->dim) / tmp);
     PyMem_Free (othercoords);
 
     return PyFloat_FromDouble (RAD2DEG (angle));
@@ -643,10 +667,12 @@
     PyVector* v = (PyVector*)self;
     double r, theta, phi;
     r = sqrt (_ScalarProduct (v->coords, v->coords, v->dim));
+    if (r == 0.f)
+        return Py_BuildValue ("(ddd)", 0.f, 0.f, 0.f);
 
     theta = acos (v->coords[2] / r);
     phi = atan2 (v->coords[1], v->coords[0]);
-    return Py_BuildValue ("(ddd)", r, theta, phi);
+    return Py_BuildValue ("(ddd)", r, RAD2DEG(theta), RAD2DEG(phi));
 }
 
 
diff -r fb31d86448f9 -r 8eafbb955d09 test/math_test.py
--- a/test/math_test.py	Mon Apr 12 15:51:01 2010 +0200
+++ b/test/math_test.py	Mon Apr 12 17:44:30 2010 +0200
@@ -24,15 +24,14 @@
         v = from_polar(*v1.as_polar())
         self.assertEqual(v1, v)
         self.assertEqual(e1.as_polar(), (1, 0))
-        self.assertEqual(e2.as_polar(), (1, math.pi / 2))
-        self.assertEqual((2 * e2).as_polar(),
-                         (2, math.pi / 2))
+        self.assertEqual(e2.as_polar(), (1, 90))
+        self.assertEqual((2 * e2).as_polar(), (2, 90))
         self.assertRaises(TypeError, lambda : from_polar((None, None)))
         self.assertRaises(TypeError, lambda : from_polar("ab"))
         self.assertRaises(TypeError, lambda : from_polar((None, 1)))
         self.assertRaises(TypeError, lambda : from_polar((1, 2, 3)))
         self.assertRaises(TypeError, lambda : from_polar((1,)))
-        v = from_polar(.5, math.pi / 2.)
+        v = from_polar(.5, 90)
         self.assertEqual(v, .5 * e2)
 
     def test_pygame2_math_base_vector_from_spherical(self):
@@ -49,18 +48,17 @@
         from_spherical = pmath.vector_from_spherical
         v = from_spherical(*v1.as_spherical())
         self.assertEqual(v1, v)
-        self.assertEqual(e1.as_spherical(), (1, math.pi / 2., 0))
-        self.assertEqual(e2.as_spherical(), (1, math.pi / 2., math.pi / 2))
+        self.assertEqual(e1.as_spherical(), (1, 90, 0))
+        self.assertEqual(e2.as_spherical(), (1, 90, 90))
         self.assertEqual(e3.as_spherical(), (1, 0, 0))
-        self.assertEqual((2 * e2).as_spherical(),
-                         (2, math.pi / 2., math.pi / 2))
+        self.assertEqual((2 * e2).as_spherical(), (2, 90, 90))
         self.assertRaises(TypeError, lambda : from_spherical((None, None, None)))
         self.assertRaises(TypeError, lambda : from_spherical("abc"))
         self.assertRaises(TypeError, lambda : from_spherical((None, 1, 2)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2, 3, 4)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2, 3)))
-        v = from_spherical(.5, math.pi / 2., math.pi / 2.)
+        v = from_spherical(.5, 90, 90)
         self.assertEqual(v, .5 * e2)
 
 if __name__ == "__main__":
diff -r fb31d86448f9 -r 8eafbb955d09 test/math_vector2_test.py
--- a/test/math_vector2_test.py	Mon Apr 12 15:51:01 2010 +0200
+++ b/test/math_vector2_test.py	Mon Apr 12 17:44:30 2010 +0200
@@ -413,7 +413,7 @@
         self.assertEqual(self.v1.y, self.l1[1])
         # v2 is paralell to v1
         self.assertAlmostEqual(self.v1.x * v.y - self.v1.y * v.x, 0.)
-        self.assertRaises(ZeroDivisionError, lambda : self.zeroVec.normalize())
+        self.assertRaises(ValueError, lambda : self.zeroVec.normalize())
 
     def test_pygame2_math_base_Vector_normalize_ip(self):
 
@@ -429,8 +429,7 @@
         self.assertAlmostEqual(v.x * v.x + v.y * v.y, 1.)
         # v2 is paralell to v1
         self.assertAlmostEqual(self.v1.x * v.y - self.v1.y * v.x, 0.)
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.zeroVec.normalize_ip())
+        self.assertRaises(ValueError, lambda : self.zeroVec.normalize_ip())
 
     def test_pygame2_math_base_Vector_distance(self):
 
@@ -501,7 +500,7 @@
         self.assertEqual(v.reflect(n), Vector2(1, 1))
         self.assertEqual(v.reflect(3*n), v.reflect(n))
         self.assertEqual(v.reflect(-v), -v)
-        self.assertRaises(ZeroDivisionError, lambda : v.reflect(self.zeroVec))
+        self.assertRaises(ValueError, lambda : v.reflect(self.zeroVec))
 
     def test_pygame2_math_base_Vector_reflect_ip(self):
 
@@ -519,7 +518,7 @@
         v2 = Vector2(v1)
         v2.reflect_ip(-v1)
         self.assertEqual(v2, -v1)
-        self.assertRaises(ZeroDivisionError, lambda : v2.reflect_ip(Vector2()))
+        self.assertRaises(ValueError, lambda : v2.reflect_ip(Vector2()))
 
     def test_pygame2_math_base_Vector_scale_to(self):
 
@@ -529,8 +528,7 @@
         v = Vector2(1, 1)
         v.scale_to(2.5)
         self.assertEqual(v, Vector2(2.5, 2.5) / math.sqrt(2))
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.zeroVec.scale_to(1))
+        self.assertRaises(ValueError, lambda : self.zeroVec.scale_to(1))
         self.assertEqual(v.scale_to(0), None)
         self.assertEqual(v, self.zeroVec)
 
@@ -564,15 +562,15 @@
         v = from_polar(*self.v1.as_polar())
         self.assertEqual(self.v1, v)
         self.assertEqual(self.e1.as_polar(), (1, 0))
-        self.assertEqual(self.e2.as_polar(), (1, math.pi / 2))
+        self.assertEqual(self.e2.as_polar(), (1, 90))
         self.assertEqual((2 * self.e2).as_polar(),
-                         (2, math.pi / 2))
+                         (2, 90))
         self.assertRaises(TypeError, lambda : from_polar((None, None)))
         self.assertRaises(TypeError, lambda : from_polar("ab"))
         self.assertRaises(TypeError, lambda : from_polar((None, 1)))
         self.assertRaises(TypeError, lambda : from_polar((1, 2, 3)))
         self.assertRaises(TypeError, lambda : from_polar((1,)))
-        v = from_polar(.5, math.pi / 2.)
+        v = from_polar(.5, 90)
         self.assertEqual(v, .5 * self.e2)
 
     def test_pygame2_math_base_Vector2_cross(self):
diff -r fb31d86448f9 -r 8eafbb955d09 test/math_vector3_test.py
--- a/test/math_vector3_test.py	Mon Apr 12 15:51:01 2010 +0200
+++ b/test/math_vector3_test.py	Mon Apr 12 17:44:30 2010 +0200
@@ -162,7 +162,7 @@
         self.assertEqual(type(b), type(self.v1))
         self.assertEqual(type(c), type(self.v1))
         def bogus_subscript_ass():
-            v = Vector2()
+            v = Vector3()
             v["spam"] = 3
         self.assertRaises(TypeError, bogus_subscript_ass)
         self.assertRaises(TypeError, lambda : v["spam"])
@@ -629,7 +629,7 @@
                  (self.v1.z * v.x - self.v1.x * v.z) ** 2 +
                  (self.v1.x * v.y - self.v1.y * v.x) ** 2)
         self.assertAlmostEqual(cross, 0.)
-        self.assertRaises(ZeroDivisionError, lambda : self.zeroVec.normalize())
+        self.assertRaises(ValueError, lambda : self.zeroVec.normalize())
         
     def test_normalize_ip(self):
         v = +self.v1
@@ -644,8 +644,7 @@
                  (self.v1.z * v.x - self.v1.x * v.z) ** 2 +
                  (self.v1.x * v.y - self.v1.y * v.x) ** 2)
         self.assertAlmostEqual(cross, 0.)
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.zeroVec.normalize_ip())
+        self.assertRaises(ValueError, lambda : self.zeroVec.normalize_ip())
 
     def test_normalized(self):
         self.assertEqual(self.v1.normalized, False)
@@ -668,7 +667,7 @@
         v = Vector3(1, 1, 1)
         v.scale_to(2.5)
         self.assertEqual(v, Vector3(2.5, 2.5, 2.5) / math.sqrt(3))
-        self.assertRaises(ZeroDivisionError, lambda : self.zeroVec.scale_to(1))
+        self.assertRaises(ValueError, lambda : self.zeroVec.scale_to(1))
         self.assertEqual(v.scale_to(0), None)
         self.assertEqual(v, self.zeroVec)
 
@@ -688,7 +687,7 @@
         self.assertEqual(v.reflect(n), Vector3(1, 1, 1))
         self.assertEqual(v.reflect(3*n), v.reflect(n))
         self.assertEqual(v.reflect(-v), -v)
-        self.assertRaises(ZeroDivisionError, lambda : v.reflect(self.zeroVec))
+        self.assertRaises(ValueError, lambda : v.reflect(self.zeroVec))
         
     def test_reflect_ip(self):
         v1 = Vector3(1, -1, 1)
@@ -702,7 +701,7 @@
         v2 = Vector3(v1)
         v2.reflect_ip(-v1)
         self.assertEqual(v2, -v1)
-        self.assertRaises(ZeroDivisionError, lambda : v2.reflect_ip(self.zeroVec))
+        self.assertRaises(ValueError, lambda : v2.reflect_ip(self.zeroVec))
 
     def test_distance(self):
         diff = self.v1 - self.v2
@@ -723,11 +722,9 @@
                                self.v2.distance_squared(self.v1))
     
     def test_slerp(self):
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.zeroVec.slerp(self.v1, .5))
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.v1.slerp(self.zeroVec, .5))
-        self.assertRaises(ZeroDivisionError,
+        self.assertRaises(ValueError, lambda : self.zeroVec.slerp(self.v1, .5))
+        self.assertRaises(ValueError, lambda : self.v1.slerp(self.zeroVec, .5))
+        self.assertRaises(ValueError,
                           lambda : self.zeroVec.slerp(self.zeroVec, .5))
         steps = 10
         angle_step = self.e1.angle_to(self.e2) / steps
@@ -748,18 +745,17 @@
         from_spherical = pmath.vector_from_spherical
         v = from_spherical(*self.v1.as_spherical ())
         self.assertEqual(self.v1, v)
-        self.assertEqual(self.e1.as_spherical(), (1, math.pi / 2., 0))
-        self.assertEqual(self.e2.as_spherical(), (1, math.pi / 2., math.pi / 2))
+        self.assertEqual(self.e1.as_spherical(), (1, 90, 0))
+        self.assertEqual(self.e2.as_spherical(), (1, 90, 90))
         self.assertEqual(self.e3.as_spherical(), (1, 0, 0))
-        self.assertEqual((2 * self.e2).as_spherical(),
-                         (2, math.pi / 2., math.pi / 2))
+        self.assertEqual((2 * self.e2).as_spherical(), (2, 90, 90))
         self.assertRaises(TypeError, lambda : from_spherical((None, None, None)))
         self.assertRaises(TypeError, lambda : from_spherical("abc"))
         self.assertRaises(TypeError, lambda : from_spherical((None, 1, 2)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2, 3, 4)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2, 3)))
-        v = from_spherical(.5, math.pi / 2., math.pi / 2.)
+        v = from_spherical(.5, 90, 90)
         self.assertEqual(v, .5 * self.e2)
 
 if __name__ == "__main__":
diff -r fb31d86448f9 -r 836db69eedd1 src/math/vector.c
--- a/src/math/vector.c	Mon Apr 12 15:51:01 2010 +0200
+++ b/src/math/vector.c	Mon Apr 12 16:29:16 2010 +0200
@@ -632,7 +632,7 @@
     length = sqrt (_ScalarProduct(self->coords, self->coords, self->dim));
     if (length == 0)
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "can not normalize vector of length 0");
         return NULL;
     }
@@ -652,7 +652,7 @@
     length = sqrt (_ScalarProduct (self->coords, self->coords, self->dim));
     if (length == 0)
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "can not normalize vector of length 0");
         return NULL;
     }
@@ -703,7 +703,7 @@
 
     if ((length1 < self->epsilon) || (length2 < self->epsilon))
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "can not use slerp with zero-Vector");
         PyMem_Free (othercoords);
         return NULL;
@@ -828,7 +828,7 @@
 
     if (oldlength < self->epsilon)
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "cannot scale a vector with zero length");
         return NULL;
     }
@@ -874,7 +874,7 @@
         nlength += ncoords[i] * ncoords[i];
     if (nlength < eps)
     {
-        PyErr_SetString (PyExc_ZeroDivisionError,
+        PyErr_SetString (PyExc_ValueError,
             "normal must not be a zero-length vector");
         goto ret;
     }
@@ -1139,6 +1139,11 @@
         double tmp;
         if (!DoubleFromObj (other, &tmp))
             break;
+        if (tmp == 0.f)
+        {
+            PyErr_SetString (PyExc_ZeroDivisionError, "division by zero");
+            return NULL;
+        }
         tmp = 1.f / tmp;
         retval = PyVector_NewSpecialized (dim);
         if (!retval)
@@ -1152,6 +1157,11 @@
         double tmp;
         if (!DoubleFromObj (other, &tmp))
             break;
+        if (tmp == 0.f)
+        {
+            PyErr_SetString (PyExc_ZeroDivisionError, "division by zero");
+            return NULL;
+        }
         tmp = 1. / tmp;
         for (i = 0; i < dim; i++)
             vcoords[i] *= tmp;
@@ -1164,6 +1174,11 @@
         double tmp;
         if (!DoubleFromObj (other, &tmp))
             break;
+        if (tmp == 0.f)
+        {
+            PyErr_SetString (PyExc_ZeroDivisionError, "division by zero");
+            return NULL;
+        }
         tmp = 1. / tmp;
         retval = PyVector_NewSpecialized(dim);
         if (!retval)
@@ -1177,6 +1192,11 @@
         double tmp;
         if (!DoubleFromObj (other, &tmp))
             break;
+        if (tmp == 0.f)
+        {
+            PyErr_SetString (PyExc_ZeroDivisionError, "division by zero");
+            return NULL;
+        }
         tmp = 1. / tmp;
         for (i = 0; i < dim; i++)
             v->coords[i] = floor (vcoords[i] * tmp);
@@ -1317,7 +1337,7 @@
     Py_ssize_t i;
     for (i = 0; i < self->dim; i++)
     {
-        if (fabs (self->coords[i]) > self->epsilon)
+        if (self->coords[i] != 0.f)
             return 1;
     }
     return 0;
diff -r fb31d86448f9 -r 836db69eedd1 src/math/vector3.c
--- a/src/math/vector3.c	Mon Apr 12 15:51:01 2010 +0200
+++ b/src/math/vector3.c	Mon Apr 12 16:29:16 2010 +0200
@@ -34,7 +34,7 @@
 static PyObject* _vector3_get_z (PyObject *self, void *closure);
 static int _vector3_set_z (PyObject *self, PyObject *value, void *closure);
 
-static void _do_rotate (double *dst_coords, const double *src_coords,
+static int _do_rotate (double *dst_coords, const double *src_coords,
     const double* axis_coords, double angle, double epsilon);
 
 static PyObject* _vector3_rotate (PyObject *self, PyObject *args);
@@ -261,7 +261,7 @@
 }
 
 /* Vector3 methods */
-static void
+static int
 _do_rotate (double *dst_coords, const double *src_coords,
     const double* axis_coords, double angle, double epsilon)
 {
@@ -282,6 +282,13 @@
         axis[i] = axis_coords[i];
     }
 
+    if (axislen < epsilon)
+    {
+        PyErr_SetString (PyExc_ValueError,
+            "rotation axis is too close to zero.");
+        return 0;
+    }
+ 
     /* normalize the axis */
     if (axislen - 1 > epsilon)
     {
@@ -353,6 +360,7 @@
              src_coords[1] * (axis[1] * axis[2] * coscompl + axis[0] * sinv) +
              src_coords[2] * (cosv + axis[2] * axis[2] * coscompl));
     }
+    return 1;
 }
 
 static PyObject*
@@ -384,7 +392,12 @@
         return NULL;
     }
     ret = (PyVector*) PyVector3_New (0.f, 0.f, 0.f);
-    _do_rotate (ret->coords, v->coords, axiscoords, angle, v->epsilon);
+    if (!ret || 
+        !_do_rotate (ret->coords, v->coords, axiscoords, angle, v->epsilon))
+    {
+        Py_XDECREF(ret);
+        ret = NULL;
+    }
     PyMem_Free (axiscoords);
     return (PyObject*) ret;
 }
@@ -418,7 +431,11 @@
     }
 
     memcpy (tmp, v->coords, sizeof (double) * 3);
-    _do_rotate (v->coords, tmp, axiscoords, angle, v->epsilon);
+    if (!_do_rotate (v->coords, tmp, axiscoords, angle, v->epsilon))
+    {
+        PyMem_Free (axiscoords);
+        return NULL;
+    }
     PyMem_Free (axiscoords);
     Py_RETURN_NONE;
 }
@@ -606,7 +623,7 @@
 static PyObject*
 _vector3_angleto (PyObject *self, PyObject *args)
 {
-    double angle, tmp1, tmp2;
+    double angle, tmp, squared_length1, squared_length2;
     double *othercoords;
     Py_ssize_t otherdim;
     PyVector* v = (PyVector*)self;
@@ -628,10 +645,17 @@
         return NULL;
     }
     
-    tmp1 = _ScalarProduct (v->coords, v->coords, v->dim);
-    tmp2 = _ScalarProduct (othercoords, othercoords, otherdim);
-    angle = acos (_ScalarProduct (v->coords, othercoords, v->dim) /
-        sqrt (tmp1 * tmp2));
+    squared_length1 = _ScalarProduct (v->coords, v->coords, v->dim);
+    squared_length2 = _ScalarProduct (othercoords, othercoords, otherdim);
+    tmp = sqrt(squared_length1 * squared_length2);
+    if (tmp == 0.f)
+    {
+        PyErr_SetString (PyExc_ValueError, "angle to zero vector is undefined");
+        PyMem_Free (othercoords);
+        return NULL;
+    }
+
+    angle = acos (_ScalarProduct (v->coords, othercoords, v->dim) / tmp);
     PyMem_Free (othercoords);
 
     return PyFloat_FromDouble (RAD2DEG (angle));
@@ -643,6 +667,8 @@
     PyVector* v = (PyVector*)self;
     double r, theta, phi;
     r = sqrt (_ScalarProduct (v->coords, v->coords, v->dim));
+    if (r == 0.f)
+        return Py_BuildValue ("(ddd)", 0.f, 0.f, 0.f);
 
     theta = acos (v->coords[2] / r);
     phi = atan2 (v->coords[1], v->coords[0]);
diff -r 631736a6ae2b -r 5efe286b0f07 src/math/vector.c
--- a/src/math/vector.c	Mon Apr 12 16:32:39 2010 +0200
+++ b/src/math/vector.c	Mon Apr 12 17:01:19 2010 +0200
@@ -669,7 +669,7 @@
     PyObject *other;
     PyVector *ret;
     double *othercoords;
-    double angle, t, length1, length2, f0, f1, f2;
+    double angle, t, length1, length2, f0, f1, f2, tmp;
 
     if (!PyArg_ParseTuple(args, "Od:slerp", &other, &t))
         return NULL;
@@ -708,8 +708,11 @@
         PyMem_Free (othercoords);
         return NULL;
     }
-    angle = acos (_ScalarProduct (self->coords, othercoords, self->dim) /
-        (length1 * length2));
+    tmp = _ScalarProduct (self->coords, othercoords, self->dim) /
+        (length1 * length2);
+    /* make sure tmp is in the range [-1:1] so acos won't return NaN */
+    tmp = (tmp < -1 ? -1 : (tmp > 1 ? 1 : tmp));
+    angle = acos (tmp);
 
     if (t < 0)
     {
@@ -726,12 +729,28 @@
         PyMem_Free (othercoords);
         return NULL;
     }
-    f0 = ((length2 - length1) * t + length1) / sin (angle);
-    f1 = sin (angle * (1 - t)) / length1;
-    f2 = sin (angle * t) / length2;
-    for (i = 0; i < self->dim; ++i)
-        ret->coords[i] = (self->coords[i] * f1 + othercoords[i] * f2) * f0;
-
+    /* special case angle==0 and angle==360 */
+    if ((fabs(angle) < self->epsilon) || 
+        (fabs(fabs(angle) - 2 * M_PI) < self->epsilon)) {
+        /* approximate with lerp, because slerp diverges with 1/sin(angle) */
+        for (i = 0; i < self->dim; ++i)
+            ret->coords[i] = self->coords[i] * (1 - t) + othercoords[i] * t;
+    }
+    /* special case angle==180 and angle==-180 */
+    else if (fabs(fabs(angle) - M_PI) < self->epsilon) {
+        PyErr_SetString(PyExc_ValueError, 
+                        "SLERP with 180 degrees is undefined.");
+        Py_DECREF(ret);
+        PyMem_Free (othercoords);
+        return NULL;
+    }
+    else {
+        f0 = ((length2 - length1) * t + length1) / sin (angle);
+        f1 = sin (angle * (1 - t)) / length1;
+        f2 = sin (angle * t) / length2;
+        for (i = 0; i < self->dim; ++i)
+            ret->coords[i] = (self->coords[i] * f1 + othercoords[i] * f2) * f0;
+    }
     PyMem_Free (othercoords);
     return (PyObject*) ret;
 }
@@ -765,9 +784,9 @@
         return NULL;
     }
 
-    if (fabs (t) > 1)
+    if (t < 0 || t > 1)
     {
-        PyErr_SetString (PyExc_ValueError, "t must be in range [-1, 1]");
+        PyErr_SetString (PyExc_ValueError, "t must be in range [0, 1]");
         PyMem_Free (othercoords);
         return NULL;
     }
diff -r 631736a6ae2b -r 5efe286b0f07 src/math/vector2.c
--- a/src/math/vector2.c	Mon Apr 12 16:32:39 2010 +0200
+++ b/src/math/vector2.c	Mon Apr 12 17:01:19 2010 +0200
@@ -360,7 +360,7 @@
     double r, phi;
     r = sqrt(_ScalarProduct (self->coords, self->coords, self->dim));
     phi = atan2 (self->coords[1], self->coords[0]);
-    return Py_BuildValue ("(dd)", r, phi);
+    return Py_BuildValue ("(dd)", r, RAD2DEG(phi));
 }
 
 /* C API */
diff -r 631736a6ae2b -r 5efe286b0f07 src/math/vector3.c
--- a/src/math/vector3.c	Mon Apr 12 16:32:39 2010 +0200
+++ b/src/math/vector3.c	Mon Apr 12 17:01:19 2010 +0200
@@ -672,7 +672,7 @@
 
     theta = acos (v->coords[2] / r);
     phi = atan2 (v->coords[1], v->coords[0]);
-    return Py_BuildValue ("(ddd)", r, theta, phi);
+    return Py_BuildValue ("(ddd)", r, RAD2DEG(theta), RAD2DEG(phi));
 }
 
 
diff -r 631736a6ae2b -r 5efe286b0f07 test/math_test.py
--- a/test/math_test.py	Mon Apr 12 16:32:39 2010 +0200
+++ b/test/math_test.py	Mon Apr 12 17:01:19 2010 +0200
@@ -24,15 +24,14 @@
         v = from_polar(*v1.as_polar())
         self.assertEqual(v1, v)
         self.assertEqual(e1.as_polar(), (1, 0))
-        self.assertEqual(e2.as_polar(), (1, math.pi / 2))
-        self.assertEqual((2 * e2).as_polar(),
-                         (2, math.pi / 2))
+        self.assertEqual(e2.as_polar(), (1, 90))
+        self.assertEqual((2 * e2).as_polar(), (2, 90))
         self.assertRaises(TypeError, lambda : from_polar((None, None)))
         self.assertRaises(TypeError, lambda : from_polar("ab"))
         self.assertRaises(TypeError, lambda : from_polar((None, 1)))
         self.assertRaises(TypeError, lambda : from_polar((1, 2, 3)))
         self.assertRaises(TypeError, lambda : from_polar((1,)))
-        v = from_polar(.5, math.pi / 2.)
+        v = from_polar(.5, 90)
         self.assertEqual(v, .5 * e2)
 
     def test_pygame2_math_base_vector_from_spherical(self):
@@ -49,18 +48,17 @@
         from_spherical = pmath.vector_from_spherical
         v = from_spherical(*v1.as_spherical())
         self.assertEqual(v1, v)
-        self.assertEqual(e1.as_spherical(), (1, math.pi / 2., 0))
-        self.assertEqual(e2.as_spherical(), (1, math.pi / 2., math.pi / 2))
+        self.assertEqual(e1.as_spherical(), (1, 90, 0))
+        self.assertEqual(e2.as_spherical(), (1, 90, 90))
         self.assertEqual(e3.as_spherical(), (1, 0, 0))
-        self.assertEqual((2 * e2).as_spherical(),
-                         (2, math.pi / 2., math.pi / 2))
+        self.assertEqual((2 * e2).as_spherical(), (2, 90, 90))
         self.assertRaises(TypeError, lambda : from_spherical((None, None, None)))
         self.assertRaises(TypeError, lambda : from_spherical("abc"))
         self.assertRaises(TypeError, lambda : from_spherical((None, 1, 2)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2, 3, 4)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2, 3)))
-        v = from_spherical(.5, math.pi / 2., math.pi / 2.)
+        v = from_spherical(.5, 90, 90)
         self.assertEqual(v, .5 * e2)
 
 if __name__ == "__main__":
diff -r 631736a6ae2b -r 5efe286b0f07 test/math_vector2_test.py
--- a/test/math_vector2_test.py	Mon Apr 12 16:32:39 2010 +0200
+++ b/test/math_vector2_test.py	Mon Apr 12 17:01:19 2010 +0200
@@ -413,7 +413,7 @@
         self.assertEqual(self.v1.y, self.l1[1])
         # v2 is paralell to v1
         self.assertAlmostEqual(self.v1.x * v.y - self.v1.y * v.x, 0.)
-        self.assertRaises(ZeroDivisionError, lambda : self.zeroVec.normalize())
+        self.assertRaises(ValueError, lambda : self.zeroVec.normalize())
 
     def test_pygame2_math_base_Vector_normalize_ip(self):
 
@@ -429,8 +429,7 @@
         self.assertAlmostEqual(v.x * v.x + v.y * v.y, 1.)
         # v2 is paralell to v1
         self.assertAlmostEqual(self.v1.x * v.y - self.v1.y * v.x, 0.)
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.zeroVec.normalize_ip())
+        self.assertRaises(ValueError, lambda : self.zeroVec.normalize_ip())
 
     def test_pygame2_math_base_Vector_distance(self):
 
@@ -501,7 +500,7 @@
         self.assertEqual(v.reflect(n), Vector2(1, 1))
         self.assertEqual(v.reflect(3*n), v.reflect(n))
         self.assertEqual(v.reflect(-v), -v)
-        self.assertRaises(ZeroDivisionError, lambda : v.reflect(self.zeroVec))
+        self.assertRaises(ValueError, lambda : v.reflect(self.zeroVec))
 
     def test_pygame2_math_base_Vector_reflect_ip(self):
 
@@ -519,7 +518,7 @@
         v2 = Vector2(v1)
         v2.reflect_ip(-v1)
         self.assertEqual(v2, -v1)
-        self.assertRaises(ZeroDivisionError, lambda : v2.reflect_ip(Vector2()))
+        self.assertRaises(ValueError, lambda : v2.reflect_ip(Vector2()))
 
     def test_pygame2_math_base_Vector_scale_to(self):
 
@@ -529,8 +528,7 @@
         v = Vector2(1, 1)
         v.scale_to(2.5)
         self.assertEqual(v, Vector2(2.5, 2.5) / math.sqrt(2))
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.zeroVec.scale_to(1))
+        self.assertRaises(ValueError, lambda : self.zeroVec.scale_to(1))
         self.assertEqual(v.scale_to(0), None)
         self.assertEqual(v, self.zeroVec)
 
@@ -564,15 +562,15 @@
         v = from_polar(*self.v1.as_polar())
         self.assertEqual(self.v1, v)
         self.assertEqual(self.e1.as_polar(), (1, 0))
-        self.assertEqual(self.e2.as_polar(), (1, math.pi / 2))
+        self.assertEqual(self.e2.as_polar(), (1, 90))
         self.assertEqual((2 * self.e2).as_polar(),
-                         (2, math.pi / 2))
+                         (2, 90))
         self.assertRaises(TypeError, lambda : from_polar((None, None)))
         self.assertRaises(TypeError, lambda : from_polar("ab"))
         self.assertRaises(TypeError, lambda : from_polar((None, 1)))
         self.assertRaises(TypeError, lambda : from_polar((1, 2, 3)))
         self.assertRaises(TypeError, lambda : from_polar((1,)))
-        v = from_polar(.5, math.pi / 2.)
+        v = from_polar(.5, 90)
         self.assertEqual(v, .5 * self.e2)
 
     def test_pygame2_math_base_Vector2_cross(self):
diff -r 631736a6ae2b -r 5efe286b0f07 test/math_vector3_test.py
--- a/test/math_vector3_test.py	Mon Apr 12 16:32:39 2010 +0200
+++ b/test/math_vector3_test.py	Mon Apr 12 17:01:19 2010 +0200
@@ -162,7 +162,7 @@
         self.assertEqual(type(b), type(self.v1))
         self.assertEqual(type(c), type(self.v1))
         def bogus_subscript_ass():
-            v = Vector2()
+            v = Vector3()
             v["spam"] = 3
         self.assertRaises(TypeError, bogus_subscript_ass)
         self.assertRaises(TypeError, lambda : v["spam"])
@@ -629,7 +629,7 @@
                  (self.v1.z * v.x - self.v1.x * v.z) ** 2 +
                  (self.v1.x * v.y - self.v1.y * v.x) ** 2)
         self.assertAlmostEqual(cross, 0.)
-        self.assertRaises(ZeroDivisionError, lambda : self.zeroVec.normalize())
+        self.assertRaises(ValueError, lambda : self.zeroVec.normalize())
         
     def test_normalize_ip(self):
         v = +self.v1
@@ -644,8 +644,7 @@
                  (self.v1.z * v.x - self.v1.x * v.z) ** 2 +
                  (self.v1.x * v.y - self.v1.y * v.x) ** 2)
         self.assertAlmostEqual(cross, 0.)
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.zeroVec.normalize_ip())
+        self.assertRaises(ValueError, lambda : self.zeroVec.normalize_ip())
 
     def test_normalized(self):
         self.assertEqual(self.v1.normalized, False)
@@ -668,7 +667,7 @@
         v = Vector3(1, 1, 1)
         v.scale_to(2.5)
         self.assertEqual(v, Vector3(2.5, 2.5, 2.5) / math.sqrt(3))
-        self.assertRaises(ZeroDivisionError, lambda : self.zeroVec.scale_to(1))
+        self.assertRaises(ValueError, lambda : self.zeroVec.scale_to(1))
         self.assertEqual(v.scale_to(0), None)
         self.assertEqual(v, self.zeroVec)
 
@@ -688,7 +687,7 @@
         self.assertEqual(v.reflect(n), Vector3(1, 1, 1))
         self.assertEqual(v.reflect(3*n), v.reflect(n))
         self.assertEqual(v.reflect(-v), -v)
-        self.assertRaises(ZeroDivisionError, lambda : v.reflect(self.zeroVec))
+        self.assertRaises(ValueError, lambda : v.reflect(self.zeroVec))
         
     def test_reflect_ip(self):
         v1 = Vector3(1, -1, 1)
@@ -702,7 +701,7 @@
         v2 = Vector3(v1)
         v2.reflect_ip(-v1)
         self.assertEqual(v2, -v1)
-        self.assertRaises(ZeroDivisionError, lambda : v2.reflect_ip(self.zeroVec))
+        self.assertRaises(ValueError, lambda : v2.reflect_ip(self.zeroVec))
 
     def test_distance(self):
         diff = self.v1 - self.v2
@@ -723,11 +722,9 @@
                                self.v2.distance_squared(self.v1))
     
     def test_slerp(self):
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.zeroVec.slerp(self.v1, .5))
-        self.assertRaises(ZeroDivisionError,
-                          lambda : self.v1.slerp(self.zeroVec, .5))
-        self.assertRaises(ZeroDivisionError,
+        self.assertRaises(ValueError, lambda : self.zeroVec.slerp(self.v1, .5))
+        self.assertRaises(ValueError, lambda : self.v1.slerp(self.zeroVec, .5))
+        self.assertRaises(ValueError,
                           lambda : self.zeroVec.slerp(self.zeroVec, .5))
         steps = 10
         angle_step = self.e1.angle_to(self.e2) / steps
@@ -748,18 +745,17 @@
         from_spherical = pmath.vector_from_spherical
         v = from_spherical(*self.v1.as_spherical ())
         self.assertEqual(self.v1, v)
-        self.assertEqual(self.e1.as_spherical(), (1, math.pi / 2., 0))
-        self.assertEqual(self.e2.as_spherical(), (1, math.pi / 2., math.pi / 2))
+        self.assertEqual(self.e1.as_spherical(), (1, 90, 0))
+        self.assertEqual(self.e2.as_spherical(), (1, 90, 90))
         self.assertEqual(self.e3.as_spherical(), (1, 0, 0))
-        self.assertEqual((2 * self.e2).as_spherical(),
-                         (2, math.pi / 2., math.pi / 2))
+        self.assertEqual((2 * self.e2).as_spherical(), (2, 90, 90))
         self.assertRaises(TypeError, lambda : from_spherical((None, None, None)))
         self.assertRaises(TypeError, lambda : from_spherical("abc"))
         self.assertRaises(TypeError, lambda : from_spherical((None, 1, 2)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2, 3, 4)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2)))
         self.assertRaises(TypeError, lambda : from_spherical((1, 2, 3)))
-        v = from_spherical(.5, math.pi / 2., math.pi / 2.)
+        v = from_spherical(.5, 90, 90)
         self.assertEqual(v, .5 * self.e2)
 
 if __name__ == "__main__":
diff -r 5efe286b0f07 -r 8eafbb955d09 src/base/basemod.c
--- a/src/base/basemod.c	Mon Apr 12 17:01:19 2010 +0200
+++ b/src/base/basemod.c	Mon Apr 12 17:44:30 2010 +0200
@@ -109,8 +109,8 @@
     return 0;
 }
 
-unsigned long
-UlongFromObj (PyObject* obj, long* val)
+int
+UlongFromObj (PyObject* obj, unsigned long* val)
 {
     PyObject* longobj;
     unsigned long tmp;
diff -r 5efe286b0f07 -r 8eafbb955d09 src/base/internals.h
--- a/src/base/internals.h	Mon Apr 12 17:01:19 2010 +0200
+++ b/src/base/internals.h	Mon Apr 12 17:44:30 2010 +0200
@@ -60,7 +60,7 @@
 int ASCIIFromObj (PyObject *obj, char **text, PyObject **freeme);
 int UTF8FromObj (PyObject *obj, char **text, PyObject **freeme);
 int LongFromObj (PyObject* obj, long* val);
-unsigned long UlongFromObj (PyObject* obj, long* val);
+int UlongFromObj (PyObject* obj, unsigned long* val);
 int ColorFromObj (PyObject *obj, pguint32 *val);
 
 extern PyTypeObject PyColor_Type;
diff -r 5efe286b0f07 -r 8eafbb955d09 src/math/vector.c
--- a/src/math/vector.c	Mon Apr 12 17:01:19 2010 +0200
+++ b/src/math/vector.c	Mon Apr 12 17:44:30 2010 +0200
@@ -538,12 +538,18 @@
     PyVector *v = (PyVector *) self;
     Py_ssize_t i;
     
-    PyObject *tuple = PyTuple_New (v->dim);
+    PyObject *tmp, *tuple = PyTuple_New (v->dim);
     if (!tuple)
         return NULL;
     for (i = 0; i < v->dim; i++)
     {
-        PyTuple_SET_ITEM (tuple, i, PyFloat_FromDouble (v->coords[i]));
+        tmp = PyFloat_FromDouble (v->coords[i]);
+        if (!tmp)
+        {
+            Py_DECREF (tuple);
+            return NULL;
+        }
+        PyTuple_SET_ITEM (tuple, i, tmp);
     }
     return tuple;
 }
@@ -841,9 +847,7 @@
     if (!DoubleFromObj (args, &newlength))
         return NULL;
 
-    for (i = 0; i < self->dim; ++i)
-        oldlength += self->coords[i] * self->coords[i];
-    oldlength = sqrt (oldlength);
+    oldlength = sqrt (_ScalarProduct (self->coords, self->coords, self->dim));
 
     if (oldlength < self->epsilon)
     {
@@ -888,9 +892,7 @@
     }
 
     /* Normalize the normal */
-    nlength = 0;
-    for (i = 0; i < ndim; i++)
-        nlength += ncoords[i] * ncoords[i];
+    nlength = _ScalarProduct(ncoords, ncoords, ndim);
     if (nlength < eps)
     {
         PyErr_SetString (PyExc_ValueError,
@@ -906,9 +908,7 @@
     }
 
     /* Calculate the dot product for the projection. */
-    dotprod = 0;
-    for (i = 0; i < dim; i++)
-        dotprod += srccoords[i] * ncoords[i];
+    dotprod = _ScalarProduct(srccoords, ncoords, dim);
         
     dstcoords = PyMem_New (double, dim);
     if (!dstcoords)
@@ -954,68 +954,54 @@
     Py_RETURN_NONE;
 }
 
-static PyObject*
-_vector_distance (PyVector *self, PyObject *args)
+static double
+_vector_distance_squared_as_double(PyVector *self, PyObject *args)
 {
     Py_ssize_t otherdim, i;
-    double *othercoords, distance, tmp;
+    double *othercoords, distance_squared, tmp;
 
     if (!IsVectorCompatible (args))
     {
         PyErr_SetString (PyExc_TypeError, "other must be a vector compatible");
-        return NULL;
+        return -1;
     }
 
     othercoords = VectorCoordsFromObj (args, &otherdim);
     if (!othercoords)
-        return NULL;
+        return -1;
     if (otherdim != self->dim)
     {
         PyErr_SetString (PyExc_ValueError,
             "must have same the same dimension as vector");
         PyMem_Free (othercoords);
-        return NULL;
+        return -1;
     }
-    distance = 0;
+    distance_squared = 0;
     for (i = 0; i < self->dim; i++)
     {
         tmp = othercoords[i] - self->coords[i];
-        distance += tmp * tmp;
+        distance_squared += tmp * tmp;
     }
     PyMem_Free (othercoords);
-    return PyFloat_FromDouble (sqrt (distance));
+    return distance_squared;
+ }
+
+static PyObject*
+_vector_distance (PyVector *self, PyObject *args)
+{
+    double distance_squared = _vector_distance_squared_as_double (self, args);
+    if (distance_squared == -1 && PyErr_Occurred())
+        return NULL;
+    return PyFloat_FromDouble (sqrt (distance_squared));
 }
 
 static PyObject*
 _vector_distance_squared (PyVector *self, PyObject *args)
 {
-    Py_ssize_t otherdim, i;
-    double *othercoords, distance, tmp;
-
-    if (!IsVectorCompatible (args))
-    {
-        PyErr_SetString (PyExc_TypeError, "other must be a vector compatible");
+    double distance_squared = _vector_distance_squared_as_double (self, args);
+    if (distance_squared == -1 && PyErr_Occurred())
         return NULL;
-    }
-
-    othercoords = VectorCoordsFromObj (args, &otherdim);
-    if (!othercoords)
-        return NULL;
-    if (otherdim != self->dim)
-    {
-        PyErr_SetString (PyExc_ValueError,
-            "must have same the same dimension as vector");
-        PyMem_Free (othercoords);
-        return NULL;
-    }
-    distance = 0;
-    for (i = 0; i < self->dim; i++)
-    {
-        tmp = othercoords[i] - self->coords[i];
-        distance += tmp * tmp;
-    }
-    PyMem_Free (othercoords);
-    return PyFloat_FromDouble (distance);
+    return PyFloat_FromDouble (distance_squared);
 }
 
 static PyObject*
@@ -1326,7 +1312,7 @@
 }
 
 /**
- * -vector1, ~vector1
+ * -vector1, +vector1
  */
 static PyObject*
 _vector_neg (PyVector *self)
@@ -1636,7 +1622,7 @@
     double diff;
     PyVector *v = NULL, *v2 = NULL;
     PyObject *other = NULL;
-    int swap = 0, retval = 1;
+    int retval = 1;
     
     if (PyVector_Check (o1))
     {
@@ -1645,7 +1631,6 @@
     }
     else if (PyVector_Check (o2))
     {
-        swap = 1;
         v = (PyVector *) o2;
         other = o1;
     }
@@ -1686,13 +1671,6 @@
             }
         }
     }
-    if (swap == 1)
-    {
-        if (retval == 0)
-            retval = 1;
-        else
-            retval = 0;
-    }
 
     switch (op)
     {
diff -r 5efe286b0f07 -r 8eafbb955d09 src/math/vector3.c
--- a/src/math/vector3.c	Mon Apr 12 17:01:19 2010 +0200
+++ b/src/math/vector3.c	Mon Apr 12 17:44:30 2010 +0200
@@ -290,7 +290,7 @@
     }
  
     /* normalize the axis */
-    if (axislen - 1 > epsilon)
+    if (fabs(axislen - 1) > epsilon)
     {
         nfactor = 1. / sqrt (axislen);
         for (i = 0; i < 3; ++i)