aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Includes/cpython/array.pxd
blob: f5865c65e3b71367a62385f7245120569c7b20a1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
""" 
  array.pxd 

  Cython interface to Python's array.array module. 

  * 1D contiguous data view 
  * tools for fast array creation, maximum C-speed and handiness 
  * suitable as allround light weight auto-array within Cython code too 

  Usage: 

  >>> cimport array 
 
  Usage through Cython buffer interface (Py2.3+):

    >>> def f(arg1, unsigned i, double dx) 
    ...     array.array[double] a = arg1 
    ...     a[i] += dx 

  Fast C-level new_array(_zeros), resize_array, copy_array, Py_SIZE(obj), 
  zero_array 

    cdef array.array[double] k = array.copy(d)
    cdef array.array[double] n = array.array(d, Py_SIZE(d) * 2 ) 
    cdef array.array[double] m = array.zeros_like(FLOAT_TEMPLATE) 
    array.resize(f, 200000) 

  Zero overhead with naked data pointer views by union:
  _f, _d, _i, _c, _u, ...
  => Original C array speed + Python dynamic memory management 
 
    cdef array.array a = inarray 
    if
    a._d[2] += 0.66   # use as double array without extra casting 

    float *subview = vector._f + 10  # starting from 10th element 
    unsigned char *subview_buffer = vector._B + 4

  Suitable as lightweight arrays intra Cython without speed penalty.
  Replacement for C stack/malloc arrays; no trouble with refcounting,
  mem.leaks; seamless Python compatibility, buffer() optional 
 

  last changes: 2009-05-15 rk 
              : 2009-12-06 bp 
              : 2012-05-02 andreasvc 
              : (see revision control) 
""" 
from libc.string cimport strcat, strncat, \ 
    memset, memchr, memcmp, memcpy, memmove 
 
from cpython.object cimport Py_SIZE 
from cpython.ref cimport PyTypeObject, Py_TYPE 
from cpython.exc cimport PyErr_BadArgument 
from cpython.mem cimport PyObject_Malloc, PyObject_Free
 
cdef extern from *:  # Hard-coded utility code hack. 
    ctypedef class array.array [object arrayobject] 
    ctypedef object GETF(array a, Py_ssize_t ix) 
    ctypedef object SETF(array a, Py_ssize_t ix, object o) 
    ctypedef struct arraydescr:  # [object arraydescr]: 
            char typecode
            int itemsize 
            GETF getitem    # PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); 
            SETF setitem    # int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); 
 
    ctypedef union __data_union: 
        # views of ob_item: 
        float* as_floats        # direct float pointer access to buffer 
        double* as_doubles      # double ... 
        int*    as_ints 
        unsigned int *as_uints 
        unsigned char *as_uchars 
        signed char *as_schars 
        char *as_chars 
        unsigned long *as_ulongs 
        long *as_longs 
        unsigned long long *as_ulonglongs
        long long *as_longlongs
        short *as_shorts 
        unsigned short *as_ushorts 
        Py_UNICODE *as_pyunicodes 
        void *as_voidptr 
 
    ctypedef class array.array [object arrayobject]: 
        cdef __cythonbufferdefaults__ = {'ndim' : 1, 'mode':'c'} 
 
        cdef: 
            Py_ssize_t ob_size 
            arraydescr* ob_descr    # struct arraydescr *ob_descr; 
            __data_union data 
 
        def __getbuffer__(self, Py_buffer* info, int flags): 
            # This implementation of getbuffer is geared towards Cython 
            # requirements, and does not yet fulfill the PEP.
            # In particular strided access is always provided regardless 
            # of flags 
            item_count = Py_SIZE(self) 
 
            info.suboffsets = NULL 
            info.buf = self.data.as_chars 
            info.readonly = 0 
            info.ndim = 1 
            info.itemsize = self.ob_descr.itemsize   # e.g. sizeof(float) 
            info.len = info.itemsize * item_count 
 
            info.shape = <Py_ssize_t*> PyObject_Malloc(sizeof(Py_ssize_t) + 2)
            if not info.shape: 
                raise MemoryError() 
            info.shape[0] = item_count      # constant regardless of resizing 
            info.strides = &info.itemsize 
 
            info.format = <char*> (info.shape + 1) 
            info.format[0] = self.ob_descr.typecode 
            info.format[1] = 0 
            info.obj = self 
 
        def __releasebuffer__(self, Py_buffer* info): 
            PyObject_Free(info.shape)
 
    array newarrayobject(PyTypeObject* type, Py_ssize_t size, arraydescr *descr) 
 
    # fast resize/realloc 
    # not suitable for small increments; reallocation 'to the point' 
    int resize(array self, Py_ssize_t n) except -1 
    # efficient for small increments (not in Py2.3-) 
    int resize_smart(array self, Py_ssize_t n) except -1 
 
 
cdef inline array clone(array template, Py_ssize_t length, bint zero): 
    """ fast creation of a new array, given a template array. 
    type will be same as template. 
    if zero is true, new array will be initialized with zeroes.""" 
    cdef array op = newarrayobject(Py_TYPE(template), length, template.ob_descr)
    if zero and op is not None: 
        memset(op.data.as_chars, 0, length * op.ob_descr.itemsize) 
    return op 
 
cdef inline array copy(array self): 
    """ make a copy of an array. """ 
    cdef array op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)
    memcpy(op.data.as_chars, self.data.as_chars, Py_SIZE(op) * op.ob_descr.itemsize) 
    return op 
 
cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n) except -1: 
    """ efficient appending of new stuff of same type
    (e.g. of same array type) 
    n: number of elements (not number of bytes!) """ 
    cdef Py_ssize_t itemsize = self.ob_descr.itemsize 
    cdef Py_ssize_t origsize = Py_SIZE(self) 
    resize_smart(self, origsize + n) 
    memcpy(self.data.as_chars + origsize * itemsize, stuff, n * itemsize) 
    return 0 
 
cdef inline int extend(array self, array other) except -1: 
    """ extend array with data from another array; types must match. """ 
    if self.ob_descr.typecode != other.ob_descr.typecode: 
        PyErr_BadArgument() 
    return extend_buffer(self, other.data.as_chars, Py_SIZE(other)) 
 
cdef inline void zero(array self): 
    """ set all elements of array to zero. """ 
    memset(self.data.as_chars, 0, Py_SIZE(self) * self.ob_descr.itemsize)