1from libc.stdlib cimport malloc, free
2from cpython.object cimport Py_EQ, Py_NE
3
4def double_ptr_slice(x, L, int a, int b):
5    """
6    >>> L = list(range(10))
7    >>> double_ptr_slice(5, L, 0, 10)
8    >>> double_ptr_slice(6, L, 0, 10)
9    >>> double_ptr_slice(None, L, 0, 10)
10    >>> double_ptr_slice(0, L, 3, 7)
11    >>> double_ptr_slice(5, L, 3, 7)
12    >>> double_ptr_slice(9, L, 3, 7)
13
14    >>> double_ptr_slice(EqualsEvens(), L, 0, 10)
15    >>> double_ptr_slice(EqualsEvens(), L, 1, 10)
16    """
17    cdef double *L_c = NULL
18    try:
19        L_c = <double*>malloc(len(L) * sizeof(double))
20        for i, a in enumerate(L):
21            L_c[i] = L[i]
22        assert (x in L_c[:b]) == (x in L[:b])
23        assert (x not in L_c[:b]) == (x not in L[:b])
24        assert (x in L_c[a:b]) == (x in L[a:b])
25        assert (x not in L_c[a:b]) == (x not in L[a:b])
26        assert (x in L_c[a:b:2]) == (x in L[a:b:2])
27        assert (x not in L_c[a:b:2]) == (x not in L[a:b:2])
28    finally:
29        free(L_c)
30
31def void_ptr_slice(py_x, L, int a, int b):
32    """
33    >>> L = list(range(10))
34    >>> void_ptr_slice(5, L, 0, 10)
35    >>> void_ptr_slice(6, L, 0, 10)
36    >>> void_ptr_slice(None, L, 0, 10)
37    >>> void_ptr_slice(0, L, 3, 7)
38    >>> void_ptr_slice(5, L, 3, 7)
39    >>> void_ptr_slice(9, L, 3, 7)
40    """
41    # I'm using the fact that small Python ints are cached.
42    cdef void **L_c = NULL
43    cdef void *x = <void*>py_x
44    try:
45        L_c = <void**>malloc(len(L) * sizeof(void*))
46        for i, a in enumerate(L):
47            L_c[i] = <void*>L[i]
48        assert (x in L_c[:b]) == (py_x in L[:b])
49        assert (x not in L_c[:b]) == (py_x not in L[:b])
50        assert (x in L_c[a:b]) == (py_x in L[a:b])
51        assert (x not in L_c[a:b]) == (py_x not in L[a:b])
52        assert (x in L_c[a:b:2]) == (py_x in L[a:b:2])
53        assert (x not in L_c[a:b:2]) == (py_x not in L[a:b:2])
54    finally:
55        free(L_c)
56
57cdef class EqualsEvens:
58    """
59    >>> e = EqualsEvens()
60    >>> e == 2
61    True
62    >>> e == 5
63    False
64    >>> [e == k for k in range(4)]
65    [True, False, True, False]
66    """
67    def __richcmp__(self, other, int op):
68        if op == Py_EQ:
69            return other % 2 == 0
70        elif op == Py_NE:
71            return other % 2 == 1
72        else:
73            return False
74