Commits

Anonymous committed 219506a

More math module portage (from trunk). Fixed memory leak in sdl.time. Fixed width/height args in base.Rect constructor for some 64 bit platforms.

  • Participants
  • Parent commits 3cf808f
  • Branches pgreloaded

Comments (0)

Files changed (10)

File doc/src/mathbase.xml

     <call>vector_from_polar (p1, p2) -> Vector2</call>
     <desc></desc>
   </func>
-
+  <func name="vector_from_spherical">
+    <call>vector_from_spherical (p1, p2, p3) -> Vector2</call>
+    <desc></desc>
+  </func>
 
   <class name="Vector">
     <constructor>Vector () -> Vector</constructor>
       <desc></desc>
     </method>
     <method name="cross">
-      <call>cross (v) -> Vector</call>
+      <call>cross (v) -> Vector2</call>
       <desc></desc>
     </method>
   </class>
     <attr name="z">
       <desc>Gets or sets third element of the :class:`Vector3`.</desc>
     </attr>
+    <method name="rotate_x">
+      <call>rotate_x () -> Vector3</call>
+      <desc></desc>
+    </method>
+    <method name="rotate_x_ip">
+      <call>rotate_x_ip () -> None</call>
+      <desc></desc>
+    </method>
+    <method name="rotate_y">
+      <call>rotate_y () -> Vector3</call>
+      <desc></desc>
+    </method>
+    <method name="rotate_y_ip">
+      <call>rotate_y_ip () -> None</call>
+      <desc></desc>
+    </method>
+    <method name="rotate_z">
+      <call>rotate_z () -> Vector3</call>
+      <desc></desc>
+    </method>
+    <method name="rotate_z_ip">
+      <call>rotate_z_ip () -> None</call>
+      <desc></desc>
+    </method>
+    <method name="rotate">
+      <call>rotate () -> Vector3</call>
+      <desc></desc>
+    </method>
+    <method name="rotate_ip">
+      <call>rotate_ip () -> Vector3</call>
+      <desc></desc>
+    </method>
+    <method name="angle_to">
+      <call>angle_to (v) -> float</call>
+      <desc></desc>
+    </method>
+    <method name="cross">
+      <call>cross (v) -> Vector3</call>
+      <desc></desc>
+    </method>
+    <method name="as_spherical">
+      <call>as_spherical () -> float, float, float</call>
+      <desc></desc>
+    </method>
   </class>
 
 </module>

File src/base/rect.c

     pgint16 x, y;
     pgint32 w, h;
 
-    if (!PyArg_ParseTuple (args, "iiii", &x, &y, &w, &h))
+    if (!PyArg_ParseTuple (args, "iill", &x, &y, &w, &h))
     {
         x = y = 0;
         PyErr_Clear ();
-        if (!PyArg_ParseTuple (args, "ii", &w, &h))
+        if (!PyArg_ParseTuple (args, "ll", &w, &h))
         {
             PyObject *pt, *rect;
             PyErr_Clear ();

File src/math/mathmod.c

 #include "mathbase_doc.h"
 
 static PyObject* _frompolar (PyObject* mod, PyObject *args);
+static PyObject* _fromspherical (PyObject* mod, PyObject *args);
 
 static PyMethodDef _math_methods[] = {
     { "vector_from_polar", _frompolar, METH_VARARGS,
       DOC_BASE_VECTOR_FROM_POLAR },
+    { "vector_from_spherical", _fromspherical, METH_VARARGS,
+      DOC_BASE_VECTOR_FROM_SPHERICAL },
     { NULL, NULL, 0, NULL },
 };
 
     return PyVector2_New (c1, c2);
 }
 
+static PyObject*
+_fromspherical (PyObject* mod, PyObject *args)
+{
+    double r, phi, theta, c1, c2, c3;
+
+    if (!PyArg_ParseTuple (args, "ddd:vector_from_spherical", &r, &theta, &phi))
+        return NULL;
+
+    c1 = r * sin (theta) * cos (phi);
+    c3 = r * sin (theta) * sin (phi);
+    c2 = r * cos (theta);
+
+    return PyVector3_New (c1, c2, c3);
+}
+
 /* Internally used methods */
 double
 _ScalarProduct (const double *coords1, const double *coords2, Py_ssize_t size)
 double*
 VectorCoordsFromObj (PyObject *object, Py_ssize_t *dims)
 {
-    double *coords;
+    double *coords= NULL;
 
     if (!object || !dims)
     {
         PyErr_SetString (PyExc_ValueError, "arguments must not be NULL");
         return NULL;
     }
+
     if (PyVector_Check (object))
     {
         *dims = ((PyVector*)object)->dim;
     else
     {
         PyErr_SetString (PyExc_TypeError,
-            "object must be a Vector or sequence");
+            "object must be a vector or sequence");
         return NULL;
     }
 }
         NULL, NULL, NULL, NULL
     };
 #endif
-    PyVector_Type.tp_new = PyType_GenericNew;
     if (PyType_Ready (&PyVector_Type) < 0)
         goto fail;
     Py_INCREF (&PyVector_Type);

File src/math/pgmath.h

 extern "C" {
 #endif
 
+#define VEC_EPSILON 1e-6
+
 #define PYGAME_MATH_FIRSTSLOT 0
 #define PYGAME_MATH_NUMSLOTS 1
 #ifndef PYGAME_MATH_INTERNAL

File src/math/vector.c

 #include "pgmath.h"
 #include "mathbase_doc.h"
 
+static PyObject* _vector_new (PyTypeObject *type, PyObject *args,
+    PyObject *kwds);
 static int _vector_init (PyObject *self, PyObject *args, PyObject *kwds);
 static void _vector_dealloc (PyVector *self);
 static PyObject* _vector_repr (PyObject *self);
 static PyObject* _vector_normalize_ip (PyVector *self);
 static PyObject* _vector_slerp (PyVector *self, PyObject *args);
 static PyObject* _vector_lerp (PyVector *self, PyObject *args);
+static PyObject* _vector_dot (PyVector *self, PyObject *args);
 static PyObject* _vector_scaletolength (PyVector *self, PyObject *args);
 static PyObject* _vector_reflect (PyVector *self, PyObject *args);
 static PyObject* _vector_reflect_ip (PyVector *self, PyObject *args);
 static int _vector_ass_subscript (PyVector *self, PyObject *op,
     PyObject *value);
 
+/* Iterator support. */
+typedef struct
+{
+    PyObject_HEAD
+    long it_index;
+    PyVector *vec;
+} _vectoriter;
+/* vector iterator functions */
+static void _vectoriter_dealloc (_vectoriter *it);
+static PyObject *_vectoriter_next (_vectoriter *it);
+static PyObject *_vectoriter_len (_vectoriter *it);
+static PyObject *_vector_iter (PyObject *vec);
+
+static PyMethodDef _vectoriter_methods[] =
+{
+    {"__length_hint__", (PyCFunction)_vectoriter_len, METH_NOARGS, NULL},
+    { NULL, NULL, 0, NULL} /* sentinel */
+};
+
+static PyTypeObject _PyVectorIter_Type =
+{
+    TYPE_HEAD (NULL,0)
+    "VectorIterator",          /* tp_name */
+    sizeof(_vectoriter),       /* tp_basicsize */
+    0,                         /* tp_itemsize */
+    (destructor)_vectoriter_dealloc, /* tp_dealloc */
+    0,                         /* tp_print */
+    0,                         /* tp_getattr */
+    0,                         /* tp_setattr */
+    0,                         /* tp_compare */
+    0,                         /* tp_repr */
+    0,                         /* tp_as_number */
+    0,                         /* tp_as_sequence */
+    0,                         /* tp_as_mapping */
+    0,                         /* tp_hash */
+    0,                         /* tp_call */
+    0,                         /* tp_str */
+    0,                         /* tp_getattro */
+    0,                         /* tp_setattro */
+    0,                         /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,        /* tp_flags */
+    0,                         /* tp_doc */
+    0,                         /* tp_traverse */
+    0,                         /* tp_clear */
+    0,                         /* tp_richcompare */
+    0,                         /* tp_weaklistoffset */
+    PyObject_SelfIter,         /* tp_iter */
+    (iternextfunc)_vectoriter_next, /* tp_iternext */
+    _vectoriter_methods,        /* tp_methods */
+    0,                         /* tp_members */
+    0,                         /* tp_getset */
+    0,                          /* tp_base */
+    0,                          /* tp_dict */
+    0,                          /* tp_descr_get */
+    0,                          /* tp_descr_set */
+    0,                          /* tp_dictoffset */
+    0,                         /* tp_init */
+    0,                          /* tp_alloc */
+    0,                          /* tp_new */
+    0,                          /* tp_free */
+    0,                          /* tp_is_gc */
+    0,                          /* tp_bases */
+    0,                          /* tp_mro */
+    0,                          /* tp_cache */
+    0,                          /* tp_subclasses */
+    0,                          /* tp_weaklist */
+    0,                          /* tp_del */
+#if PY_VERSION_HEX >= 0x02060000
+    0                           /* tp_version_tag */
+#endif
+
+};
+
 /**
  * Methods for the PyVector.
  */
       DOC_BASE_VECTOR_REFLECT },
     { "reflect_ip", (PyCFunction) _vector_reflect_ip, METH_VARARGS,
       DOC_BASE_VECTOR_REFLECT_IP },
