interfaces/python: improve draft wrapper alpha_norm example, add some unit tests
authorPaul Brossier <piem@piem.org>
Wed, 30 Sep 2009 15:42:13 +0000 (17:42 +0200)
committerPaul Brossier <piem@piem.org>
Wed, 30 Sep 2009 15:42:13 +0000 (17:42 +0200)
interfaces/python/README [new file with mode: 0644]
interfaces/python/aubio-types.h [new file with mode: 0644]
interfaces/python/aubiomodule.c
interfaces/python/py-fvec.c [new file with mode: 0644]
interfaces/python/setup.py
interfaces/python/test_aubio.py [new file with mode: 0644]

diff --git a/interfaces/python/README b/interfaces/python/README
new file mode 100644 (file)
index 0000000..adfb22c
--- /dev/null
@@ -0,0 +1,5 @@
+This module wraps the aubio library for python using the numpy module.
+
+http://docs.python.org/c-api/index.html
+
+http://docs.scipy.org/doc/numpy/reference/c-api.html
diff --git a/interfaces/python/aubio-types.h b/interfaces/python/aubio-types.h
new file mode 100644 (file)
index 0000000..82fae6a
--- /dev/null
@@ -0,0 +1,13 @@
+#include <Python.h>
+#include <structmember.h>
+#define NO_IMPORT_ARRAY
+#include <numpy/arrayobject.h>
+#include <aubio.h>
+
+typedef struct
+{
+  PyObject_HEAD fvec_t * o;
+  uint_t length;
+  uint_t channels;
+} Py_fvec;
+extern PyTypeObject Py_fvecType;
index eb21dea46dcca342d7cbfeb88d2107b08a5e80dd..ffa3294e95f6f36ba1ed8cb9c9c74e89d37c45ae 100644 (file)
 #include <Python.h>
-#include <structmember.h>
+#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API
 #include <numpy/arrayobject.h>
-#include <aubio.h>
 
-static char aubio_module_doc[] = "Python module for the aubio library";
-
-/* fvec type definition 
-
-class fvec():
-    def __init__(self, length = 1024, channels = 1):
-        self.length = length 
-        self.channels = channels 
-        self.data = array(length, channels)
-
-*/
+#include "aubio-types.h"
 
-#define Py_fvec_default_length   1024
-#define Py_fvec_default_channels 1
-
-static char Py_fvec_doc[] = "fvec object";
-
-typedef struct
-{
-  PyObject_HEAD fvec_t * o;
-  uint_t length;
-  uint_t channels;
-} Py_fvec;
+static char Py_alpha_norm_doc[] = "compute alpha normalisation factor";
 
 static PyObject *
-Py_fvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
+Py_alpha_norm (PyObject * self, PyObject * args)
 {
-  int length = 0, channels = 0;
-  Py_fvec *self;
-  static char *kwlist[] = { "length", "channels", NULL };
-
-  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
-          &length, &channels)) {
-    return NULL;
-  }
-
-
-  self = (Py_fvec *) type->tp_alloc (type, 0);
-
-  self->length = Py_fvec_default_length;
-  self->channels = Py_fvec_default_channels;
-
-  if (self == NULL) {
-    return NULL;
-  }
+  PyObject *input;
+  Py_fvec *vec;
+  smpl_t alpha;
+  PyObject *result;
+  PyObject *array;
+  uint_t i;
 
