[Numpy-svn] r5631 - in trunk/numpy/doc/swig: . test

numpy-svn at scipy.org numpy-svn at scipy.org
Tue Aug 12 14:46:32 EDT 2008


Author: stefan
Date: 2008-08-12 13:46:31 -0500 (Tue, 12 Aug 2008)
New Revision: 5631

Added:
   trunk/numpy/doc/swig/test/Fortran.cxx
   trunk/numpy/doc/swig/test/Fortran.h
   trunk/numpy/doc/swig/test/Fortran.i
   trunk/numpy/doc/swig/test/testFortran.py
Modified:
   trunk/numpy/doc/swig/numpy.i
   trunk/numpy/doc/swig/test/Makefile
   trunk/numpy/doc/swig/test/setup.py
   trunk/numpy/doc/swig/test/testArray.py
   trunk/numpy/doc/swig/test/testMatrix.py
   trunk/numpy/doc/swig/test/testTensor.py
   trunk/numpy/doc/swig/test/testVector.py
Log:
Correctly handle Fortran-contiguous arrays in SWIG wrappers.


Modified: trunk/numpy/doc/swig/numpy.i
===================================================================
--- trunk/numpy/doc/swig/numpy.i	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/numpy.i	2008-08-12 18:46:31 UTC (rev 5631)
@@ -196,7 +196,7 @@
     }
     else
     {
-      py_obj = PyArray_FromObject(input, typecode, 0, 0);
+      py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_DEFAULT);
       /* If NULL, PyArray_FromObject will have set python error value.*/
       ary = (PyArrayObject*) py_obj;
       *is_new_object = 1;
@@ -229,6 +229,30 @@
     return result;
   }
 
+  /* Given a PyArrayObject, check to see if it is Fortran-contiguous.
+   * If so, return the input pointer, but do not flag it as not a new
+   * object.  If it is not Fortran-contiguous, create a new
+   * PyArrayObject using the original data, flag it as a new object
+   * and return the pointer.
+   */
+  PyArrayObject* make_fortran(PyArrayObject* ary, int* is_new_object,
+                              int min_dims, int max_dims)
+  {
+    PyArrayObject* result;
+    if (array_is_fortran(ary))
+    {
+      result = ary;
+      *is_new_object = 0;
+    }
+    else
+    {
+      Py_INCREF(ary->descr);
+      result = (PyArrayObject*) PyArray_FromArray(ary, ary->descr, NPY_FORTRAN);
+      *is_new_object = 1;
+    }
+    return result;
+  }
+
   /* 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
@@ -255,8 +279,37 @@
     *is_new_object = is_new1 || is_new2;
     return ary1;
   }
-}
 
+  /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the
+   * specified type.  If the input object is not a Fortran-ordered
+   * PyArrayObject, a new one will be created and the new object flag
+   * will be set.
+   */
+  PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input,
+                                                       int typecode,
+                                                       int* is_new_object)
+  {
+    int is_new1 = 0;
+    int is_new2 = 0;
+    PyArrayObject* ary2;
+    PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode,
+                                                        &is_new1);
+    if (ary1)
+    {
+      ary2 = make_fortran(ary1, &is_new2, 0, 0);
+      if (is_new1 && is_new2)
+      {
+        Py_DECREF(ary1);
+      }
+      ary1 = ary2;
+    }
+    *is_new_object = is_new1 || is_new2;
+    return ary1;
+  }
+
+} /* end fragment */
+
+
 /**********************************************************************/
 
 %fragment("NumPy_Array_Requirements", "header",
@@ -716,8 +769,8 @@
   (PyArrayObject* array=NULL, int is_new_object=0)
 {
   npy_intp size[2] = { -1, -1 };
-  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
-                                                   &is_new_object);
+  array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE,
+                                                &is_new_object);
   if (!array || !require_dimensions(array, 2) ||
       !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail;
   $1 = (DATA_TYPE*) array_data(array);
@@ -864,8 +917,8 @@
   (PyArrayObject* array=NULL, int is_new_object=0)
 {
   npy_intp size[3] = { -1, -1, -1 };
-  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
-                                                   &is_new_object);
+  array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE,
+                                                &is_new_object);
   if (!array || !require_dimensions(array, 3) ||
       !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail;
   $1 = (DATA_TYPE*) array_data(array);

Added: trunk/numpy/doc/swig/test/Fortran.cxx
===================================================================
--- trunk/numpy/doc/swig/test/Fortran.cxx	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/Fortran.cxx	2008-08-12 18:46:31 UTC (rev 5631)
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include "Fortran.h"
+
+#define TEST_FUNCS(TYPE, SNAME) \
+\
+TYPE SNAME ## SecondElement(TYPE * matrix, int rows, int cols) {	  \
+  TYPE result = matrix[1];                                \
+  return result;                                          \
+}                                                         \
+
+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   )

Added: trunk/numpy/doc/swig/test/Fortran.h
===================================================================
--- trunk/numpy/doc/swig/test/Fortran.h	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/Fortran.h	2008-08-12 18:46:31 UTC (rev 5631)
@@ -0,0 +1,21 @@
+#ifndef FORTRAN_H
+#define FORTRAN_H
+
+#define TEST_FUNC_PROTOS(TYPE, SNAME) \
+\
+TYPE SNAME ## SecondElement(    TYPE * matrix, int rows, int cols); \
+
+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   )
+
+#endif

Added: trunk/numpy/doc/swig/test/Fortran.i
===================================================================
--- trunk/numpy/doc/swig/test/Fortran.i	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/Fortran.i	2008-08-12 18:46:31 UTC (rev 5631)
@@ -0,0 +1,36 @@
+// -*- c++ -*-
+%module Fortran
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "Fortran.h"
+%}
+
+// Get the NumPy typemaps
+%include "../numpy.i"
+
+%init %{
+  import_array();
+%}
+
+%define %apply_numpy_typemaps(TYPE)
+
+%apply (TYPE* IN_FARRAY2, int DIM1, int DIM2) {(TYPE* matrix, int rows, int cols)};
+
+%enddef    /* %apply_numpy_typemaps() macro */
+
+%apply_numpy_typemaps(signed char       )
+%apply_numpy_typemaps(unsigned char     )
+%apply_numpy_typemaps(short             )
+%apply_numpy_typemaps(unsigned short    )
+%apply_numpy_typemaps(int               )
+%apply_numpy_typemaps(unsigned int      )
+%apply_numpy_typemaps(long              )
+%apply_numpy_typemaps(unsigned long     )
+%apply_numpy_typemaps(long long         )
+%apply_numpy_typemaps(unsigned long long)
+%apply_numpy_typemaps(float             )
+%apply_numpy_typemaps(double            )
+
+// Include the header file to be wrapped
+%include "Fortran.h"

Modified: trunk/numpy/doc/swig/test/Makefile
===================================================================
--- trunk/numpy/doc/swig/test/Makefile	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/Makefile	2008-08-12 18:46:31 UTC (rev 5631)
@@ -1,13 +1,13 @@
 # SWIG
-INTERFACES = Array.i Farray.i Vector.i Matrix.i Tensor.i
+INTERFACES = Array.i Farray.i Vector.i Matrix.i Tensor.i Fortran.i
 WRAPPERS   = $(INTERFACES:.i=_wrap.cxx)
 PROXIES    = $(INTERFACES:.i=.py      )
 
 # Default target: build the tests
 .PHONY : all
 all: $(WRAPPERS) Array1.cxx Array1.h Farray.cxx Farray.h Vector.cxx Vector.h \
-	Matrix.cxx Matrix.h Tensor.cxx Tensor.h
-	./setup.py build
+	Matrix.cxx Matrix.h Tensor.cxx Tensor.h Fortran.h Fortran.cxx
+	./setup.py build_ext -i
 
 # Test target: run the tests
 .PHONY : test
@@ -17,6 +17,7 @@
 	python testTensor.py
 	python testArray.py
 	python testFarray.py
+	python testFortran.py
 
 # Rule: %.i -> %_wrap.cxx
 %_wrap.cxx: %.i %.h ../numpy.i
@@ -28,5 +29,6 @@
 .PHONY : clean
 clean:
 	$(RM) -r build
+	$(RM) *.so
 	$(RM) $(WRAPPERS)
 	$(RM) $(PROXIES)

Modified: trunk/numpy/doc/swig/test/setup.py
===================================================================
--- trunk/numpy/doc/swig/test/setup.py	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/setup.py	2008-08-12 18:46:31 UTC (rev 5631)
@@ -49,10 +49,18 @@
                     include_dirs = [numpy_include],
                     )
 
+_Fortran = Extension("_Fortran",
+                    ["Fortran_wrap.cxx",
+                     "Fortran.cxx"],
+                    include_dirs = [numpy_include],
+                    )
+
 # NumyTypemapTests setup
 setup(name        = "NumpyTypemapTests",
       description = "Functions that work on arrays",
       author      = "Bill Spotz",
-      py_modules  = ["Array", "Farray", "Vector", "Matrix", "Tensor"],
-      ext_modules = [_Array , _Farray , _Vector , _Matrix , _Tensor ]
+      py_modules  = ["Array", "Farray", "Vector", "Matrix", "Tensor",
+                     "Fortran"],
+      ext_modules = [_Array , _Farray , _Vector , _Matrix , _Tensor,
+                     _Fortran]
       )

Modified: trunk/numpy/doc/swig/test/testArray.py
===================================================================
--- trunk/numpy/doc/swig/test/testArray.py	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/testArray.py	2008-08-12 18:46:31 UTC (rev 5631)
@@ -14,10 +14,6 @@
 else:
     BadListError = ValueError
 
-# Add the distutils-generated build directory to the python search path and then
-# import the extension module
-libDir = "lib.%s-%s" % (get_platform(), sys.version[:3])
-sys.path.insert(0,os.path.join("build", libDir))
 import Array
 
 ######################################################################

Added: trunk/numpy/doc/swig/test/testFortran.py
===================================================================
--- trunk/numpy/doc/swig/test/testFortran.py	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/testFortran.py	2008-08-12 18:46:31 UTC (rev 5631)
@@ -0,0 +1,169 @@
+#! /usr/bin/env python
+
+# System imports
+from   distutils.util import get_platform
+import os
+import sys
+import unittest
+
+# Import NumPy
+import numpy as np
+major, minor = [ int(d) for d in np.__version__.split(".")[:2] ]
+if major == 0: BadListError = TypeError
+else:          BadListError = ValueError
+
+import Fortran
+
+######################################################################
+
+class FortranTestCase(unittest.TestCase):
+
+    def __init__(self, methodName="runTests"):
+        unittest.TestCase.__init__(self, methodName)
+        self.typeStr  = "double"
+        self.typeCode = "d"
+
+    # Test (type* IN_FARRAY2, int DIM1, int DIM2) typemap
+    def testSecondElementContiguous(self):
+        "Test luSplit function with a Fortran-array"
+        print >>sys.stderr, self.typeStr, "... ",
+        second = Fortran.__dict__[self.typeStr + "SecondElement"]
+        matrix = np.arange(9).reshape(3, 3).astype(self.typeCode)
+        self.assertEquals(second(matrix), 3)
+
+    def testSecondElementFortran(self):
+        "Test luSplit function with a Fortran-array"
+        print >>sys.stderr, self.typeStr, "... ",
+        second = Fortran.__dict__[self.typeStr + "SecondElement"]
+        matrix = np.asfortranarray(np.arange(9).reshape(3, 3),
+                                   self.typeCode)
+        self.assertEquals(second(matrix), 3)
+
+    def testSecondElementObject(self):
+        "Test luSplit function with a Fortran-array"
+        print >>sys.stderr, self.typeStr, "... ",
+        second = Fortran.__dict__[self.typeStr + "SecondElement"]
+        matrix = np.asfortranarray([[0,1,2],[3,4,5],[6,7,8]], self.typeCode)
+        self.assertEquals(second(matrix), 3)
+
+######################################################################
+
+class scharTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "schar"
+        self.typeCode = "b"
+
+######################################################################
+
+class ucharTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "uchar"
+        self.typeCode = "B"
+
+######################################################################
+
+class shortTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "short"
+        self.typeCode = "h"
+
+######################################################################
+
+class ushortTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "ushort"
+        self.typeCode = "H"
+
+######################################################################
+
+class intTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "int"
+        self.typeCode = "i"
+
+######################################################################
+
+class uintTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "uint"
+        self.typeCode = "I"
+
+######################################################################
+
+class longTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "long"
+        self.typeCode = "l"
+
+######################################################################
+
+class ulongTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "ulong"
+        self.typeCode = "L"
+
+######################################################################
+
+class longLongTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "longLong"
+        self.typeCode = "q"
+
+######################################################################
+
+class ulongLongTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "ulongLong"
+        self.typeCode = "Q"
+
+######################################################################
+
+class floatTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "float"
+        self.typeCode = "f"
+
+######################################################################
+
+class doubleTestCase(FortranTestCase):
+    def __init__(self, methodName="runTest"):
+        FortranTestCase.__init__(self, methodName)
+        self.typeStr  = "double"
+        self.typeCode = "d"
+
+######################################################################
+
+if __name__ == "__main__":
+
+    # Build the test suite
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(    scharTestCase))
+    suite.addTest(unittest.makeSuite(    ucharTestCase))
+    suite.addTest(unittest.makeSuite(    shortTestCase))
+    suite.addTest(unittest.makeSuite(   ushortTestCase))
+    suite.addTest(unittest.makeSuite(      intTestCase))
+    suite.addTest(unittest.makeSuite(     uintTestCase))
+    suite.addTest(unittest.makeSuite(     longTestCase))
+    suite.addTest(unittest.makeSuite(    ulongTestCase))
+    suite.addTest(unittest.makeSuite( longLongTestCase))
+    suite.addTest(unittest.makeSuite(ulongLongTestCase))
+    suite.addTest(unittest.makeSuite(    floatTestCase))
+    suite.addTest(unittest.makeSuite(   doubleTestCase))
+
+    # Execute the test suite
+    print "Testing 2D Functions of Module Matrix"
+    print "NumPy version", np.__version__
+    print
+    result = unittest.TextTestRunner(verbosity=2).run(suite)
+    sys.exit(len(result.errors) + len(result.failures))

Modified: trunk/numpy/doc/swig/test/testMatrix.py
===================================================================
--- trunk/numpy/doc/swig/test/testMatrix.py	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/testMatrix.py	2008-08-12 18:46:31 UTC (rev 5631)
@@ -12,10 +12,6 @@
 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
-libDir = "lib.%s-%s" % (get_platform(), sys.version[:3])
-sys.path.insert(0,os.path.join("build", libDir))
 import Matrix
 
 ######################################################################

Modified: trunk/numpy/doc/swig/test/testTensor.py
===================================================================
--- trunk/numpy/doc/swig/test/testTensor.py	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/testTensor.py	2008-08-12 18:46:31 UTC (rev 5631)
@@ -13,10 +13,6 @@
 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
-libDir = "lib.%s-%s" % (get_platform(), sys.version[:3])
-sys.path.insert(0,os.path.join("build", libDir))
 import Tensor
 
 ######################################################################

Modified: trunk/numpy/doc/swig/test/testVector.py
===================================================================
--- trunk/numpy/doc/swig/test/testVector.py	2008-08-12 06:56:11 UTC (rev 5630)
+++ trunk/numpy/doc/swig/test/testVector.py	2008-08-12 18:46:31 UTC (rev 5631)
@@ -12,10 +12,6 @@
 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
-libDir = "lib.%s-%s" % (get_platform(), sys.version[:3])
-sys.path.insert(0,os.path.join("build", libDir))
 import Vector
 
 ######################################################################




More information about the Numpy-svn mailing list