Mercurial > pytave
changeset 143:fe783134c61c
Fix conversion of integer types by using strictly sized integers
* octave_to_python.cc (pytave::octvalue_to_pyarrobj): Convert Octave sized
integer types into the corresponding NumPy sized integer types.
(pytave::create_array, pytave::create_sint_array, pytave::create_uint_array):
Delete unnecessary conversion heuristics.
* python_to_octave.cc (pytave::copy_pyarrobj_to_octarray_boot): Convert NumPy
sized integer types into the corresponding Octave sized integer types. Add
special cases to convert ambiguous NPY_LONG, NPY_LONGLONG, NPY_ULONG, and
NPY_ULONGLONG types.
(pytave::pyarr_to_octvalue): Add missing cases for NPY_ULONG and NPY_ULONGLONG.
author | Mike Miller <mtmiller@octave.org> |
---|---|
date | Mon, 04 Apr 2016 22:51:54 -0700 |
parents | dc2876fdbfaf |
children | ad964e46cd48 |
files | octave_to_python.cc python_to_octave.cc |
diffstat | 2 files changed, 93 insertions(+), 137 deletions(-) [+] |
line wrap: on
line diff
--- a/octave_to_python.cc Mon Apr 04 17:54:22 2016 -0700 +++ b/octave_to_python.cc Mon Apr 04 22:51:54 2016 -0700 @@ -26,7 +26,6 @@ #endif #include <boost/python.hpp> -#include <boost/type_traits/integral_constant.hpp> #include <octave/oct.h> #include <octave/ov.h> @@ -37,14 +36,6 @@ #include "exceptions.h" #include "octave_to_python.h" -/* From docs: - * Note that the names of the element type constants refer to the C data - * 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. NPY_INT ). - */ - using namespace boost::python; namespace pytave { @@ -134,69 +125,6 @@ return pyarr; } - template <class PythonPrimitive, class OctaveBase> - static PyArrayObject *create_array(const OctaveBase &octarr, - int pyarraytype, boost::true_type) { - return create_array<PythonPrimitive, OctaveBase> (octarr, pyarraytype); - } - - template <class PythonPrimitive, class OctaveBase> - static PyArrayObject *create_array(const OctaveBase &octarr, - int pyarraytype, boost::false_type) { - assert(0); - return 0; - } - - 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; - 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, 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, NPY_USHORT, inst); - } else { - std::ostringstream os; - os << "NumPy arrays do not support unsigned " << (bytes*8) - << "-bit values on this architecture."; - throw value_convert_exception(os.str()); - } - } - - template <class CLASS, size_t bytes> - inline static PyArrayObject *create_sint_array(CLASS value) { - 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, NPY_INT, inst); - } - else if (bytes == sizeof(long long)) { - boost::integral_constant<bool, bytes == sizeof(long long) && bytes != sizeof(int)> 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, NPY_LONG, inst); - } else if (bytes == sizeof(char)) { - boost::integral_constant<bool, bytes == sizeof(char)> 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, NPY_SHORT, inst); - } else { - std::ostringstream os; - os << "NumPy arrays do not support signed " << (bytes*8) - << "-bit values on this architecture."; - throw value_convert_exception(os.str()); - } - } - static PyArrayObject *octvalue_to_pyarrobj(const octave_value &matrix) { if (matrix.is_double_type ()) { if (matrix.is_complex_type ()) { @@ -220,34 +148,40 @@ throw value_convert_exception("Unknown float matrix type"); } - if (matrix.is_int64_type()) { - return create_sint_array<int64NDArray, sizeof(int64_t)>( - matrix.int64_array_value()); + if (matrix.is_int8_type()) { + return create_array<int8_t, int8NDArray>( + matrix.int8_array_value(), NPY_INT8); } - if (matrix.is_uint32_type()) { - return create_uint_array<uint32NDArray, sizeof(uint32_t)>( - matrix.uint32_array_value()); + if (matrix.is_int16_type()) { + return create_array<int16_t, int16NDArray>( + matrix.int16_array_value(), NPY_INT16); } if (matrix.is_int32_type()) { - return create_sint_array<int32NDArray, sizeof(int32_t)>( - matrix.int32_array_value()); + return create_array<int32_t, int32NDArray>( + matrix.int32_array_value(), NPY_INT32); + } + if (matrix.is_int64_type()) { + return create_array<int64_t, int64NDArray>( + matrix.int64_array_value(), NPY_INT64); + } + + if (matrix.is_uint8_type()) { + return create_array<uint8_t, uint8NDArray>( + matrix.uint8_array_value(), NPY_UINT8); } if (matrix.is_uint16_type()) { - return create_uint_array<uint16NDArray, sizeof(uint16_t)>( - matrix.uint16_array_value()); - } - if (matrix.is_int16_type()) { - return create_sint_array<int16NDArray, sizeof(int16_t)>( - matrix.int16_array_value()); + return create_array<uint16_t, uint16NDArray>( + matrix.uint16_array_value(), NPY_UINT16); } - if (matrix.is_uint8_type()) { - return create_uint_array<uint8NDArray, sizeof(uint8_t)>( - matrix.uint8_array_value()); + if (matrix.is_uint32_type()) { + return create_array<uint32_t, uint32NDArray>( + matrix.uint32_array_value(), NPY_UINT32); } - if (matrix.is_int8_type()) { - return create_sint_array<int8NDArray, sizeof(int8_t)>( - matrix.int8_array_value()); + if (matrix.is_uint64_type()) { + return create_array<uint64_t, uint64NDArray>( + matrix.uint64_array_value(), NPY_UINT64); } + if (matrix.is_bool_type()) { return create_array<bool, boolNDArray>( matrix.bool_array_value(), NPY_BOOL);
--- a/python_to_octave.cc Mon Apr 04 17:54:22 2016 -0700 +++ b/python_to_octave.cc Mon Apr 04 22:51:54 2016 -0700 @@ -148,44 +148,60 @@ (matrix, pyarr); \ break; \ - // Prefer int to other types of the same size. - // E.g. on 32-bit x86 architectures: sizeof(long) == sizeof(int). + // Coerce NumPy's long type into one of two possible sized integer types int type_num = PyArray_TYPE (pyarr); switch (type_num) { case NPY_LONG: - if (sizeof(long) == sizeof(int)) { - type_num = NPY_INT; + if (sizeof(npy_long) == sizeof(int64_t)) { + type_num = NPY_INT64; + } + else if (sizeof(npy_long) == sizeof(int32_t)) { + type_num = NPY_INT32; + } + break; + case NPY_LONGLONG: + if (sizeof(npy_longlong) == sizeof(int64_t)) { + type_num = NPY_INT64; + } + else if (sizeof(npy_longlong) == sizeof(int32_t)) { + type_num = NPY_INT32; } break; - case NPY_SHORT: - if (sizeof(short) == sizeof(int)) { - type_num = NPY_INT; + case NPY_ULONG: + if (sizeof(npy_ulong) == sizeof(uint64_t)) { + type_num = NPY_UINT64; + } + else if (sizeof(npy_ulong) == sizeof(uint32_t)) { + type_num = NPY_UINT32; } break; - case NPY_USHORT: - if (sizeof(unsigned short) == sizeof(unsigned int)) { - type_num = NPY_UINT; + case NPY_ULONGLONG: + if (sizeof(npy_ulonglong) == sizeof(uint64_t)) { + type_num = NPY_UINT64; + } + else if (sizeof(npy_ulonglong) == sizeof(uint32_t)) { + type_num = NPY_UINT32; } break; } switch (type_num) { - 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 *) + ARRAYCASE(NPY_INT8, int8_t) + ARRAYCASE(NPY_INT16, int16_t) + ARRAYCASE(NPY_INT32, int32_t) + ARRAYCASE(NPY_INT64, int64_t) + ARRAYCASE(NPY_UINT8, uint8_t) + ARRAYCASE(NPY_UINT16, uint16_t) + ARRAYCASE(NPY_UINT32, uint32_t) + ARRAYCASE(NPY_UINT64, uint64_t) + ARRAYCASE(NPY_FLOAT, float) + ARRAYCASE(NPY_DOUBLE, double) + ARRAYCASE(NPY_CFLOAT, FloatComplex) + ARRAYCASE(NPY_CDOUBLE, Complex) + ARRAYCASE(NPY_BOOL, bool) + ARRAYCASE(NPY_CHAR, char) + ARRAYCASE(NPY_STRING, char) + ARRAYCASE(NPY_OBJECT, PyObject *) default: throw object_convert_exception( @@ -224,22 +240,6 @@ } 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; - case 2: - pyarrobj_to_octvalueNd<uint16NDArray>(octvalue, pyarr, dims); - break; - case 4: - pyarrobj_to_octvalueNd<uint32NDArray>(octvalue, pyarr, dims); - break; - default: - throw object_convert_exception("Unknown unsigned integer."); - } case NPY_BYTE: case NPY_SHORT: case NPY_INT: @@ -262,6 +262,28 @@ throw object_convert_exception("Unknown integer."); } break; + case NPY_UBYTE: + case NPY_USHORT: + case NPY_UINT: + case NPY_ULONG: + case NPY_ULONGLONG: + switch (PyArray_ITEMSIZE (pyarr)) { + case 1: + pyarrobj_to_octvalueNd<uint8NDArray>(octvalue, pyarr, dims); + break; + case 2: + pyarrobj_to_octvalueNd<uint16NDArray>(octvalue, pyarr, dims); + break; + case 4: + pyarrobj_to_octvalueNd<uint32NDArray>(octvalue, pyarr, dims); + break; + case 8: + pyarrobj_to_octvalueNd<uint64NDArray>(octvalue, pyarr, dims); + break; + default: + throw object_convert_exception("Unknown unsigned integer."); + } + break; case NPY_FLOAT: pyarrobj_to_octvalueNd<FloatNDArray>(octvalue, pyarr, dims); break; @@ -274,15 +296,15 @@ case NPY_CDOUBLE: pyarrobj_to_octvalueNd<ComplexNDArray>(octvalue, pyarr, dims); break; + case NPY_BOOL: + pyarrobj_to_octvalueNd<boolNDArray>(octvalue, pyarr, dims); + break; 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 NPY_BOOL: - pyarrobj_to_octvalueNd<boolNDArray>(octvalue, pyarr, dims); - break; case NPY_STRING: { if (PyArray_ITEMSIZE (pyarr) == 1)