-  if (length > 0) {
-    self->length = length;
-  } else if (length < 0) {
-    PyErr_SetString (PyExc_ValueError,
-        "can not use negative number of elements");
+  if (!PyArg_ParseTuple (args, "Of:alpha_norm", &input, &alpha)) {
     return NULL;
   }
 
-  if (channels > 0) {
-    self->channels = channels;
-  } else if (channels < 0) {
-    PyErr_SetString (PyExc_ValueError,
-        "can not use negative number of channels");
+  if (input == NULL) {
     return NULL;
   }
 
+  // parsing input object into a Py_fvec
+  if (PyObject_TypeCheck (input, &Py_fvecType)) {
+    // input is an fvec, nothing else to do
+    vec = (Py_fvec *) input;
+  } else if (PyArray_Check(input)) {
 
-  return (PyObject *) self;
-}
-
-static int
-Py_fvec_init (Py_fvec * self, PyObject * args, PyObject * kwds)
-{
-  self->o = new_fvec (self->length, self->channels);
-  if (self->o == NULL) {
-    return -1;
-  }
-
-  return 0;
-}
-
-static void
-Py_fvec_del (Py_fvec * self)
-{
-  del_fvec (self->o);
-  self->ob_type->tp_free ((PyObject *) self);
-}
-
-static PyObject *
-Py_fvec_repr (Py_fvec * self, PyObject * unused)
-{
-  PyObject *format = NULL;
-  PyObject *args = NULL;
-  PyObject *result = NULL;
-
-  format = PyString_FromString ("aubio fvec of %d elements with %d channels");
-  if (format == NULL) {
-    goto fail;
-  }
-
-  args = Py_BuildValue ("II", self->length, self->channels);
-  if (args == NULL) {
-    goto fail;
-  }
-
-  result = PyString_Format (format, args);
-
-fail:
-  Py_XDECREF (format);
-  Py_XDECREF (args);
-
-  return result;
-}
-
-static PyObject *
-Py_fvec_print (Py_fvec * self, PyObject * unused)
-{
-  fvec_print (self->o);
-  return Py_None;
-}
-
-static PyObject *
-Py_fvec_array (Py_fvec * self)
-{
-  PyObject *array = NULL;
-  if (self->channels == 1) {
-    npy_intp dims[] = { self->length, 1 };
-    array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[0]);
-  } else {
-    uint_t i;
-    npy_intp dims[] = { self->length, 1 };
-    PyObject *concat = PyList_New (0), *tmp = NULL;
-    for (i = 0; i < self->channels; i++) {
-      tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[i]);
-      PyList_Append (concat, tmp);
-      Py_DECREF (tmp);
+    // we got an array, convert it to an fvec 
+    if (PyArray_NDIM (input) == 0) {
+      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
+      goto fail;
+    } else if (PyArray_NDIM (input) > 2) {
+      PyErr_SetString (PyExc_ValueError, "input array has more than two dimensions");
+      goto fail;
     }
-    array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2);
-    Py_DECREF (concat);
-  }
-  return array;
-}
 
