[Numpy-svn] r3574 - trunk/numpy/doc/swig

numpy-svn@scip... numpy-svn@scip...
Wed Mar 14 10:48:04 CDT 2007


Author: wfspotz@sandia.gov
Date: 2007-03-14 10:47:12 -0500 (Wed, 14 Mar 2007)
New Revision: 3574

Added:
   trunk/numpy/doc/swig/numpy_swig.html
   trunk/numpy/doc/swig/numpy_swig.txt
Removed:
   trunk/numpy/doc/swig/HelperFunctions.txt
Modified:
   trunk/numpy/doc/swig/Makefile
   trunk/numpy/doc/swig/README
   trunk/numpy/doc/swig/Series.i
   trunk/numpy/doc/swig/numpy.i
   trunk/numpy/doc/swig/series.cxx
   trunk/numpy/doc/swig/series.h
   trunk/numpy/doc/swig/setup.py
   trunk/numpy/doc/swig/testSeries.py
Log:
In numpy.i:

  * I consolidated several macros

      TYPEMAP_IN1
      TYPEMAP_IN2
      TYPEMAP_INPLACE1
      TYPEMAP_INPLACE2
      TYPEMAP_ARGOUT1
      TYPEMAP_ARGOUT2

    into a single macros, %numpy_typemaps().  This makes expanding the
    typemaps for a given data type much easier.

  * The %numpy_typemaps() macro is now expanded for::

      signed char
      unsigned char
      short
      unsigned short
      int
      unsigned int
      long
      unsigned long
      long long
      unsigned long long
      float
      double
      PyObject
      char

  * I changed the ARGOUT typemaps to check for multiple output
    arguments, and form a tuple if necessary.

  * Updated the code to work with released numpy versions 0.9.6,
    0.9.8, 1.0 and 1.0.1.

  * Upgraded the dimension arrays to use type npy_intp.

I also added documentation: numpy_swig.txt is a numpy.i users guide in
restructured text format; numpy_swig.html is the same content in
HTML.  The Makefile can produce this with 'make html', assuming
docutils is installed.

The series.h and series.cxx files have been refactored to use macros
to generate repetitive code for different types.  All the supported
types have tests for all of the non-ARGOUT typemaps.  ARGOUT typemap
tests still need to be written.


Deleted: trunk/numpy/doc/swig/HelperFunctions.txt
===================================================================
--- trunk/numpy/doc/swig/HelperFunctions.txt	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/HelperFunctions.txt	2007-03-14 15:47:12 UTC (rev 3574)
@@ -1,104 +0,0 @@
-/***********************************************************************
-    Helper functions from numpy.i, translated by John Hunter
-************************************************************************/
-
-#define is_array(a)            ((a) && PyArray_Check((PyArrayObject *)a))
-#define array_type(a)          (int)(((PyArrayObject *)a)->descr->type_num)
-#define array_dimensions(a)    (((PyArrayObject *)a)->nd)
-#define array_size(a,i)        (((PyArrayObject *)a)->dimensions[i])
-#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS(a))
-
-/* Given a PyObject, return a string describing its type.
- */
-char* pytype_string(PyObject* py_obj)
-
-/* Given a Numeric typecode, return a string describing the type.
- */
-char* typecode_string(int typecode)
-
-/* Make sure input has correct numeric type.  Allow character and byte
- * to match.  Also allow int and long to match.
- */
-int type_match(int actual_type, int desired_type)
-
-/* Given a PyObject pointer, cast it to a PyArrayObject pointer if
- * legal.  If not, set the python error string appropriately and
- * return NULL.
- */
-PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode)
-
-/* Convert the given PyObject to a Numeric array with the given
- * typecode.  On Success, return a valid PyArrayObject* with the
- * correct type.  On failure, the python error string will be set and
- * the routine returns NULL.
- */
-PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode,
-                                             int* is_new_object)
-
-/* Given a PyArrayObject, check to see if it is contiguous.  If so,
- * return the input pointer and flag it as not a new object.  If it is
- * not contiguous, create a new PyArrayObject using the original data,
- * flag it as a new object and return the pointer.
- */
-PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object,
-                               int min_dims, int max_dims)
-
-/* Convert a given PyObject to a contiguous PyArrayObject of the
- * specified type.  If the input object is not a contiguous
- * PyArrayObject, a new one will be created and the new object flag
- * will be set.
- */
-PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input,
-                                                        int typecode,
-                                                        int* is_new_object)
-
-/* Test whether a python object is contiguous.  If array is
- * contiguous, return 1.  Otherwise, set the python error string and
- * return 0.
- */
-int require_contiguous(PyArrayObject* ary)
-
-/* Require the given PyArrayObject to have a specified number of
- * dimensions.  If the array has the specified number of dimensions,
- * return 1.  Otherwise, set the python error string and return 0.
- */
-int require_dimensions(PyArrayObject* ary, int exact_dimensions)
-
-/* Require the given PyArrayObject to have one of a list of specified
- * number of dimensions.  If the array has one of the specified number
- * of dimensions, return 1.  Otherwise, set the python error string
- * and return 0.
- */
-int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n)
-
-/* Require the given PyArrayObject to have a specified shape.  If the
- * array has the specified shape, return 1.  Otherwise, set the python
- * error string and return 0.
- */
-int require_size(PyArrayObject* ary, int* size, int n)
-
-/***********************************************************************
-    Helper functions from Anna Omelchenko and Michel Sanner
-************************************************************************/
-
-/********************************************************************
-  The following function tries to create a contiguous numeric array of type 
- typecode from a Python object. Works for list, tuples and numeric arrays.
-
-  obj:        Numeric array , Python object
-  typecode:   data type PyArray_{ CHAR, UBYTE, SBYTE, SHORT, INT, LONG, FLOAT,
-                                DOUBLE, CFLOAT, CDOUBLE }
-  expectnd:   required number of dimensions. Used for checking. Ignored if <=0.
-  expectdims: array of expected extends. Used for checking. Ignored if <=0.
-
-  Raises ValueError exceptions if:
-  - the PyArray_ContiguousFromObject fails
-  - the array has a bad shape
-  - the extent of a given dimension doesn't match the specified extent.
-If obj  is a contiguous PyArrayObject  then a reference is returned;
-If op  is PyObject sequence object(list, tuple) then a new PyArrayObject  is created
- and returned. 
-********************************************************************/
-
-static PyArrayObject *contiguous_typed_array(PyObject *obj, int typecode,
-                                      int expectnd, int *expectdims)

Modified: trunk/numpy/doc/swig/Makefile
===================================================================
--- trunk/numpy/doc/swig/Makefile	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/Makefile	2007-03-14 15:47:12 UTC (rev 3574)
@@ -1,3 +1,4 @@
+# SWIG
 INTERFACES = Series.i
 WRAPPERS   = $(INTERFACES:.i=_wrap.cxx)
 PROXIES    = $(INTERFACES:.i=.py      )
@@ -2,2 +3,12 @@
 
+# ReStructured Text
+RST2HTML = rst2html.py
+RFLAGS = --generator --time --no-xml-declaration
+
+# Web pages that need to be made
+WEB_PAGES = numpy_swig.html
+
+# List all of the subdirectories here for recursive make
+SUBDIRS = 
+
 all: $(WRAPPERS) series.cxx series.h
@@ -8,7 +19,14 @@
 %_wrap.cxx: %.i numpy.i series.h
 	swig -c++ -python $<
 
+html: $(WEB_PAGES)
+
+%.html: %.txt
+	$(RST2HTML) $(RFLAGS) $< $@
+
 clean:
 	$(RM) -r build
 	$(RM) $(WRAPPERS)
 	$(RM) $(PROXIES)
+
+.PHONY : html clean

Modified: trunk/numpy/doc/swig/README
===================================================================
--- trunk/numpy/doc/swig/README	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/README	2007-03-14 15:47:12 UTC (rev 3574)
@@ -1,16 +1,15 @@
 Notes for the swig_numpy/new directory
 ======================================
 
-This set of files is for developing and testing file numpy.i, which
-is intended to be a set of typemaps for helping SWIG interface between
-C and C++ code that uses C arrays and the python module Numeric (also
-known informally as NumPy, also to be replaced in the future with
-scipy_core).  It is ultimately hoped that numpy.i will be included
-as part of the SWIG and/or SciPy distribution(s).
+This set of files is for developing and testing file numpy.i, which is
+intended to be a set of typemaps for helping SWIG interface between C
+and C++ code that uses C arrays and the python module NumPy.  It is
+ultimately hoped that numpy.i will be included as part of the SWIG
+distribution.
 
 In the spirit of "writing your tests first", I will begin by
 describing the tests, as they are a good example of what we are trying
-to do with numpy.i.  The files related to testing are
+to do with numpy.i.  The files related to testing are::
 
     series.h
     series.cxx
@@ -18,34 +17,34 @@
 
 The series.h header file contains prototypes for functions that
 illustrate the wrapping issues we wish to address.  Right now, this
-consists of functions with argument signatures of the form
+consists of functions with argument signatures of the form::
 
     (type* IN_ARRAY1, int DIM1)
     (type* IN_ARRAY2, int DIM1, int DIM2)
     (type* INPLACE_ARRAY1, int DIM1)
+    (type* INPLACE_ARRAY2, int DIM1, int DIM2)
 
 which take a pointer to an array of type "type", whose length is
 specified by the integer(s) DIM1 (and DIM2).
 
 The objective for the IN_ARRAY signatures is for SWIG to generate
 python wrappers that take a container that constitutes a valid
-argument to the Numeric.array constructor, and can be used to build an
+argument to the numpy array constructor, and can be used to build an
 array of type "type".  Currently, types "char", "unsigned char",
 "signed char", "short", "int", "long", "float", "double" and
 "PyObject" are supported, although only the types "short", "int",
 "long", "float" and "double" are tested.
 
 The objective for the INPLACE_ARRAY signatures is for SWIG to generate
-python wrappers that accept a Numeric array of any of the above-listed
+python wrappers that accept a numpy array of any of the above-listed
 types.
 
 The source file series.cxx contains the actual implementations of the
 functions described in series.h.  The python script testSeries.py
 tests the resulting python wrappers using the unittest module.
 
-The SWIG interface file Series.i is used to generate the wrapper
-code.  It is pretty short, but everything in it is important.  The
-SWIG_FILE_WITH_INIT macro allows numpy.i to be used with multiple
+The SWIG interface file Series.i is used to generate the wrapper code.
+The SWIG_FILE_WITH_INIT macro allows numpy.i to be used with multiple
 python modules.  If it is specified, then the %init block found in
 Series.i is required.  The other things done in Series.i are the
 inclusion of the series.h and numpy.i files, and the "%apply"
@@ -55,10 +54,10 @@
 a _Series extension module and a Series python module.  The Makefile
 automates everything, setting up the dependencies, calling swig to
 generate the wrappers, and calling setup.py to compile the wrapper
-code and generate the shared object.  Targets "all" (default) and
-"clean" ar supported.
+code and generate the shared object.  Targets "all" (default),
+"clean" and "html" (generate HTML documentation) are supported.
 
-To build and test the code, simply execute from the shell,
+To build and test the code, simply execute from the shell::
 
     $ make
     $ testSeries.py
@@ -66,57 +65,15 @@
 ================================================================================
 
 ToDo
-====
+----
 
-  * Tests for the (INPLACE_ARRAY2, DIM1, DIM2) nedd to be added to
-    series.h, series.cxx and testSeries.py.
+  * Support for complex data types should be added.  Currently swig
+    dies with a syntax error when the %numpy_typemaps macro isused
+    with complex types.
 
-  * Support for complex data types should be added.  Currently the
-    macro substitution doesn't seem to like the two words you need to
-    specify "complex double", etc.
-
-  * ARGOUT typemaps need to be implemented and tested.  I stalled on
-    this because SWIG implements a new method for aggregating output
-    arguments; it has changed from a tuple to a list and requires
-    importing a different SWIG library file.  I didn't particularly
-    want to spend time trying to support both approaches, and I ended
-    up not finishing a typemap for either.
-
-
-Notes Bill:
-
-The numpy.i file currently defines typemaps of the form
-
-      (type* IN_ARRAY1, int DIM1)
-      (type* IN_ARRAY2, int DIM1, int DIM2)
-      (type* INPLACE_ARRAY1, int DIM1)
-      (type* INPLACE_ARRAY2, int DIM1, int DIM2)
-
-and has the beginnings of typemaps of the form
-
-      (type* ARGOUT_ARRAY[ANY])
-      (type* ARGOUT_ARRAY[ANY][ANY])
-
-where "type" is almost any type supported by Numeric (I have had 
-trouble with complex), the "1" suffix can be used with any dimension 
-array as long as DIM1 reflects the total size, and the "2" suffix is 
-for explicitly 2-dimensional arrays.  IN_ARRAYs can be any reasonable 
-container that can be used to construct a Numeric array.  
-INPLACE_ARRAYs must be Numeric arrays.
-
-I hit a snag with the ARGOUT typemaps, because the swig libraries have 
-changed and I did not know the best way to proceed.  Basically, the old 
-way produced a tuple on the LHS if needed and the new way produces a 
-list.  I forget why swig made the change, but the actual swig library 
-file you import changed because of it and I didn't feel like spending 
-time trying to support both approaches.
-
-So the ARGOUT typemaps need to be finished, functions that would use 
-them need to be added to series.{h,cxx} and tests for the resulting 
-python interface need to be added to testSeries.py.
-
-Most of the functions I deal with cannot use the ARGOUT typemaps 
-anyway, because they usually involve input arrays that share the same 
-dimension arguments as the output arrays, which will require a special 
-approach.  So I don't have a lot of motivation there . . . but it 
-definitely needs to be done before any kind of release.
+  * Better ARGOUT typemaps need to be implemented and tested.  I
+    stalled on this because SWIG implements a new method for
+    aggregating output arguments; it has changed from a tuple to a
+    list and requires importing a different SWIG library file.  I
+    didn't particularly want to spend time trying to support both
+    approaches, and I ended up not finishing a typemap for either.

