speed up unpacking of small integers in Py3
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 9 Mar 2013 15:26:35 +0000 (16:26 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 9 Mar 2013 15:26:35 +0000 (16:26 +0100)
Cython/Compiler/PyrexTypes.py

index 52bf076..dddcd79 100755 (executable)
@@ -1385,6 +1385,9 @@ proto="""
 static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *);
 """,
 impl="""
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#include "longintrepr.h"
+#endif
 static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
     const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
@@ -1406,8 +1409,33 @@ static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x
                                 "can't convert negative value to %(type)s");
                 return (%(type)s)-1;
             }
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+            switch (Py_SIZE(x)) {
+                case  0: return 0;
+                case  1: {
+                    digit d = ((PyLongObject*)x)->ob_digit[0];
+                    if (sizeof(digit) < sizeof(%(type)s) || likely(d == (digit)(%(type)s)d))
+                        return (%(type)s)d;
+                }
+            }
+#endif
             return (%(type)s)PyLong_AsUnsigned%(TypeName)s(x);
         } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+            switch (Py_SIZE(x)) {
+                case  0: return 0;
+                case  1: {
+                    digit d = ((PyLongObject*)x)->ob_digit[0];
+                    if (sizeof(digit) < sizeof(%(type)s) || likely((((%(type)s)d) > 0) && (d == (digit)(%(type)s)d)))
+                        return (%(type)s)d;
+                }
+                case -1: {
+                    digit d = ((PyLongObject*)x)->ob_digit[0];
+                    if (sizeof(digit) < sizeof(%(type)s) || likely((((%(type)s)d) > 0) && (d == (digit)(%(type)s)d)))
+                        return -(%(type)s)d;
+                }
+            }
+#endif
             return (%(type)s)PyLong_As%(TypeName)s(x);
         }
     } else {