-static Py_ssize_t
-Py_fvec_getchannels (Py_fvec * self)
-{
-  return self->channels;
-}
-
-static PyObject *
-Py_fvec_getitem (Py_fvec * self, Py_ssize_t index)
-{
-  PyObject *array;
-
-  if (index < 0 || index >= self->channels) {
-    PyErr_SetString (PyExc_IndexError, "no such channel");
-    return NULL;
-  }
-
-  npy_intp dims[] = { self->length, 1 };
-  array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[index]);
-  return array;
-}
-
-static int
-Py_fvec_setitem (Py_fvec * self, Py_ssize_t index, PyObject * o)
-{
-  PyObject *array;
-
-  if (index < 0 || index >= self->channels) {
-    PyErr_SetString (PyExc_IndexError, "no such channel");
-    return -1;
-  }
-
-  array = PyArray_FROM_OT (o, NPY_FLOAT);
-  if (array == NULL) {
-    PyErr_SetString (PyExc_ValueError, "should be an array of float");
-    goto fail;
-  }
-
-  if (PyArray_NDIM (array) != 1) {
-    PyErr_SetString (PyExc_ValueError, "should be a one-dimensional array");
-    goto fail;
-  }
-
-  if (PyArray_SIZE (array) != self->length) {
-    PyErr_SetString (PyExc_ValueError,
-        "should be an array of same length as target fvec");
-    goto fail;
-  }
-
-  self->o->data[index] = (smpl_t *) PyArray_GETPTR1 (array, 0);
-
-  return 0;
-
-fail:
-  return -1;
-}
-
-static PyMemberDef Py_fvec_members[] = {
-  // TODO remove READONLY flag and define getter/setter
-  {"length", T_INT, offsetof (Py_fvec, length), READONLY,
-      "length attribute"},
-  {"channels", T_INT, offsetof (Py_fvec, channels), READONLY,
-      "channels attribute"},
-  {NULL}                        /* Sentinel */
-};
-
-static PyMethodDef Py_fvec_methods[] = {
-  {"dump", (PyCFunction) Py_fvec_print, METH_NOARGS,
-      "Dumps the contents of the vector to stdout."},
-  {"__array__", (PyCFunction) Py_fvec_array, METH_NOARGS,
-      "Returns the first channel as a numpy array."},
-  {NULL}
-};
-
-static PySequenceMethods Py_fvec_tp_as_sequence = {
-  (lenfunc) Py_fvec_getchannels,        /* sq_length         */
-  0,                            /* sq_concat         */
-  0,                            /* sq_repeat         */
-  (ssizeargfunc) Py_fvec_getitem,       /* sq_item           */
-  0,                            /* sq_slice          */
-  (ssizeobjargproc) Py_fvec_setitem,    /* sq_ass_item       */
-  0,                            /* sq_ass_slice      */
-  0,                            /* sq_contains       */
-  0,                            /* sq_inplace_concat */
-  0,                            /* sq_inplace_repeat */
-};
-
-
-static PyTypeObject Py_fvecType = {
-  PyObject_HEAD_INIT (NULL)
-      0,                        /* ob_size           */
-  "fvec",                       /* tp_name           */
-  sizeof (Py_fvec),             /* tp_basicsize      */
-  0,                            /* tp_itemsize       */
-  (destructor) Py_fvec_del,     /* tp_dealloc        */
-  0,                            /* tp_print          */
-  0,                            /* tp_getattr        */
-  0,                            /* tp_setattr        */
-  0,                            /* tp_compare        */
-  (reprfunc) Py_fvec_repr,      /* tp_repr           */
-  0,                            /* tp_as_number      */
-  &Py_fvec_tp_as_sequence,      /* 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          */
-  Py_fvec_doc,                  /* tp_doc            */
-  0,                            /* tp_traverse       */
-  0,                            /* tp_clear          */
-  0,                            /* tp_richcompare    */
-  0,                            /* tp_weaklistoffset */
-  0,                            /* tp_iter           */
-  0,                            /* tp_iternext       */
-  Py_fvec_methods,              /* tp_methods        */
-  Py_fvec_members,              /* tp_members        */
-  0,                            /* tp_getset         */
-  0,                            /* tp_base           */
-  0,                            /* tp_dict           */
-  0,                            /* tp_descr_get      */
-  0,                            /* tp_descr_set      */
-  0,                            /* tp_dictoffset     */
-  (initproc) Py_fvec_init,      /* tp_init           */
-  0,                            /* tp_alloc          */
-  Py_fvec_new,                  /* tp_new            */
-};
-
-/* end of fvec type definition */
+    if (!PyArray_ISFLOAT (input)) {
+      PyErr_SetString (PyExc_ValueError, "input array should be float");
+      goto fail;
+    } else if (PyArray_TYPE (input) != NPY_FLOAT) {
+      // input data type is not float32, casting 
+      array = PyArray_Cast ( (PyArrayObject*) input, NPY_FLOAT);
+      if (array == NULL) {
+        PyErr_SetString (PyExc_IndexError, "failed converting to NPY_FLOAT");
+        goto fail;
+      }
+    } else {
+      // input data type is float32, nothing else to do
+      array = input;
+    }
 
-static PyObject *
-Py_alpha_norm (PyObject * self, PyObject * args)
-{
-  Py_fvec *vec;
-  smpl_t alpha;
-  PyObject *result;
+    // create a new fvec object
+    vec = (Py_fvec*) PyObject_New (Py_fvec, &Py_fvecType); 
+    if (PyArray_NDIM (array) == 1) {
+      vec->channels = 1;
+      vec->length = PyArray_SIZE (array);
+    } else {
+      vec->channels = PyArray_DIM (array, 0);
+      vec->length = PyArray_DIM (array, 1);
+    }
 
-  if (!PyArg_ParseTuple (args, "Of:alpha_norm", &vec, &alpha)) {
-    return NULL;
-  }
+    // FIXME should not need to allocate fvec
+    vec->o = new_fvec (vec->length, vec->channels);
+    for (i = 0; i < vec->channels; i++) {
+      vec->o->data[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
+    }
 
-  if (vec == NULL) {
+  } else {
+    PyErr_SetString (PyExc_ValueError, "can only accept array or fvec as input");
     return NULL;
   }
 
+  // compute the function
   result = Py_BuildValue ("f", vec_alpha_norm (vec->o, alpha));
   if (result == NULL) {
     return NULL;
@@ -295,15 +83,17 @@ Py_alpha_norm (PyObject * self, PyObject * args)
 
   return result;
 
+fail:
+    return NULL;
 }
 
-static char Py_alpha_norm_doc[] = "compute alpha normalisation factor";
-
 static PyMethodDef aubio_methods[] = {
   {"alpha_norm", Py_alpha_norm, METH_VARARGS, Py_alpha_norm_doc},
   {NULL, NULL}                  /* Sentinel */
 };
 
+static char aubio_module_doc[] = "Python module for the aubio library";
+
 PyMODINIT_FUNC
 init_aubio (void)
 {
diff --git a/interfaces/python/py-fvec.c b/interfaces/python/py-fvec.c
new file mode 100644 (file)
index 0000000..72d812e
--- /dev/null
@@ -0,0 +1,260 @@
+#include "aubio-types.h"
+
+/* fvec type definition 
+
+class fvec():
+    def __init__(self, length = 1024, channels = 1):
+        self.length = length 
+        self.channels = channels 
+        self.data = array(length, channels)
+
+*/
+
+#define Py_fvec_default_length   1024
+#define Py_fvec_default_channels 1
+
+static char Py_fvec_doc[] = "fvec object";
+
+static PyObject *
+Py_fvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
+{
+  int length= 0, channels = 0;
+  Py_fvec *self;
+  static char *kwlist[] = { "length", "channels", NULL };
+
+  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
+          &length, &channels)) {
+    return NULL;
+  }
+
+
+  self = (Py_fvec *) type->tp_alloc (type, 0);
+
+  self->length = Py_fvec_default_length;
+  self->channels = Py_fvec_default_channels;
+
+  if (self == NULL) {
+    return NULL;
+  }
+
+  if (length > 0) {
+    self->length = length;
+  } else if (length < 0) {
+    PyErr_SetString (PyExc_ValueError,
+        "can not use negative number of elements");
+    return NULL;
+  }
+
+  if (channels > 0) {
+    self->channels = channels;
+  } else if (channels < 0) {
+    PyErr_SetString (PyExc_ValueError,
+        "can not use negative number of channels");
+    return NULL;
+  }
+
+
+  return (PyObject *) self;
+}
+
+static int
+Py_fvec_init (Py_fvec * self, PyObject * args, PyObject * kwds)
+{
+  self->o = new_fvec (self->length, self->channels);
+  if (self->o == NULL) {
+    return -1;
+  }
+
+  return 0;
+}
+
+static void
+Py_fvec_del (Py_fvec * self)
+{
+  del_fvec (self->o);
+  self->ob_type->tp_free ((PyObject *) self);
+}
+
+static PyObject *
+Py_fvec_repr (Py_fvec * self, PyObject * unused)
+{
+  PyObject *format = NULL;
+  PyObject *args = NULL;
+  PyObject *result = NULL;
+
+  format = PyString_FromString ("aubio fvec of %d elements with %d channels");
+  if (format == NULL) {
+    goto fail;
+  }
+
+  args = Py_BuildValue ("II", self->length, self->channels);
+  if (args == NULL) {
+    goto fail;
+  }
+
+  result = PyString_Format (format, args);
+
+fail:
+  Py_XDECREF (format);
+  Py_XDECREF (args);
+
+  return result;
+}
+
+static PyObject *
+Py_fvec_print (Py_fvec * self, PyObject * unused)
+{
+  fvec_print (self->o);
+  return Py_None;
+}
+
+static PyObject *
+Py_fvec_array (Py_fvec * self)
+{
+  PyObject *array = NULL;
+  if (self->channels == 1) {
+    npy_intp dims[] = { self->length, 1 };
+    array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[0]);
+  } else {
+    uint_t i;
+    npy_intp dims[] = { self->length, 1 };
+    PyObject *concat = PyList_New (0), *tmp = NULL;
+    for (i = 0; i < self->channels; i++) {
+      tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[i]);
+      PyList_Append (concat, tmp);
+      Py_DECREF (tmp);
+    }
+    array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2);
+    Py_DECREF (concat);
+  }
+  return array;
+}
+
+static Py_ssize_t
+Py_fvec_getchannels (Py_fvec * self)
+{
+  return self->channels;
+}
+
+static PyObject *
+Py_fvec_getitem (Py_fvec * self, Py_ssize_t index)
+{
+  PyObject *array;
+
+  if (index < 0 || index >= self->channels) {
+    PyErr_SetString (PyExc_IndexError, "no such channel");
+    return NULL;
+  }
+
+  npy_intp dims[] = { self->length, 1 };
+  array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[index]);
+  return array;
+}
+
+static int
+Py_fvec_setitem (Py_fvec * self, Py_ssize_t index, PyObject * o)
+{
+  PyObject *array;
+
+  if (index < 0 || index >= self->channels) {
+    PyErr_SetString (PyExc_IndexError, "no such channel");
+    return -1;
+  }
+
+  array = PyArray_FROM_OT (o, NPY_FLOAT);
+  if (array == NULL) {
+    PyErr_SetString (PyExc_ValueError, "should be an array of float");
+    goto fail;
+  }
+
+  if (PyArray_NDIM (array) != 1) {
+    PyErr_SetString (PyExc_ValueError, "should be a one-dimensional array");
+    goto fail;
+  }
+
+  if (PyArray_SIZE (array) != self->length) {
+    PyErr_SetString (PyExc_ValueError,
+        "should be an array of same length as target fvec");
+    goto fail;
+  }
+
+  self->o->data[index] = (smpl_t *) PyArray_GETPTR1 (array, 0);
+
+  return 0;
+
+fail:
+  return -1;
+}
+
+static PyMemberDef Py_fvec_members[] = {
+  // TODO remove READONLY flag and define getter/setter
+  {"length", T_INT, offsetof (Py_fvec, length), READONLY,
+      "length attribute"},
+  {"channels", T_INT, offsetof (Py_fvec, channels), READONLY,
+      "channels attribute"},
+  {NULL}                        /* Sentinel */
+};
+
+static PyMethodDef Py_fvec_methods[] = {
+  {"dump", (PyCFunction) Py_fvec_print, METH_NOARGS,
+      "Dumps the contents of the vector to stdout."},
+  {"__array__", (PyCFunction) Py_fvec_array, METH_NOARGS,
+      "Returns the first channel as a numpy array."},
+  {NULL}
+};
+
+static PySequenceMethods Py_fvec_tp_as_sequence = {
+  (lenfunc) Py_fvec_getchannels,        /* sq_length         */
+  0,                                    /* sq_concat         */
+  0,                                    /* sq_repeat         */
+  (ssizeargfunc) Py_fvec_getitem,       /* sq_item           */
+  0,                                    /* sq_slice          */
+  (ssizeobjargproc) Py_fvec_setitem,    /* sq_ass_item       */
+  0,                                    /* sq_ass_slice      */
+  0,                                    /* sq_contains       */
+  0,                                    /* sq_inplace_concat */
+  0,                                    /* sq_inplace_repeat */
+};
+
+
+PyTypeObject Py_fvecType = {
+  PyObject_HEAD_INIT (NULL)
+  0,                            /* ob_size           */
+  "fvec",                       /* tp_name           */
+  sizeof (Py_fvec),             /* tp_basicsize      */
+  0,                            /* tp_itemsize       */
+  (destructor) Py_fvec_del,     /* tp_dealloc        */
+  0,                            /* tp_print          */
+  0,                            /* tp_getattr        */
+  0,                            /* tp_setattr        */
+  0,                            /* tp_compare        */
+  (reprfunc) Py_fvec_repr,      /* tp_repr           */
+  0,                            /* tp_as_number      */
+  &Py_fvec_tp_as_sequence,      /* 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          */
+  Py_fvec_doc,                  /* tp_doc            */
+  0,                            /* tp_traverse       */
+  0,                            /* tp_clear          */
+  0,                            /* tp_richcompare    */
+  0,                            /* tp_weaklistoffset */
+  0,                            /* tp_iter           */
+  0,                            /* tp_iternext       */
+  Py_fvec_methods,              /* tp_methods        */
+  Py_fvec_members,              /* tp_members        */
+  0,                            /* tp_getset         */
+  0,                            /* tp_base           */
+  0,                            /* tp_dict           */
+  0,                            /* tp_descr_get      */
+  0,                            /* tp_descr_set      */
+  0,                            /* tp_dictoffset     */
+  (initproc) Py_fvec_init,      /* tp_init           */
+  0,                            /* tp_alloc          */
+  Py_fvec_new,                  /* tp_new            */
+};
index bb2aa869188898f213b7f743ffc73cb48c9bd92c..17aa301ac72ba769cf021e9fb46aa59017a69f40 100644 (file)
@@ -3,7 +3,7 @@ from distutils.core import setup, Extension
 setup(name="_aubio", version="1.0",
       ext_modules = [ 
         Extension("_aubio",
-            ["aubiomodule.c"],
+            ["aubiomodule.c", "py-fvec.c"],
             include_dirs=['../../build/default/src', '../../src' ],
             library_dirs=['../../build/default/src', '../../src/.libs' ],
             libraries=['aubio'])])
