Mercurial > pytave
changeset 51:b001edc0f81a
implement Python->Octave conversions of Character and PyObject arrays
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 03 Jun 2009 16:41:44 +0200 |
parents | 2a2f1e2f2be3 (current diff) 22e74c46bea2 (diff) |
children | a5beba1b4611 57f243330695 43a413b7c151 |
files | ChangeLog python_to_octave.cc test/test.py |
diffstat | 4 files changed, 107 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Thu May 28 11:20:17 2009 +0200 +++ b/ChangeLog Wed Jun 03 16:41:44 2009 +0200 @@ -1,3 +1,21 @@ +2009-06-03 Jaroslav Hajek <highegg@gmail.com> + + * python_to_octave.cc (copy_pyarrobj_to_octarray<PyObject *, + Cell>): New template specialization. + (matching_type<PyObject *, octave_value>): Ditto. + (copy_pyarrobj_to_octarray_boot): Include PyArray_CHAR + and PyArray_Object cases. + (pyarr_to_octvalue): Likewise. + * test/test.py: Add tests for the new conversions. + +2009-06-03 David Grundberg <individ@acc.umu.se> + + * octave_to_python.cc (create_uint_array, create_sint_array): + Prefer int to other datatypes of identical size. + (is_1xn_or_0x0): Whitespace. + * python_to_octave.cc (copy_pyarrobj_to_octarray_dispatch): Prefer + int to other datatypes of identical size. + 2009-05-28 Jaroslav Hajek <highegg@gmail.com> * configure.ac: Remove --enable-float-matrices option.
--- a/octave_to_python.cc Thu May 28 11:20:17 2009 +0200 +++ b/octave_to_python.cc Wed Jun 03 16:41:44 2009 +0200 @@ -117,13 +117,14 @@ template <class CLASS, size_t bytes> inline static PyArrayObject *create_uint_array(CLASS value) { if (bytes == sizeof(int)) { - boost::integral_constant<bool, bytes==sizeof(int)> inst; + boost::integral_constant<bool, bytes == sizeof(int)> inst; return create_array<unsigned int, CLASS>(value, PyArray_UINT, inst); } else if (bytes == sizeof(char)) { - boost::integral_constant<bool, bytes==sizeof(char)> inst; + boost::integral_constant<bool, bytes == sizeof(char)> inst; return create_array<unsigned char, CLASS>(value, PyArray_UBYTE, inst); } else if (bytes == sizeof(short)) { - boost::integral_constant<bool, bytes==sizeof(short)> inst; + boost::integral_constant<bool, + bytes == sizeof(short) && bytes != sizeof(int)> inst; return create_array<unsigned short, CLASS>(value, PyArray_USHORT, inst); } else { ostringstream os; @@ -135,17 +136,21 @@ template <class CLASS, size_t bytes> inline static PyArrayObject *create_sint_array(CLASS value) { - if (bytes == sizeof(long)) { - boost::integral_constant<bool, bytes==sizeof(long)> inst; + if (bytes == sizeof(int)) { + // 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); + } else if (bytes == sizeof(long)) { + boost::integral_constant<bool, + bytes==sizeof(long) && bytes != sizeof(int)> inst; return create_array<long, CLASS>(value, PyArray_LONG, inst); - } else if (bytes == sizeof(int)) { - boost::integral_constant<bool, bytes==sizeof(int)> inst; - return create_array<signed int, CLASS>(value, PyArray_INT, inst); } else if (bytes == sizeof(char)) { - boost::integral_constant<bool, bytes==sizeof(char)> inst; + boost::integral_constant<bool, bytes == sizeof(char)> inst; return create_array<signed char, CLASS>(value, PyArray_SBYTE, inst); } else if (bytes == sizeof(short)) { - boost::integral_constant<bool, bytes==sizeof(short)> inst; + boost::integral_constant<bool, + bytes==sizeof(short) && bytes != sizeof(int)> inst; return create_array<signed short, CLASS>(value, PyArray_SHORT, inst); } else { ostringstream os; @@ -218,7 +223,7 @@ } static inline bool is_1xn_or_0x0(const dim_vector& dv) { - return (dv.length() == 2 && (dv(0) == 1 || (dv(0) == 0 && dv(1) == 0))); + return (dv.length() == 2 && (dv(0) == 1 || (dv(0) == 0 && dv(1) == 0))); } static void octcell_to_pyobject(boost::python::object &py_object,
--- a/python_to_octave.cc Thu May 28 11:20:17 2009 +0200 +++ b/python_to_octave.cc Wed Jun 03 16:41:44 2009 +0200 @@ -69,6 +69,35 @@ } } + template <> + void copy_pyarrobj_to_octarray<PyObject *, Cell>(Cell &matrix, + const PyArrayObject* const 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) { + // Last dimension, base case + for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + PyObject *pobj = *(PyObject **) + &ptr[offset + i*pyarr->strides[dimension]]; + pyobj_to_octvalue (matrix.elem(matindex + i*matstride), + object(handle<PyObject> (borrowed (pobj)))); + } + } else { + for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + copy_pyarrobj_to_octarray<PyObject *, Cell>( + matrix, + pyarr, + matindex + i*matstride, + matstride * pyarr->dimensions[dimension], + dimension + 1, + offset + i*pyarr->strides[dimension]); + } + } + } + template <class PythonPrimitive, class OctaveBase> static void copy_pyarrobj_to_octarray_dispatch(OctaveBase &matrix, const PyArrayObject* const pyarr, @@ -89,6 +118,7 @@ template <class X> class matching_type<X, octave_int<X> > : public boost::true_type { }; template <> class matching_type<float, double> : public boost::true_type { }; template <> class matching_type<FloatComplex, Complex> : public boost::true_type { }; + template <> class matching_type<PyObject *, octave_value> : public boost::true_type { }; template <class PythonPrimitive, class OctaveBase> static void copy_pyarrobj_to_octarray_dispatch(OctaveBase &matrix, @@ -106,8 +136,29 @@ (matrix, pyarr); \ break; \ - switch (pyarr->descr->type_num) { -// ARRAYCASE(PyArray_CHAR, ) + // 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; + switch (type_num) { + case PyArray_LONG: + if (sizeof(long) == sizeof(int)) { + type_num = PyArray_INT; + } + break; + case PyArray_SHORT: + if (sizeof(short) == sizeof(int)) { + type_num = PyArray_INT; + } + break; + case PyArray_USHORT: + if (sizeof(unsigned short) == sizeof(unsigned int)) { + type_num = PyArray_UINT; + } + break; + } + + switch (type_num) { + ARRAYCASE(PyArray_CHAR, char) ARRAYCASE(PyArray_UBYTE, unsigned char) ARRAYCASE(PyArray_SBYTE, signed char) ARRAYCASE(PyArray_SHORT, signed short) @@ -127,7 +178,9 @@ /* Commonly Numeric.array(..., Numeric.Complex) */ ARRAYCASE(PyArray_CDOUBLE, Complex) -// ARRAYCASE(PyArray_OBJECT, ) + + ARRAYCASE(PyArray_OBJECT, PyObject *) + default: throw object_convert_exception( PyEval_GetFuncName((PyObject*)pyarr) @@ -213,6 +266,14 @@ case PyArray_CDOUBLE: pyarrobj_to_octvalueNd<ComplexNDArray>(octvalue, pyarr, dims); break; + case PyArray_CHAR: + pyarrobj_to_octvalueNd<charNDArray>(octvalue, pyarr, dims); + // FIXME: is the following needed? + octvalue = octvalue.convert_to_str(true, true, '"'); + break; + case PyArray_OBJECT: + pyarrobj_to_octvalueNd<Cell>(octvalue, pyarr, dims); + break; default: throw object_convert_exception( PyEval_GetFuncDesc((PyObject*)(pyarr)) + string(" ") @@ -287,11 +348,6 @@ if (error_state) throw object_convert_exception("Octave error"); - // Some things are assumed since we have converted a Python list to - // a cell. - assert(c.dims().length() == 2); - assert(c.dim1() == 1); - // We do not bother measuring 1x1 values, since they are replicated // to fill up the necessary dimensions. if(!(c.dims().length() == 2 && c.dims()(0) == 1 && c.dims()(1) == 1)) {
--- a/test/test.py Thu May 28 11:20:17 2009 +0200 +++ b/test/test.py Wed Jun 03 16:41:44 2009 +0200 @@ -22,6 +22,10 @@ arr3f = Numeric.array([[[1.32, 2, 3, 4],[5,6,7,8]],[[9, 10, 11, 12],[13,14,15,16]]], Numeric.Float32) arr1c = Numeric.array([[1+2j, 3+4j, 5+6j, 7+0.5j]], Numeric.Complex) arr1fc = Numeric.array([[1+2j, 3+4j, 5+6j, 7+0.5j]], Numeric.Complex32) +arr1o = Numeric.array([["abc",1.0,2+3j]],Numeric.PyObject) +arr2o = Numeric.array([["abc",1.0,2+3j],[4.0,arr1i,"def"]],Numeric.PyObject) +arr1ch = Numeric.array(["abc"],Numeric.Character) +arr2ch = Numeric.array(["abc","def"],Numeric.Character) alimit_int32 = Numeric.array([[-2147483648, 2147483647]], Numeric.Int32); alimit_int16 = Numeric.array([[-32768, 32767, -32769, 32768]], Numeric.Int16); @@ -270,3 +274,8 @@ testsetget("xxx", [1,2,3]) testlocalscope(5) + +# Try converting Numeric arrays of objects and characters + +testexpect(arr1o,arr1o[0].tolist()) +testexpect(arr1ch,arr1ch.tostring())