+    { "dot", (PyCFunction) _vector_dot, METH_VARARGS, DOC_BASE_VECTOR_DOT },
     { "distance", (PyCFunction) _vector_distance, METH_VARARGS,
       DOC_BASE_VECTOR_DISTANCE },
     { "distance_squared", (PyCFunction) _vector_distance_squared, METH_VARARGS,
     (binaryfunc)0,                    /* nb_xor;       __xor__ */
     (binaryfunc)0,                    /* nb_or;        __or__ */
 #ifndef IS_PYTHON_3
-    (coercion)0,                      /* nb_coerce;    __coerce__ */
+    (coercion) 0,                     /* nb_coerce;    __coerce__ */
 #endif
     (unaryfunc)0,                     /* nb_int;       __int__ */
     (unaryfunc)0,                     /* nb_long;      __long__ */
 static PySequenceMethods _vector_as_sequence =
 {
     (lenfunc) _vector_len,                    /* sq_length;    __len__ */
-    (binaryfunc)0,                            /* sq_concat;    __add__ */
-    (ssizeargfunc)0,                          /* sq_repeat;    __mul__ */
+    (binaryfunc) 0,                           /* sq_concat;    __add__ */
+    (ssizeargfunc) 0,                         /* sq_repeat;    __mul__ */
     (ssizeargfunc) _vector_item,              /* sq_item;      __getitem__ */
     (ssizessizeargfunc) _vector_slice,        /* sq_slice;     __getslice__ */
     (ssizeobjargproc) _vector_ass_item,       /* sq_ass_item;  __setitem__ */
     0,                          /* tp_getattro */
     0,                          /* tp_setattro */
     0,                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES,
     DOC_BASE_VECTOR,
     0,                          /* tp_traverse */
     0,                          /* tp_clear */
     _vector_richcompare,        /* tp_richcompare */
     0,                          /* tp_weaklistoffset */
-    0,                          /* tp_iter */
+    _vector_iter,               /* tp_iter */
     0,                          /* tp_iternext */
     _vector_methods,            /* tp_methods */
     0,                          /* tp_members */
     0,                          /* tp_dictoffset */
     (initproc)_vector_init,     /* tp_init */
     0,                          /* tp_alloc */
-    0,                          /* tp_new */
+    (newfunc)_vector_new,       /* tp_new */
     0,                          /* tp_free */
     0,                          /* tp_is_gc */
     0,                          /* tp_bases */
 #endif
 };
 
+static PyObject*
+_vector_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyVector *vector = (PyVector *)type->tp_alloc (type, 0);
+    if (!vector)
+        return NULL;
+    vector->dim = 0;
+    vector->coords = NULL;
+    vector->epsilon = VEC_EPSILON;
+    return (PyObject*) vector;
+}
+
 static int
 _vector_init (PyObject *self, PyObject *args, PyObject *kwds)
 {
     PyObject *elems = NULL;
     int isseq = 0;
+    int isvec = 0;
     int dim = 0;
     PyVector *vector = (PyVector *) self;
     
     if (!PyArg_ParseTuple (args, "O", &elems))
         return -1;
-    if (PySequence_Check (elems))
+
+    if (PyVector_Check (elems))
+    {
+        vector->dim = ((PyVector*) elems)->dim;
+        isvec = 1;
+    }
+    else if (PySequence_Check (elems))
     {
         /* The passed argument is a list of vector elements */
         isseq = 1;
     else
     {
         PyErr_SetString (PyExc_TypeError,
-            "argument must be a sequence of vector elements or integer");
+            "argument must be a vector, sequence or integer");
         return -1;
     }
 
     if (!isseq)
     {
         Py_ssize_t i;
-        for (i = 0; i < vector->dim; i++)
-            vector->coords[i] = 0.f;
+        if (!isvec)
+        {
+            for (i = 0; i < vector->dim; i++)
+                vector->coords[i] = 0.f;
+        }        
+        else
+        {
+            memcpy (vector->coords, ((PyVector*)elems)->coords,
+                sizeof (double) * vector->dim);
+        }
     }
     else
     {
             vector->coords[i] = tmp;
         }
     }
-    vector->epsilon = DBL_EPSILON;
     return 0;
 }
 
 static PyObject*
 _vector_repr (PyObject *self)
 {
+    char b[32];
+    Py_ssize_t i;
     PyVector *v = (PyVector*) self;
-    /* TODO */
-    return Text_FromFormat ("Vector%d()", v->dim);
+#ifdef IS_PYTHON_3
+    PyObject *tmp1, *tmp2;
+#endif
+#if PY_VERSION_HEX < 0x02050000
+    PyObject *string = Text_FromFormat ("Vector%d(", v->dim);
+#else
+    PyObject *string = Text_FromFormat ("Vector%zd(", v->dim);
+#endif
+
+    for (i = 0; i < (v->dim - 1); i++)
+    {
+        if (!PyOS_ascii_formatd (b, 32, "%.8f", v->coords[i]))
+        {
+            Py_DECREF (string);
+            return NULL;
+        }
+#ifdef IS_PYTHON_3
+        tmp1 = string;
+        tmp2 = Text_FromFormat ("%s, ", b);
+        string = PyUnicode_Concat (tmp1, tmp2);
+        Py_XDECREF (tmp1);
+        Py_XDECREF (tmp2);
+        if (!string)
+            return NULL;
+#else
+        PyString_ConcatAndDel (&string, PyString_FromFormat ("%s, ", b));
+#endif        
+    }
+
+    if (!PyOS_ascii_formatd (b, 32, "%.8f", v->coords[v->dim - 1]))
+    {
+        Py_DECREF (string);
+        return NULL;
+    }
+#ifdef IS_PYTHON_3
+    tmp1 = string;
+    tmp2 = Text_FromFormat ("%s)", b);
+    string = PyUnicode_Concat (tmp1, tmp2);
+    Py_XDECREF (tmp1);
+    Py_XDECREF (tmp2);
+#else
+    PyString_ConcatAndDel (&string, PyString_FromFormat ("%s)", b));
+#endif        
+    return string;
 }
 
 /* Vector getters/setters */
 static PyObject*
 _vector_generic_math (PyObject *o1, PyObject *o2, int op)
 {
-    PyVector *v, *retval;
+    PyVector *v;
+    PyObject *retval = NULL;
     PyObject *other;
-    Py_ssize_t dim, otherdim = 0, i;
+    Py_ssize_t dim, otherdim, i;
+    double *coords = NULL;
+    double *vcoords = NULL;
     
     if (!o1 || !o2)
     {
     {
         v = (PyVector *) o1;
         other = o2;
+        vcoords = v->coords;
     }
     else if (PyVector_Check (o2))
     {
         return NULL;
     }
     dim = v->dim;
-    
-    if (PyVector_Check (other))
+    vcoords = v->coords;
+
+    coords = VectorCoordsFromObj (other, &otherdim);
+    if (coords)
     {
         op |= OP_ARG_VECTOR;
-        otherdim = ((PyVector*) other)->dim;
         /* right-hand vector must have less dimensions than left-hand. */
         if (otherdim > dim)
         {
             PyErr_SetString (PyExc_TypeError,
                 "right op must not have more dimensions than left op");
+            PyMem_Free (coords);
             return NULL;
         }
     }
         op |= OP_ARG_NUMBER;
     else
         op |= OP_ARG_UNKNOWN;
+    PyErr_Clear (); /* Set by VectorCoordsFromObj */
 
     switch (op)
     {
     case OP_ADD | OP_ARG_VECTOR:
     case OP_ADD | OP_ARG_VECTOR | OP_ARG_REVERSE:
     {
-        retval = (PyVector *) PyVector_NewSpecialized (dim);
+        retval = PyVector_NewSpecialized (dim);
         if (!retval)
-            return NULL;
-        memcpy (retval->coords, v->coords, sizeof (double) * dim);
+            break;
+        memcpy (((PyVector*)retval)->coords, vcoords, sizeof (double) * dim);
         for (i = 0; i < otherdim; i++)
-            retval->coords[i] += ((PyVector*)other)->coords[i];
-        return (PyObject*) retval;
+            ((PyVector*)retval)->coords[i] += coords[i];
+        break;
     }
     case OP_IADD | OP_ARG_VECTOR:
     {
-        for (i = 0; i < otherdim; i++)
-            v->coords[i] += ((PyVector*)other)->coords[i];
-        return (PyObject*) v;
+        for (i = 0; i < dim; i++)
+            vcoords[i] += coords[i];
+        retval = (PyObject*)v;
+        Py_INCREF (retval);
+        break;
     }
     case OP_SUB | OP_ARG_VECTOR:
+    {
+        retval = PyVector_NewSpecialized (dim);
+        if (!retval)
+            break;
+        for (i = 0; i < otherdim; i++)
+            ((PyVector*)retval)->coords[i] = vcoords[i] - coords[i];
+        break;
+    }
     case OP_SUB | OP_ARG_VECTOR | OP_ARG_REVERSE:
     {
-        retval = (PyVector *) PyVector_NewSpecialized (dim);
+        retval = PyVector_NewSpecialized (dim);
         if (!retval)
-            return NULL;
-        memcpy (retval->coords, v->coords, sizeof (double) * dim);
+            break;
         for (i = 0; i < otherdim; i++)
-            retval->coords[i] -= ((PyVector*)other)->coords[i];
-        return (PyObject*) retval;
+            ((PyVector*)retval)->coords[i] = coords[i] - vcoords[i];
+        break;
     }
     case OP_ISUB | OP_ARG_VECTOR:
     {
-        for (i = 0; i < otherdim; i++)
-            v->coords[i] -= ((PyVector*)other)->coords[i];
-        return (PyObject*) v;
+        for (i = 0; i < dim; i++)
+            vcoords[i] -= coords[i];
+        retval = (PyObject*)v;
+        Py_INCREF (retval);
+        break;
     }
     case OP_MUL | OP_ARG_VECTOR:
     case OP_MUL | OP_ARG_VECTOR | OP_ARG_REVERSE:
     {
         double tmp = 0.f;
-        for (i = 0; i < otherdim; i++)
-            tmp += v->coords[i] * ((PyVector*)other)->coords[i];
-        return PyFloat_FromDouble (tmp);
+        for (i = 0; i < dim; i++)
+            tmp += vcoords[i] * coords[i];
+        retval = PyFloat_FromDouble (tmp);
+        break;
     }
     case OP_MUL | OP_ARG_NUMBER:
     case OP_MUL | OP_ARG_NUMBER | OP_ARG_REVERSE:
     {
         double tmp;
         if (!DoubleFromObj (other, &tmp))
-            return NULL;
+            break;
         
-        retval = (PyVector *) PyVector_NewSpecialized (dim);
+        retval = PyVector_NewSpecialized (dim);
         if (!retval)
-            return NULL;
+            break;
         for (i = 0; i < dim; i++)
-            retval->coords[i] = v->coords[i] * tmp;
-        return (PyObject *) retval;
+            ((PyVector*)retval)->coords[i] = vcoords[i] * tmp;
+        break;
     }
     case OP_IMUL | OP_ARG_NUMBER:
     {
         double tmp;
         if (!DoubleFromObj (other, &tmp))
-            return NULL;
+            break;
         for (i = 0; i < dim; i++)
-            v->coords[i] *= tmp;
-        return (PyObject *) v;
+            vcoords[i] *= tmp;
+        retval = (PyObject*)v;
+        Py_INCREF (retval);
+        break;
     }
     case OP_DIV | OP_ARG_NUMBER:
     {
         double tmp;
         if (!DoubleFromObj (other, &tmp))
-            return NULL;
+            break;
         tmp = 1.f / tmp;
-        retval = (PyVector *) PyVector_NewSpecialized (dim);
+        retval = PyVector_NewSpecialized (dim);
         if (!retval)
-            return NULL;
+            break;
         for (i = 0; i < dim; i++)
-            retval->coords[i] = v->coords[i] * tmp;
-        return (PyObject *) retval;
+            ((PyVector*)retval)->coords[i] = vcoords[i] * tmp;
+        break;
     }
     case OP_IDIV | OP_ARG_NUMBER:
     {
         double tmp;
         if (!DoubleFromObj (other, &tmp))
-            return NULL;
+            break;
         tmp = 1. / tmp;
         for (i = 0; i < dim; i++)
-            v->coords[i] *= tmp;
-        return (PyObject *) v;
+            vcoords[i] *= tmp;
+        retval = (PyObject *) v;
+        Py_INCREF (retval);
+        break;
     }
     case OP_FLOOR_DIV | OP_ARG_NUMBER:
     {
         double tmp;
         if (!DoubleFromObj (other, &tmp))
-            return NULL;
+            break;
         tmp = 1. / tmp;
-        retval = (PyVector *) PyVector_NewSpecialized(dim);
+        retval = PyVector_NewSpecialized(dim);
         if (!retval)
-            return NULL;
+            break;
         for (i = 0; i < dim; i++)
-            retval->coords[i] = floor (v->coords[i] * tmp);
-        return (PyObject *) retval;
+            ((PyVector*)retval)->coords[i] = floor (vcoords[i] * tmp);
+        break;
     }
     case OP_IFLOOR_DIV | OP_ARG_NUMBER:
     {
         double tmp;
         if (!DoubleFromObj (other, &tmp))
-            return NULL;
+            break;
         tmp = 1. / tmp;
         for (i = 0; i < dim; i++)
-            v->coords[i] = floor (v->coords[i] * tmp);
-        return (PyObject *) v;
+            v->coords[i] = floor (vcoords[i] * tmp);
+        retval = (PyObject *) v;
+        Py_INCREF (retval);
+        break;
     }
     default:
-        Py_INCREF (Py_NotImplemented);
-        return Py_NotImplemented;
+        PyErr_Clear ();
+        PyErr_SetString (PyExc_NotImplementedError,
+            "operation for those types not supported");
+        break;
     }
+    
+    if (coords)
+        PyMem_Free (coords);
+    return (PyObject*) retval;
 }
 
 /**
         ihigh = self->dim;
     
     len = ihigh - ilow;
-    if (len == 0)
+    if (len <= 1)
     {
         /* Return single number */
-        return PyFloat_FromDouble (self->coords[ihigh]);
+        return PyFloat_FromDouble (self->coords[ilow]);
     }
     
     retval = (PyVector *) PyVector_NewSpecialized (len);
     return (PyObject *) retval;
 }
 