diff --git a/interfaces/python/test_aubio.py b/interfaces/python/test_aubio.py
new file mode 100644 (file)
index 0000000..9532a54
--- /dev/null
@@ -0,0 +1,72 @@
+import unittest
+from _aubio import *
+from numpy import array
+
+class aubiomodule_test_case(unittest.TestCase):
+
+  def setUp(self):
+    """ try importing aubio """
+
+  def test_vector(self):
+    a = fvec()
+    a.length, a.channels
+    a[0]
+    array(a)
+    a = fvec(10)
+    a = fvec(1, 2)
+    array(a).T
+    a[0] = range(a.length)
+    a[1][0] = 2
+
+  def test_wrong_values(self):
+    self.assertRaises (ValueError, fvec, -10)
+    self.assertRaises (ValueError, fvec, 1, -1)
+  
+    a = fvec(2, 3)
+    self.assertRaises (IndexError, a.__getitem__, 3)
+    self.assertRaises (IndexError, a[0].__getitem__, 2)
+
+  def test_alpha_norm_of_fvec(self):
+    a = fvec(2, 2)
+    self.assertEquals (alpha_norm(a, 1), 0)
+    a[0] = [1, 2] 
+    self.assertEquals (alpha_norm(a, 1), 1.5)
+    a[1] = [1, 2] 
+    self.assertEquals (alpha_norm(a, 1), 3)
+    a[0] = [0, 1]; a[1] = [1, 0]
+    self.assertEquals (alpha_norm(a, 2), 1)
+
+  def test_alpha_norm_of_array_of_float32(self):
+    a = array(1, dtype = 'float32')
+    self.assertRaises (ValueError, alpha_norm, a, 1)
+    a = array([[[1,2],[3,4]]], dtype = 'float32')
+    self.assertRaises (ValueError, alpha_norm, a, 1)
+    a = array(range(10), dtype = 'float32')
+    self.assertEquals (alpha_norm(a, 1), 4.5)
+    a = array([range(10), range(10)], dtype = 'float32')
+    self.assertEquals (alpha_norm(a, 1), 9)
+
+  def test_alpha_norm_of_array_of_float64(self):
+    a = array(1, dtype = 'float64')
+    self.assertRaises (ValueError, alpha_norm, a, 1)
+    a = array([[[1,2],[3,4]]], dtype = 'float64')
+    self.assertRaises (ValueError, alpha_norm, a, 1)
+    a = array(range(10), dtype = 'float64')
+    self.assertEquals (alpha_norm(a, 1), 4.5)
+    a = array([range(10), range(10)], dtype = 'float64')
+    self.assertEquals (alpha_norm(a, 1), 9)
+
+  def test_alpha_norm_of_array_of_int(self):
+    a = array(1, dtype = 'int')
+    self.assertRaises (ValueError, alpha_norm, a, 1)
+    a = array([[[1,2],[3,4]]], dtype = 'int')
+    self.assertRaises (ValueError, alpha_norm, a, 1)
+    a = array(range(10), dtype = 'int')
+    self.assertRaises (ValueError, alpha_norm, a, 1)
+
+  def test_alpha_norm_of_array_of_string (self):
+    a = "hello"
+    self.assertRaises (ValueError, alpha_norm, a, 1)
+
+if __name__ == '__main__':
+  unittest.main()