optimise list/tuple slicing, original patch by Zaur Shibzukhov
authorStefan Behnel <stefan_ml@behnel.de>
Sun, 10 Mar 2013 14:57:33 +0000 (15:57 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sun, 10 Mar 2013 14:57:33 +0000 (15:57 +0100)
Cython/Compiler/ExprNodes.py
Cython/Utility/ObjectHandling.c
tests/run/typed_slice.pyx

index f5c8beb..7579d19 100755 (executable)
@@ -3654,9 +3654,20 @@ class SliceIndexNode(ExprNode):
                     stop_code,
                     code.error_goto_if_null(result, self.pos)))
         else:
+            if self.base.type is list_type:
+                code.globalstate.use_utility_code(
+                    UtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c"))
+                cfunc = '__Pyx_PyList_GetSlice'
+            elif self.base.type is tuple_type:
+                code.globalstate.use_utility_code(
+                    UtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c"))
+                cfunc = '__Pyx_PyTuple_GetSlice'
+            else:
+                cfunc = '__Pyx_PySequence_GetSlice'
             code.putln(
-                "%s = __Pyx_PySequence_GetSlice(%s, %s, %s); %s" % (
+                "%s = %s(%s, %s, %s); %s" % (
                     result,
+                    cfunc,
                     self.base.py_result(),
                     start_code,
                     stop_code,
index 151d60d..02a0c64 100644 (file)
@@ -397,6 +397,88 @@ static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i,
     return __Pyx_DelItem_Generic(o, PyInt_FromSsize_t(i));
 }
 
+
+/////////////// SliceTupleAndList.proto ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop);
+static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop);
+#else
+#define __Pyx_PyList_GetSlice(seq, start, stop)   PySequence_GetSlice(seq, start, stop)
+#define __Pyx_PyTuple_GetSlice(seq, start, stop)  PySequence_GetSlice(seq, start, stop)
+#endif
+
+/////////////// SliceTupleAndList ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE void __Pyx_crop_slice(Py_ssize_t* _start, Py_ssize_t* _stop, Py_ssize_t* _length) {
+    Py_ssize_t start = *_start, stop = *_stop, length = *_length;
+    if (start < 0) {
+        start += length;
+        if (start < 0)
+            start = 0;
+    }
+
+    if (stop < 0)
+        stop += length;
+    else if (stop > length)
+        stop = length;
+
+    *_length = stop - start;
+    *_start = start;
+    *_stop = stop;
+}
+
+#if __STDC_VERSION__ >= 199901L
+static CYTHON_INLINE void Pyx_copy_object_array(PyObject** restrict src, PyObject** restrict dest, Py_ssize_t length) {
+#else
+static CYTHON_INLINE void Pyx_copy_object_array(PyObject** src, PyObject** dest, Py_ssize_t length) {
+#endif
+    PyObject *v;
+    Py_ssize_t i;
+    for (i = 0; i < length; i++) {
+        v = dest[i] = src[i];
+        Py_INCREF(v);
+    }
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice(
+            PyObject* src, Py_ssize_t start, Py_ssize_t stop) {
+    PyObject* dest;
+    Py_ssize_t length = PyList_GET_SIZE(src);
+    __Pyx_crop_slice(&start, &stop, &length);
+    if (unlikely(length <= 0))
+        return PyList_New(0);
+
+    dest = PyList_New(length);
+    if (unlikely(!dest))
+        return NULL;
+    Pyx_copy_object_array(
+        ((PyListObject*)src)->ob_item + start,
+        ((PyListObject*)dest)->ob_item,
+        length);
+    return dest;
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice(
+                PyObject* src, Py_ssize_t start, Py_ssize_t stop) {
+    PyObject* dest;
+    Py_ssize_t length = PyTuple_GET_SIZE(src);
+    __Pyx_crop_slice(&start, &stop, &length);
+    if (unlikely(length <= 0))
+        return PyTuple_New(0);
+
+    dest = PyTuple_New(length);
+    if (unlikely(!dest))
+        return NULL;
+    Pyx_copy_object_array(
+        ((PyTupleObject*)src)->ob_item + start,
+        ((PyTupleObject*)dest)->ob_item,
+        length);
+    return dest;
+}
+#endif
+
 /////////////// FindPy2Metaclass.proto ///////////////
 
 static PyObject *__Pyx_FindPy2Metaclass(PyObject *bases); /*proto*/
index 8e63eb1..cd911a5 100644 (file)
-def slice_list(list l):
+# mode: run
+# tag: list, tuple, slice
+
+def slice_list(list l, int start, int stop):
     """
-    >>> slice_list([1,2,3,4])
+    >>> slice_list([1,2,3,4], 1, 3)
+    [2, 3]
+    >>> slice_list([1,2,3,4], 1, 7)
+    [2, 3, 4]
+    >>> slice_list([], 1, 3)
+    []
+    >>> slice_list([1], 1, 3)
+    []
+    >>> slice_list([1,2,3,4], -3, -1)
     [2, 3]
+    >>> slice_list([1,2,3,4], -10, -1)
+    [1, 2, 3]
+    >>> slice_list([], -3, -1)
+    []
+    >>> slice_list([1], -3, -1)
+    []
+    """
+    return l[start:stop]
+
+def slice_list_start(list l, int start):
     """
-    return l[1:3]
+    >>> slice_list_start([1,2,3,4], 1)
+    [2, 3, 4]
+    >>> slice_list_start([], 1)
+    []
+    >>> slice_list_start([1], 1)
+    []
+    >>> slice_list_start([1], 2)
+    []
+    >>> slice_list_start([1,2,3,4], -3)
+    [2, 3, 4]
+    >>> slice_list_start([1,2,3,4], -10)
+    [1, 2, 3, 4]
+    >>> slice_list_start([], -3)
+    []
+    >>> slice_list_start([1], -3)
+    [1]
+    """
+    return l[start:]
+
+
+def slice_list_stop(list l, int stop):
+    """
+    >>> slice_list_stop([1,2,3,4], 3)
+    [1, 2, 3]
+    >>> slice_list_stop([1,2,3,4], 7)
+    [1, 2, 3, 4]
+    >>> slice_list_stop([], 3)
+    []
+    >>> slice_list_stop([1], 3)
+    [1]
+    >>> slice_list_stop([1,2,3,4], -3)
+    [1]
+    >>> slice_list_stop([1,2,3,4], -10)
+    []
+    >>> slice_list_stop([], -1)
+    []
+    >>> slice_list_stop([1], -1)
+    []
+    >>> slice_list_stop([1, 2], -3)
+    []
+    """
+    return l[:stop]
+
 
 def slice_list_copy(list l):
-    cdef list retlist = l[1:3]
-    return retlist
+    """
+    >>> slice_list_copy([])
+    []
+    >>> slice_list_copy([1,2,3])
+    [1, 2, 3]
+    """
+    return l[:]
 
-def slice_tuple(tuple t):
+
+def slice_tuple_copy(tuple l):
     """
-    >>> l = [1,2,3,4]
-    >>> slice_tuple(tuple(l))
+    >>> slice_tuple_copy(())
+    ()
+    >>> slice_tuple_copy((1,2,3))
+    (1, 2, 3)
+    """
+    return l[:]
+
+
+def slice_tuple(tuple t, int start, int stop):
+    """
+    >>> slice_tuple((1,2,3,4), 1, 3)
+    (2, 3)
+    >>> slice_tuple((1,2,3,4), 1, 7)
+    (2, 3, 4)
+    >>> slice_tuple((), 1, 3)
+    ()
+    >>> slice_tuple((1,), 1, 3)
+    ()
+    >>> slice_tuple((1,2,3,4), -3, -1)
     (2, 3)
+    >>> slice_tuple((1,2,3,4), -10, -1)
+    (1, 2, 3)
+    >>> slice_tuple((), -3, -1)
+    ()
+    >>> slice_tuple((1,), -3, -1)
+    ()
+    """
+    return t[start:stop]
+
+
+def slice_tuple_start(tuple t, int start):
+    """
+    >>> slice_tuple_start((1,2,3,4), 1)
+    (2, 3, 4)
+    >>> slice_tuple_start((), 1)
+    ()
+    >>> slice_tuple_start((1,), 1)
+    ()
+    >>> slice_tuple_start((1,2,3,4), -3)
+    (2, 3, 4)
+    >>> slice_tuple_start((1,2,3,4), -10)
+    (1, 2, 3, 4)
+    >>> slice_tuple_start((), -3)
+    ()
+    >>> slice_tuple_start((1,), -3)
+    (1,)
     """
-    return t[1:3]
+    return t[start:]
+
+def slice_tuple_stop(tuple t, int stop):
+    """
+    >>> slice_tuple_stop((1,2,3,4), 3)
+    (1, 2, 3)
+    >>> slice_tuple_stop((1,2,3,4), 7)
+    (1, 2, 3, 4)
+    >>> slice_tuple_stop((), 3)
+    ()
+    >>> slice_tuple_stop((1,), 3)
+    (1,)
+    >>> slice_tuple_stop((1,2,3,4), -1)
+    (1, 2, 3)
+    >>> slice_tuple_stop((), -1)
+    ()
+    """
+    return t[:stop]
+
 
 def slice_list_assign_list(list l):
     """
@@ -27,6 +157,7 @@ def slice_list_assign_list(list l):
     l[1:3] = [1,2,3,4]
     return l
 
+
 def slice_list_assign_tuple(list l):
     """
     >>> l = [1,2,3,4]
@@ -37,6 +168,7 @@ def slice_list_assign_tuple(list l):
     l[1:3] = (1,2,3,4)
     return l
 
+
 def slice_list_assign(list l, value):
     """
     >>> l = [1,2,3,4]
@@ -60,6 +192,7 @@ def slice_charp(py_string_arg):
     cdef char* s = py_string
     return s[1:3].decode(u'ASCII')
 
+
 def slice_charp_repeat(py_string_arg):
     """
     >>> print("%s" % slice_charp_repeat('abcdefg'))