+/**
+ * vector[x,y] = p
+ */
 static int
-_vector_ass_slice(PyVector *self, Py_ssize_t ilow, Py_ssize_t ihigh,
+_vector_ass_slice (PyVector *self, Py_ssize_t ilow, Py_ssize_t ihigh,
     PyObject *v)
 {
     Py_ssize_t i, len;
 static PyObject*
 _vector_subscript (PyVector *self, PyObject *op)
 {
-    if (PyIndex_Check (op) || PyInt_Check (op) || PyLong_Check (op))
+    if (PySlice_Check (op))
+    {
+        /* A slice */
+        PyVector *retval;
+        Py_ssize_t slicelen, step, start, stop, cur, i;
+        int ret;
+
+        ret = PySlice_GetIndicesEx ((PySliceObject *) op,
+            self->dim, &start, &stop, &step, &slicelen);
+        if (ret < 0 || slicelen < 0)
+            return NULL;
+        if (slicelen == 0)
+            Py_RETURN_NONE;
+
+        if (step == 1)
+            return _vector_slice (self, start, stop);
+        retval = (PyVector *) PyVector_NewSpecialized (slicelen);
+        if (!retval)
+            return NULL;
+        for (cur = start, i = 0; i < slicelen; cur += step, i++)
+            retval->coords[i] = self->coords[cur];
+        return (PyObject *) retval;
+    }
+    else if (PyIndex_Check (op) || PyInt_Check (op) || PyLong_Check (op))
     {
         Py_ssize_t i;
 #if PY_VERSION_HEX >= 0x02050000
         if (!IntFromObj (op, &i))
             return NULL;
 #endif
+        if (i < 0)
+            i += self->dim;
         return _vector_item (self, i);
     }
     /* TODO */
 static int
 _vector_ass_subscript (PyVector *self, PyObject *op, PyObject *value)
 {
+    if (!value)
+    {
+        PyErr_SetString (PyExc_ValueError, 
+            "deletion of vector components is not supported");
+        return -1;
+    }
+
     if (PyIndex_Check (op) || PyInt_Check (op) || PyLong_Check (op))
     {
         Py_ssize_t i;
 #endif
         return _vector_ass_item (self, i, value);
     }
-    /* TODO */
-    return 0;
+    else if (PySlice_Check (op))
+    {
+        /* A slice */
+        double *coords, sval = 0.f;
+        Py_ssize_t dim;
+        Py_ssize_t slicelen, step, start, stop, cur, i;
+        int ret, issingle = 0;
+
+        ret = PySlice_GetIndicesEx ((PySliceObject *) op, self->dim,
+            &start, &stop, &step, &slicelen);
+        if (ret < 0 || slicelen <= 0)
+            return -1;
+
+        if (step == 1)
+            return _vector_ass_slice (self, start, stop, value);
+        
+        if (PySequence_Check (value))
+        {
+            Py_ssize_t size = PySequence_Size (value);
+            if (size == 1)
+            {
+                if (!DoubleFromSeqIndex (value, (Py_ssize_t)0, &sval))
+                    return -1;
+                issingle = 1;
+            }
+        }
+        else if (DoubleFromObj (value, &sval))
+            issingle = 1;
+        else
+            return -1;
+
+        if (issingle)
+        {
+            /* Single value assignment to all. */
+            for (cur = start, i = 0; i < slicelen; cur += step, i++)
+                self->coords[cur] = sval;
+            return 0;
+        }
+
+        coords = VectorCoordsFromObj (value, &dim);
+        if (!coords)
+            return -1;
+
+        for (cur = start, i = 0; i < slicelen; cur += step, i++)
+            self->coords[i] = coords[cur];
+        PyMem_Free (coords);
+        return 0;
+    }
+    return -1;
 }
 
 static PyObject*
     double diff;
     PyVector *v = NULL, *v2 = NULL;
     PyObject *other = NULL;
-    int swap = 0, retval = 0;
+    int swap = 0, retval = 1;
     
     if (PyVector_Check (o1))
     {
         v = (PyVector *) o1;
-        if (PyVector_Check (o2))
-        {
-            v2 = (PyVector *) o2;
-            otherdim = v2->dim;
-        }
-        else if (PySequence_Check (o2))
-        {
-            other = o2;
-            otherdim = PySequence_Size (other);
-        }
-        else
-        {
-            Py_INCREF (Py_NotImplemented);
-            return Py_NotImplemented;
-        }
+        other = o2;
     }
     else if (PyVector_Check (o2))
     {
         swap = 1;
         v = (PyVector *) o2;
-        if (PyVector_Check (o1))
-        {
-            v2 = (PyVector *) o1;
-            otherdim = v2->dim;
-        }
-        else if (PySequence_Check (o1))
-        {
-            other = o1;
-            otherdim = PySequence_Size (other);
-        }
-        else
-        {
-            Py_INCREF (Py_NotImplemented);
-            return Py_NotImplemented;
-        }
+        other = o1;
     }
+
+    if (PyVector_Check (other))
+    {
+        v2 = (PyVector *) other;
+        otherdim = v2->dim;
+    }
+    else if (PySequence_Check (other))
+        otherdim = PySequence_Size (other);
     else
     {
         Py_INCREF (Py_NotImplemented);
     }
 
     if (v->dim != otherdim)
-        Py_RETURN_FALSE;
-
-    for (i = 0; i < v->dim; i++)
+        retval = 0;
+    else
     {
-        if (v2)
-            diff = v->coords[i] - v2->coords[i];
-        else
+        for (i = 0; i < v->dim; i++)
         {
-            double tmp;
-            if (!DoubleFromSeqIndex (other, i, &tmp))
-                return NULL;
-            diff = v->coords[i] - tmp;
-        }
-        
-        if (isnan (diff) || fabs (diff) >= v->epsilon)
-        {
-            retval = (swap == 1) ? 1 : 0;
-            break;
+            if (v2)
+                diff = v->coords[i] - v2->coords[i];
+            else
+            {
+                double tmp;
+                if (!DoubleFromSeqIndex (other, i, &tmp))
+                    return NULL;
+                diff = v->coords[i] - tmp;
+            }
+            
+            if (isnan (diff) || fabs (diff) >= v->epsilon)
+            {
+                retval = 0;
+                break;
+            }
         }
     }
-    retval = (swap == 1) ? 0 : 1;
-    
+    if (swap == 1)
+    {
+        if (retval == 0)
+            retval = 1;
+        else
+            retval = 0;
+    }
+
     switch (op)
     {
     case Py_EQ:
     }
 }
 
+/* Iterator support */
+static PyObject*
+_vector_iter (PyObject *vec)
+{
+    _vectoriter *it;
+    if (!PyVector_Check (vec))
+    {
+        PyErr_BadInternalCall ();
+        return NULL;
+    }
+
+    it = PyObject_New (_vectoriter, &_PyVectorIter_Type);
+    if (!it)
+        return NULL;
+    it->it_index = 0;
+    Py_INCREF (vec);
+    it->vec = (PyVector *)vec;
+    return (PyObject *)it;
+}
+
+static void
+_vectoriter_dealloc (_vectoriter *it)
+{
+    if (!it)
+        return;
+    Py_XDECREF (it->vec);
+    PyObject_Del (it);
+}
+
+static PyObject*
+_vectoriter_next (_vectoriter *it)
+{
+    if (!it || !it->vec)
+        return NULL;
+    if (!PyVector_Check (it->vec))
+        return NULL;
+
+    if (it->it_index < it->vec->dim)
+    {
+        double item = it->vec->coords[it->it_index];
+        ++(it->it_index);
+        return PyFloat_FromDouble (item);
+    }
+    
+    Py_DECREF (it->vec);
+    it->vec = NULL;
+    return NULL;
+}
+
+static PyObject*
+_vectoriter_len (_vectoriter *it)
+{
+    Py_ssize_t len = 0;
+    if (it && it->vec)
+        len = it->vec->dim - it->it_index;
+    return PyInt_FromSsize_t (len);
+}
+
+
 /* C API */
 PyObject*
 PyVector_New (Py_ssize_t dim)
     if (!v)
         return NULL;
     v->dim = dim;
-    v->epsilon = DBL_EPSILON;
+    v->epsilon = VEC_EPSILON;
     v->coords = PyMem_New (double, dim);
     if (!v->coords)
     {

File src/math/vector2.c

 static PyObject* _vector2_get_y (PyObject *self, void *closure);
 static int _vector2_set_y (PyObject *self, PyObject *value, void *closure);
 
-static void _do_rotate (double *dst_coords, double *src_coords, double angle,
-    double epsilon);
+static void _do_rotate (double *dst_coords, const double *src_coords,
+    double angle, double epsilon);
 
 static PyObject* _vector2_rotate (PyObject *self, PyObject *args);
 static PyObject* _vector2_rotate_ip (PyObject *self, PyObject *args);
       DOC_BASE_VECTOR2_ROTATE_IP },
     { "cross", _vector2_cross, METH_VARARGS, DOC_BASE_VECTOR2_CROSS },
     { "angle_to", _vector2_angleto, METH_VARARGS, DOC_BASE_VECTOR2_ANGLE_TO },
-    { "as_polar", _vector2_aspolar, METH_VARARGS, DOC_BASE_VECTOR2_AS_POLAR },
+    { "as_polar", _vector2_aspolar, METH_NOARGS, DOC_BASE_VECTOR2_AS_POLAR },
     { NULL, NULL, 0, NULL },
 };
 
         return NULL;
     }
     vector->vector.coords[0] = vector->vector.coords[1] = 0.f;
-    vector->vector.epsilon = DBL_EPSILON;
+    vector->vector.epsilon = VEC_EPSILON;
     return (PyObject *) vector;
 }
 
 _vector2_init (PyObject *self, PyObject *args, PyObject *kwds)
 {
     PyVector2 *vector = (PyVector2 *) self;
-    double x, y;
+    double x = 0.f, y = 0.f;
 
-    if (!PyArg_ParseTuple (args, "dd", &x, &y))
-        return -1;
+    if (!PyArg_ParseTuple (args, "|dd", &x, &y))
+    {
+        PyObject *seq;
+        Py_ssize_t dim;
+        double *coords;
+
+        PyErr_Clear ();
+        if (!PyArg_ParseTuple (args, "O", &seq))
+            return -1;
+        coords = VectorCoordsFromObj (seq, &dim);
+        if (!coords)
+            return -1;
+        x = coords[0];
+        y = coords[1];
+        PyMem_Free (coords);
+    }
+
     vector->vector.coords[0] = x;
     vector->vector.coords[1] = y;
     return 0;
 /* Vector2 methods */
 
 static void
-_do_rotate (double *dst_coords, double *src_coords, double angle,
+_do_rotate (double *dst_coords, const double *src_coords, double angle,
     double epsilon)
 {
     /* make sure angle is in range [0, 360) */
     double angle;
     PyObject *other;
     PyVector *v = (PyVector*) self;
-    double retval, *othercoords;
+    double *othercoords;
     Py_ssize_t otherdim;
 
-    if (!PyArg_ParseTuple (args, "O:cross", &other))
+    if (!PyArg_ParseTuple (args, "O:angleto", &other))
         return NULL;
 
     if (!IsVectorCompatible (other))

File src/math/vector3.c

 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,
+    const double* axis_coords, double angle, double epsilon);
+
+static PyObject* _vector3_rotate (PyObject *self, PyObject *args);
+static PyObject* _vector3_rotate_ip (PyObject *self, PyObject *args);
+static PyObject* _vector3_rotate_x (PyObject *self, PyObject *args);
+static PyObject* _vector3_rotate_x_ip (PyObject *self, PyObject *args);
+static PyObject* _vector3_rotate_y (PyObject *self, PyObject *args);
+static PyObject* _vector3_rotate_y_ip (PyObject *self, PyObject *args);
+static PyObject* _vector3_rotate_z (PyObject *self, PyObject *args);
+static PyObject* _vector3_rotate_z_ip (PyObject *self, PyObject *args);
+static PyObject* _vector3_cross (PyObject *self, PyObject *args);
+static PyObject* _vector3_angleto (PyObject *self, PyObject *args);
+static PyObject* _vector3_asspherical (PyObject *self);
+
 /**
  * Methods for the PyVector3.
  */
 static PyMethodDef _vector3_methods[] =
 {
+    { "rotate_x", _vector3_rotate_x, METH_VARARGS, DOC_BASE_VECTOR3_ROTATE_X },
+    { "rotate_x_ip", _vector3_rotate_x_ip, METH_VARARGS,
+      DOC_BASE_VECTOR3_ROTATE_X_IP },
+    { "rotate_y", _vector3_rotate_y, METH_VARARGS, DOC_BASE_VECTOR3_ROTATE_Y },
+    { "rotate_y_ip", _vector3_rotate_y_ip, METH_VARARGS,
+      DOC_BASE_VECTOR3_ROTATE_Y_IP },
+    { "rotate_z", _vector3_rotate_z, METH_VARARGS, DOC_BASE_VECTOR3_ROTATE_Z },
+    { "rotate_z_ip", _vector3_rotate_z_ip, METH_VARARGS,
+      DOC_BASE_VECTOR3_ROTATE_Z_IP },
+    { "rotate", _vector3_rotate, METH_VARARGS, DOC_BASE_VECTOR3_ROTATE },
+    { "rotate_ip", _vector3_rotate_ip, METH_VARARGS,
+      DOC_BASE_VECTOR3_ROTATE_IP },
+    { "cross", _vector3_cross, METH_VARARGS, DOC_BASE_VECTOR3_CROSS },
+    { "angle_to", _vector3_angleto, METH_VARARGS, DOC_BASE_VECTOR3_ANGLE_TO },
+    { "as_spherical", (PyCFunction)_vector3_asspherical, METH_NOARGS,
+      DOC_BASE_VECTOR3_AS_SPHERICAL },
     { NULL, NULL, 0, NULL },
 };
 
     }
     vector->vector.coords[0] = vector->vector.coords[1] =
         vector->vector.coords[2] = 0.f;
-    vector->vector.epsilon = DBL_EPSILON;
+    vector->vector.epsilon = VEC_EPSILON;
     return (PyObject *) vector;
 }
 
 _vector3_init (PyObject *self, PyObject *args, PyObject *kwds)
 {
     PyVector3 *vector = (PyVector3 *) self;
-    double x, y, z;
+    double x = 0.f, y = 0.f, z = 0.f;
 
-    if (!PyArg_ParseTuple (args, "ddd", &x, &y, &z))
-        return -1;
+    if (!PyArg_ParseTuple (args, "|ddd", &x, &y, &z))
+    {
+        PyObject *seq;
+        Py_ssize_t dim;
+        double *coords;
+
+        PyErr_Clear ();
+        if (!PyArg_ParseTuple (args, "O", &seq))
+            return -1;
+        coords = VectorCoordsFromObj (seq, &dim);
+        if (!coords)
+            return -1;
+        if (dim < 3)
+        {
+            PyErr_SetString (PyExc_ValueError,
+                "sequence or vector must have at least three dimensions");
+            PyMem_Free (coords);
+            return -1;
+        }
+        x = coords[0];
+        y = coords[1];
+        z = coords[2];
+        PyMem_Free (coords);
+    }
     vector->vector.coords[0] = x;
     vector->vector.coords[1] = y;
     vector->vector.coords[2] = z;
     return 0;
 }
 
