cython

Форк
0
174 строки · 6.2 Кб
1
"""
2
  array.pxd
3

4
  Cython interface to Python's array.array module.
5

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

10
  Usage:
11

12
  >>> cimport array
13

14
  Usage through Cython buffer interface (Py2.3+):
15

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

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

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

28
  Zero overhead with naked data pointer views by union:
29
  _f, _d, _i, _c, _u, ...
30
  => Original C array speed + Python dynamic memory management
31

32
    cdef array.array a = inarray
33
    if
34
    a._d[2] += 0.66   # use as double array without extra casting
35

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

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

43

44
  last changes: 2009-05-15 rk
45
              : 2009-12-06 bp
46
              : 2012-05-02 andreasvc
47
              : (see revision control)
48
"""
49

50
cdef extern from *:
51
    """
52
    #if CYTHON_COMPILING_IN_PYPY
53
    #ifdef _MSC_VER
54
    #pragma message ("This module uses CPython specific internals of 'array.array', which are not available in PyPy.")
55
    #else
56
    #warning This module uses CPython specific internals of 'array.array', which are not available in PyPy.
57
    #endif
58
    #endif
59
    """
60

61
from libc.string cimport memset, memcpy
62

63
from cpython.object cimport Py_SIZE
64
from cpython.ref cimport PyTypeObject, Py_TYPE
65
from cpython.exc cimport PyErr_BadArgument
66
from cpython.mem cimport PyObject_Malloc, PyObject_Free
67

68
cdef extern from *:  # Hard-coded utility code hack.
69
    ctypedef class array.array [object arrayobject]
70
    ctypedef object GETF(array a, Py_ssize_t ix)
71
    ctypedef object SETF(array a, Py_ssize_t ix, object o)
72
    ctypedef struct arraydescr:  # [object arraydescr]:
73
            char typecode
74
            int itemsize
75
            GETF getitem    # PyObject * (*getitem)(struct arrayobject *, Py_ssize_t);
76
            SETF setitem    # int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
77

78
    ctypedef union __data_union:
79
        # views of ob_item:
80
        float* as_floats        # direct float pointer access to buffer
81
        double* as_doubles      # double ...
82
        int*    as_ints
83
        unsigned int *as_uints
84
        unsigned char *as_uchars
85
        signed char *as_schars
86
        char *as_chars
87
        unsigned long *as_ulongs
88
        long *as_longs
89
        unsigned long long *as_ulonglongs
90
        long long *as_longlongs
91
        short *as_shorts
92
        unsigned short *as_ushorts
93
        Py_UNICODE *as_pyunicodes
94
        void *as_voidptr
95

96
    ctypedef class array.array [object arrayobject]:
97
        cdef __cythonbufferdefaults__ = {'ndim' : 1, 'mode':'c'}
98

99
        cdef:
100
            Py_ssize_t ob_size
101
            arraydescr* ob_descr    # struct arraydescr *ob_descr;
102
            __data_union data
103

104
        def __getbuffer__(self, Py_buffer* info, int flags):
105
            # This implementation of getbuffer is geared towards Cython
106
            # requirements, and does not yet fulfill the PEP.
107
            # In particular strided access is always provided regardless
108
            # of flags
109
            item_count = Py_SIZE(self)
110

111
            info.suboffsets = NULL
112
            info.buf = self.data.as_chars
113
            info.readonly = 0
114
            info.ndim = 1
115
            info.itemsize = self.ob_descr.itemsize   # e.g. sizeof(float)
116
            info.len = info.itemsize * item_count
117

118
            info.shape = <Py_ssize_t*> PyObject_Malloc(sizeof(Py_ssize_t) + 2)
119
            if not info.shape:
120
                raise MemoryError()
121
            info.shape[0] = item_count      # constant regardless of resizing
122
            info.strides = &info.itemsize
123

124
            info.format = <char*> (info.shape + 1)
125
            info.format[0] = self.ob_descr.typecode
126
            info.format[1] = 0
127
            info.obj = self
128

129
        def __releasebuffer__(self, Py_buffer* info):
130
            PyObject_Free(info.shape)
131

132
    array newarrayobject(PyTypeObject* type, Py_ssize_t size, arraydescr *descr)
133

134
    # fast resize/realloc
135
    # not suitable for small increments; reallocation 'to the point'
136
    int resize(array self, Py_ssize_t n) except -1
137
    # efficient for small increments (not in Py2.3-)
138
    int resize_smart(array self, Py_ssize_t n) except -1
139

140

141
cdef inline array clone(array template, Py_ssize_t length, bint zero):
142
    """ fast creation of a new array, given a template array.
143
    type will be same as template.
144
    if zero is true, new array will be initialized with zeroes."""
145
    cdef array op = newarrayobject(Py_TYPE(template), length, template.ob_descr)
146
    if zero and op is not None:
147
        memset(op.data.as_chars, 0, length * op.ob_descr.itemsize)
148
    return op
149

150
cdef inline array copy(array self):
151
    """ make a copy of an array. """
152
    cdef array op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)
153
    memcpy(op.data.as_chars, self.data.as_chars, Py_SIZE(op) * op.ob_descr.itemsize)
154
    return op
155

156
cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n) except -1:
157
    """ efficient appending of new stuff of same type
158
    (e.g. of same array type)
159
    n: number of elements (not number of bytes!) """
160
    cdef Py_ssize_t itemsize = self.ob_descr.itemsize
161
    cdef Py_ssize_t origsize = Py_SIZE(self)
162
    resize_smart(self, origsize + n)
163
    memcpy(self.data.as_chars + origsize * itemsize, stuff, n * itemsize)
164
    return 0
165

166
cdef inline int extend(array self, array other) except -1:
167
    """ extend array with data from another array; types must match. """
168
    if self.ob_descr.typecode != other.ob_descr.typecode:
169
        PyErr_BadArgument()
170
    return extend_buffer(self, other.data.as_chars, Py_SIZE(other))
171

172
cdef inline void zero(array self) noexcept:
173
    """ set all elements of array to zero. """
174
    memset(self.data.as_chars, 0, Py_SIZE(self) * self.ob_descr.itemsize)
175

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.