Modified: trunk/numpy/doc/swig/Series.i
===================================================================
--- trunk/numpy/doc/swig/Series.i	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/Series.i	2007-03-14 15:47:12 UTC (rev 3574)
@@ -1,3 +1,4 @@
+// -*- c++ -*-
 %module Series
 
 %{
@@ -5,27 +6,124 @@
 #include "series.h"
 %}
 
-/* Get the Numeric typemaps */
+// Get the Numeric typemaps
 %include "numpy.i"
 
 %init %{
   import_array();
 %}
 
-/* Apply the Numeric typemaps for 1D input arrays */
-%apply (short*  IN_ARRAY1, int DIM1) {(short*  series, int size)};
-%apply (int*    IN_ARRAY1, int DIM1) {(int*    series, int size)};
-%apply (long*   IN_ARRAY1, int DIM1) {(long*   series, int size)};
-%apply (float*  IN_ARRAY1, int DIM1) {(float*  series, int size)};
-%apply (double* IN_ARRAY1, int DIM1) {(double* series, int size)};
+// Apply the Numeric typemaps for 1D input arrays
+%apply (signed char*        IN_ARRAY1, int DIM1)
+      {(signed char*        series,    int size)};
+%apply (unsigned char*      IN_ARRAY1, int DIM1)
+      {(unsigned char*      series,    int size)};
+%apply (short*              IN_ARRAY1, int DIM1)
+      {(short*              series,    int size)};
+%apply (unsigned short*     IN_ARRAY1, int DIM1)
+      {(unsigned short*     series,    int size)};
+%apply (int*                IN_ARRAY1, int DIM1)
+      {(int*                series,    int size)};
+%apply (unsigned int*       IN_ARRAY1, int DIM1)
+      {(unsigned int*       series,    int size)};
+%apply (long*               IN_ARRAY1, int DIM1)
+      {(long*               series,    int size)};
+%apply (unsigned long*      IN_ARRAY1, int DIM1)
+      {(unsigned long*      series,    int size)};
+%apply (long long*          IN_ARRAY1, int DIM1)
+      {(long long*          series,    int size)};
+%apply (unsigned long long* IN_ARRAY1, int DIM1)
+      {(unsigned long long* series,    int size)};
+%apply (float*              IN_ARRAY1, int DIM1)
+      {(float*              series,    int size)};
+%apply (double*             IN_ARRAY1, int DIM1)
+      {(double*             series,    int size)};
+%apply (long double*        IN_ARRAY1, int DIM1)
+      {(long double*        series,    int size)};
 
-/* Apply the Numeric typemaps for 2D input arrays */
-%apply (int*    IN_ARRAY2, int DIM1, int DIM2) {(int*    matrix, int rows, int cols)};
-%apply (double* IN_ARRAY2, int DIM1, int DIM2) {(double* matrix, int rows, int cols)};
+// Apply the Numeric typemaps for 1D input/output arrays
+%apply (signed char*        INPLACE_ARRAY1, int DIM1)
+      {(signed char*        array,          int size)};
+%apply (unsigned char*      INPLACE_ARRAY1, int DIM1)
+      {(unsigned char*      array,          int size)};
+%apply (short*              INPLACE_ARRAY1, int DIM1)
+      {(short*              array,          int size)};
+%apply (unsigned short*     INPLACE_ARRAY1, int DIM1)
+      {(unsigned short*     array,          int size)};
+%apply (int*                INPLACE_ARRAY1, int DIM1)
+      {(int*                array,          int size)};
+%apply (unsigned int*       INPLACE_ARRAY1, int DIM1)
+      {(unsigned int*       array,          int size)};
+%apply (long*               INPLACE_ARRAY1, int DIM1)
+      {(long*               array,          int size)};
+%apply (unsigned long*      INPLACE_ARRAY1, int DIM1)
+      {(unsigned long*      array,          int size)};
+%apply (long long*          INPLACE_ARRAY1, int DIM1)
+      {(long long*          array,          int size)};
+%apply (unsigned long long* INPLACE_ARRAY1, int DIM1)
+      {(unsigned long long* array,          int size)};
+%apply (float*              INPLACE_ARRAY1, int DIM1)
+      {(float*              array,          int size)};
+%apply (double*             INPLACE_ARRAY1, int DIM1)
+      {(double*             array,          int size)};
+%apply (long double*        INPLACE_ARRAY1, int DIM1)
+      {(long double*        array,          int size)};
 
-/* Apply the Numeric typemaps for 1D input/output arrays */
-%apply (int*    INPLACE_ARRAY1, int DIM1) {(int*    array,   int size)};
-%apply (double* INPLACE_ARRAY1, int DIM1) {(double* array,   int size)};
+// Apply the Numeric typemaps for 2D input arrays
+%apply (signed char*        IN_ARRAY2, int DIM1, int DIM2)
+      {(signed char*        matrix,    int rows, int cols)};
+%apply (unsigned char*      IN_ARRAY2, int DIM1, int DIM2)
+      {(unsigned char*      matrix,    int rows, int cols)};
+%apply (short*              IN_ARRAY2, int DIM1, int DIM2)
+      {(short*              matrix,    int rows, int cols)};
+%apply (unsigned short*     IN_ARRAY2, int DIM1, int DIM2)
+      {(unsigned short*     matrix,    int rows, int cols)};
+%apply (int*                IN_ARRAY2, int DIM1, int DIM2)
+      {(int*                matrix,    int rows, int cols)};
+%apply (unsigned int*       IN_ARRAY2, int DIM1, int DIM2)
+      {(unsigned int*       matrix,    int rows, int cols)};
+%apply (long*               IN_ARRAY2, int DIM1, int DIM2)
+      {(long*               matrix,    int rows, int cols)};
+%apply (unsigned long*      IN_ARRAY2, int DIM1, int DIM2)
+      {(unsigned long*      matrix,    int rows, int cols)};
+%apply (long long*          IN_ARRAY2, int DIM1, int DIM2)
+      {(long long*          matrix,    int rows, int cols)};
+%apply (unsigned long long* IN_ARRAY2, int DIM1, int DIM2)
+      {(unsigned long long* matrix,    int rows, int cols)};
+%apply (float*              IN_ARRAY2, int DIM1, int DIM2)
+      {(float*              matrix,    int rows, int cols)};
+%apply (double*             IN_ARRAY2, int DIM1, int DIM2)
+      {(double*             matrix,    int rows, int cols)};
+%apply (long double*        IN_ARRAY2, int DIM1, int DIM2)
+      {(long double*        matrix,    int rows, int cols)};
 
-/* Include the header file to be wrapped */
+// Apply the Numeric typemaps for 2D input/output arrays
+%apply (signed char*        INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(signed char*        array,          int rows, int cols)};
+%apply (unsigned char*      INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(unsigned char*      array,          int rows, int cols)};
+%apply (short*              INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(short*              array,          int rows, int cols)};
+%apply (unsigned short*     INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(unsigned short*     array,          int rows, int cols)};
+%apply (int*                INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(int*                array,          int rows, int cols)};
+%apply (unsigned int*       INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(unsigned int*       array,          int rows, int cols)};
+%apply (long*               INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(long*               array,          int rows, int cols)};
+%apply (unsigned long*      INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(unsigned long*      array,          int rows, int cols)};
+%apply (long long*          INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(long long*          array,          int rows, int cols)};
+%apply (unsigned long long* INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(unsigned long long* array,          int rows, int cols)};
+%apply (float*              INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(float*              array,          int rows, int cols)};
+%apply (double*             INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(double*             array,          int rows, int cols)};
+%apply (long double*        INPLACE_ARRAY2, int DIM1, int DIM2)
+      {(long double*        array,          int rows, int cols)};
+
+// Include the header file to be wrapped
 %include "series.h"

Modified: trunk/numpy/doc/swig/numpy.i
===================================================================
--- trunk/numpy/doc/swig/numpy.i	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/numpy.i	2007-03-14 15:47:12 UTC (rev 3574)
@@ -6,10 +6,11 @@
 #include "stdio.h"
 #include <numpy/arrayobject.h>
 
-/* The following code originally appeared in enthought/kiva/agg/src/numeric.i,
- * author unknown.  It was translated from C++ to C by John Hunter.  Bill
- * Spotz has modified it slightly to fix some minor bugs, add some comments
- * and some functionality.
+/* The following code originally appeared in
+ * enthought/kiva/agg/src/numeric.i, author unknown.  It was
+ * translated from C++ to C by John Hunter.  Bill Spotz has modified
+ * it slightly to fix some minor bugs, upgrade to numpy (all
+ * versions), add some comments and some functionality.
  */
 
 /* Macros to extract array attributes.
@@ -20,6 +21,37 @@
 #define array_size(a,i)        (((PyArrayObject *)a)->dimensions[i])
 #define array_is_contiguous(a) (PyArray_ISCONTIGUOUS(a))
 
+/* Support older NumPy data type names
+*/
+#if NDARRAY_VERSION < 0x01000000
+#define NPY_BOOL        PyArray_BOOL
+#define NPY_BYTE        PyArray_BYTE
+#define NPY_UBYTE       PyArray_UBYTE
+#define NPY_SHORT       PyArray_SHORT
+#define NPY_USHORT      PyArray_USHORT
+#define NPY_INT         PyArray_INT
+#define NPY_UINT        PyArray_UINT
+#define NPY_LONG        PyArray_LONG
+#define NPY_ULONG       PyArray_ULONG
+#define NPY_LONGLONG    PyArray_LONGLONG
+#define NPY_ULONGLONG   PyArray_ULONGLONG
+#define NPY_FLOAT       PyArray_FLOAT
+#define NPY_DOUBLE      PyArray_DOUBLE
+#define NPY_LONGDOUBLE  PyArray_LONGDOUBLE
+#define NPY_CFLOAT      PyArray_CFLOAT
+#define NPY_CDOUBLE     PyArray_CDOUBLE
+#define NPY_CLONGDOUBLE PyArray_CLONGDOUBLE
+#define NPY_OBJECT      PyArray_OBJECT
+#define NPY_STRING      PyArray_STRING
+#define NPY_UNICODE     PyArray_UNICODE
+#define NPY_VOID        PyArray_VOID
+#define NPY_NTYPES      PyArray_NTYPES
+#define NPY_NOTYPE      PyArray_NOTYPE
+#define NPY_CHAR        PyArray_CHAR
+#define NPY_USERDEF     PyArray_USERDEF
+#define npy_intp        intp
+#endif
+
 /* Given a PyObject, return a string describing its type.
  */
 char* pytype_string(PyObject* py_obj) {
@@ -38,13 +70,18 @@
   return "unkown type";
 }
 
-/* Given a Numeric typecode, return a string describing the type.
+/* Given a NumPy typecode, return a string describing the type.
  */
 char* typecode_string(int typecode) {
-  char* type_names[20] = {"char","unsigned byte","byte","short",
-			  "unsigned short","int","unsigned int","long",
-			  "float","double","complex float","complex double",
-			  "object","ntype","unkown"};
+  static char* type_names[24] = {"bool", "byte", "unsigned byte",
+				 "short", "unsigned short", "int",
+				 "unsigned int", "long", "unsigned long",
+				 "long long", "unsigned long long",
+				 "float", "double", "long double",
+				 "complex float", "complex double",
+				 "complex long double", "object",
+				 "string", "unicode", "void", "ntypes",
+				 "notype", "char"};
   return type_names[typecode];
 }
 
@@ -57,45 +94,43 @@
 
 /* Given a PyObject pointer, cast it to a PyArrayObject pointer if
  * legal.  If not, set the python error string appropriately and
- * return NULL./
+ * return NULL.
  */
 PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode) {
   PyArrayObject* ary = NULL;
-  if (is_array(input) && (typecode == PyArray_NOTYPE || 
-			  PyArray_EquivTypenums(array_type(input), 
-						typecode))) {
-        ary = (PyArrayObject*) input;
-    }
-    else if is_array(input) {
-      char* desired_type = typecode_string(typecode);
-      char* actual_type = typecode_string(array_type(input));
-      PyErr_Format(PyExc_TypeError, 
-		   "Array of type '%s' required.  Array of type '%s' given", 
-		   desired_type, actual_type);
-      ary = NULL;
-    }
-    else {
-      char * desired_type = typecode_string(typecode);
-      char * actual_type = pytype_string(input);
-      PyErr_Format(PyExc_TypeError, 
-		   "Array of type '%s' required.  A %s was given", 
-		   desired_type, actual_type);
-      ary = NULL;
-    }
+  if (is_array(input) && (typecode == NPY_NOTYPE ||
+			  type_match(array_type(input), typecode))) {
+    ary = (PyArrayObject*) input;
+  }
+  else if is_array(input) {
+    char* desired_type = typecode_string(typecode);
+    char* actual_type = typecode_string(array_type(input));
+    PyErr_Format(PyExc_TypeError, 
+		 "Array of type '%s' required.  Array of type '%s' given", 
+		 desired_type, actual_type);
+    ary = NULL;
+  }
+  else {
+    char * desired_type = typecode_string(typecode);
+    char * actual_type = pytype_string(input);
+    PyErr_Format(PyExc_TypeError, 
+		 "Array of type '%s' required.  A %s was given", 
+		 desired_type, actual_type);
+    ary = NULL;
+  }
   return ary;
 }
 
-/* Convert the given PyObject to a Numeric array with the given
+/* Convert the given PyObject to a NumPy array with the given
  * typecode.  On Success, return a valid PyArrayObject* with the
  * correct type.  On failure, the python error string will be set and
  * the routine returns NULL.
  */
 PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode,
-                                             int* is_new_object)
-{
+                                             int* is_new_object) {
   PyArrayObject* ary = NULL;
   PyObject* py_obj;
-  if (is_array(input) && (typecode == PyArray_NOTYPE || type_match(array_type(input),typecode))) {
+  if (is_array(input) && (typecode == NPY_NOTYPE || type_match(array_type(input),typecode))) {
     ary = (PyArrayObject*) input;
     *is_new_object = 0;
   }
@@ -114,8 +149,7 @@
  * flag it as a new object and return the pointer.
  */
 PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object,
-                               int min_dims, int max_dims)
-{
+                               int min_dims, int max_dims) {
   PyArrayObject* result;
   if (array_is_contiguous(ary)) {
     result = ary;
@@ -216,7 +250,7 @@
  * array has the specified shape, return 1.  Otherwise, set the python
  * error string and return 0.
  */
-int require_size(PyArrayObject* ary, int* size, int n) {
+int require_size(PyArrayObject* ary, npy_intp* size, int n) {
   int i;
   int success = 1;
   int len;
@@ -253,236 +287,202 @@
   }
   return success;
 }
-/* End John Hunter translation (with modifications by Bill Spotz) */
+/* End John Hunter translation (with modifications by Bill Spotz)
+ */
 
 %}
 
-/* TYPEMAP_IN macros
+/* %numpy_typemaps() macro
  *
- * This family of typemaps allows pure input C arguments of the form
+ * This macro defines a family of typemaps that allow pure input C
+ * arguments of the form
  *
- *     (type* IN_ARRAY1, int DIM1)
- *     (type* IN_ARRAY2, int DIM1, int DIM2)
+ *     (TYPE* IN_ARRAY1, int DIM1)
+ *     (TYPE* IN_ARRAY2, int DIM1, int DIM2)
+ *     (TYPE* INPLACE_ARRAY1, int DIM1)
+ *     (TYPE* INPLACE_ARRAY2, int DIM1, int DIM2)
+ *     (TYPE* ARGOUT_ARRAY1[ANY])
+ *     (TYPE* ARGOUT_ARRAY2[ANY][ANY])
  *
- * where "type" is any type supported by the Numeric module, to be
- * called in python with an argument list of a single array (or any
- * python object that can be passed to the Numeric.array constructor
- * to produce an arrayof te specified shape).  This can be applied to
- * a existing functions using the %apply directive:
+ * where "TYPE" is any type supported by the NumPy module.  In python,
+ * the dimensions will not need to be specified.  The IN_ARRAYs can be
+ * a numpy array or any sequence that can be converted to a numpy
+ * array of the specified type.  The INPLACE_ARRAYs must be numpy
+ * arrays of the appropriate type.  The ARGOUT_ARRAYs will be returned
+ * as numpy arrays of the appropriate type.
+
+ * These typemaps can be applied to existing functions using the
+ * %apply directive:
  *
- *     %apply (double* IN_ARRAY1, int DIM1) {double* series, int length}
- *     %apply (double* IN_ARRAY2, int DIM1, int DIM2) {double* mx, int rows, int cols}
+ *     %apply (double* IN_ARRAY1, int DIM1) {double* series, int length};
  *     double sum(double* series, int length);
+ *
+ *     %apply (double* IN_ARRAY2, int DIM1, int DIM2) {double* mx, int rows, int cols};
  *     double max(double* mx, int rows, int cols);
  *
- * or with
+ *     %apply (double* INPLACE_ARRAY1, int DIM1) {double* series, int length};
+ *     void negate(double* series, int length);
  *
+ *     %apply (double* INPLACE_ARRAY2, int DIM1, int DIM2) {double* mx, int rows, int cols};
+ *     void normalize(double* mx, int rows, int cols);
+ *
+ *     %apply (double* ARGOUT_ARRAY1[ANY] {double series, int length};
+ *     void negate(double* series, int length);
+ *
+ *     %apply (double* ARGOUT_ARRAY2[ANY][ANY]) {double* mx, int rows, int cols};
+ *     void normalize(double* mx, int rows, int cols);
+ *
+ * or directly with
+ *
  *     double sum(double* IN_ARRAY1, int DIM1);
  *     double max(double* IN_ARRAY2, int DIM1, int DIM2);
+ *     void sum(double* INPLACE_ARRAY1, int DIM1);
+ *     void sum(double* INPLACE_ARRAY2, int DIM1, int DIM2);
+ *     void sum(double* ARGOUT_ARRAY1[ANY]);
+ *     void sum(double* ARGOUT_ARRAY2[ANY][ANY]);
  */
 
-/* One dimensional input arrays */
-%define TYPEMAP_IN1(type,typecode)
-%typemap(in) (type* IN_ARRAY1, int DIM1)
-             (PyArrayObject* array=NULL, int is_new_object) {
-  int size[1] = {-1};
-  array = obj_to_array_contiguous_allow_conversion($input, typecode, &is_new_object);
-  if (!array || !require_dimensions(array,1) || !require_size(array,size,1)) SWIG_fail;
-  $1 = (type*) array->data;
-  $2 = array->dimensions[0];
+%define %numpy_typemaps(TYPE, TYPECODE)
+
+/* Typemap suite for (TYPE* IN_ARRAY1, int DIM1)
+ */
+%typemap(in) (TYPE* IN_ARRAY1, int DIM1)
+             (PyArrayObject* array=NULL, int is_new_object=0) {
+  array = obj_to_array_contiguous_allow_conversion($input, TYPECODE, &is_new_object);
+  npy_intp size[1] = {-1};
+  if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail;
+  $1 = (TYPE*) array->data;
+  $2 = (int) array->dimensions[0];
 }
-%typemap(freearg) (type* IN_ARRAY1, int DIM1) {
+%typemap(freearg) (TYPE* IN_ARRAY1, int DIM1) {
   if (is_new_object$argnum && array$argnum) Py_DECREF(array$argnum);
 }
-%enddef
 
-/* Define concrete examples of the TYPEMAP_IN1 macros */
-TYPEMAP_IN1(char,          PyArray_CHAR  )
-TYPEMAP_IN1(unsigned char, PyArray_UBYTE )
-TYPEMAP_IN1(signed char,   PyArray_SBYTE )
-TYPEMAP_IN1(short,         PyArray_SHORT )
-TYPEMAP_IN1(int,           PyArray_INT   )
-TYPEMAP_IN1(long,          PyArray_LONG  )
-TYPEMAP_IN1(float,         PyArray_FLOAT )
-TYPEMAP_IN1(double,        PyArray_DOUBLE)
-TYPEMAP_IN1(PyObject,      PyArray_OBJECT)
-
-#undef TYPEMAP_IN1
-
- /* Two dimensional input arrays */
-%define TYPEMAP_IN2(type,typecode)
-  %typemap(in) (type* IN_ARRAY2, int DIM1, int DIM2)
-               (PyArrayObject* array=NULL, int is_new_object) {
-  int size[2] = {-1,-1};
-  array = obj_to_array_contiguous_allow_conversion($input, typecode, &is_new_object);
-  if (!array || !require_dimensions(array,2) || !require_size(array,size,1)) SWIG_fail;
-  $1 = (type*) array->data;
-  $2 = array->dimensions[0];
-  $3 = array->dimensions[1];
+/* Typemap suite for (TYPE* IN_ARRAY2, int DIM1, int DIM2)
+ */
+%typemap(in) (TYPE* IN_ARRAY2, int DIM1, int DIM2)
+             (PyArrayObject* array=NULL, int is_new_object=0) {
+  array = obj_to_array_contiguous_allow_conversion($input, TYPECODE, &is_new_object);
+  npy_intp size[2] = {-1,-1};
+  if (!array || !require_dimensions(array, 2) || !require_size(array, size, 1)) SWIG_fail;
+  $1 = (TYPE*) array->data;
+  $2 = (int) array->dimensions[0];
+  $3 = (int) array->dimensions[1];
 }
-%typemap(freearg) (type* IN_ARRAY2, int DIM1, int DIM2) {
+%typemap(freearg) (TYPE* IN_ARRAY2, int DIM1, int DIM2) {
   if (is_new_object$argnum && array$argnum) Py_DECREF(array$argnum);
 }
-%enddef
 
-/* Define concrete examples of the TYPEMAP_IN2 macros */
-TYPEMAP_IN2(char,          PyArray_CHAR  )
-TYPEMAP_IN2(unsigned char, PyArray_UBYTE )
-TYPEMAP_IN2(signed char,   PyArray_SBYTE )
-TYPEMAP_IN2(short,         PyArray_SHORT )
-TYPEMAP_IN2(int,           PyArray_INT   )
-TYPEMAP_IN2(long,          PyArray_LONG  )
-TYPEMAP_IN2(float,         PyArray_FLOAT )
-TYPEMAP_IN2(double,        PyArray_DOUBLE)
-TYPEMAP_IN2(PyObject,      PyArray_OBJECT)
-
-#undef TYPEMAP_IN2
-
-/* TYPEMAP_INPLACE macros
- *
- * This family of typemaps allows input/output C arguments of the form
- *
- *     (type* INPLACE_ARRAY1, int DIM1)
- *     (type* INPLACE_ARRAY2, int DIM1, int DIM2)
- *
- * where "type" is any type supported by the Numeric module, to be
- * called in python with an argument list of a single contiguous
- * Numeric array.  This can be applied to an existing function using
- * the %apply directive:
- *
- *     %apply (double* INPLACE_ARRAY1, int DIM1) {double* series, int length}
- *     %apply (double* INPLACE_ARRAY2, int DIM1, int DIM2) {double* mx, int rows, int cols}
- *     void negate(double* series, int length);
- *     void normalize(double* mx, int rows, int cols);
- *     
- *
- * or with
- *
- *     void sum(double* INPLACE_ARRAY1, int DIM1);
- *     void sum(double* INPLACE_ARRAY2, int DIM1, int DIM2);
+/* Typemap suite for (TYPE* INPLACE_ARRAY1, int DIM1)
  */
-
- /* One dimensional input/output arrays */
-%define TYPEMAP_INPLACE1(type,typecode)
-%typemap(in) (type* INPLACE_ARRAY1, int DIM1) (PyArrayObject* temp=NULL) {
-  int i;
-  temp = obj_to_array_no_conversion($input,typecode);
+%typemap(in) (TYPE* INPLACE_ARRAY1, int DIM1) (PyArrayObject* temp=NULL) {
+  temp = obj_to_array_no_conversion($input, TYPECODE);
   if (!temp  || !require_contiguous(temp)) SWIG_fail;
-  $1 = (type*) temp->data;
+  $1 = (TYPE*) temp->data;
   $2 = 1;
-  for (i=0; i<temp->nd; ++i) $2 *= temp->dimensions[i];
+  for (int i=0; i<temp->nd; ++i) $2 *= temp->dimensions[i];
 }
-%enddef
 
-/* Define concrete examples of the TYPEMAP_INPLACE1 macro */
-TYPEMAP_INPLACE1(char,          PyArray_CHAR  )
-TYPEMAP_INPLACE1(unsigned char, PyArray_UBYTE )
-TYPEMAP_INPLACE1(signed char,   PyArray_SBYTE )
-TYPEMAP_INPLACE1(short,         PyArray_SHORT )
-TYPEMAP_INPLACE1(int,           PyArray_INT   )
-TYPEMAP_INPLACE1(long,          PyArray_LONG  )
-TYPEMAP_INPLACE1(float,         PyArray_FLOAT )
-TYPEMAP_INPLACE1(double,        PyArray_DOUBLE)
-TYPEMAP_INPLACE1(PyObject,      PyArray_OBJECT)
-
-#undef TYPEMAP_INPLACE1
-
- /* Two dimensional input/output arrays */
-%define TYPEMAP_INPLACE2(type,typecode)
-  %typemap(in) (type* INPLACE_ARRAY2, int DIM1, int DIM2) (PyArrayObject* temp=NULL) {
-  temp = obj_to_array_no_conversion($input,typecode);
+/* Typemap suite for (TYPE* INPLACE_ARRAY2, int DIM1, int DIM2)
+ */
+%typemap(in) (TYPE* INPLACE_ARRAY2, int DIM1, int DIM2) (PyArrayObject* temp=NULL) {
+  temp = obj_to_array_no_conversion($input, TYPECODE);
   if (!temp || !require_contiguous(temp)) SWIG_fail;
-  $1 = (type*) temp->data;
-  $2 = temp->dimensions[0];
-  $3 = temp->dimensions[1];
+  $1 = (TYPE*) temp->data;
+  $2 = (int) temp->dimensions[0];
+  $3 = (int) temp->dimensions[1];
 }
-%enddef
 
-/* Define concrete examples of the TYPEMAP_INPLACE2 macro */
-TYPEMAP_INPLACE2(char,          PyArray_CHAR  )
-TYPEMAP_INPLACE2(unsigned char, PyArray_UBYTE )
-TYPEMAP_INPLACE2(signed char,   PyArray_SBYTE )
-TYPEMAP_INPLACE2(short,         PyArray_SHORT )
-TYPEMAP_INPLACE2(int,           PyArray_INT   )
-TYPEMAP_INPLACE2(long,          PyArray_LONG  )
-TYPEMAP_INPLACE2(float,         PyArray_FLOAT )
-TYPEMAP_INPLACE2(double,        PyArray_DOUBLE)
-TYPEMAP_INPLACE2(PyObject,      PyArray_OBJECT)
+/* Typemap suite for (TYPE ARGOUT_ARRAY1[ANY])
+ */
+%typemap(in,numinputs=0) (TYPE ARGOUT_ARRAY1[ANY]) {
+  $1 = (TYPE*) malloc($1_dim0*sizeof(TYPE));
+  if (!$1) {
+    PyErr_SetString(PyExc_RuntimeError, "Failed to allocate memory");
+    SWIG_fail;
+  }
+}
+%typemap(argout) (TYPE ARGOUT_ARRAY1[ANY]) {
+  PyObject * obj = NULL;
+  npy_intp dimensions[1] = { $1_dim0 };
+  PyObject* outArray = PyArray_FromDimsAndData(1, dimensions, TYPECODE, (char*)$1);
+  if ($result == Py_None) {
+    Py_DECREF($result);
+    $result = outArray;
+  }
+  else {
+    if (!PyTuple_Check($result)) $result = Py_BuildValue("(O)", $result);
+    obj = Py_Build_Value("(O)", outArray);
+    $result = PySequence_Concat($result, obj);
+  }
+}
 
-#undef TYPEMAP_INPLACE2
-
-/* TYPEMAP_ARGOUT macros
- *
- * This family of typemaps allows output C arguments of the form
- *
- *     (type* ARGOUT_ARRAY[ANY])
- *     (type* ARGOUT_ARRAY[ANY][ANY])
- *
- * where "type" is any type supported by the Numeric module, to be
- * called in python with an argument list of a single contiguous
- * Numeric array.  This can be applied to an existing function using
- * the %apply directive:
- *
- *     %apply (double* ARGOUT_ARRAY[ANY] {double series, int length}
- *     %apply (double* ARGOUT_ARRAY[ANY][ANY]) {double* mx, int rows, int cols}
- *     void negate(double* series, int length);
- *     void normalize(double* mx, int rows, int cols);
- *     
- *
- * or with
- *
- *     void sum(double* ARGOUT_ARRAY[ANY]);
- *     void sum(double* ARGOUT_ARRAY[ANY][ANY]);
+/* Typemap suite for (TYPE ARGOUT_ARRAY2[ANY][ANY])
  */
-
- /* One dimensional input/output arrays */
-%define TYPEMAP_ARGOUT1(type,typecode)
-%typemap(in,numinputs=0) type ARGOUT_ARRAY[ANY] {
-  $1 = (type*) malloc($1_dim0*sizeof(type));
+%typemap(in,numinputs=0) (TYPE ARGOUT_ARRAY2[ANY][ANY]) {
+  $1 = (TYPE*) malloc($1_dim0 * $1_dim1 * sizeof(TYPE));
   if (!$1) {
     PyErr_SetString(PyExc_RuntimeError, "Failed to allocate memory");
     SWIG_fail;
   }
 }
-%typemap(argout) ARGOUT_ARRAY[ANY] {
-  int dimensions[1] = {$1_dim0};
-  PyObject* outArray = PyArray_FromDimsAndData(1, dimensions, typecode, (char*)$1);
+%typemap(argout) (TYPE ARGOUT_ARRAY1[ANY][ANY]) {
+  PyObject * obj = NULL;
+  npy_intp dimensions[2] = { $1_dim0, $1_dim1 };
+  PyObject* outArray = PyArray_FromDimsAndData(1, dimensions, TYPECODE, (char*)$1);
+  if ($result == Py_None) {
+    Py_DECREF($result);
+    $result = outArray;
+  }
+  else {
+    if (!PyTuple_Check($result)) $result = Py_BuildValue("(O)", $result);
+    obj = Py_Build_Value("(O)", outArray);
+    $result = PySequence_Concat($result, obj);
+  }
 }
-%enddef
 
-/* Define concrete examples of the TYPEMAP_ARGOUT1 macro */
-TYPEMAP_ARGOUT1(char,          PyArray_CHAR  )
-TYPEMAP_ARGOUT1(unsigned char, PyArray_UBYTE )
-TYPEMAP_ARGOUT1(signed char,   PyArray_SBYTE )
-TYPEMAP_ARGOUT1(short,         PyArray_SHORT )
-TYPEMAP_ARGOUT1(int,           PyArray_INT   )
-TYPEMAP_ARGOUT1(long,          PyArray_LONG  )
-TYPEMAP_ARGOUT1(float,         PyArray_FLOAT )
-TYPEMAP_ARGOUT1(double,        PyArray_DOUBLE)
-TYPEMAP_ARGOUT1(PyObject,      PyArray_OBJECT)
+%enddef    /* %numpy_typemaps() macro */
 
-#undef TYPEMAP_ARGOUT1
 
- /* Two dimensional input/output arrays */
-%define TYPEMAP_ARGOUT2(type,typecode)
-  %typemap(in) (type* ARGOUT_ARRAY2, int DIM1, int DIM2) (PyArrayObject* temp=NULL) {
-  temp = obj_to_array_no_conversion($input,typecode);
-  if (!temp || !require_contiguous(temp)) SWIG_fail;
-  $1 = (type*) temp->data;
-  $2 = temp->dimensions[0];
-  $3 = temp->dimensions[1];
-}
-%enddef
+/* Concrete instances of the %numpy_typemaps() macro: Each invocation
+ * below applies all of the typemaps above to the specified data type.
+ */
+%numpy_typemaps(signed char,         NPY_BYTE     ) /**/
+%numpy_typemaps(unsigned char,       NPY_UBYTE    ) /**/
+%numpy_typemaps(short,               NPY_SHORT    ) /**/
+%numpy_typemaps(unsigned short,      NPY_USHORT   ) /**/
+%numpy_typemaps(int,                 NPY_INT      ) /**/
+%numpy_typemaps(unsigned int,        NPY_UINT     ) /**/
+%numpy_typemaps(long,                NPY_LONG     ) /**/
+%numpy_typemaps(unsigned long,       NPY_ULONG    ) /**/
+%numpy_typemaps(long long,           NPY_LONGLONG ) /**/
+%numpy_typemaps(unsigned long long,  NPY_ULONGLONG) /**/
+%numpy_typemaps(float,               NPY_FLOAT    ) /**/
+%numpy_typemaps(double,              NPY_DOUBLE   ) /**/
+%numpy_typemaps(PyObject,            NPY_OBJECT   )
+%numpy_typemaps(char,                NPY_CHAR     )
 
-/* Define concrete examples of the TYPEMAP_ARGOUT2 macro */
-TYPEMAP_ARGOUT2(char,          PyArray_CHAR  )
-TYPEMAP_ARGOUT2(unsigned char, PyArray_UBYTE )
-TYPEMAP_ARGOUT2(signed char,   PyArray_SBYTE )
-TYPEMAP_ARGOUT2(short,         PyArray_SHORT )
-TYPEMAP_ARGOUT2(int,           PyArray_INT   )
-TYPEMAP_ARGOUT2(long,          PyArray_LONG  )
-TYPEMAP_ARGOUT2(float,         PyArray_FLOAT )
-TYPEMAP_ARGOUT2(double,        PyArray_DOUBLE)
-TYPEMAP_ARGOUT2(PyObject,      PyArray_OBJECT)
+/* ***************************************************************
+ * The follow macro expansion does not work, because C++ bool is 4
+ * bytes and NPY_BOOL is 1 byte
+ */
+/*%numpy_typemaps(bool, NPY_BOOL)
+ */
 
-#undef TYPEMAP_ARGOUT2
+/* ***************************************************************
+ * On my Mac, I get the following warning for this macro expansion:
+ * 'swig/python detected a memory leak of type 'long double *', no destructor found.'
+ */
+/*%numpy_typemaps(long double, NPY_LONGDOUBLE)
+ */
+
+/* ***************************************************************
+ * Swig complains about a syntax error for the following macros
+ * expansions:
+ */
+/*%numpy_typemaps(complex float,       NPY_CFLOAT     )
+ */
+/*%numpy_typemaps(complex double,      NPY_CDOUBLE    )
+ */
+/*%numpy_typemaps(complex long double, NPY_CLONGDOUBLE)
+ */

Added: trunk/numpy/doc/swig/numpy_swig.html
===================================================================
--- trunk/numpy/doc/swig/numpy_swig.html	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/numpy_swig.html	2007-03-14 15:47:12 UTC (rev 3574)
@@ -0,0 +1,604 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>numpy.i: a SWIG Interface File for NumPy</title>
+<meta name="author" content="Bill Spotz" />
+<meta name="date" content="10 March, 2007" />
+<style type="text/css">
+
+/*
+:Author: David Goodger
+:Contact: goodger@users.sourceforge.net
+:Date: $Date: 2005-12-18 01:56:14 +0100 (Sun, 18 Dec 2005) $
+:Revision: $Revision: 4224 $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin-left: 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left {
+  clear: left }
+
+img.align-right {
+  clear: right }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font-family: serif ;
+  font-size: 100% }
+
+pre.literal-block, pre.doctest-block {
+  margin-left: 2em ;
+  margin-right: 2em ;
+  background-color: #eeeeee }
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+tt.docutils {
+  background-color: #eeeeee }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="numpy-i-a-swig-interface-file-for-numpy">
+<h1 class="title">numpy.i: a SWIG Interface File for NumPy</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Bill Spotz</td></tr>
+<tr class="field"><th class="docinfo-name">Institution:</th><td class="field-body">Sandia National Laboratories</td>
+</tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>10 March, 2007</td></tr>
+</tbody>
+</table>
+<div class="section">
+<h1><a id="introduction" name="introduction">Introduction</a></h1>
+<p>The Simple Wrapper and Interface Generator (or <a class="reference" href="http://www.swig.org">SWIG</a>) is a powerful tool for generating wrapper
+code for interfacing to a wide variety of scripting languages.
+<a class="reference" href="http://www.swig.org">SWIG</a> can parse header files, and using only the code prototypes,
+create an interface to the target language.  But <a class="reference" href="http://www.swig.org">SWIG</a> is not
+omnipotent.  For example, it cannot know from the prototype:</p>
+<pre class="literal-block">
+double rms(double* seq, int n);
+</pre>
+<p>what exactly <tt class="docutils literal"><span class="pre">seq</span></tt> is.  Is it a single value to be altered in-place?
+Is it an array, and if so what is its length?  Is it input-only?
+Output-only?  Input-output?  <a class="reference" href="http://www.swig.org">SWIG</a> cannot determine these details,
+and does not attempt to do so.</p>
+<p>Making an educated guess, humans can conclude that this is probably a
+routine that takes an input-only array of length <tt class="docutils literal"><span class="pre">n</span></tt> of <tt class="docutils literal"><span class="pre">double</span></tt>
+values called <tt class="docutils literal"><span class="pre">seq</span></tt> and returns the root mean square.  The default
+behavior of <a class="reference" href="http://www.swig.org">SWIG</a>, however, will be to create a wrapper function
+that compiles, but is nearly impossible to use from the scripting
+language in the way the C routine was intended.</p>
+<p>For <a class="reference" href="http://www.python.org">python</a>, the preferred way of handling
+contiguous (or technically, <em>strided</em>) blocks of homogeneous data is
+with the module <a class="reference" href="http://numpy.scipy.org">NumPy</a>, which provides full
+object-oriented access to arrays of data.  Therefore, the most logical
+python interface for the <tt class="docutils literal"><span class="pre">rms</span></tt> function would be:</p>
+<pre class="literal-block">
+def rms(seq):
+</pre>
+<p>where <tt class="docutils literal"><span class="pre">seq</span></tt> would be a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array of <tt class="docutils literal"><span class="pre">double</span></tt> values, and its
+length <tt class="docutils literal"><span class="pre">n</span></tt> would be extracted from <tt class="docutils literal"><span class="pre">seq</span></tt> internally before being
+passed to the C routine.  Even better, since <a class="reference" href="http://numpy.scipy.org">NumPy</a> supports
+construction of arrays from arbitrary <a class="reference" href="http://www.python.org">python</a> sequences, <tt class="docutils literal"><span class="pre">seq</span></tt>
+itself could be a nearly arbitrary sequence (so long as each element
+can be converted to a <tt class="docutils literal"><span class="pre">double</span></tt>) and the wrapper code would
+internally convert it to a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array before extracting its data
+and length.</p>
+<p><a class="reference" href="http://www.swig.org">SWIG</a> allows these types of conversions to be defined via a
+mechanism called typemaps.  This document provides information on how
+to use <tt class="docutils literal"><span class="pre">numpy.i</span></tt>, a <a class="reference" href="http://www.swig.org">SWIG</a> interface file that defines a series of
+typemaps intended to make the type of array-related conversions
+described above relatively simple to implement.  For example, suppose
+that the <tt class="docutils literal"><span class="pre">rms</span></tt> function prototype defined above was in a header file
+named <tt class="docutils literal"><span class="pre">rms.h</span></tt>.  To obtain the python interface discussed above, your
+<a class="reference" href="http://www.swig.org">SWIG</a> interface file would need the following:</p>
+<pre class="literal-block">
+%{
+#include &quot;rms.h&quot;
+%}
+%include &quot;numpy.i&quot;
+%apply (double* IN_ARRAY1, int DIM1) {(double* seq, int n)};
+%include &quot;rms.h&quot;
+</pre>
+<p>Typemaps are keyed off a list of one or more function arguments,
+either by type or by type and name.  We will refer to such lists as
+<em>signatures</em>.  One of the many typemaps defined by <tt class="docutils literal"><span class="pre">numpy.i</span></tt> is used
+above and has the signature <tt class="docutils literal"><span class="pre">(double*</span> <span class="pre">IN_ARRAY1,</span> <span class="pre">int</span> <span class="pre">DIM1)</span></tt>.  The
+argument names are intended to suggest that the <tt class="docutils literal"><span class="pre">double*</span></tt> argument
+is an input array of one dimension and that the <tt class="docutils literal"><span class="pre">int</span></tt> represents
+that dimension.  This is precisely the pattern in the <tt class="docutils literal"><span class="pre">rms</span></tt>
+prototype.</p>
+<p>Hopefully, no actual prototypes to be wrapped will have the names
+<tt class="docutils literal"><span class="pre">IN_ARRAY1</span></tt> and <tt class="docutils literal"><span class="pre">DIM1</span></tt>.  We use the <tt class="docutils literal"><span class="pre">%apply</span></tt> directive to apply
+the typemap for one-dimensional input arrays of type <tt class="docutils literal"><span class="pre">double</span></tt> to the
+actual prototype used by <tt class="docutils literal"><span class="pre">rms</span></tt>.  Using <tt class="docutils literal"><span class="pre">numpy.i</span></tt> effectively,
+therefore, requires knowing what typemaps are available and what they
+do.</p>
+</div>
+<div class="section">
+<h1><a id="using-numpy-i" name="using-numpy-i">Using numpy.i</a></h1>
+<p>The <tt class="docutils literal"><span class="pre">numpy.i</span></tt> file is currently located in the <tt class="docutils literal"><span class="pre">numpy/docs/swig</span></tt>
+sub-directory under the <tt class="docutils literal"><span class="pre">numpy</span></tt> installation directory.  Typically,
+you will want to copy it to the directory where you are developing
+your wrappers.</p>
+<p>A simple module that only uses a single <a class="reference" href="http://www.swig.org">SWIG</a> interface file should
+include the following:</p>
+<pre class="literal-block">
+%{
+#define SWIG_FILE_WITH_INIT
+%}
+%include &quot;numpy.i&quot;
+%init %{
+import_array();
+%}
+</pre>
+<p>Only one interface file should call <tt class="docutils literal"><span class="pre">import_array()</span></tt>.  If you have
+more than one <a class="reference" href="http://www.swig.org">SWIG</a> interface file, then subsequent files should not
+<tt class="docutils literal"><span class="pre">#define</span> <span class="pre">SWIG_FILE_WITH_INIT</span></tt> and should not call
+<tt class="docutils literal"><span class="pre">import_array()</span></tt>.</p>
+</div>
+<div class="section">
+<h1><a id="available-typemaps" name="available-typemaps">Available Typemaps</a></h1>
+<p>The typemap directives provided by <tt class="docutils literal"><span class="pre">numpy.i</span></tt> for arrays of different
+data types, say <tt class="docutils literal"><span class="pre">double</span></tt> and <tt class="docutils literal"><span class="pre">int</span></tt>, are identical to one another
+except for the C and <a class="reference" href="http://numpy.scipy.org">NumPy</a> type specifications.  The typemaps are
+therefore implemented via a macro:</p>
+<pre class="literal-block">
+%numpy_typemaps(TYPE, TYPECODE)
+</pre>
+<p>that can be invoked for appropriate <tt class="docutils literal"><span class="pre">(TYPE,</span> <span class="pre">TYPECODE)</span></tt> pairs.  For
+example:</p>
+<pre class="literal-block">
+%numpy_typemaps(double, NPY_DOUBLE)
+%numpy_typemaps(int,    NPY_INT   )
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">numpy.i</span></tt> interface file uses the <tt class="docutils literal"><span class="pre">%numpy_typemaps</span></tt> macro to
+implement typemaps for the following C-types:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">signed</span> <span class="pre">char</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">char</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">short</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">short</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">int</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">int</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">long</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span> <span class="pre">long</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">float</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">double</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">PyObject</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">char</span></tt></li>
+</ul>
+</blockquote>
+<p>Note that C++ type <tt class="docutils literal"><span class="pre">bool</span></tt> is not supported in the list above.  NumPy
+bools are a single byte, while the C++ <tt class="docutils literal"><span class="pre">bool</span></tt> is four bytes (at
+least on my system).  Therefore:</p>
+<pre class="literal-block">
+%numpy_typemaps(bool, NPY_BOOL)
+</pre>
+<p>will result in typemaps that will produce code that reference
+improper data lengths.  You can implement the following macro
+expansion:</p>
+<pre class="literal-block">
+%numpy_typemaps(bool, NPY_UINT)
+</pre>
+<p>to fix the data length problem, and <a class="reference" href="#input-arrays">Input Arrays</a> will work fine,
+but <a class="reference" href="#in-place-arrays">In-place Arrays</a> will fail type-checking.</p>
+<p>In the following descriptions, we reference a generic <tt class="docutils literal"><span class="pre">TYPE</span></tt>, which
+could be any of the C-types listed above.</p>
+<div class="section">
+<h2><a id="input-arrays" name="input-arrays">Input Arrays</a></h2>
+<p>Input arrays are defined as arrays of data that are passed into a
+routine but are not altered in-place or returned to the user.  The
+python input array is therefore allowed to be almost any python
+sequence (such as a list) that can be converted to the requested type
+of array.  The input array signatures are</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(TYPE*</span> <span class="pre">IN_ARRAY1,</span> <span class="pre">int</span> <span class="pre">DIM1)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(TYPE*</span> <span class="pre">IN_ARRAY2,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2)</span></tt></li>
+</ul>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="in-place-arrays" name="in-place-arrays">In-place Arrays</a></h2>
+<p>In-place arrays are defined as arrays that are modified in-place.  The
+input values may or may not be used, but the values at the time the
+function returns are significant.  The provided python argument must
+therefore be a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array of the required type.  The in-place
+signatures are</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(TYPE*</span> <span class="pre">INPLACE_ARRAY1,</span> <span class="pre">int</span> <span class="pre">DIM1)</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(TYPE*</span> <span class="pre">INPLACE_ARRAY2,</span> <span class="pre">int</span> <span class="pre">DIM1,</span> <span class="pre">int</span> <span class="pre">DIM2)</span></tt></li>
+</ul>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="argout-arrays" name="argout-arrays">Argout Arrays</a></h2>
+<p>Argout arrays are arrays that appear in the input arguments in C, but
+are in fact output arrays.  This pattern occurs often when there is
+more than one output variable and the single return argument is
+therefore not sufficient.  In python, the convential way to return
+multiple arguments is to pack them into a tuple and return the tuple.
+This is what the argout typemaps do.  If a wrapped function that uses
+argout these argout typemaps has more than one return argument, they
+are so packed.  The python user does not pass these arrays in, they
+simply get returned.  The argout signatures are</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">(TYPE</span> <span class="pre">ARGOUT_ARRAY1[ANY])</span></tt></li>
+<li><tt class="docutils literal"><span class="pre">(TYPE</span> <span class="pre">ARGOUT_ARRAY2[ANY][ANY])</span></tt></li>
+</ul>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="helper-functions" name="helper-functions">Helper Functions</a></h1>
+<p>The <tt class="docutils literal"><span class="pre">numpy.i</span></tt> file containes several macros and routines that it
+uses internally to build its typemaps.  However, these functions may
+be useful elsewhere in your interface file.</p>
+<div class="section">
+<h2><a id="macros" name="macros">Macros</a></h2>
+<blockquote>
+<dl class="docutils">
+<dt><strong>is_array(a)</strong></dt>
+<dd>Evaluates as true if <tt class="docutils literal"><span class="pre">a</span></tt> is non-<tt class="docutils literal"><span class="pre">NULL</span></tt> and can be cast to a
+<tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_type(a)</strong></dt>
+<dd>Evaluates to the integer data type code of <tt class="docutils literal"><span class="pre">a</span></tt>, assuming <tt class="docutils literal"><span class="pre">a</span></tt> can
+be cast to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_dimensions(a)</strong></dt>
+<dd>Evaluates to the integer number of dimensions of <tt class="docutils literal"><span class="pre">a</span></tt>, assuming
+<tt class="docutils literal"><span class="pre">a</span></tt> can be cast to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_size(a,i)</strong></dt>
+<dd>Evaluates to the <tt class="docutils literal"><span class="pre">i</span></tt>-th dimension size of <tt class="docutils literal"><span class="pre">a</span></tt>, assuming <tt class="docutils literal"><span class="pre">a</span></tt>
+can be cast to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>.</dd>
+<dt><strong>array_is_contiguous(a)</strong></dt>
+<dd>Evaluates as true if <tt class="docutils literal"><span class="pre">a</span></tt> is a contiguous array.  Equivalent to
+<tt class="docutils literal"><span class="pre">(PyArray_ISCONTIGUOUS(a))</span></tt>.</dd>
+</dl>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="routines" name="routines">Routines</a></h2>
+<blockquote>
+<dl class="docutils">
+<dt><strong>char* pytype_string(PyObject* py_obj)</strong></dt>
+<dd>Given a <tt class="docutils literal"><span class="pre">PyObject*</span></tt>, return a string describing its type.</dd>
+<dt><strong>char* typecode_string(int typecode)</strong></dt>
+<dd>Given a <a class="reference" href="http://numpy.scipy.org">NumPy</a> integer typecode, return a string describing the type.</dd>
+<dt><strong>int type_match(int actual_type, int desired_type)</strong></dt>
+<dd>Make sure input has correct <a class="reference" href="http://numpy.scipy.org">NumPy</a> type.  Allow character and
+byte to match.  Also allow int and long to match.</dd>
+<dt><strong>PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode)</strong></dt>
+<dd>Given a <tt class="docutils literal"><span class="pre">PyObject*</span></tt>, cast it to a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> if legal.
+If not, set the python error string appropriately and return
+<tt class="docutils literal"><span class="pre">NULL</span></tt>.</dd>
+<dt><strong>PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode, int* is_new_object)</strong></dt>
+<dd>Convert the given <tt class="docutils literal"><span class="pre">PyObject*</span></tt> to a <a class="reference" href="http://numpy.scipy.org">NumPy</a> array with the given
+typecode.  On Success, return a valid <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> with the
+correct type.  On failure, the python error string will be set and
+the routine returns <tt class="docutils literal"><span class="pre">NULL</span></tt>.</dd>
+<dt><strong>PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object, int min_dims, int max_dims)</strong></dt>
+<dd>Given a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>, check to see if it is contiguous.  If
+so, return the input pointer and flag it as not a new object.  If
+it is not contiguous, create a new <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> using the
+original data, flag it as a new object and return the pointer.</dd>
+<dt><strong>PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, int typecode, int* is_new_object)</strong></dt>
+<dd>Convert a given <tt class="docutils literal"><span class="pre">PyObject*</span></tt> to a contiguous <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>
+of the specified type.  If the input object is not a contiguous
+<tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt>, a new one will be created and the new object
+flag will be set.</dd>
+<dt><strong>int require_contiguous(PyArrayObject* ary)</strong></dt>
+<dd>Test whether a <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> is contiguous.  If array is
+contiguous, return 1.  Otherwise, set the python error string and
+return 0.</dd>
+<dt><strong>int require_dimensions(PyArrayObject* ary, int exact_dimensions)</strong></dt>
+<dd>Require the given <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> to have a specified number of
+dimensions.  If the array has the specified number of dimensions,
+return 1.  Otherwise, set the python error string and return 0.</dd>
+<dt><strong>int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n)</strong></dt>
+<dd>Require the given <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> to have one of a list of
+specified number of dimensions.  If the array has one of the
+specified number of dimensions, return 1.  Otherwise, set the
+python error string and return 0.</dd>
+<dt><strong>int require_size(PyArrayObject* ary, int* size, int n)</strong></dt>
+<dd>Require the given <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> to have a specified shape.
+If the array has the specified shape, return 1.  Otherwise, set
+the python error string and return 0.</dd>
+<dt><strong>static PyArrayObject *contiguous_typed_array(PyObject *obj, int typecode, int expectnd, int *expectdims)</strong></dt>
+<dd>This function tries to create a contiguous <a class="reference" href="http://numpy.scipy.org">NumPy</a> array of type
+typecode from an arbitrary python object <tt class="docutils literal"><span class="pre">obj</span></tt>.  This should
+work for any sequence object.  The argument <tt class="docutils literal"><span class="pre">expectnd</span></tt> is the
+expected number of dimensions, ignored if &lt;= 0.  The argument
+<tt class="docutils literal"><span class="pre">expectdims</span></tt> is an array of expected dimensions, ignored if &lt;=
+0.  This routine raises a <tt class="docutils literal"><span class="pre">ValueError</span></tt> exception if the
+underlying <tt class="docutils literal"><span class="pre">PyArray_ContiguousFromObject</span></tt> routine fails, if the
+array has a bad shape, if the extent of a given dimension doesn't
+match the specified extent.  If <tt class="docutils literal"><span class="pre">obj</span></tt> is a contiguous
+<tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> then a reference is returned; if <tt class="docutils literal"><span class="pre">obj</span></tt> is a
+python sequence, then a new <tt class="docutils literal"><span class="pre">PyArrayObject*</span></tt> is created and
+returned.</dd>
+</dl>
+</blockquote>
+</div>
+</div>
+<div class="section">
+<h1><a id="acknowledgements" name="acknowledgements">Acknowledgements</a></h1>
+<p>Many people have worked to glue <a class="reference" href="http://www.swig.org">SWIG</a> and <a class="reference" href="http://numpy.scipy.org">NumPy</a> (and its
+predecessors Numeric and numarray) together.  The effort to
+standardize this work into <tt class="docutils literal"><span class="pre">numpy.i</span></tt> began at the 2005 SciPy
+Conference with a conversation between Fernando Perez and myself.
+Fernando collected helper functions and typemaps from Michael Hunter,
+Anna Omelchenko and Michael Sanner.  Their work has made this end
+result possible.</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2007-03-14 15:24 UTC.
+Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/numpy/doc/swig/numpy_swig.txt
===================================================================
--- trunk/numpy/doc/swig/numpy_swig.txt	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/numpy_swig.txt	2007-03-14 15:47:12 UTC (rev 3574)
@@ -0,0 +1,319 @@
+========================================
+numpy.i: a SWIG Interface File for NumPy
+========================================
+
+:Author:      Bill Spotz
+:Institution: Sandia National Laboratories
+:Date:        10 March, 2007
+
+Introduction
+============
+
+The Simple Wrapper and Interface Generator (or `SWIG
+<http://www.swig.org>`_) is a powerful tool for generating wrapper
+code for interfacing to a wide variety of scripting languages.
+`SWIG`_ can parse header files, and using only the code prototypes,
+create an interface to the target language.  But `SWIG`_ is not
+omnipotent.  For example, it cannot know from the prototype::
+
+    double rms(double* seq, int n);
+
+what exactly ``seq`` is.  Is it a single value to be altered in-place?
+Is it an array, and if so what is its length?  Is it input-only?
+Output-only?  Input-output?  `SWIG`_ cannot determine these details,
+and does not attempt to do so.
+
+Making an educated guess, humans can conclude that this is probably a
+routine that takes an input-only array of length ``n`` of ``double``
+values called ``seq`` and returns the root mean square.  The default
+behavior of `SWIG`_, however, will be to create a wrapper function
+that compiles, but is nearly impossible to use from the scripting
+language in the way the C routine was intended.
+
+For `python <http://www.python.org>`_, the preferred way of handling
+contiguous (or technically, *strided*) blocks of homogeneous data is
+with the module `NumPy <http://numpy.scipy.org>`_, which provides full
+object-oriented access to arrays of data.  Therefore, the most logical
+python interface for the ``rms`` function would be::
+
+    def rms(seq):
+
+where ``seq`` would be a `NumPy`_ array of ``double`` values, and its
+length ``n`` would be extracted from ``seq`` internally before being
+passed to the C routine.  Even better, since `NumPy`_ supports
+construction of arrays from arbitrary `python`_ sequences, ``seq``
+itself could be a nearly arbitrary sequence (so long as each element
+can be converted to a ``double``) and the wrapper code would
+internally convert it to a `NumPy`_ array before extracting its data
+and length.
+
+`SWIG`_ allows these types of conversions to be defined via a
+mechanism called typemaps.  This document provides information on how
+to use ``numpy.i``, a `SWIG`_ interface file that defines a series of
+typemaps intended to make the type of array-related conversions
+described above relatively simple to implement.  For example, suppose
+that the ``rms`` function prototype defined above was in a header file
+named ``rms.h``.  To obtain the python interface discussed above, your
+`SWIG`_ interface file would need the following::
+
+    %{
+    #include "rms.h"
+    %}
+    %include "numpy.i"
+    %apply (double* IN_ARRAY1, int DIM1) {(double* seq, int n)};
+    %include "rms.h"
+
+Typemaps are keyed off a list of one or more function arguments,
+either by type or by type and name.  We will refer to such lists as
+*signatures*.  One of the many typemaps defined by ``numpy.i`` is used
+above and has the signature ``(double* IN_ARRAY1, int DIM1)``.  The
+argument names are intended to suggest that the ``double*`` argument
+is an input array of one dimension and that the ``int`` represents
+that dimension.  This is precisely the pattern in the ``rms``
+prototype.
+
+Hopefully, no actual prototypes to be wrapped will have the names
+``IN_ARRAY1`` and ``DIM1``.  We use the ``%apply`` directive to apply
+the typemap for one-dimensional input arrays of type ``double`` to the
+actual prototype used by ``rms``.  Using ``numpy.i`` effectively,
+therefore, requires knowing what typemaps are available and what they
+do.
+
+Using numpy.i
+=============
+
+The ``numpy.i`` file is currently located in the ``numpy/docs/swig``
+sub-directory under the ``numpy`` installation directory.  Typically,
+you will want to copy it to the directory where you are developing
+your wrappers.
+
+A simple module that only uses a single `SWIG`_ interface file should
+include the following::
+
+    %{
+    #define SWIG_FILE_WITH_INIT
+    %}
+    %include "numpy.i"
+    %init %{
+    import_array();
+    %}
+
+Only one interface file should call ``import_array()``.  If you have
+more than one `SWIG`_ interface file, then subsequent files should not
+``#define SWIG_FILE_WITH_INIT`` and should not call
+``import_array()``.
+
+Available Typemaps
+==================
+
+The typemap directives provided by ``numpy.i`` for arrays of different
+data types, say ``double`` and ``int``, are identical to one another
+except for the C and `NumPy`_ type specifications.  The typemaps are
+therefore implemented via a macro::
+
+    %numpy_typemaps(TYPE, TYPECODE)
+
+that can be invoked for appropriate ``(TYPE, TYPECODE)`` pairs.  For
+example::
+
+    %numpy_typemaps(double, NPY_DOUBLE)
+    %numpy_typemaps(int,    NPY_INT   )
+
+The ``numpy.i`` interface file uses the ``%numpy_typemaps`` macro to
+implement typemaps for the following C-types:
+
+  * ``signed char``
+  * ``unsigned char``
+  * ``short``
+  * ``unsigned short``
+  * ``int``
+  * ``unsigned int``
+  * ``long``
+  * ``unsigned long``
+  * ``long long``
+  * ``unsigned long long``
+  * ``float``
+  * ``double``
+  * ``PyObject``
+  * ``char``
+
+Note that C++ type ``bool`` is not supported in the list above.  NumPy
+bools are a single byte, while the C++ ``bool`` is four bytes (at
+least on my system).  Therefore::
+
+    %numpy_typemaps(bool, NPY_BOOL)
+
+will result in typemaps that will produce code that reference
+improper data lengths.  You can implement the following macro
+expansion::
+
+    %numpy_typemaps(bool, NPY_UINT)
+
+to fix the data length problem, and `Input Arrays`_ will work fine,
+but `In-place Arrays`_ will fail type-checking.
+
+In the following descriptions, we reference a generic ``TYPE``, which
+could be any of the C-types listed above.
+
+Input Arrays
+------------
+
+Input arrays are defined as arrays of data that are passed into a
+routine but are not altered in-place or returned to the user.  The
+python input array is therefore allowed to be almost any python
+sequence (such as a list) that can be converted to the requested type
+of array.  The input array signatures are
+
+  * ``(TYPE* IN_ARRAY1, int DIM1)``
+  * ``(TYPE* IN_ARRAY2, int DIM1, int DIM2)``
+
+In-place Arrays
+---------------
+
+In-place arrays are defined as arrays that are modified in-place.  The
+input values may or may not be used, but the values at the time the
+function returns are significant.  The provided python argument must
+therefore be a `NumPy`_ array of the required type.  The in-place
+signatures are
+
+  * ``(TYPE* INPLACE_ARRAY1, int DIM1)``
+  * ``(TYPE* INPLACE_ARRAY2, int DIM1, int DIM2)``
+
+Argout Arrays
+-------------
+
+Argout arrays are arrays that appear in the input arguments in C, but
+are in fact output arrays.  This pattern occurs often when there is
+more than one output variable and the single return argument is
+therefore not sufficient.  In python, the convential way to return
+multiple arguments is to pack them into a tuple and return the tuple.
+This is what the argout typemaps do.  If a wrapped function that uses
+argout these argout typemaps has more than one return argument, they
+are so packed.  The python user does not pass these arrays in, they
+simply get returned.  The argout signatures are
+
+  * ``(TYPE ARGOUT_ARRAY1[ANY])``
+  * ``(TYPE ARGOUT_ARRAY2[ANY][ANY])``
+
+Helper Functions
+================
+
+The ``numpy.i`` file containes several macros and routines that it
+uses internally to build its typemaps.  However, these functions may
+be useful elsewhere in your interface file.
+
+Macros
+------
+
+  **is_array(a)**
+    Evaluates as true if ``a`` is non-``NULL`` and can be cast to a
+    ``PyArrayObject*``.
+
+  **array_type(a)**
+    Evaluates to the integer data type code of ``a``, assuming ``a`` can
+    be cast to a ``PyArrayObject*``.
+
+  **array_dimensions(a)**
+    Evaluates to the integer number of dimensions of ``a``, assuming
+    ``a`` can be cast to a ``PyArrayObject*``.
+
+  **array_size(a,i)**
+    Evaluates to the ``i``-th dimension size of ``a``, assuming ``a``
+    can be cast to a ``PyArrayObject*``.
+
+  **array_is_contiguous(a)**
+    Evaluates as true if ``a`` is a contiguous array.  Equivalent to
+    ``(PyArray_ISCONTIGUOUS(a))``.
+
+Routines
+--------
+
+  **char* pytype_string(PyObject* py_obj)**
+    Given a ``PyObject*``, return a string describing its type.
+
+
+  **char* typecode_string(int typecode)**
+    Given a `NumPy`_ integer typecode, return a string describing the type.
+
+
+  **int type_match(int actual_type, int desired_type)**
+    Make sure input has correct `NumPy`_ type.  Allow character and
+    byte to match.  Also allow int and long to match.
+
+
+  **PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode)**
+    Given a ``PyObject*``, cast it to a ``PyArrayObject*`` if legal.
+    If not, set the python error string appropriately and return
+    ``NULL``.
+
+
+  **PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode, int* is_new_object)**
+    Convert the given ``PyObject*`` to a `NumPy`_ array with the given
+    typecode.  On Success, return a valid ``PyArrayObject*`` with the
+    correct type.  On failure, the python error string will be set and
+    the routine returns ``NULL``.
+
+
+  **PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object, int min_dims, int max_dims)**
+    Given a ``PyArrayObject*``, check to see if it is contiguous.  If
+    so, return the input pointer and flag it as not a new object.  If
+    it is not contiguous, create a new ``PyArrayObject*`` using the
+    original data, flag it as a new object and return the pointer.
+
+
+  **PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, int typecode, int* is_new_object)**
+    Convert a given ``PyObject*`` to a contiguous ``PyArrayObject*``
+    of the specified type.  If the input object is not a contiguous
+    ``PyArrayObject*``, a new one will be created and the new object
+    flag will be set.
+
+
+  **int require_contiguous(PyArrayObject* ary)**
+    Test whether a ``PyArrayObject*`` is contiguous.  If array is
+    contiguous, return 1.  Otherwise, set the python error string and
+    return 0.
+
+
+  **int require_dimensions(PyArrayObject* ary, int exact_dimensions)**
+    Require the given ``PyArrayObject*`` to have a specified number of
+    dimensions.  If the array has the specified number of dimensions,
+    return 1.  Otherwise, set the python error string and return 0.
+
+
+  **int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n)**
+    Require the given ``PyArrayObject*`` to have one of a list of
+    specified number of dimensions.  If the array has one of the
+    specified number of dimensions, return 1.  Otherwise, set the
+    python error string and return 0.
+
+
+  **int require_size(PyArrayObject* ary, int* size, int n)**
+    Require the given ``PyArrayObject*`` to have a specified shape.
+    If the array has the specified shape, return 1.  Otherwise, set
+    the python error string and return 0.
+
+
+  **static PyArrayObject *contiguous_typed_array(PyObject *obj, int typecode, int expectnd, int *expectdims)**
+    This function tries to create a contiguous `NumPy`_ array of type
+    typecode from an arbitrary python object ``obj``.  This should
+    work for any sequence object.  The argument ``expectnd`` is the
+    expected number of dimensions, ignored if <= 0.  The argument
+    ``expectdims`` is an array of expected dimensions, ignored if <=
+    0.  This routine raises a ``ValueError`` exception if the
+    underlying ``PyArray_ContiguousFromObject`` routine fails, if the
+    array has a bad shape, if the extent of a given dimension doesn't
+    match the specified extent.  If ``obj`` is a contiguous
+    ``PyArrayObject*`` then a reference is returned; if ``obj`` is a
+    python sequence, then a new ``PyArrayObject*`` is created and
+    returned.
+
+Acknowledgements
+================
+
+Many people have worked to glue `SWIG`_ and `NumPy`_ (and its
+predecessors Numeric and numarray) together.  The effort to
+standardize this work into ``numpy.i`` began at the 2005 SciPy
+Conference with a conversation between Fernando Perez and myself.
+Fernando collected helper functions and typemaps from Michael Hunter,
+Anna Omelchenko and Michael Sanner.  Their work has made this end
+result possible.

Modified: trunk/numpy/doc/swig/series.cxx
===================================================================
--- trunk/numpy/doc/swig/series.cxx	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/series.cxx	2007-03-14 15:47:12 UTC (rev 3574)
@@ -3,143 +3,68 @@
 #include <iostream>
 #include "series.h"
 
-// *** One Dimensional Arrays ***
-
-// Functions that take 1D arrays of type SHORT as input
-short shortSum(short* series, int size) {
-  short result = 0;
-  for (int i=0; i<size; ++i) result += series[i];
-  return result;
+// The following macro defines a family of functions with the forms
+//
+//     TYPE SNAMEProd( TYPE * series, int size);
+//     void SNAMEOnes( TYPE * array,  int size);
+//     TYPE SNAMEMax(  TYPE * matrix, int rows, int cols);
+//     void SNAMEFloor(TYPE * array,  int rows, int cols, TYPE floor);
+//
+// for any specified type TYPE (for example: short, unsigned int, long
+// long, etc.) with given short name SNAME (for example: short, uint,
+// longLong, etc.).  The macro is then expanded for the given
+// TYPE/SNAME pairs.  The resulting functions are for testing numpy
+// interfaces, respectively, for:
+//
+//  * 1D input arrays
+//  * 1D in-place arrays
+//  * 2D input arrays
+//  * 2D in-place arrays
+//
+#define TEST_FUNCS(TYPE, SNAME) \
+\
+TYPE SNAME ## Prod(TYPE * series, int size) {     \
+  TYPE result = 1;                                \
+  for (int i=0; i<size; ++i) result *= series[i]; \
+  return result;                                  \
+}                                                 \
+\
+void SNAME ## Ones(TYPE * array, int size) { \
+  for (int i=0; i<size; ++i) array[i] = 1;   \
+}                                            \
+\
+TYPE SNAME ## Max(TYPE * matrix, int rows, int cols) {	  \
+  int i, j, index;                                        \
+  TYPE result = matrix[0];                                \
+  for (j=0; j<cols; ++j) {                                \
+    for (i=0; i<rows; ++i) {                              \
+      index = j*rows + i;                                 \
+      if (matrix[index] > result) result = matrix[index]; \
+    }                                                     \
+  }                                                       \
+  return result;                                          \
+}                                                         \
+\
+void SNAME ## Floor(TYPE * array, int rows, int cols, TYPE floor) { \
+  int i, j, index;                                                    \
+  for (j=0; j<cols; ++j) {                                            \
+    for (i=0; i<rows; ++i) {                                          \
+      index = j*rows + i;                                             \
+      if (array[index] < floor) array[index] = 0;                     \
+    }                                                                 \
+  }                                                                   \
 }
 
-short shortProd(short* series, int size) {
-  short result = 1;
-  for (int i=0; i<size; ++i) result *= series[i];
-  return result;
-}
-
-// Functions that take 1D arrays of type INT as input
-int intSum(int* series, int size) {
-  int result = 0;
-  for (int i=0; i<size; ++i) result += series[i];
-  return result;
-}
-
-int intProd(int* series, int size) {
-  int result = 1;
-  for (int i=0; i<size; ++i) result *= series[i];
-  return result;
-}
-
-// Functions that take 1D arrays of type LONG as input
-long longSum(long* series, int size) {
-  long result = 0;
-  for (int i=0; i<size; ++i) result += series[i];
-  return result;
-}
-
-long longProd(long* series, int size) {
-  long result = 1;
-  for (int i=0; i<size; ++i) result *= series[i];
-  return result;
-}
-
-// Functions that take 1D arrays of type FLOAT as input
-float floatSum(float* series, int size) {
-  float result = 0.0;
-  for (int i=0; i<size; ++i) result += series[i];
-  return result;
-}
-
-float floatProd(float* series, int size) {
-  float result = 1.0;
-  for (int i=0; i<size; ++i) result *= series[i];
-  return result;
-}
-
-// Functions that take 1D arrays of type DOUBLE as input
-double doubleSum(double* series, int size) {
-  double result = 0.0;
-  for (int i=0; i<size; ++i) result += series[i];
-  return result;
-}
-
-double doubleProd(double* series, int size) {
-  double result = 1.0;
-  for (int i=0; i<size; ++i) result *= series[i];
-  return result;
-}
-
-// Functions that manipulate 1D arrays of type INT in-place
-void intZeros(int* array, int size) {
-  for (int i=0; i<size; ++i) array[i] = 0;
-}
-
-void intOnes(int* array, int size) {
-  for (int i=0; i<size; ++i) array[i] = 1;
-}
-
-void intNegate(int* array, int size) {
-  for (int i=0; i<size; ++i) array[i] *= -1;
-}
-
-// Functions that manipulate 1D arrays of type DOUBLE in-place
-void doubleZeros(double* array, int size) {
-  for (int i=0; i<size; ++i) array[i] = 0.0;
-}
-
-void doubleOnes(double* array, int size) {
-  for (int i=0; i<size; ++i) array[i] = 1.0;
-}
-
-void doubleNegate(double* array, int size) {
-  for (int i=0; i<size; ++i) array[i] *= -1.0;
-}
-
-// *** Two Dimensional Arrays ***
-
-// Functions that take 2D arrays of type INT as input
-int intMax(int* matrix, int rows, int cols) {
-  int i, j, index;
-  int result = matrix[0];
-  for (j=0; j<cols; ++j) {
-    for (i=0; i<rows; ++i) {
-      index = j*rows + i;
-      if (matrix[index] > result) result = matrix[index];
-    }
-  }
-  return result;
-}
-
-void intFloor(int* matrix, int rows, int cols, int floor) {
-  int i, j, index;
-  for (j=0; j<cols; ++j) {
-    for (i=0; i<rows; ++i) {
-      index = j*rows + i;
-      if (matrix[index] < floor) matrix[index] = 0;
-    }
-  }
-}
-
-// Functions that take 2D arrays of type DOUBLE as input
-double doubleMax(double* matrix, int rows, int cols) {
-  int i, j, index;
-  double result = matrix[0];
-  for (j=0; j<cols; ++j) {
-    for (i=0; i<rows; ++i) {
-      index = j*rows + i;
-      if (matrix[index] > result) result = matrix[index];
-    }
-  }
-  return result;
-}
-
-void doubleFloor(double* matrix, int rows, int cols, double floor) {
-  int i, j, index;
-  for (j=0; j<cols; ++j) {
-    for (i=0; i<rows; ++i) {
-      index = j*rows + i;
-      if (matrix[index] < floor) matrix[index] = 0.0;
-    }
-  }
-}
+TEST_FUNCS(signed char       , schar     )
+TEST_FUNCS(unsigned char     , uchar     )
+TEST_FUNCS(short             , short     )
+TEST_FUNCS(unsigned short    , ushort    )
+TEST_FUNCS(int               , int       )
+TEST_FUNCS(unsigned int      , uint      )
+TEST_FUNCS(long              , long      )
+TEST_FUNCS(unsigned long     , ulong     )
+TEST_FUNCS(long long         , longLong  )
+TEST_FUNCS(unsigned long long, ulongLong )
+TEST_FUNCS(float             , float     )
+TEST_FUNCS(double            , double    )
+TEST_FUNCS(long double       , longDouble)

Modified: trunk/numpy/doc/swig/series.h
===================================================================
--- trunk/numpy/doc/swig/series.h	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/series.h	2007-03-14 15:47:12 UTC (rev 3574)
@@ -1,40 +1,44 @@
 #ifndef SERIES_H
 #define SERIES_H
 
-/*** One Dimensional Arrays ***/
+// The following macro defines the prototypes for a family of
+// functions with the forms
+//
+//     TYPE SNAMEProd( TYPE * series, int size);
+//     void SNAMEOnes( TYPE * array,  int size);
+//     TYPE SNAMEMax(  TYPE * matrix, int rows, int cols);
+//     void SNAMEFloor(TYPE * array,  int rows, int cols, TYPE floor);
+//
+// for any specified type TYPE (for example: short, unsigned int, long
+// long, etc.) with given short name SNAME (for example: short, uint,
+// longLong, etc.).  The macro is then expanded for the given
+// TYPE/SNAME pairs.  The resulting functions are for testing numpy
+// interfaces, respectively, for:
+//
+//  * 1D input arrays
+//  * 1D in-place arrays
+//  * 2D input arrays
+//  * 2D in-place arrays
+//
+#define TEST_FUNC_PROTOS(TYPE, SNAME) \
+\
+TYPE SNAME ## Prod( TYPE * series, int size); \
+void SNAME ## Ones( TYPE * array,  int size); \
+TYPE SNAME ## Max(  TYPE * matrix, int rows, int cols); \
+void SNAME ## Floor(TYPE * array,  int rows, int cols, TYPE floor);
 
-/* Examples of functions that take 1D C arrays as input */
-short shortSum( short* series, int size);
-short shortProd(short* series, int size);
+TEST_FUNC_PROTOS(signed char       , schar     )
+TEST_FUNC_PROTOS(unsigned char     , uchar     )
+TEST_FUNC_PROTOS(short             , short     )
+TEST_FUNC_PROTOS(unsigned short    , ushort    )
+TEST_FUNC_PROTOS(int               , int       )
+TEST_FUNC_PROTOS(unsigned int      , uint      )
+TEST_FUNC_PROTOS(long              , long      )
+TEST_FUNC_PROTOS(unsigned long     , ulong     )
+TEST_FUNC_PROTOS(long long         , longLong  )
+TEST_FUNC_PROTOS(unsigned long long, ulongLong )
+TEST_FUNC_PROTOS(float             , float     )
+TEST_FUNC_PROTOS(double            , double    )
+TEST_FUNC_PROTOS(long double       , longDouble)
 
-int intSum( int* series, int size);
-int intProd(int* series, int size);
-
-long longSum( long* series, int size);
-long longProd(long* series, int size);
-
-float floatSum( float* series, int size);
-float floatProd(float* series, int size);
-
-double doubleSum( double* series, int size);
-double doubleProd(double* series, int size);
-
-/* Examples of functions that manipulate 1D C arrays as in-place */
-void intZeros( int* array, int size);
-void intOnes(  int* array, int size);
-void intNegate(int* array, int size);
-
-void doubleZeros( double* array, int size);
-void doubleOnes(  double* array, int size);
-void doubleNegate(double* array, int size);
-
-/*** Two Dimensional Arrays ***/
-
-/* Examples of functions that take 2D arrays as input */
-int intMax(int* matrix, int rows, int cols);
-void intFloor(int* matrix, int rows, int cols, int floor);
-
-double doubleMax(double* matrix, int rows, int cols);
-void doubleFloor(double* matrix, int rows, int cols, double floor);
-
 #endif

Modified: trunk/numpy/doc/swig/setup.py
===================================================================
--- trunk/numpy/doc/swig/setup.py	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/setup.py	2007-03-14 15:47:12 UTC (rev 3574)
@@ -7,12 +7,17 @@
 # Third-party modules - we depend on numpy for everything
 import numpy
 
+# Obtain the numpy include directory.  This logic works across numpy versions.
+try:
+    numpy_include = numpy.get_include()
+except AttributeError:
+    numpy_include = numpy.get_numpy_include()
+
 # _Series extension module
 _Series = Extension("_Series",
                     ["Series_wrap.cxx",
                      "series.cxx"],
-                    include_dirs = [numpy.get_numpy_include()],
-#                    libraries = ["m"]
+                    include_dirs = [numpy_include],
                     )
 
 # Series setup

Modified: trunk/numpy/doc/swig/testSeries.py
===================================================================
--- trunk/numpy/doc/swig/testSeries.py	2007-03-12 17:07:19 UTC (rev 3573)
+++ trunk/numpy/doc/swig/testSeries.py	2007-03-14 15:47:12 UTC (rev 3574)
@@ -6,7 +6,11 @@
 import sys
 import unittest
 
+# Import NumPy
 import numpy as N
+major, minor = [ int(d) for d in N.__version__.split(".")[:2] ]
+if major == 0: BadListError = TypeError
+else:          BadListError = ValueError
 
 # Add the distutils-generated build directory to the python search path and then
 # import the extension module
@@ -18,26 +22,148 @@
 
 class SeriesTestCase(unittest.TestCase):
 
-    ########################################################
-    ### Test functions that take 1D arrays of type SHORT ###
-    def testShortSum(self):
-        "Test the shortSum function"
-        self.assertEquals(Series.shortSum([1,2,3,4]), 10)
+    ####################################################
+    ### Test functions that take arrays of type BYTE ###
+    def testScharProd(self):
+        "Test the scharProd function"
+        self.assertEquals(Series.scharProd([1,2,3,4]), 24)
 
+    def testScharProdNonContainer(self):
+        "Test the scharProd function with None"
+        self.assertRaises(TypeError, Series.scharProd, None)
+
+    def testScharOnes(self):
+        "Test the scharOnes function"
+        myArray = N.zeros(5,'b')
+        Series.scharOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testScharMax(self):
+        "Test the scharMax function"
+        matrix = [[-6,5,-4],[3,-2,1]]
+        self.assertEquals(Series.scharMax(matrix), 5)
+
+    def testScharMaxNonContainer(self):
+        "Test the scharMax function with None"
+        self.assertRaises(TypeError, Series.scharMax, None)
+
+    def testScharMaxWrongDim(self):
+        "Test the scharMax function with a 1D array"
+        self.assertRaises(TypeError, Series.scharMax, [0, -1, 2, -3])
+
+    def testScharFloor(self):
+        "Test the scharFloor function"
+        matrix = N.array([[10,-2],[-6,7]],'b')
+        Series.scharFloor(matrix,0)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    #####################################################
+    ### Test functions that take arrays of type UBYTE ###
+    def testUcharProd(self):
+        "Test the ucharProd function"
+        self.assertEquals(Series.ucharProd([1,2,3,4]), 24)
+
+    def testUcharProdNonContainer(self):
+        "Test the ucharProd function with None"
+        self.assertRaises(TypeError, Series.ucharProd, None)
+
+    def testUcharOnes(self):
+        "Test the ucharOnes function"
+        myArray = N.zeros(5,'B')
+        Series.ucharOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testUcharMax(self):
+        "Test the ucharMax function"
+        matrix = [[6,5,4],[3,2,1]]
+        self.assertEquals(Series.ucharMax(matrix), 6)
+
+    def testUcharMaxNonContainer(self):
+        "Test the ucharMax function with None"
+        self.assertRaises(TypeError, Series.ucharMax, None)
+
+    def testUcharMaxWrongDim(self):
+        "Test the ucharMax function with a 1D array"
+        self.assertRaises(TypeError, Series.ucharMax, [0, 1, 2, 3])
+
+    def testUcharFloor(self):
+        "Test the ucharFloor function"
+        matrix = N.array([[10,2],[6,7]],'B')
+        Series.ucharFloor(matrix,7)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    #####################################################
+    ### Test functions that take arrays of type SHORT ###
     def testShortProd(self):
         "Test the shortProd function"
         self.assertEquals(Series.shortProd([1,2,3,4]), 24)
 
+    def testShortProdNonContainer(self):
+        "Test the shortProd function with None"
+        self.assertRaises(TypeError, Series.shortProd, None)
+
+    def testShortOnes(self):
+        "Test the shortOnes function"
+        myArray = N.zeros(5,'h')
+        Series.shortOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testShortMax(self):
+        "Test the shortMax function"
+        matrix = [[-6,5,-4],[3,-2,1]]
+        self.assertEquals(Series.shortMax(matrix), 5)
+
+    def testShortMaxNonContainer(self):
+        "Test the shortMax function with None"
+        self.assertRaises(TypeError, Series.shortMax, None)
+
+    def testShortMaxWrongDim(self):
+        "Test the shortMax function with a 1D array"
+        self.assertRaises(TypeError, Series.shortMax, [0, -1, 2, -3])
+
+    def testShortFloor(self):
+        "Test the shortFloor function"
+        matrix = N.array([[10,-2],[-6,7]],'h')
+        Series.shortFloor(matrix,0)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
     ######################################################
-    ### Test functions that take 1D arrays of type INT ###
-    def testIntSum(self):
-        "Test the intSum function"
-        self.assertEquals(Series.intSum([1,2,3,4]), 10)
+    ### Test functions that take arrays of type USHORT ###
+    def testUshortProd(self):
+        "Test the ushortProd function"
+        self.assertEquals(Series.ushortProd([1,2,3,4]), 24)
 
-    def testIntSumBadContainer(self):
-        "Test the intSum function with an invalid list"
-        self.assertRaises(TypeError, Series.intSum, [1,2,"junk"])
+    def testUshortProdNonContainer(self):
+        "Test the ushortProd function with None"
+        self.assertRaises(TypeError, Series.ushortProd, None)
 
+    def testUshortOnes(self):
+        "Test the ushortOnes function"
+        myArray = N.zeros(5,'H')
+        Series.ushortOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testUshortMax(self):
+        "Test the ushortMax function"
+        matrix = [[6,5,4],[3,2,1]]
+        self.assertEquals(Series.ushortMax(matrix), 6)
+
+    def testUshortMaxNonContainer(self):
+        "Test the ushortMax function with None"
+        self.assertRaises(TypeError, Series.ushortMax, None)
+
+    def testUshortMaxWrongDim(self):
+        "Test the ushortMax function with a 1D array"
+        self.assertRaises(TypeError, Series.ushortMax, [0, 1, 2, 3])
+
+    def testUshortFloor(self):
+        "Test the ushortFloor function"
+        matrix = N.array([[10,2],[6,7]],'H')
+        Series.ushortFloor(matrix,7)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    ###################################################
+    ### Test functions that take arrays of type INT ###
     def testIntProd(self):
         "Test the intProd function"
         self.assertEquals(Series.intProd([1,2,3,4]), 24)
@@ -46,84 +172,255 @@
         "Test the intProd function with None"
         self.assertRaises(TypeError, Series.intProd, None)
 
-    def testIntZeros(self):
-        "Test the intZeros function"
-        myArray = N.ones(5,'i')
-        Series.intZeros(myArray)
-        N.testing.assert_array_equal(myArray, N.array([0,0,0,0,0]))
-
-    def testIntZerosNonArray(self):
-        "Test the intZeros function with an integer"
-        self.assertRaises(TypeError, Series.intZeros, 5)
-
     def testIntOnes(self):
         "Test the intOnes function"
         myArray = N.zeros(5,'i')
         Series.intOnes(myArray)
         N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
 
-    def testIntNegate(self):
-        "Test the intNegate function"
-        myArray = N.arange(5,dtype='i')
-        Series.intNegate(myArray)
-        N.testing.assert_array_equal(myArray, N.array([0,-1,-2,-3,-4]))
+    def testIntMax(self):
+        "Test the intMax function"
+        matrix = [[-6,5,-4],[3,-2,1]]
+        self.assertEquals(Series.intMax(matrix), 5)
 
-    #######################################################
-    ### Test functions that take 1D arrays of type LONG ###
-    def testLongSum(self):
-        "Test the longSum function"
-        self.assertEquals(Series.longSum([1,2,3,4]), 10)
+    def testIntMaxNonContainer(self):
+        "Test the intMax function with None"
+        self.assertRaises(TypeError, Series.intMax, None)
 
-    def testLongSumMultiDimensional(self):
-        "Test the longSum function with multi-dimensional array"
-        self.assertRaises(TypeError, Series.longSum, [[1,2,3],[9,8,7]])
+    def testIntMaxWrongDim(self):
+        "Test the intMax function with a 1D array"
+        self.assertRaises(TypeError, Series.intMax, [0, -1, 2, -3])
 
+    def testIntFloor(self):
+        "Test the intFloor function"
+        matrix = N.array([[10,-2],[-6,7]],'i')
+        Series.intFloor(matrix,0)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    ####################################################
+    ### Test functions that take arrays of type UINT ###
+    def testUintProd(self):
+        "Test the uintProd function"
+        self.assertEquals(Series.uintProd([1,2,3,4]), 24)
+
+    def testUintProdNonContainer(self):
+        "Test the uintProd function with None"
+        self.assertRaises(TypeError, Series.uintProd, None)
+
+    def testUintOnes(self):
+        "Test the uintOnes function"
+        myArray = N.zeros(5,'I')
+        Series.uintOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testUintMax(self):
+        "Test the uintMax function"
+        matrix = [[6,5,4],[3,2,1]]
+        self.assertEquals(Series.uintMax(matrix), 6)
+
+    def testUintMaxNonContainer(self):
+        "Test the uintMax function with None"
+        self.assertRaises(TypeError, Series.uintMax, None)
+
+    def testUintMaxWrongDim(self):
+        "Test the uintMax function with a 1D array"
+        self.assertRaises(TypeError, Series.uintMax, [0, 1, 2, 3])
+
+    def testUintFloor(self):
+        "Test the uintFloor function"
+        matrix = N.array([[10,2],[6,7]],'I')
+        Series.uintFloor(matrix,7)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    ####################################################
+    ### Test functions that take arrays of type LONG ###
     def testLongProd(self):
         "Test the longProd function"
         self.assertEquals(Series.longProd([1,2,3,4]), 24)
 
+    def testLongProdNonContainer(self):
+        "Test the longProd function with None"
+        self.assertRaises(TypeError, Series.longProd, None)
+
+    def testLongOnes(self):
+        "Test the longOnes function"
+        myArray = N.zeros(5,'l')
+        Series.longOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testLongMax(self):
+        "Test the longMax function"
+        matrix = [[-6,5,-4],[3,-2,1]]
+        self.assertEquals(Series.longMax(matrix), 5)
+
+    def testLongMaxNonContainer(self):
+        "Test the longMax function with None"
+        self.assertRaises(TypeError, Series.longMax, None)
+
+    def testLongMaxWrongDim(self):
+        "Test the longMax function with a 1D array"
+        self.assertRaises(TypeError, Series.longMax, [0, -1, 2, -3])
+
+    def testLongFloor(self):
+        "Test the longFloor function"
+        matrix = N.array([[10,-2],[-6,7]],'l')
+        Series.longFloor(matrix,0)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    #####################################################
+    ### Test functions that take arrays of type ULONG ###
+    def testUlongProd(self):
+        "Test the ulongProd function"
+        self.assertEquals(Series.ulongProd([1,2,3,4]), 24)
+
+    def testUlongProdNonContainer(self):
+        "Test the ulongProd function with None"
+        self.assertRaises(TypeError, Series.ulongProd, None)
+
+    def testUlongOnes(self):
+        "Test the ulongOnes function"
+        myArray = N.zeros(5,'L')
+        Series.ulongOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testUlongMax(self):
+        "Test the ulongMax function"
+        matrix = [[6,5,4],[3,2,1]]
+        self.assertEquals(Series.ulongMax(matrix), 6)
+
+    def testUlongMaxNonContainer(self):
+        "Test the ulongMax function with None"
+        self.assertRaises(TypeError, Series.ulongMax, None)
+
+    def testUlongMaxWrongDim(self):
+        "Test the ulongMax function with a 1D array"
+        self.assertRaises(TypeError, Series.ulongMax, [0, 1, 2, 3])
+
+    def testUlongFloor(self):
+        "Test the ulongFloor function"
+        matrix = N.array([[10,2],[6,7]],'L')
+        Series.ulongFloor(matrix,7)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
     ########################################################
-    ### Test functions that take 1D arrays of type FLOAT ###
-    def testFloatSum(self):
-        "Test the floatSum function (to 5 decimal places)"
-        self.assertAlmostEquals(Series.floatSum([1,2,3.14,4]), 10.14, 5)
+    ### Test functions that take arrays of type LONGLONG ###
+    def testLongLongProd(self):
+        "Test the longLongProd function"
+        self.assertEquals(Series.longLongProd([1,2,3,4]), 24)
 
-    def testFloatSumBadContainer(self):
-        "Test the floatSum function with a dictionary"
-        self.assertRaises(TypeError, Series.floatSum, {"key":"value"})
+    def testLongLongProdNonContainer(self):
+        "Test the longLongProd function with None"
+        self.assertRaises(TypeError, Series.longLongProd, None)
 
+    def testLongLongOnes(self):
+        "Test the longLongOnes function"
+        myArray = N.zeros(5,'q')
+        Series.longLongOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testLongLongMax(self):
+        "Test the longLongMax function"
+        matrix = [[-6,5,-4],[3,-2,1]]
+        self.assertEquals(Series.longLongMax(matrix), 5)
+
+    def testLongLongMaxNonContainer(self):
+        "Test the longLongMax function with None"
+        self.assertRaises(TypeError, Series.longLongMax, None)
+
+    def testLongLongMaxWrongDim(self):
+        "Test the longLongMax function with a 1D array"
+        self.assertRaises(TypeError, Series.longLongMax, [0, -1, 2, -3])
+
+    def testLongLongFloor(self):
+        "Test the longLongFloor function"
+        matrix = N.array([[10,-2],[-6,7]],'q')
+        Series.longLongFloor(matrix,0)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    #########################################################
+    ### Test functions that take arrays of type ULONGLONG ###
+    def testUlonglongProd(self):
+        "Test the ulongLongProd function"
+        self.assertEquals(Series.ulongLongProd([1,2,3,4]), 24)
+
+    def testUlongLongProdNonContainer(self):
+        "Test the ulongLongProd function with None"
+        self.assertRaises(TypeError, Series.ulongLongProd, None)
+
+    def testUlongLongOnes(self):
+        "Test the ulongLongOnes function"
+        myArray = N.zeros(5,'Q')
+        Series.ulongLongOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1,1,1,1,1]))
+
+    def testUlongLongMax(self):
+        "Test the ulongLongMax function"
+        matrix = [[6,5,4],[3,2,1]]
+        self.assertEquals(Series.ulongLongMax(matrix), 6)
+
+    def testUlongLongMaxNonContainer(self):
+        "Test the ulongLongMax function with None"
+        self.assertRaises(TypeError, Series.ulongLongMax, None)
+
+    def testUlongLongMaxWrongDim(self):
+        "Test the ulongLongMax function with a 1D array"
+        self.assertRaises(TypeError, Series.ulongLongMax, [0, 1, 2, 3])
+
+    def testUlongLongFloor(self):
+        "Test the ulongLongFloor function"
+        matrix = N.array([[10,2],[6,7]],'Q')
+        Series.ulongLongFloor(matrix,7)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    #####################################################
+    ### Test functions that take arrays of type FLOAT ###
     def testFloatProd(self):
         "Test the floatProd function (to 5 decimal places)"
         self.assertAlmostEquals(Series.floatProd((1,2.718,3,4)), 32.616, 5)
 
     def testFloatProdBadContainer(self):
         "Test the floatProd function with an invalid list"
-        self.assertRaises(TypeError, Series.floatProd, [3.14, "pi"])
+        self.assertRaises(BadListError, Series.floatProd, [3.14, "pi"])
 
-    #########################################################
-    ### Test functions that take 1D arrays of type DOUBLE ###
-    def testDoubleSum(self):
-        "Test the doubleSum function"
-        self.assertEquals(Series.doubleSum([1,2,3.14,4]), 10.14)
+    def testFloatOnes(self):
+        "Test the floatOnes function"
+        myArray = N.zeros(5,'f')
+        Series.floatOnes(myArray)
+        N.testing.assert_array_equal(myArray, N.array([1.,1.,1.,1.,1.]))
 
-    def testDoubleSumNonContainer(self):
-        "Test the doubleSum function with None"
-        self.assertRaises(TypeError, Series.doubleSum, None)
+    def testFloatOnesNonArray(self):
+        "Test the floatOnes function with a list"
+        self.assertRaises(TypeError, Series.floatOnes, [True, 0, 2.718, "pi"])
 
+    def testFloatMax(self):
+        "Test the floatMax function"
+        matrix = [[-6,5,-4],[3.14,-2.718,1]]
+        self.assertEquals(Series.floatMax(matrix), 5.0)
+
+    def testFloatMaxNonContainer(self):
+        "Test the floatMax function with None"
+        self.assertRaises(TypeError, Series.floatMax, None)
+
+    def testFloatMaxWrongDim(self):
+        "Test the floatMax function with a 1D array"
+        self.assertRaises(TypeError, Series.floatMax, [0.0, -1, 2.718, -3.14])
+
+    def testFloatFloor(self):
+        "Test the floatFloor function"
+        matrix = N.array([[10,-2],[-6,7]],'f')
+        Series.floatFloor(matrix,0)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
+
+    ######################################################
+    ### Test functions that take arrays of type DOUBLE ###
     def testDoubleProd(self):
         "Test the doubleProd function"
         self.assertEquals(Series.doubleProd((1,2.718,3,4)), 32.616)
 
     def testDoubleProdBadContainer(self):
         "Test the doubleProd function with an invalid list"
-        self.assertRaises(TypeError, Series.doubleProd, [3.14, "pi"])
+        self.assertRaises(BadListError, Series.doubleProd, [3.14, "pi"])
 
-    def testDoubleZeros(self):
-        "Test the doubleZeros function"
-        myArray = N.ones(5,'d')
-        Series.doubleZeros(myArray)
-        N.testing.assert_array_equal(myArray, N.array([0.,0.,0.,0.,0.]))
-
     def testDoubleOnes(self):
         "Test the doubleOnes function"
         myArray = N.zeros(5,'d')
@@ -134,44 +431,45 @@
         "Test the doubleOnes function with a list"
         self.assertRaises(TypeError, Series.doubleOnes, [True, 0, 2.718, "pi"])
 
-    def testDoubleNegate(self):
-        "Test the doubleNegate function"
-        myArray = N.arange(5) * 1.0
-        Series.doubleNegate(myArray)
-        N.testing.assert_array_equal(myArray, N.array([0.,-1.,-2.,-3.,-4.]))
-
-    #########################################################
-    ### Test functions that take 2D arrays of type DOUBLE ###
-    def testIntMax(self):
-        "Test the intMax function"
-        matrix = [[6,-5,4],[-3,2,-1]]
-        self.assertEquals(Series.intMax(matrix), 6)
-
-    def testIntMaxNonContainer(self):
-        "Test the intMax function with None"
-        self.assertRaises(TypeError, Series.intMax, None)
-
-    def testIntFloor(self):
-        "Test the intFloor function"
-        matrix = N.array([[10,-2],[-6,7]])
-        Series.intFloor(matrix,0)
-        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
-
     def testDoubleMax(self):
         "Test the doubleMax function"
         matrix = [[-6,5,-4],[3.14,-2.718,1]]
         self.assertEquals(Series.doubleMax(matrix), 5.0)
 
+    def testDoubleMaxNonContainer(self):
+        "Test the doubleMax function with None"
+        self.assertRaises(TypeError, Series.doubleMax, None)
+
     def testDoubleMaxWrongDim(self):
         "Test the doubleMax function with a 1D array"
         self.assertRaises(TypeError, Series.doubleMax, [0.0, -1, 2.718, -3.14])
 
     def testDoubleFloor(self):
         "Test the doubleFloor function"
-        matrix = N.array([[10,-2.718],[-6,3.14]])
-        Series.doubleFloor(matrix,5.0)
-        N.testing.assert_array_equal(matrix, N.array([[10.0,0],[0,0]]))
+        matrix = N.array([[10,-2],[-6,7]],'d')
+        Series.doubleFloor(matrix,0)
+        N.testing.assert_array_equal(matrix, N.array([[10,0],[0,7]]))
 
+    # ##########################################################
+    # ### Test functions that take arrays of type LONGDOUBLE ###
+    # def testLongDoubleProd(self):
+    #     "Test the longDoubleProd function"
+    #     self.assertEquals(Series.longDoubleProd((1,2.718,3,4)), 32.616)
+
+    # def testLongDoubleProdBadContainer(self):
+    #     "Test the longDoubleProd function with an invalid list"
+    #     self.assertRaises(BadListError, Series.longDoubleProd, [3.14, "pi"])
+
+    # def testLongDoubleOnes(self):
+    #     "Test the longDoubleOnes function"
+    #     myArray = N.zeros(5,'g')
+    #     Series.longDoubleOnes(myArray)
+    #     N.testing.assert_array_equal(myArray, N.array([1.,1.,1.,1.,1.]))
+
+    # def testLongDoubleOnesNonArray(self):
+    #     "Test the longDoubleOnes function with a list"
+    #     self.assertRaises(TypeError, Series.longDoubleOnes, [True, 0, 2.718, "pi"])
+
 ######################################################################
 
 if __name__ == "__main__":



More information about the Numpy-svn mailing list