Mercurial > pytave
changeset 108:74f17b2a5d45
Use the latest NumPy API
* arrayobjectdefs.h: Include current API headers.
* octave_to_python.cc, python_to_octave.cc: Use current NumPy functions and
types.
* pytave.cc: Fix comments.
author | Mike Miller <mtmiller@octave.org> |
---|---|
date | Fri, 18 Sep 2015 00:00:09 -0400 |
parents | 691ef5c6b9e2 |
children | bd6215fa1d87 |
files | arrayobjectdefs.h octave_to_python.cc pytave.cc python_to_octave.cc |
diffstat | 4 files changed, 110 insertions(+), 135 deletions(-) [+] |
line wrap: on
line diff
--- a/arrayobjectdefs.h Tue Apr 28 21:31:10 2015 -0400 +++ b/arrayobjectdefs.h Fri Sep 18 00:00:09 2015 -0400 @@ -29,11 +29,8 @@ #endif #define PY_ARRAY_UNIQUE_SYMBOL pytave_array_symbol #include <Python.h> -/* We use the oldnumeric.h header files because pytave was originally written - for the Numeric array library, which has since then been deprecated. We use - the NumPy compability headers. */ -#include <numpy/oldnumeric.h> -#include <numpy/old_defines.h> +#include <numpy/npy_no_deprecated_api.h> +#include <numpy/arrayobject.h> /* Emacs * Local Variables:
--- a/octave_to_python.cc Tue Apr 28 21:31:10 2015 -0400 +++ b/octave_to_python.cc Fri Sep 18 00:00:09 2015 -0400 @@ -19,7 +19,6 @@ */ #include <boost/python.hpp> -#include <boost/python/numeric.hpp> #include <boost/type_traits/integral_constant.hpp> /* Both boost::python and octave define HAVE_STAT and HAVE_FSTAT. Ideally, @@ -44,7 +43,7 @@ * types, not the Python data types. A Python int is equivalent to a C long, * and a Python float corresponds to a C double . Many of the element types * listed above do not have corresponding Python scalar types - * (e.g. PyArray_INT ). + * (e.g. NPY_INT ). */ using namespace boost::python; @@ -59,22 +58,22 @@ const unsigned int matstride, const int dimension, const unsigned int offset) { - unsigned char *ptr = (unsigned char*) pyarr->data; - if (dimension == pyarr->nd - 1) { + unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); + if (dimension == PyArray_NDIM (pyarr) - 1) { // Last dimension, base case - for (int i = 0; i < pyarr->dimensions[dimension]; i++) { - *(PythonPrimitive *)&ptr[offset + i*pyarr->strides[dimension]] + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { + *(PythonPrimitive *)&ptr[offset + i*PyArray_STRIDE (pyarr, dimension)] = matrix.elem(matindex + i*matstride); } } else { - for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { copy_octarray_to_pyarrobj<PythonPrimitive, OctaveBase>( pyarr, matrix, matindex + i*matstride, - matstride * pyarr->dimensions[dimension], + matstride * PyArray_DIM (pyarr, dimension), dimension + 1, - offset + i*pyarr->strides[dimension]); + offset + i*PyArray_STRIDE (pyarr, dimension)); } } } @@ -87,25 +86,25 @@ const unsigned int matstride, const int dimension, const unsigned int offset) { - unsigned char *ptr = (unsigned char*) pyarr->data; - if (dimension == pyarr->nd - 1) { + unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); + if (dimension == PyArray_NDIM (pyarr) - 1) { // Last dimension, base case - for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { object pyobj; octvalue_to_pyobj (pyobj, matrix.elem(matindex + i*matstride)); Py_INCREF (pyobj.ptr()); - *(PyObject **)&ptr[offset + i*pyarr->strides[dimension]] + *(PyObject **)&ptr[offset + i*PyArray_STRIDE (pyarr, dimension)] = pyobj.ptr(); } } else { - for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { copy_octarray_to_pyarrobj<PyObject *, Cell>( pyarr, matrix, matindex + i*matstride, - matstride * pyarr->dimensions[dimension], + matstride * PyArray_DIM (pyarr, dimension), dimension + 1, - offset + i*pyarr->strides[dimension]); + offset + i*PyArray_STRIDE (pyarr, dimension)); } } } @@ -153,17 +152,17 @@ inline static PyArrayObject *create_uint_array(CLASS value) { if (bytes == sizeof(int)) { boost::integral_constant<bool, bytes == sizeof(int)> inst; - return create_array<unsigned int, CLASS>(value, PyArray_UINT, inst); + return create_array<unsigned int, CLASS>(value, NPY_UINT, inst); } else if (bytes == sizeof(char)) { boost::integral_constant<bool, bytes == sizeof(char)> inst; - return create_array<unsigned char, CLASS>(value, PyArray_UBYTE, inst); + return create_array<unsigned char, CLASS>(value, NPY_UBYTE, inst); } else if (bytes == sizeof(short)) { boost::integral_constant<bool, bytes == sizeof(short) && bytes != sizeof(int)> inst; - return create_array<unsigned short, CLASS>(value, PyArray_USHORT, inst); + return create_array<unsigned short, CLASS>(value, NPY_USHORT, inst); } else { std::ostringstream os; - os << "Numeric arrays does not support unsigned " << (bytes*8) + os << "NumPy arrays do not support unsigned " << (bytes*8) << "-bit values on this architecture."; throw value_convert_exception(os.str()); } @@ -175,27 +174,25 @@ // We test int first since we prefer int to other datatypes of the // same size. boost::integral_constant<bool, bytes == sizeof(int)> inst; - return create_array<signed int, CLASS>(value, PyArray_INT, inst); + return create_array<signed int, CLASS>(value, NPY_INT, inst); } - // PyArray_LONGLONG does not exist (AFAIR) in legacy Numeric arrays, but - // Numpy is kind enough to provide us with the old-style defines. else if (bytes == sizeof(long long)) { boost::integral_constant<bool, bytes == sizeof(long long) && bytes != sizeof(int)> inst; - return create_array<long, CLASS>(value, PyArray_LONGLONG, inst); + return create_array<long, CLASS>(value, NPY_LONGLONG, inst); } else if (bytes == sizeof(long)) { boost::integral_constant<bool, bytes == sizeof(long) && bytes != sizeof(int) && bytes != sizeof(long long)> inst; - return create_array<long, CLASS>(value, PyArray_LONG, inst); + return create_array<long, CLASS>(value, NPY_LONG, inst); } else if (bytes == sizeof(char)) { boost::integral_constant<bool, bytes == sizeof(char)> inst; - return create_array<signed char, CLASS>(value, PyArray_SBYTE, inst); + return create_array<signed char, CLASS>(value, NPY_BYTE, inst); } else if (bytes == sizeof(short)) { boost::integral_constant<bool, bytes==sizeof(short) && bytes != sizeof(int)> inst; - return create_array<signed short, CLASS>(value, PyArray_SHORT, inst); + return create_array<signed short, CLASS>(value, NPY_SHORT, inst); } else { std::ostringstream os; - os << "Numeric arrays doesn't support signed " << (bytes*8) + os << "NumPy arrays do not support signed " << (bytes*8) << "-bit values on this architecture."; throw value_convert_exception(os.str()); } @@ -205,10 +202,10 @@ if (matrix.is_double_type ()) { if (matrix.is_complex_type ()) { return create_array<Complex, ComplexNDArray> - (matrix.complex_array_value(), PyArray_CDOUBLE); + (matrix.complex_array_value(), NPY_CDOUBLE); } else if (matrix.is_real_type()) { return create_array<double, NDArray>(matrix.array_value(), - PyArray_DOUBLE); + NPY_DOUBLE); } else throw value_convert_exception("Unknown double matrix type"); } @@ -216,10 +213,10 @@ if (matrix.is_single_type ()) { if (matrix.is_complex_type ()) { return create_array<FloatComplex, FloatComplexNDArray> - (matrix.float_complex_array_value(), PyArray_CFLOAT); + (matrix.float_complex_array_value(), NPY_CFLOAT); } else if (matrix.is_real_type()) { return create_array<float, FloatNDArray>( - matrix.float_array_value(), PyArray_FLOAT); + matrix.float_array_value(), NPY_FLOAT); } else throw value_convert_exception("Unknown float matrix type"); } @@ -253,21 +250,16 @@ matrix.int8_array_value()); } if (matrix.is_bool_type()) { - // NumPY has logical arrays, and even provides an old-style #define. return create_array<bool, boolNDArray>( - matrix.bool_array_value(), PyArray_BOOL); - // Numeric does not support bools, and we used to have uint8 as a - // fallback, back when we had support for Numeric. - // return create_uint_array<uint8NDArray, sizeof(uint8_t)>( - // matrix.uint8_array_value()); + matrix.bool_array_value(), NPY_BOOL); } if (matrix.is_string()) { return create_array<char, charNDArray>( - matrix.char_array_value(), PyArray_CHAR); + matrix.char_array_value(), NPY_CHAR); } if (matrix.is_cell()) { return create_array<PyObject *, Cell>( - matrix.cell_value(), PyArray_OBJECT); + matrix.cell_value(), NPY_OBJECT); } throw value_convert_exception("Octave matrix type not known, "
--- a/pytave.cc Tue Apr 28 21:31:10 2015 -0400 +++ b/pytave.cc Fri Sep 18 00:00:09 2015 -0400 @@ -102,10 +102,10 @@ uselocale(old_locale); #endif - // Initialize Python Numeric Array + // Initialize NumPy Array // This is actually a macro that becomes a block expression. If an error - // occurs, e.g. Numeric Array not installed, an exception is set. + // occurs, e.g. NumPy not installed, an exception is set. import_array() // Let boost use numpy
--- a/python_to_octave.cc Tue Apr 28 21:31:10 2015 -0400 +++ b/python_to_octave.cc Fri Sep 18 00:00:09 2015 -0400 @@ -49,70 +49,70 @@ template <class PythonPrimitive, class OctaveBase> static void copy_pyarrobj_to_octarray(OctaveBase &matrix, - const PyArrayObject* const pyarr, + PyArrayObject* pyarr, const int unsigned matindex, const unsigned int matstride, const int dimension, const unsigned int offset) { - unsigned char *ptr = (unsigned char*) pyarr->data; - if (dimension == pyarr->nd - 1) { + unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); + if (dimension == PyArray_NDIM (pyarr) - 1) { // Last dimension, base case - for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { matrix.elem(matindex + i*matstride) = *(PythonPrimitive*) - &ptr[offset + i*pyarr->strides[dimension]]; + &ptr[offset + i*PyArray_STRIDE (pyarr, dimension)]; } - } else if (pyarr->nd == 0) { + } else if (PyArray_NDIM (pyarr) == 0) { matrix.elem(0) = *(PythonPrimitive*) ptr; } else { - for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { copy_pyarrobj_to_octarray<PythonPrimitive, OctaveBase>( matrix, pyarr, matindex + i*matstride, - matstride * pyarr->dimensions[dimension], + matstride * PyArray_DIM (pyarr, dimension), dimension + 1, - offset + i*pyarr->strides[dimension]); + offset + i*PyArray_STRIDE (pyarr, dimension)); } } } template <> void copy_pyarrobj_to_octarray<PyObject *, Cell>(Cell &matrix, - const PyArrayObject* const pyarr, + PyArrayObject* pyarr, const int unsigned matindex, const unsigned int matstride, const int dimension, const unsigned int offset) { - unsigned char *ptr = (unsigned char*) pyarr->data; - if (dimension == pyarr->nd - 1) { + unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); + if (dimension == PyArray_NDIM (pyarr) - 1) { // Last dimension, base case - for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { PyObject *pobj = *(PyObject **) - &ptr[offset + i*pyarr->strides[dimension]]; + &ptr[offset + i*PyArray_STRIDE (pyarr, dimension)]; pyobj_to_octvalue (matrix.elem(matindex + i*matstride), object(handle<PyObject> (borrowed (pobj)))); } - } else if (pyarr->nd == 0) { + } else if (PyArray_NDIM (pyarr) == 0) { PyObject *pobj = *(PyObject **) ptr; pyobj_to_octvalue (matrix.elem(0), object(handle<PyObject> (borrowed (pobj)))); } else { - for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { copy_pyarrobj_to_octarray<PyObject *, Cell>( matrix, pyarr, matindex + i*matstride, - matstride * pyarr->dimensions[dimension], + matstride * PyArray_DIM (pyarr, dimension), dimension + 1, - offset + i*pyarr->strides[dimension]); + offset + i*PyArray_STRIDE (pyarr, dimension)); } } } template <class PythonPrimitive, class OctaveBase> static void copy_pyarrobj_to_octarray_dispatch(OctaveBase &matrix, - const PyArrayObject* const pyarr, + PyArrayObject* pyarr, const boost::true_type&) { copy_pyarrobj_to_octarray<PythonPrimitive, OctaveBase> (matrix, pyarr, 0, 1, 0, 0); @@ -120,7 +120,7 @@ template <class PythonPrimitive, class OctaveBase> static void copy_pyarrobj_to_octarray_dispatch(OctaveBase &matrix, - const PyArrayObject* const pyarr, + PyArrayObject* pyarr, const boost::false_type&) { assert(0); } @@ -134,14 +134,14 @@ template <class PythonPrimitive, class OctaveBase> static void copy_pyarrobj_to_octarray_dispatch(OctaveBase &matrix, - const PyArrayObject* const pyarr) { + PyArrayObject* pyarr) { matching_type<PythonPrimitive, typename OctaveBase::element_type> inst; copy_pyarrobj_to_octarray_dispatch<PythonPrimitive, OctaveBase> (matrix, pyarr, inst); } template <class OctaveBase> static void copy_pyarrobj_to_octarray_boot(OctaveBase &matrix, - const PyArrayObject* const pyarr) { + PyArrayObject* pyarr) { #define ARRAYCASE(AC_pyarrtype, AC_primitive) case AC_pyarrtype: \ copy_pyarrobj_to_octarray_dispatch<AC_primitive, OctaveBase>\ @@ -150,52 +150,42 @@ // Prefer int to other types of the same size. // E.g. on 32-bit x86 architectures: sizeof(long) == sizeof(int). - int type_num = pyarr->descr->type_num; + int type_num = PyArray_TYPE (pyarr); switch (type_num) { - case PyArray_LONG: + case NPY_LONG: if (sizeof(long) == sizeof(int)) { - type_num = PyArray_INT; + type_num = NPY_INT; } break; - case PyArray_SHORT: + case NPY_SHORT: if (sizeof(short) == sizeof(int)) { - type_num = PyArray_INT; + type_num = NPY_INT; } break; - case PyArray_USHORT: + case NPY_USHORT: if (sizeof(unsigned short) == sizeof(unsigned int)) { - type_num = PyArray_UINT; + type_num = NPY_UINT; } break; } switch (type_num) { - ARRAYCASE(PyArray_CHAR, char) - ARRAYCASE(PyArray_UBYTE, unsigned char) - ARRAYCASE(PyArray_SBYTE, signed char) - ARRAYCASE(PyArray_SHORT, signed short) - ARRAYCASE(PyArray_USHORT, unsigned short) - ARRAYCASE(PyArray_INT, signed int) - ARRAYCASE(PyArray_UINT, unsigned int) - ARRAYCASE(PyArray_LONG, signed long) - ARRAYCASE(PyArray_LONGLONG, signed long long) - - /* Commonly Numeric.array(..., Numeric.Float32) */ - ARRAYCASE(PyArray_FLOAT, float) - - /* Commonly Numeric.array(..., Numeric.Float) */ - ARRAYCASE(PyArray_DOUBLE, double) - - /* Commonly Numeric.array(..., Numeric.Complex32) */ - ARRAYCASE(PyArray_CFLOAT, FloatComplex) - - /* Commonly Numeric.array(..., Numeric.Complex) */ - ARRAYCASE(PyArray_CDOUBLE, Complex) - - ARRAYCASE(PyArray_BOOL, bool) - ARRAYCASE(PyArray_STRING, char) - - ARRAYCASE(PyArray_OBJECT, PyObject *) + ARRAYCASE(NPY_CHAR, char) + ARRAYCASE(NPY_BYTE, signed char) + ARRAYCASE(NPY_UBYTE, unsigned char) + ARRAYCASE(NPY_SHORT, signed short) + ARRAYCASE(NPY_USHORT, unsigned short) + ARRAYCASE(NPY_INT, signed int) + ARRAYCASE(NPY_UINT, unsigned int) + ARRAYCASE(NPY_LONG, signed long) + ARRAYCASE(NPY_LONGLONG, signed long long) + ARRAYCASE(NPY_FLOAT, float) + ARRAYCASE(NPY_DOUBLE, double) + ARRAYCASE(NPY_CFLOAT, FloatComplex) + ARRAYCASE(NPY_CDOUBLE, Complex) + ARRAYCASE(NPY_BOOL, bool) + ARRAYCASE(NPY_STRING, char) + ARRAYCASE(NPY_OBJECT, PyObject *) default: throw object_convert_exception( @@ -207,7 +197,7 @@ template <class OctaveBase> static void pyarrobj_to_octvalueNd(octave_value &octvalue, - const PyArrayObject* const pyarr, + PyArrayObject* pyarr, dim_vector dims) { OctaveBase array(dims); copy_pyarrobj_to_octarray_boot<OctaveBase>(array, pyarr); @@ -217,27 +207,27 @@ static void pyarr_to_octvalue(octave_value &octvalue, PyArrayObject *pyarr) { dim_vector dims; - switch (pyarr->nd) { + switch (PyArray_NDIM (pyarr)) { case 0: dims = dim_vector (1, 1); break; case 1: // Always make PyArray vectors row vectors. - dims = dim_vector(1, pyarr->dimensions[0]); + dims = dim_vector(1, PyArray_DIM (pyarr, 0)); break; default: - dims.resize(pyarr->nd); - for (int d = 0; d < pyarr->nd; d++) { - dims(d) = pyarr->dimensions[d]; + dims.resize(PyArray_NDIM (pyarr)); + for (int d = 0; d < PyArray_NDIM (pyarr); d++) { + dims(d) = PyArray_DIM (pyarr, d); } break; } - switch (pyarr->descr->type_num) { - case PyArray_UBYTE: - case PyArray_USHORT: - case PyArray_UINT: - switch (pyarr->descr->elsize) { + switch (PyArray_TYPE (pyarr)) { + case NPY_UBYTE: + case NPY_USHORT: + case NPY_UINT: + switch (PyArray_ITEMSIZE (pyarr)) { case 1: pyarrobj_to_octvalueNd<uint8NDArray>(octvalue, pyarr, dims); break; @@ -250,12 +240,12 @@ default: throw object_convert_exception("Unknown unsigned integer."); } - case PyArray_SBYTE: - case PyArray_SHORT: - case PyArray_INT: - case PyArray_LONG: - case PyArray_LONGLONG: - switch (pyarr->descr->elsize) { + case NPY_BYTE: + case NPY_SHORT: + case NPY_INT: + case NPY_LONG: + case NPY_LONGLONG: + switch (PyArray_ITEMSIZE (pyarr)) { case 1: pyarrobj_to_octvalueNd<int8NDArray>(octvalue, pyarr, dims); break; @@ -272,38 +262,34 @@ throw object_convert_exception("Unknown integer."); } break; - case PyArray_FLOAT: + case NPY_FLOAT: pyarrobj_to_octvalueNd<FloatNDArray>(octvalue, pyarr, dims); break; - case PyArray_DOUBLE: + case NPY_DOUBLE: pyarrobj_to_octvalueNd<NDArray>(octvalue, pyarr, dims); break; - case PyArray_CFLOAT: + case NPY_CFLOAT: pyarrobj_to_octvalueNd<FloatComplexNDArray>(octvalue, pyarr, dims); break; - case PyArray_CDOUBLE: + case NPY_CDOUBLE: pyarrobj_to_octvalueNd<ComplexNDArray>(octvalue, pyarr, dims); break; - case PyArray_CHAR: - case_PyArray_CHAR: + case NPY_CHAR: + case_NPY_CHAR: pyarrobj_to_octvalueNd<charNDArray>(octvalue, pyarr, dims); // FIXME: is the following needed? octvalue = octvalue.convert_to_str(true, true, '"'); break; - case PyArray_BOOL: - // PyArray_BOOL is an NumPy-ism (was not part of origin Numeric - // interface.) + case NPY_BOOL: pyarrobj_to_octvalueNd<boolNDArray>(octvalue, pyarr, dims); break; - case PyArray_STRING: + case NPY_STRING: { - // PyArray_STRING is an NumPy-ism (was not part of origin Numeric - // interface.) - if (pyarr->descr->elsize == 1) - goto case_PyArray_CHAR; + if (PyArray_ITEMSIZE (pyarr) == 1) + goto case_NPY_CHAR; else { // Create a new descriptor of the data. - PyArray_Descr *view_descr = PyArray_DescrFromType(PyArray_CHAR); + PyArray_Descr *view_descr = PyArray_DescrFromType(NPY_CHAR); // Create a new view of the NumPy array. PyArrayObject *view = (PyArrayObject *)PyArray_View (pyarr, view_descr, NULL); // Store in a handle to ensure proper destruction. @@ -313,7 +299,7 @@ } } break; - case PyArray_OBJECT: + case NPY_OBJECT: pyarrobj_to_octvalueNd<Cell>(octvalue, pyarr, dims); break; default: