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.
parent 8fc6e20b
...@@ -164,7 +164,6 @@ from cpython.weakref cimport * ...@@ -164,7 +164,6 @@ from cpython.weakref cimport *
from cpython.getargs cimport * from cpython.getargs cimport *
from cpython.pythread cimport * from cpython.pythread cimport *
from cpython.pystate cimport * from cpython.pystate cimport *
from cpython.array cimport *
# Python <= 2.x # Python <= 2.x
from cpython.cobject cimport * from cpython.cobject cimport *
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
Suitable as lightweight arrays intra Cython without speed penalty. Suitable as lightweight arrays intra Cython without speed penalty.
Replacement for C stack/malloc arrays; no trouble with refcounting, 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 IMPORTANT: arrayarray.h (arrayobject, arraydescr) is not part of
...@@ -48,23 +48,17 @@ ...@@ -48,23 +48,17 @@
last changes: 2009-05-15 rk last changes: 2009-05-15 rk
: 2009-12-06 bp : 2009-12-06 bp
: 2012-05-02 andreasvc
""" """
from libc cimport stdlib from libc cimport stdlib
from libc.string cimport strcat, strncat, \
memset, memchr, memcmp, memcpy, memmove
cdef extern from "stdlib.h" nogil: from cpython.ref cimport PyTypeObject
void *memset(void *str, int c, size_t n) from cpython.exc cimport PyErr_BadArgument
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)
cdef extern from "arrayarray.h": cdef extern from "arrayarray.h":
ctypedef void PyTypeObject
ctypedef short Py_UNICODE ctypedef short Py_UNICODE
int PyErr_BadArgument()
ctypedef class array.array [object arrayobject] ctypedef class array.array [object arrayobject]
ctypedef object GETF(array a, Py_ssize_t ix) ctypedef object GETF(array a, Py_ssize_t ix)
ctypedef object SETF(array a, Py_ssize_t ix, object o) ctypedef object SETF(array a, Py_ssize_t ix, object o)
...@@ -79,17 +73,10 @@ cdef extern from "arrayarray.h": ...@@ -79,17 +73,10 @@ cdef extern from "arrayarray.h":
cdef: cdef:
PyTypeObject* ob_type PyTypeObject* ob_type
int ob_size # number of valid items;
unsigned length # == ob_size (by union) unsigned length # == ob_size (by union)
char* ob_item # to first item
Py_ssize_t allocated # bytes
arraydescr* ob_descr # struct arraydescr *ob_descr; 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 float* _f # direct float pointer access to buffer
double* _d # double ... double* _d # double ...
int* _i int* _i
...@@ -112,7 +99,7 @@ cdef extern from "arrayarray.h": ...@@ -112,7 +99,7 @@ cdef extern from "arrayarray.h":
cdef unsigned rows, columns, itemsize cdef unsigned rows, columns, itemsize
info.suboffsets = NULL info.suboffsets = NULL
info.buf = self.ob_item info.buf = self._c
info.readonly = 0 info.readonly = 0
info.ndim = 1 info.ndim = 1
info.itemsize = itemsize = self.ob_descr.itemsize # e.g. sizeof(float) info.itemsize = itemsize = self.ob_descr.itemsize # e.g. sizeof(float)
...@@ -144,44 +131,40 @@ cdef extern from "arrayarray.h": ...@@ -144,44 +131,40 @@ cdef extern from "arrayarray.h":
int resize_smart(array self, Py_ssize_t n) int resize_smart(array self, Py_ssize_t n)
# fast creation of a new array - init with zeros cdef inline array clone(array template, Py_ssize_t length, bint zero):
# yet you need a (any) template array of the same item type (but not same size) """ fast creation of a new array, given a template array.
cdef inline array zeros_like(array sametype): type will be same as template.
cdef array op = newarrayobject(<PyTypeObject*>sametype.ob_type, sametype.ob_size, sametype.ob_descr) if zero is true, new array will be initialized with zeroes."""
if op: cdef array op
memset(op.ob_item, 0, op.ob_size * op.ob_descr.itemsize) op = newarrayobject(template.ob_type, length, template.ob_descr)
return op if zero and op is not None:
memset(op._c, 0, length * op.ob_descr.itemsize)
# fast creation of a new array - no init with zeros return op
cdef inline array new_array(array sametype, unsigned n):
return newarrayobject( <PyTypeObject*>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(<PyTypeObject*>sametype.ob_type, sametype.op.ob_size,
sametype.ob_descr)
cdef inline array copy(array self): cdef inline array copy(array self):
cdef array op = newarrayobject(<PyTypeObject*>self.ob_type, self.ob_size, """ make a copy of an array. """
self.ob_descr) cdef array op
memcpy(op.ob_item, self.ob_item, op.ob_size * op.ob_descr.itemsize) op = newarrayobject(self.ob_type, self.length, self.ob_descr)
memcpy(op._c, self._c, op.length * op.ob_descr.itemsize)
return op return op
cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n): 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) """ efficent appending of new stuff of same type
n: number of elements (not number of bytes!) (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 cdef Py_ssize_t itemsize = self.ob_descr.itemsize
if -1 == resize_smart(self, orgsize + n): cdef Py_ssize_t orgsize = self.length
if resize_smart(self, orgsize + n) == -1:
return -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): 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: if self.ob_descr.typecode != self.ob_descr.typecode:
PyErr_BadArgument() PyErr_BadArgument()
return -1 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): 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)
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
See array.pxd next to this file See array.pxd next to this file
last changes: 2009-05-15 rk last changes: 2009-05-15 rk
2012-05-02 andreasvc
*/ */
...@@ -21,10 +22,10 @@ struct arrayobject; /* Forward */ ...@@ -21,10 +22,10 @@ struct arrayobject; /* Forward */
* functions aren't visible yet. * functions aren't visible yet.
*/ */
typedef struct arraydescr { typedef struct arraydescr {
int typecode; int typecode;
int itemsize; int itemsize;
PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); PyObject * (*getitem)(struct arrayobject *, Py_ssize_t);
int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
#if PY_VERSION_HEX >= 0x03000000 #if PY_VERSION_HEX >= 0x03000000
char *formats; char *formats;
#endif #endif
...@@ -32,13 +33,13 @@ typedef struct arraydescr { ...@@ -32,13 +33,13 @@ typedef struct arraydescr {
typedef struct arrayobject { typedef struct arrayobject {
PyObject_HEAD PyObject_HEAD
union { union {
int ob_size; Py_ssize_t ob_size;
unsigned length; unsigned length;
}; };
union { union {
char *ob_item; char *ob_item;
float *_f; float *_f;
double *_d; double *_d;
int *_i; int *_i;
...@@ -54,11 +55,11 @@ typedef struct arrayobject { ...@@ -54,11 +55,11 @@ typedef struct arrayobject {
void *_v; void *_v;
}; };
#if PY_VERSION_HEX >= 0x02040000 #if PY_VERSION_HEX >= 0x02040000
Py_ssize_t allocated; Py_ssize_t allocated;
#endif #endif
struct arraydescr *ob_descr; struct arraydescr *ob_descr;
#if PY_VERSION_HEX >= 0x02040000 #if PY_VERSION_HEX >= 0x02040000
PyObject *weakreflist; /* List of weak references */ PyObject *weakreflist; /* List of weak references */
#if PY_VERSION_HEX >= 0x03000000 #if PY_VERSION_HEX >= 0x03000000
int ob_exports; /* Number of exported buffers */ int ob_exports; /* Number of exported buffers */
#endif #endif
...@@ -69,50 +70,50 @@ typedef struct arrayobject { ...@@ -69,50 +70,50 @@ typedef struct arrayobject {
#ifndef NO_NEWARRAY_INLINE #ifndef NO_NEWARRAY_INLINE
/* /*
* *
* fast creation of a new array - init with zeros * fast creation of a new array
*/ */
PyObject * newarrayobject inline PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size,
(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr) { struct arraydescr *descr) {
arrayobject *op; arrayobject *op;
size_t nbytes; size_t nbytes;
if (size < 0) { if (size < 0) {
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return NULL; return NULL;
} }
nbytes = size * descr->itemsize; nbytes = size * descr->itemsize;
/* Check for overflow */ /* Check for overflow */
if (nbytes / descr->itemsize != (size_t)size) { if (nbytes / descr->itemsize != (size_t)size) {
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
op = (arrayobject *) type->tp_alloc(type, 0); op = (arrayobject *) type->tp_alloc(type, 0);
if (op == NULL) { if (op == NULL) {
return NULL; return NULL;
} }
op->ob_descr = descr; op->ob_descr = descr;
#if !( PY_VERSION_HEX < 0x02040000 ) #if !( PY_VERSION_HEX < 0x02040000 )
op->allocated = size; op->allocated = size;
op->weakreflist = NULL; op->weakreflist = NULL;
#endif #endif
Py_SIZE(op) = size; Py_SIZE(op) = size;
if (size <= 0) { if (size <= 0) {
op->ob_item = NULL; op->ob_item = NULL;
} }
else { else {
op->ob_item = PyMem_NEW(char, nbytes); op->ob_item = PyMem_NEW(char, nbytes);
if (op->ob_item == NULL) { if (op->ob_item == NULL) {
Py_DECREF(op); Py_DECREF(op);
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
} }
return (PyObject *) op; return (PyObject *) op;
} }
#else #else
PyObject * PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size,
newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr); struct arraydescr *descr);
#endif #endif /* ifndef NO_NEWARRAY_INLINE */
/* fast resize (reallocation to the point) /* fast resize (reallocation to the point)
not designed for filing small increments (but for fast opaque array apps) */ 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) { ...@@ -143,7 +144,7 @@ int resize_smart(arrayobject *self, Py_ssize_t n) {
return 0; return 0;
} }
} }
newsize = n * 3 / 2 + 1; newsize = n * 3 / 2 + 1;
PyMem_Resize(item, char, (size_t)(newsize * self->ob_descr->itemsize)); PyMem_Resize(item, char, (size_t)(newsize * self->ob_descr->itemsize));
if (item == NULL) { if (item == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment