changeset 304:a133564f4af7

Convert integer types to appropriate Python int or long types (fixes issue #55) * octave_to_python.cc (pytave::python_integer_value): New functions to construct appropriate Python int or long types based on integer size and Python version. (pytave::octscalar_to_pyobject): Use them. * pycall.cc: Add %!tests for conversion of integer types into Python.
author Mike Miller <mtmiller@octave.org>
date Mon, 08 Aug 2016 16:17:21 -0700
parents 0d94e42bacf6
children 616ec5f18d95
files octave_to_python.cc pycall.cc
diffstat 2 files changed, 66 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/octave_to_python.cc	Tue Aug 02 13:53:12 2016 -0700
+++ b/octave_to_python.cc	Mon Aug 08 16:17:21 2016 -0700
@@ -229,6 +229,42 @@
       }
   }
 
+  inline PyObject *
+  python_integer_value (int32_t value)
+  {
+#if PY_VERSION_HEX >= 0x03000000
+    return PyLong_FromLong (value);
+#else
+    return PyInt_FromLong (value);
+#endif
+  }
+
+  inline PyObject *
+  python_integer_value (uint32_t value)
+  {
+    return PyLong_FromUnsignedLong (value);
+  }
+
+  inline PyObject *
+  python_integer_value (int64_t value)
+  {
+#if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG > SIZEOF_LONG))
+    return PyLong_FromLongLong (value);
+#else
+    return PyLong_FromLong (value);
+#endif
+  }
+
+  inline PyObject *
+  python_integer_value (uint64_t value)
+  {
+#if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG > SIZEOF_LONG))
+    return PyLong_FromUnsignedLongLong (value);
+#else
+    return PyLong_FromUnsignedLong (value);
+#endif
+  }
+
   static void
   octscalar_to_pyobject (boost::python::object& py_object,
                          const octave_value& arg)
@@ -242,22 +278,22 @@
       obj = PyFloat_FromDouble (arg.double_value ());
 
     else if (arg.is_int8_type ())
-      obj = PyLong_FromLong (arg.int8_scalar_value ().value ());
+      obj = python_integer_value (arg.int8_scalar_value ().value ());
     else if (arg.is_int16_type ())
-      obj = PyLong_FromLong (arg.int16_scalar_value ().value ());
+      obj = python_integer_value (arg.int16_scalar_value ().value ());
     else if (arg.is_int32_type ())
-      obj = PyLong_FromLong (arg.int32_scalar_value ().value ());
+      obj = python_integer_value (arg.int32_scalar_value ().value ());
     else if (arg.is_int64_type ())
-      obj = PyLong_FromLong (arg.int64_scalar_value ().value ());
+      obj = python_integer_value (arg.int64_scalar_value ().value ());
 
     else if (arg.is_uint8_type ())
-      obj = PyLong_FromUnsignedLong (arg.uint8_scalar_value ().value ());
+      obj = python_integer_value (arg.uint8_scalar_value ().value ());
     else if (arg.is_uint16_type ())
-      obj = PyLong_FromUnsignedLong (arg.uint16_scalar_value ().value ());
+      obj = python_integer_value (arg.uint16_scalar_value ().value ());
     else if (arg.is_uint32_type ())
-      obj = PyLong_FromUnsignedLong (arg.uint32_scalar_value ().value ());
+      obj = python_integer_value (arg.uint32_scalar_value ().value ());
     else if (arg.is_uint64_type ())
-      obj = PyLong_FromUnsignedLong (arg.uint64_scalar_value ().value ());
+      obj = python_integer_value (arg.uint64_scalar_value ().value ());
 
     else if (arg.is_bool_type ())
       obj = PyBool_FromLong (arg.bool_value ());
--- a/pycall.cc	Tue Aug 02 13:53:12 2016 -0700
+++ b/pycall.cc	Mon Aug 08 16:17:21 2016 -0700
@@ -278,6 +278,28 @@
 %!   assert (pycall ("roundtrip", values{i}), values{i});
 %! endfor
 
+## Test conversion of integer types into Python
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==        0"), int8 (0)))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x == -2**7   "), intmin ("int8")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==  2**7 -1"), intmax ("int8")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==        0"), intmin ("uint8")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==  2**8 -1"), intmax ("uint8")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==        0"), int16 (0)))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x == -2**15  "), intmin ("int16")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==  2**15-1"), intmax ("int16")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==        0"), intmin ("uint16")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==  2**16-1"), intmax ("uint16")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==        0"), int32 (0)))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x == -2**31  "), intmin ("int32")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(0) and x ==  2**31-1"), intmax ("int32")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(2**64) and x ==        0"), intmin ("uint32")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(2**64) and x ==  2**32-1"), intmax ("uint32")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(2**64) and x ==        0"), int64 (0)))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(2**64) and x == -2**63  "), intmin ("int64")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(2**64) and x ==  2**63-1"), intmax ("int64")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(2**64) and x ==        0"), intmin ("uint64")))
+%!assert (pycall (pyeval ("lambda x: type(x) == type(2**64) and x ==  2**64-1"), intmax ("uint64")))
+
 %!error <argument type conversion>
 %! pyexec ("def intwrapper(x): return int(x)");
 %! pycall ("intwrapper", ftp ());