From 13d9929eec91ff7da2febf38a5ca6142deb27be0 Mon Sep 17 00:00:00 2001 From: Andreas van Cranenburgh Date: Wed, 2 May 2012 21:22:41 +0200 Subject: [PATCH] Single new array function Unfortunately cannot use default args in pxd file; I also wouldn't know how the two array functions could be added as methods to the array class. Restored "inline" attribute for array creation function, it can be disabled with a \#DEF Removed some unused/redundant attributes. Moved selected comments to docstrings. Replaced tabs w/spaces. --- Cython/Includes/cpython/__init__.pxd | 1 - Cython/Includes/cpython/array.pxd | 81 +++++++++-------------- Cython/Includes/cpython/arrayarray.h | 99 ++++++++++++++-------------- 3 files changed, 82 insertions(+), 99 deletions(-) diff --git a/Cython/Includes/cpython/__init__.pxd b/Cython/Includes/cpython/__init__.pxd index 39ee4ddfa20..27c11604d04 100644 --- a/Cython/Includes/cpython/__init__.pxd +++ b/Cython/Includes/cpython/__init__.pxd @@ -164,7 +164,6 @@ from cpython.weakref cimport * from cpython.getargs cimport * from cpython.pythread cimport * from cpython.pystate cimport * -from cpython.array cimport * # Python <= 2.x from cpython.cobject cimport * diff --git a/Cython/Includes/cpython/array.pxd b/Cython/Includes/cpython/array.pxd index fa5cbacf95d..e7e05c734ca 100644 --- a/Cython/Includes/cpython/array.pxd +++ b/Cython/Includes/cpython/array.pxd @@ -38,7 +38,7 @@ 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() optionA + mem.leaks; seamless Python compatibility, buffer() optional IMPORTANT: arrayarray.h (arrayobject, arraydescr) is not part of @@ -48,23 +48,17 @@ last changes: 2009-05-15 rk : 2009-12-06 bp + : 2012-05-02 andreasvc """ from libc cimport stdlib +from libc.string cimport strcat, strncat, \ + memset, memchr, memcmp, memcpy, memmove -cdef extern from "stdlib.h" nogil: - void *memset(void *str, int c, size_t n) - char *strcat(char *str1, char *str2) - char *strncat(char *str1, char *str2, size_t n) - void *memchr(void *str, int c, size_t n) - int memcmp(void *str1, void *str2, size_t n) - void *memcpy(void *str1, void *str2, size_t n) - void *memmove(void *str1, void *str2, size_t n) - +from cpython.ref cimport PyTypeObject +from cpython.exc cimport PyErr_BadArgument cdef extern from "arrayarray.h": - ctypedef void PyTypeObject ctypedef short Py_UNICODE - int PyErr_BadArgument() 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) @@ -79,17 +73,10 @@ cdef extern from "arrayarray.h": cdef: PyTypeObject* ob_type - - int ob_size # number of valid items; unsigned length # == ob_size (by union) - - char* ob_item # to first item - - Py_ssize_t allocated # bytes arraydescr* ob_descr # struct arraydescr *ob_descr; - object weakreflist # /* List of weak references */ - # view's of ob_item: + # views of ob_item: float* _f # direct float pointer access to buffer double* _d # double ... int* _i @@ -112,7 +99,7 @@ cdef extern from "arrayarray.h": cdef unsigned rows, columns, itemsize info.suboffsets = NULL - info.buf = self.ob_item + info.buf = self._c info.readonly = 0 info.ndim = 1 info.itemsize = itemsize = self.ob_descr.itemsize # e.g. sizeof(float) @@ -144,44 +131,40 @@ cdef extern from "arrayarray.h": int resize_smart(array self, Py_ssize_t n) -# fast creation of a new array - init with zeros -# yet you need a (any) template array of the same item type (but not same size) -cdef inline array zeros_like(array sametype): - cdef array op = newarrayobject(sametype.ob_type, sametype.ob_size, sametype.ob_descr) - if op: - memset(op.ob_item, 0, op.ob_size * op.ob_descr.itemsize) - return op - -# fast creation of a new array - no init with zeros -cdef inline array new_array(array sametype, unsigned n): - return newarrayobject( sametype.ob_type, n, sametype.ob_descr) - -# fast creation of a new array - no init with zeros, same length -cdef inline array empty_like(array sametype): - return newarrayobject(sametype.ob_type, sametype.op.ob_size, - sametype.ob_descr) +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 + op = newarrayobject(template.ob_type, length, template.ob_descr) + if zero and op is not None: + memset(op._c, 0, length * op.ob_descr.itemsize) + return op cdef inline array copy(array self): - cdef array op = newarrayobject(self.ob_type, self.ob_size, - self.ob_descr) - memcpy(op.ob_item, self.ob_item, op.ob_size * op.ob_descr.itemsize) + """ make a copy of an array. """ + cdef array op + op = newarrayobject(self.ob_type, self.length, self.ob_descr) + memcpy(op._c, self._c, op.length * op.ob_descr.itemsize) return op cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n): - """ efficent 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, orgsize = self.ob_size - if -1 == resize_smart(self, orgsize + n): + """ efficent 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 orgsize = self.length + if resize_smart(self, orgsize + n) == -1: return -1 - memcpy(self.ob_item + orgsize * itemsize, stuff, n * itemsize) + memcpy(self._c + orgsize * itemsize, stuff, n * itemsize) cdef inline int extend(array self, array other): + """ extend array with data from another array; types must match. """ if self.ob_descr.typecode != self.ob_descr.typecode: PyErr_BadArgument() return -1 - return extend_buffer(self, other.ob_item, other.ob_size) - + return extend_buffer(self, other._c, other.length) cdef inline void zero(array op): - memset(op.ob_item, 0, op.ob_size * op.ob_descr.itemsize) + """ set all elements of array to zero. """ + memset(op._c, 0, op.length * op.ob_descr.itemsize) diff --git a/Cython/Includes/cpython/arrayarray.h b/Cython/Includes/cpython/arrayarray.h index 691d806f340..87d5d7501fd 100644 --- a/Cython/Includes/cpython/arrayarray.h +++ b/Cython/Includes/cpython/arrayarray.h @@ -6,6 +6,7 @@ See array.pxd next to this file last changes: 2009-05-15 rk + 2012-05-02 andreasvc */ @@ -21,10 +22,10 @@ struct arrayobject; /* Forward */ * functions aren't visible yet. */ typedef struct arraydescr { - int typecode; - int itemsize; - PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); - int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); + int typecode; + int itemsize; + PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); + int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); #if PY_VERSION_HEX >= 0x03000000 char *formats; #endif @@ -32,13 +33,13 @@ typedef struct arraydescr { typedef struct arrayobject { - PyObject_HEAD + PyObject_HEAD union { - int ob_size; + Py_ssize_t ob_size; unsigned length; }; union { - char *ob_item; + char *ob_item; float *_f; double *_d; int *_i; @@ -54,11 +55,11 @@ typedef struct arrayobject { void *_v; }; #if PY_VERSION_HEX >= 0x02040000 - Py_ssize_t allocated; + Py_ssize_t allocated; #endif - struct arraydescr *ob_descr; + struct arraydescr *ob_descr; #if PY_VERSION_HEX >= 0x02040000 - PyObject *weakreflist; /* List of weak references */ + PyObject *weakreflist; /* List of weak references */ #if PY_VERSION_HEX >= 0x03000000 int ob_exports; /* Number of exported buffers */ #endif @@ -69,50 +70,50 @@ typedef struct arrayobject { #ifndef NO_NEWARRAY_INLINE /* * - * fast creation of a new array - init with zeros + * fast creation of a new array */ -PyObject * newarrayobject -(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr) { - arrayobject *op; - size_t nbytes; - - if (size < 0) { - PyErr_BadInternalCall(); - return NULL; - } - - nbytes = size * descr->itemsize; - /* Check for overflow */ - if (nbytes / descr->itemsize != (size_t)size) { - return PyErr_NoMemory(); - } - op = (arrayobject *) type->tp_alloc(type, 0); - if (op == NULL) { - return NULL; - } - op->ob_descr = descr; +inline PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size, + struct arraydescr *descr) { + arrayobject *op; + size_t nbytes; + + if (size < 0) { + PyErr_BadInternalCall(); + return NULL; + } + + nbytes = size * descr->itemsize; + /* Check for overflow */ + if (nbytes / descr->itemsize != (size_t)size) { + return PyErr_NoMemory(); + } + op = (arrayobject *) type->tp_alloc(type, 0); + if (op == NULL) { + return NULL; + } + op->ob_descr = descr; #if !( PY_VERSION_HEX < 0x02040000 ) - op->allocated = size; - op->weakreflist = NULL; + op->allocated = size; + op->weakreflist = NULL; #endif - Py_SIZE(op) = size; - if (size <= 0) { - op->ob_item = NULL; - } - else { - op->ob_item = PyMem_NEW(char, nbytes); - if (op->ob_item == NULL) { - Py_DECREF(op); - return PyErr_NoMemory(); - } - } - return (PyObject *) op; + Py_SIZE(op) = size; + if (size <= 0) { + op->ob_item = NULL; + } + else { + op->ob_item = PyMem_NEW(char, nbytes); + if (op->ob_item == NULL) { + Py_DECREF(op); + return PyErr_NoMemory(); + } + } + return (PyObject *) op; } #else -PyObject * -newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr); -#endif +PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size, + struct arraydescr *descr); +#endif /* ifndef NO_NEWARRAY_INLINE */ /* fast resize (reallocation to the point) not designed for filing small increments (but for fast opaque array apps) */ @@ -143,7 +144,7 @@ int resize_smart(arrayobject *self, Py_ssize_t n) { return 0; } } - newsize = n * 3 / 2 + 1; + newsize = n * 3 / 2 + 1; PyMem_Resize(item, char, (size_t)(newsize * self->ob_descr->itemsize)); if (item == NULL) { PyErr_NoMemory();