+/* Vector3 methods */
+static void
+_do_rotate (double *dst_coords, const double *src_coords,
+    const double* axis_coords, double angle, double epsilon)
+{
+    double sinv, cosv, coscompl;
+    double nfactor;
+    double axislen = 0;
+    double axis[3];
+    Py_ssize_t i;
+
+    /* make sure angle is in range [0, 360) */
+    angle = fmod (angle, 360.);
+    if (angle < 0)
+        angle += 360.;
+
+    for (i = 0; i < 3; ++i)
+    {
+        axislen += axis_coords[i] * axis_coords[i];
+        axis[i] = axis_coords[i];
+    }
+
+    /* normalize the axis */
+    if (axislen - 1 > epsilon)
+    {
+        nfactor = 1. / sqrt (axislen);
+        for (i = 0; i < 3; ++i)
+            axis[i] *= nfactor;
+    }
+
+    /* special-case rotation by 0, 90, 180 and 270 degrees */
+    if (fmod (angle + epsilon, 90.) < 2 * epsilon)
+    {
+        switch ((int)((angle + epsilon) / 90))
+        {
+        case 0: /* 0 degrees */
+            memcpy (dst_coords, src_coords, 3 * sizeof(double));
+            break;
+        case 1: /* 90 degrees */
+            dst_coords[0] = (src_coords[0] * (axis[0] * axis[0]) +
+                src_coords[1] * (axis[0] * axis[1] - axis[2]) +
+                src_coords[2] * (axis[0] * axis[2] + axis[1]));
+            dst_coords[1] = (src_coords[0] * (axis[0] * axis[1] + axis[2]) +
+                src_coords[1] * (axis[1] * axis[1]) +
+                src_coords[2] * (axis[1] * axis[2] - axis[0]));
+            dst_coords[2] = (src_coords[0] * (axis[0] * axis[2] - axis[1]) +
+                src_coords[1] * (axis[1] * axis[2] + axis[0]) +
+                src_coords[2] * (axis[2] * axis[2]));
+            break;
+        case 2: /* 180 degrees */
+            dst_coords[0] = (src_coords[0] * (-1 + axis[0] * axis[0] * 2) +
+                src_coords[1] * (axis[0] * axis[1] * 2) +
+                src_coords[2] * (axis[0] * axis[2] * 2));
+            dst_coords[1] = (src_coords[0] * (axis[0] * axis[1] * 2) +
+                src_coords[1] * (-1 + axis[1] * axis[1] * 2) +
+                src_coords[2] * (axis[1] * axis[2] * 2));
+            dst_coords[2] = (src_coords[0] * (axis[0] * axis[2] * 2) +
+                src_coords[1] * (axis[1] * axis[2] * 2) +
+                src_coords[2] * (-1 + axis[2] * axis[2] * 2));
+            break;
+        case 3: /* 270 degrees */
+            dst_coords[0] = (src_coords[0] * (axis[0] * axis[0]) +
+                src_coords[1] * (axis[0] * axis[1] + axis[2]) +
+                src_coords[2] * (axis[0] * axis[2] - axis[1]));
+            dst_coords[1] = (src_coords[0] * (axis[0] * axis[1] - axis[2]) +
+                src_coords[1] * (axis[1] * axis[1]) +
+                src_coords[2] * (axis[1] * axis[2] + axis[0]));
+            dst_coords[2] = (src_coords[0] * (axis[0] * axis[2] + axis[1]) +
+                src_coords[1] * (axis[1] * axis[2] - axis[0]) +
+                src_coords[2] * (axis[2] * axis[2]));
+            break;
+        }
+    }
+    else
+    {
+        angle = DEG2RAD (angle);
+        sinv = sin (angle);
+        cosv = cos (angle);
+        coscompl = 1 - cosv;
+
+        dst_coords[0] =
+            (src_coords[0] * (cosv + axis[0] * axis[0] * coscompl) +
+             src_coords[1] * (axis[0] * axis[1] * coscompl - axis[2] * sinv) +
+             src_coords[2] * (axis[0] * axis[2] * coscompl + axis[1] * sinv));
+        dst_coords[1] =
+            (src_coords[0] * (axis[0] * axis[1] * coscompl + axis[2] * sinv) +
+             src_coords[1] * (cosv + axis[1] * axis[1] * coscompl) +
+             src_coords[2] * (axis[1] * axis[2] * coscompl - axis[0] * sinv));
+        dst_coords[2] =
+            (src_coords[0] * (axis[0] * axis[2] * coscompl - axis[1] * sinv) +
+             src_coords[1] * (axis[1] * axis[2] * coscompl + axis[0] * sinv) +
+             src_coords[2] * (cosv + axis[2] * axis[2] * coscompl));
+    }
+}
+
+static PyObject*
+_vector3_rotate (PyObject *self, PyObject *args)
+{
+    PyVector *v = (PyVector *) self;
+    PyVector *ret;
+    PyObject *axis;
+    Py_ssize_t axisdim;
+    double *axiscoords, angle;
+    
+    if (!PyArg_ParseTuple (args, "dO:rotate", &angle, &axis))
+        return NULL;
+
+    if (!IsVectorCompatible (axis))
+    {
+        PyErr_SetString (PyExc_TypeError, "axis must be a vector compatible");
+        return NULL;
+    }
+
+    axiscoords = VectorCoordsFromObj (axis, &axisdim);
+    if (!axiscoords)
+        return NULL;
+    if (axisdim < v->dim)
+    {
+        PyErr_SetString (PyExc_ValueError,
+            "axis must have at least three dimensions");
+        PyMem_Free (axiscoords);
+        return NULL;
+    }
+    ret = (PyVector*) PyVector3_New (0.f, 0.f, 0.f);
+    _do_rotate (ret->coords, v->coords, axiscoords, angle, v->epsilon);
+    return (PyObject*) ret;
+}
+
+static PyObject*
+_vector3_rotate_ip (PyObject *self, PyObject *args)
+{
+    PyVector *v = (PyVector *) self;
+    PyObject *axis;
+    Py_ssize_t axisdim;
+    double *axiscoords, angle, tmp[3];
+    
+    if (!PyArg_ParseTuple (args, "dO:rotate_ip", &angle, &axis))
+        return NULL;
+
+    if (!IsVectorCompatible (axis))
+    {
+        PyErr_SetString (PyExc_TypeError, "axis must be a vector compatible");
+        return NULL;
+    }
+
+    axiscoords = VectorCoordsFromObj (axis, &axisdim);
+    if (!axiscoords)
+        return NULL;
+    if (axisdim < v->dim)
+    {
+        PyErr_SetString (PyExc_ValueError,
+            "axis must have at least three dimensions");
+        PyMem_Free (axiscoords);
+        return NULL;
+    }
+
+    memcpy (tmp, v->coords, sizeof (double) * 3);
+    _do_rotate (v->coords, tmp, axiscoords, angle, v->epsilon);
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_vector3_rotate_x (PyObject *self, PyObject *args)
+{
+    PyVector *v = (PyVector *) self;
+    PyVector *ret;
+    double sinvalue, cosvalue;
+    double angle;
+
+    if (!PyArg_ParseTuple (args, "d:rotate_x", &angle))
+        return NULL;
+    ret = (PyVector*) PyVector3_New (0.f, 0.f, 0.f);
+    if (!ret)
+        return NULL;
+
+    angle = DEG2RAD (angle);
+    sinvalue = sin (angle);
+    cosvalue = cos (angle);
+
+    ret->coords[0] = v->coords[0];
+    ret->coords[1] = v->coords[1] * cosvalue - v->coords[2] * sinvalue;
+    ret->coords[2] = v->coords[1] * sinvalue + v->coords[2] * cosvalue;
+    return (PyObject*) ret;
+}
+
+static PyObject*
+_vector3_rotate_x_ip (PyObject *self, PyObject *args)
+{
+    PyVector *v = (PyVector *) self;
+    double tmpcoords[3];
+    double sinvalue, cosvalue;
+    double angle;
+
+    if (!PyArg_ParseTuple (args, "d:rotate_x_ip", &angle))
+        return NULL;
+
+    angle = DEG2RAD (angle);
+    sinvalue = sin (angle);
+    cosvalue = cos (angle);
+    memcpy(tmpcoords, v->coords, sizeof(double) * 3);
+
+    v->coords[1] = tmpcoords[1] * cosvalue - tmpcoords[2] * sinvalue;
+    v->coords[2] = tmpcoords[1] * sinvalue + tmpcoords[2] * cosvalue;
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_vector3_rotate_y (PyObject *self, PyObject *args)
+{
+    PyVector *v = (PyVector *) self;
+    PyVector *ret;
+    double sinvalue, cosvalue;
+    double angle;
+
+    if (!PyArg_ParseTuple (args, "d:rotate_y", &angle))
+        return NULL;
+    ret = (PyVector*) PyVector3_New (0.f, 0.f, 0.f);
+    if (!ret)
+        return NULL;
+
+    angle = DEG2RAD (angle);
+    sinvalue = sin (angle);
+    cosvalue = cos (angle);
+
+    ret->coords[0] = v->coords[0] * cosvalue - v->coords[2] * sinvalue;
+    ret->coords[1] = v->coords[1];
+    ret->coords[2] = - v->coords[0] * sinvalue + v->coords[2] * cosvalue;
+    return (PyObject*) ret;
+}
+
+static PyObject*
+_vector3_rotate_y_ip (PyObject *self, PyObject *args)
+{
+    PyVector *v = (PyVector *) self;
+    double tmpcoords[3];
+    double sinvalue, cosvalue;
+    double angle;
+
+    if (!PyArg_ParseTuple (args, "d:rotate_y_ip", &angle))
+        return NULL;
+
+    angle = DEG2RAD (angle);
+    sinvalue = sin (angle);
+    cosvalue = cos (angle);
+    memcpy(tmpcoords, v->coords, sizeof(double) * 3);
+
+    v->coords[0] = tmpcoords[0] * cosvalue + tmpcoords[2] * sinvalue;
+    v->coords[2] = -tmpcoords[0] * sinvalue + tmpcoords[2] * cosvalue;
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_vector3_rotate_z (PyObject *self, PyObject *args)
+{
+    PyVector *v = (PyVector *) self;
+    PyVector *ret;
+    double sinvalue, cosvalue;
+    double angle;
+
+    if (!PyArg_ParseTuple (args, "d:rotate_z", &angle))
+        return NULL;
+    ret = (PyVector*) PyVector3_New (0.f, 0.f, 0.f);
+    if (!ret)
+        return NULL;
+
+    angle = DEG2RAD (angle);
+    sinvalue = sin (angle);
+    cosvalue = cos (angle);
+
+    ret->coords[0] = v->coords[0] * cosvalue - v->coords[1] * sinvalue;
+    ret->coords[1] = v->coords[0] * sinvalue + v->coords[1] * cosvalue;
+    ret->coords[2] = v->coords[2];
+    return (PyObject*) ret;
+}
+
+static PyObject*
+_vector3_rotate_z_ip (PyObject *self, PyObject *args)
+{
+    PyVector *v = (PyVector *) self;
+    double tmpcoords[3];
+    double sinvalue, cosvalue;
+    double angle;
+
+    if (!PyArg_ParseTuple (args, "d:rotate_z_ip", &angle))
+        return NULL;
+
+    angle = DEG2RAD (angle);
+    sinvalue = sin (angle);
+    cosvalue = cos (angle);
+    memcpy(tmpcoords, v->coords, sizeof(double) * 3);
+
+    v->coords[0] = tmpcoords[0] * cosvalue - tmpcoords[1] * sinvalue;
+    v->coords[1] = tmpcoords[0] * sinvalue + tmpcoords[1] * cosvalue;
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_vector3_cross (PyObject *self, PyObject *args)
+{
+    PyObject *other;
+    Py_ssize_t otherdim;
+    double *othercoords;
+    PyVector *v = (PyVector *) self;
+    PyVector *ret;
+
+    if (!PyArg_ParseTuple (args, "O:cross", &other))
+        return NULL;
+
+    if (!IsVectorCompatible (other))
+    {
+        PyErr_SetString (PyExc_TypeError, "other must be a vector compatible");
+        return NULL;
+    }
+
+    othercoords = VectorCoordsFromObj (other, &otherdim);
+    if (!othercoords)
+        return NULL;
+    if (otherdim < v->dim)
+    {
+        PyErr_SetString (PyExc_ValueError,
+            "other must have at least three dimensions");
+        PyMem_Free (othercoords);
+        return NULL;
+    }
+
+    ret = (PyVector*) PyVector3_New (0.f, 0.f, 0.f);
+    if (!ret)
+    {
+        PyMem_Free (othercoords);
+        return NULL;
+    }
+
+    ret->coords[0] = (v->coords[1] * othercoords[2]) -
+        (v->coords[2] * othercoords[1]);
+    ret->coords[1] = (v->coords[2] * othercoords[0]) -
+        (v->coords[0] * othercoords[2]);
+    ret->coords[2] = (v->coords[0] * othercoords[1]) -
+        (v->coords[1] * othercoords[0]);
+    return (PyObject*) ret;
+}
+
+static PyObject*
+_vector3_angleto (PyObject *self, PyObject *args)
+{
+    double angle, tmp1, tmp2;
+    double *othercoords;
+    Py_ssize_t otherdim;
+    PyObject *other;
+    PyVector* v = (PyVector*)self;
+
+    if (!PyArg_ParseTuple (args, "O:angleto", &other))
+        return NULL;
+
+    if (!IsVectorCompatible (other))
+    {
+        PyErr_SetString (PyExc_TypeError, "other must be a vector compatible");
+        return NULL;
+    }
+
+    othercoords = VectorCoordsFromObj (other, &otherdim);
+    if (!othercoords)
+        return NULL;
+    if (otherdim < v->dim)
+    {
+        PyErr_SetString (PyExc_ValueError,
+            "other must have at least three dimensions");
+        PyMem_Free (othercoords);
+        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));
+
+    return PyFloat_FromDouble (RAD2DEG (angle));
+}
+
+static PyObject*
+_vector3_asspherical (PyObject *self)
+{
+    PyVector* v = (PyVector*)self;
+    double r, theta, phi;
+    r = sqrt (_ScalarProduct (v->coords, v->coords, v->dim));
+
+    theta = acos (v->coords[2] / r);
+    phi = atan2 (v->coords[1], v->coords[0]);
+    return Py_BuildValue ("(ddd)", r, theta, phi);
+}
+
+
 /* C API */
 PyObject*
 PyVector3_New (double x, double y, double z)

File src/pgcompat.h

 
 /* Weakrefs flags changed in 3.x */
 #define Py_TPFLAGS_HAVE_WEAKREFS 0
+/* No more type checks */
+#define Py_TPFLAGS_CHECKTYPES 0
 
 /* Module creation and type heads differ a lot. */
 #define MODINIT_RETURN(x) return(x)

File src/sdl/timemod.c

     if (!id)
     {
         Py_DECREF (retval);
+        _free_timerdata (timerdata);
         PyErr_SetString (PyExc_PyGameError, SDL_GetError ());
         return NULL;
     }
 
     if (PyList_Append (state->timerlist, retval) == -1)
     {
-        Py_DECREF (retval); /* Takes care of freeing. */
+        Py_DECREF (retval);
+        _free_timerdata (timerdata);
         SDL_RemoveTimer (id);
         return NULL;
     }

File test/math_test.py

 except:
     import pgunittest as unittest
 
+import math
 import pygame2
-import pygame2.math as math
+import pygame2.math as pmath
+from pygame2.math import Vector, Vector2, Vector3
 
 class MathTest (unittest.TestCase):
 
+    def setUp (self):
+        self.zeroVec = Vector2 ()
+        self.e1 = Vector2(1, 0)
+        self.e2 = Vector2(0, 1)
+        self.t1 = (1.2, 3.4)
+        self.l1 = list(self.t1)
+        self.v1 = Vector2(self.t1)
+        self.t2 = (5.6, 7.8)
+        self.l2 = list(self.t2)
+        self.v2 = Vector2(self.t2)
+        self.s1 = 5.6
+        self.s2 = 7.8
+
+    def tearDown (self):
+        pass
+
+    def testConstructionDefault(self):
+        v = Vector2()
+        self.assertEqual(v.x, 0.)
+        self.assertEqual(v.y, 0.)
+        v = Vector3()
+        self.assertEqual(v.x, 0.)
+        self.assertEqual(v.y, 0.)
+        self.assertEqual(v.z, 0.)
+
+    def testConstructionXYZ(self):
+        v = Vector2(1.2, 3.4)
+        self.assertEqual(v.x, 1.2)
+        self.assertEqual(v.y, 3.4)
+        v = Vector3(1.2, 3.4, 5.6)
+        self.assertEqual(v.x, 1.2)
+        self.assertEqual(v.y, 3.4)
+        self.assertEqual(v.z, 5.6)
+
+    def testConstructionTuple(self):
+        v = Vector((1.2, 3.4))
+        self.assertEqual(v.elements[0], 1.2)
+        self.assertEqual(v.elements[1], 3.4)
+
+    def testConstructionList(self):
+        v = Vector([1.2, 3.4])
+        self.assertEqual(v.elements[0], 1.2)
+        self.assertEqual(v.elements[1], 3.4)
+
+    def testConstructionVector2(self):
+        v = Vector(Vector2(1.2, 3.4))
+        self.assertEqual(v.elements[0], 1.2)
+        self.assertEqual(v.elements[1], 3.4)
+
+    def testSequence(self):
+        v = Vector2(1.2, 3.4)
+        Vector2()[:]
+        self.assertEqual(len(v), 2)
+        self.assertEqual(v[0], 1.2)
+        self.assertEqual(v[1], 3.4)
+        self.assertRaises(IndexError, lambda : v[2])
+        self.assertEqual(v[-1], 3.4)
+        self.assertEqual(v[-2], 1.2)
+        self.assertRaises(IndexError, lambda : v[-3])
+        self.assertEqual(v[:], [1.2, 3.4])
+        self.assertEqual(v[1:], 3.4)
+        self.assertEqual(v[:1], 1.2)
+        self.assertEqual(list(v), [1.2, 3.4])
+        self.assertEqual(tuple(v), (1.2, 3.4))
+        v[0] = 5.6
+        v[1] = 7.8
+        self.assertEqual(v.x, 5.6)
+        self.assertEqual(v.y, 7.8)
+        v[:] = [9.1, 11.12]
+        self.assertEqual(v.x, 9.1)
+        self.assertEqual(v.y, 11.12)
+        def overpopulate ():
+            v = Vector2()
+            v[:] = [1, 2, 3]
+        self.assertRaises(ValueError, overpopulate)
+        def underpopulate():
+            v = Vector2()
+            v[:] = [1]
+        self.assertRaises(ValueError, underpopulate)
+
+    def testExtendedSlicing(self):
+        #  deletion
+        _v1 = Vector ((1.2, 3.4))
+        
+        def delSlice(vec, start=None, stop=None, step=None):
+            if start is not None and stop is not None and step is not None:
+                del vec[start:stop:step]
+            elif start is not None and stop is None and step is not None:
+                del vec[start::step]
+            elif start is None and stop is None and step is not None:
+                del vec[::step]
+        v = Vector(_v1)
+        
+        self.assertRaises(ValueError, delSlice, v, None, None, 2)
+        self.assertRaises(ValueError, delSlice, v, 1, None, 2)
+        self.assertRaises(ValueError, delSlice, v, 1, 2, 1)
+
+        #  assignment
+        v = (_v1)
+        v[::2] = [-1]
+        self.assertEqual(v, Vector ((-1, _v1.elements[1])))
+        v = Vector(_v1)
+        v[::-2] = [10]
+        self.assertEqual(v, Vector2 ((_v1.elements[0], 10)))
+        v = Vector(_v1)
+        v[::-1] = v
+        self.assertEqual(v, Vector ((_v1.elements[1], _v1.elements[0])))
+        a = Vector(_v1)
+        b = Vector(_v1)
+        c = Vector(_v1)
+        a[1:2] = [2.2]
+        b[slice(1,2)] = [2.2]
+        c[1:2:] = (2.2,)
+        self.assertEqual(a, b)
+        self.assertEqual(a, c)
+        self.assertEqual(type(a), type(_v1))
+        self.assertEqual(type(b), type(_v1))
+        self.assertEqual(type(c), type(_v1))
+
+    def testAdd(self):
+        v3 = self.v1 + self.v2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.v1.x + self.v2.x)
+        self.assertEqual(v3.y, self.v1.y + self.v2.y)
+        v3 = self.v1 + self.t2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.v1.x + self.t2[0])
+        self.assertEqual(v3.y, self.v1.y + self.t2[1])
+        v3 = self.v1 + self.l2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.v1.x + self.l2[0])
+        self.assertEqual(v3.y, self.v1.y + self.l2[1])
+        v3 = self.t1 + self.v2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.t1[0] + self.v2.x)
+        self.assertEqual(v3.y, self.t1[1] + self.v2.y)
+        v3 = self.l1 + self.v2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.l1[0] + self.v2.x)
+        self.assertEqual(v3.y, self.l1[1] + self.v2.y)
+
+    def testSub(self):
+        v3 = self.v1 - self.v2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.v1.x - self.v2.x)
+        self.assertEqual(v3.y, self.v1.y - self.v2.y)
+        v3 = self.v1 - self.t2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.v1.x - self.t2[0])
+        self.assertEqual(v3.y, self.v1.y - self.t2[1])
+        v3 = self.v1 - self.l2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.v1.x - self.l2[0])
+        self.assertEqual(v3.y, self.v1.y - self.l2[1])
+        v3 = self.t1 - self.v2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.t1[0] - self.v2.x)
+        self.assertEqual(v3.y, self.t1[1] - self.v2.y)
+        v3 = self.l1 - self.v2
+        self.assert_(isinstance(v3, type(self.v1)))
+        self.assertEqual(v3.x, self.l1[0] - self.v2.x)
+        self.assertEqual(v3.y, self.l1[1] - self.v2.y)
+
+    def testScalarMultiplication(self):
+        v = self.s1 * self.v1
+        self.assert_(isinstance(v, type(self.v1)))
+        self.assertEqual(v.x, self.s1 * self.v1.x)
+        self.assertEqual(v.y, self.s1 * self.v1.y)
+        v = self.v1 * self.s2
+        self.assertEqual(v.x, self.v1.x * self.s2)
+        self.assertEqual(v.y, self.v1.y * self.s2)
+
+    def testScalarDivision(self):
+        v = self.v1 / self.s1
+        self.assert_(isinstance(v, type(self.v1)))
+        self.assertAlmostEqual(v.x, self.v1.x / self.s1)
+        self.assertAlmostEqual(v.y, self.v1.y / self.s1)
+
+        v = self.v1 // self.s2
+        self.assert_(isinstance(v, type(self.v1)))
+        self.assertEqual(v.x, self.v1.x // self.s2)
+        self.assertEqual(v.y, self.v1.y // self.s2)
+
+    def testBool(self):
+        self.assertEqual(bool(self.zeroVec), False)
+        self.assertEqual(bool(self.v1), True)
+        self.assert_(not self.zeroVec)
+        self.assert_(self.v1)
+
+    def testUnary(self):
+        v = +self.v1
+        self.assert_(isinstance(v, type(self.v1)))
+        self.assertEqual(v.x, self.v1.x)
+        self.assertEqual(v.y, self.v1.y)
+        self.assertNotEqual(id(v), id(self.v1))
+        v = -self.v1
+        self.assert_(isinstance(v, type(self.v1)))
+        self.assertEqual(v.x, -self.v1.x)
+        self.assertEqual(v.y, -self.v1.y)
+        self.assertNotEqual(id(v), id(self.v1))
+        
+    def testCompare(self):
+        int_vec = Vector2(3, -2)
+        flt_vec = Vector2(3.0, -2.0)
+        zero_vec = Vector2(0, 0)
+        self.assertEqual(int_vec == flt_vec, True)
+        self.assertEqual(int_vec != flt_vec, False)
+        self.assertEqual(int_vec != zero_vec, True)
+        self.assertEqual(flt_vec == zero_vec, False)
+        self.assertEqual(int_vec == (3, -2), True)
+        self.assertEqual(int_vec != (3, -2), False)
+        self.assertEqual(int_vec != [0, 0], True)
+        self.assertEqual(int_vec == [0, 0], False)
+        self.assertEqual(int_vec != 5, True)
+        self.assertEqual(int_vec == 5, False)
+        self.assertEqual(int_vec != [3, -2, 0], True)
+        self.assertEqual(int_vec == [3, -2, 0], False)
+
+    def testStr(self):
+        v = Vector2(1.2, 3.4)
+        self.assertEqual(str(v), repr (v))
+        
+    def testRepr(self):
+        v = Vector2(1.2, 3.4)
+        self.assertEqual(repr (v), "Vector2(1.20000000, 3.40000000)")
+        self.assertEqual(v, eval(repr (v)))
+
+    def testIter(self):
+        it = iter (self.v1)
+        # support py2.x and 3.x
+        self.assertEqual(next(it), self.v1[0])
+        self.assertEqual(next(it), self.v1[1])
+        self.assertRaises(StopIteration, lambda : next(it))
+        it1 = iter (self.v1)
+        it2 = iter (self.v1)
+        self.assertNotEqual(id(it1), id(it2))
+        self.assertEqual(id(it1), id(iter (it1)))
+        self.assertEqual(list(it1), list(it2));
+        self.assertEqual(list(iter (self.v1)), self.l1)
+        idx = 0
+        for val in self.v1:
+            self.assertEqual(val, self.v1[idx])
+            idx += 1
+
     def test_pygame2_math_base_Vector_dimension(self):
 
         # __doc__ (as of 2010-01-06) for pygame2.math.base.Vector.dimension:
 
         # Gets the dimensions of the Vector.
         
-        self.assertRaises (ValueError, math.Vector, -1)
-        self.assertRaises (ValueError, math.Vector, 0)
-        self.assertRaises (ValueError, math.Vector, 1)
+        self.assertRaises (ValueError, Vector, -1)
+        self.assertRaises (ValueError, Vector, 0)
+        self.assertRaises (ValueError, Vector, 1)
 
         for i in range (2, 50):
-            v = math.Vector (i)
+            v = Vector (i)
             self.assertEqual (v.dimension, i)
 
     def test_pygame2_math_base_Vector_elements(self):
             v.elements = elems
         
         for i in range (2, 50):
-            v = math.Vector (i)
+            v = Vector (i)
             elems = v.elements
             self.assertEqual (len (elems), i)
             for j in range (i):
                 self.assertEqual (elems[j], 0)
-        v = math.Vector ([1,2,3,4])
+        v = Vector ([1,2,3,4])
         self.assertEqual (len (v.elements), 4)
         self.assertEqual (v.elements[0], 1)
         self.assertEqual (v.elements[1], 2)
         self.assertEqual (v.elements[2], 3)
         self.assertEqual (v.elements[3], 4)
-        v = math.Vector (10)
+        v = Vector (10)
         self.assertEqual (len (v.elements), 10)
         v.elements = (1, 2, 3, 4)
         self.assertEqual (v.elements[0], 1)
         def seteps (v, eps):
             v.epsilon = eps
         
-        v = math.Vector (2);
-        self.assertAlmostEqual (v.epsilon, 0)
+        v = Vector (2);
+        self.assertAlmostEqual (v.epsilon, 0, 5)
         v.epsilon = 0.0000004
         self.assertEqual (v.epsilon, 0.0000004)
         v.epsilon = 57293.2
         self.assertRaises (TypeError, seteps, v, "Hello")
 
     def test_pygame2_math_base_Vector2 (self):
-        self.assertRaises (TypeError, math.Vector2)
-        self.assertRaises (TypeError, math.Vector2, 0)
-        self.assertRaises (TypeError, math.Vector2, 0, 0, 0)
-        self.assertRaises (TypeError, math.Vector2, None, None)
-        self.assertRaises (TypeError, math.Vector2, None, 0)
-        self.assertRaises (TypeError, math.Vector2, 0, None)
-        self.assertRaises (TypeError, math.Vector2, "Hello", "World")
+        self.assertRaises (TypeError, Vector2, 0, 0, 0)
+        self.assertRaises (TypeError, Vector2, None, None)
+        self.assertRaises (TypeError, Vector2, None, 0)
+        self.assertRaises (TypeError, Vector2, 0, None)
+        self.assertRaises (TypeError, Vector2, "Hello", "World")
         
-        v = math.Vector2 (0, 0)
+        v = Vector2 (0, 0)
         self.assertEqual (v.dimension, 2)
         self.assertEqual (len (v.elements), 2)
         
 
         # Gets or sets first element of the Vector2.
         
-        v = math.Vector2 (10, 10)
+        v = Vector2 (10, 10)
         self.assertEqual (v.x, 10)
         v.x = 33.44
         self.assertEqual (v.x, 33.44)
 
         # Gets or sets second element of the Vector2.
 
-        v = math.Vector2 (10, 10)
+        v = Vector2 (10, 10)
         self.assertEqual (v.y, 10)
         v.y = 33.44
         self.assertEqual (v.y, 33.44)
         self.assertEqual (v.elements[1], 33.44)
 
     def test_pygame2_math_base_Vector3 (self):
-        self.assertRaises (TypeError, math.Vector3)
-        self.assertRaises (TypeError, math.Vector3, 0)
-        self.assertRaises (TypeError, math.Vector3, 0, 0)
-        self.assertRaises (TypeError, math.Vector3, 0, 0, 0, 0)
-        self.assertRaises (TypeError, math.Vector3, None, None, None)
-        self.assertRaises (TypeError, math.Vector3, None, None, 0)
-        self.assertRaises (TypeError, math.Vector3, None, 0, None)
-        self.assertRaises (TypeError, math.Vector3, None, 0, 0)
-        self.assertRaises (TypeError, math.Vector3, 0, None, 0)
-        self.assertRaises (TypeError, math.Vector3, 0, None, None)
-        self.assertRaises (TypeError, math.Vector3, 0, 0, None)
-        self.assertRaises (TypeError, math.Vector3, "Hello", "World", "!")
+        self.assertRaises (TypeError, Vector3, 0, 0, 0, 0)
+        self.assertRaises (TypeError, Vector3, None, None, None)
+        self.assertRaises (TypeError, Vector3, None, None, 0)
+        self.assertRaises (TypeError, Vector3, None, 0, None)
+        self.assertRaises (TypeError, Vector3, None, 0, 0)
+        self.assertRaises (TypeError, Vector3, 0, None, 0)
+        self.assertRaises (TypeError, Vector3, 0, None, None)
+        self.assertRaises (TypeError, Vector3, 0, 0, None)
+        self.assertRaises (TypeError, Vector3, "Hello", "World", "!")
         
-        v = math.Vector3 (0, 0, 0)
+        v = Vector3 (0, 0, 0)
         self.assertEqual (v.dimension, 3)
         self.assertEqual (len (v.elements), 3)
         
 
         # Gets or sets first element of the Vector3.
         
-        v = math.Vector3 (10, 10, 10)
+        v = Vector3 (10, 10, 10)
         self.assertEqual (v.x, 10)
         v.x = 33.44
         self.assertEqual (v.x, 33.44)
 
         # Gets or sets second element of the Vector3.
 
-        v = math.Vector3 (10, 10, 10)
+        v = Vector3 (10, 10, 10)
         self.assertEqual (v.y, 10)
         v.y = 33.44
         self.assertEqual (v.y, 33.44)
 
         # Gets or sets third element of the Vector3.
 
-        v = math.Vector3 (10, 10, 10)
+        v = Vector3 (10, 10, 10)
         self.assertEqual (v.z, 10)
         v.z = 33.44
         self.assertEqual (v.z, 33.44)
         self.assertEqual (v.elements[1], 10)
         self.assertEqual (v.elements[2], 33.44)
 
-    def todo_test_pygame2_math_base_Vector_length(self):
+    def test_pygame2_math_base_Vector_length(self):
 
         # __doc__ (as of 2010-01-07) for pygame2.math.base.Vector.length:
 
         # Gets the length of the Vector.
+        self.assertEqual(Vector2(3, 4).length, 5)
+        self.assertEqual(Vector2(-3, 4).length, 5)
+        self.assertEqual(self.zeroVec.length, 0)
 
-        self.fail() 
-
-    def todo_test_pygame2_math_base_Vector_length_squared(self):
+    def test_pygame2_math_base_Vector_length_squared(self):
 
         # __doc__ (as of 2010-01-07) for pygame2.math.base.Vector.length_squared:
 
         # Gets the length of the Vector.
+        self.assertEqual(Vector2(3, 4).length_squared, 25)
+        self.assertEqual(Vector2(-3, 4).length_squared, 25)
+        self.assertEqual(self.zeroVec.length_squared, 0)
 
-        self.fail() 
-
-    def todo_test_pygame2_math_base_Vector_normalize(self):
+    def test_pygame2_math_base_Vector_normalize(self):
 
         # __doc__ (as of 2010-01-07) for pygame2.math.base.Vector.normalize:
 
         # ormalize () -> Vector
+        v = self.v1.normalize()
+        # length is 1
+        self.assertAlmostEqual(v.x * v.x + v.y * v.y, 1.)
+        # v1 is unchanged
+        self.assertEqual(self.v1.x, self.l1[0])
+        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.fail() 
-
-    def todo_test_pygame2_math_base_Vector_normalize_ip(self):
+    def test_pygame2_math_base_Vector_normalize_ip(self):
 
         # __doc__ (as of 2010-01-07) for pygame2.math.base.Vector.normalize_ip:
 
         # ormalize_ip () -> None
+        v = +self.v1
+        # v has length != 1 before normalizing
+        self.assertNotEqual(v.x * v.x + v.y * v.y, 1.)
+        # inplace operations should return None
+        self.assertEqual(v.normalize_ip(), None)
+        # length is 1
+        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())
+
+    def test_pygame2_math_base_Vector_distance(self):
+
+        # __doc__ (as of 2010-01-09) for pygame2.math.base.Vector.distance:
+
+        # distance () -> None
+        diff = self.v1 - self.v2
+        self.assertEqual(self.e1.distance(self.e2), math.sqrt(2))
+        self.assertEqual(self.v1.distance(self.v2),
+                         math.sqrt(diff.x * diff.x + diff.y * diff.y))
+        self.assertEqual(self.v1.distance(self.v1), 0)
+        self.assertEqual(self.v1.distance(self.v2),
+                         self.v2.distance(self.v1))
+
+    def test_pygame2_math_base_Vector_distance_squared(self):
+
+        # __doc__ (as of 2010-01-09) for pygame2.math.base.Vector.distance_squared:
+
+        # distance_squared () -> None
+        diff = self.v1 - self.v2
+        self.assertEqual(self.e1.distance_squared(self.e2), 2)
+        self.assertEqual(self.v1.distance_squared(self.v2),
+                         diff.x * diff.x + diff.y * diff.y)
+        self.assertEqual(self.v1.distance_squared(self.v1), 0)
+        self.assertEqual(self.v1.distance_squared(self.v2),
+                         self.v2.distance_squared(self.v1))
+
+    def test_pygame2_math_base_Vector_dot(self):
+
+        # __doc__ (as of 2010-01-09) for pygame2.math.base.Vector.dot:
+
+        # dot () -> float
+        self.assertEqual(self.v1.dot(self.v2),
+                         self.v1.x * self.v2.x + self.v1.y * self.v2.y)
+        self.assertEqual(self.v1.dot(self.l2),
+                         self.v1.x * self.l2[0] + self.v1.y * self.l2[1])
+        self.assertEqual(self.v1.dot(self.t2),
+                         self.v1.x * self.t2[0] + self.v1.y * self.t2[1])
+        self.assertEqual(self.v1.dot(self.v2), self.v2.dot(self.v1))
+        self.assertEqual(self.v1.dot(self.v2), self.v1 * self.v2)
+
+
+    def todo_test_pygame2_math_base_Vector_lerp(self):
+
+        # __doc__ (as of 2010-01-09) for pygame2.math.base.Vector.lerp:
+
+        # lerp () -> Vector
+
+        self.fail() 
+
+    def test_pygame2_math_base_Vector_normalized(self):
+
+        # __doc__ (as of 2010-01-09) for pygame2.math.base.Vector.normalized:
+
+        # Gets whether the Vector is normalized.
+        self.assertEqual(self.v1.normalized, False)
+        v = self.v1.normalize()
+        self.assertEqual(v.normalized, True)
+        self.assertEqual(self.e2.normalized, True)
+        self.assertEqual(self.zeroVec.normalized, False)
+
+    def test_pygame2_math_base_Vector_reflect(self):
+
+        # __doc__ (as of 2010-01-09) for pygame2.math.base.Vector.reflect:
+
+        # reflect () -> Vector
+        v = Vector2(1, -1)
+        n = Vector2(0, 1)
+        self.assertEqual(v.reflect(n), Vector2(1, 1))
+        self.assertEqual(v.reflect(3*n), v.reflect(n))