#ifndef PY_BASEARRAY_H #define PY_BASEARRAY_H #include /* Return values of functions for success and failure. */ #define PY_FAIL 0 #define PY_SUCCEED 1 /* There are several places in the code where an array of dimensions is allocated statically. This is the size of that static allocation. The array creation itself could have arbitrary dimensions but all the places where static allocation is used would need to be changed to dynamic (including inside of structures). */ #define MAX_DIMS 32 /* Max/Min of two arguments. */ #define _MAX(a,b) (((a)>(b))?(a):(b)) #define _MIN(a,b) (((a)<(b))?(a):(b)) /* Boolean definitions. */ typedef unsigned char Bool; #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif static int _BoolConverter(PyObject *object, Bool *val) { if (PyObject_IsTrue(object)) *val=TRUE; else *val=FALSE; if (PyErr_Occurred()) return PY_FAIL; return PY_SUCCEED; } /* Number definitions. */ #ifdef PY_LONG_LONG typedef PY_LONG_LONG longlong; typedef unsigned PY_LONG_LONG ulonglong; #else typedef long longlong; typedef unsigned long ulonglong; #endif typedef Py_intptr_t intp; #define INTP_MAX INT_MAX typedef struct { float real, imag; } cfloat; /* Alignment of C-types. */ #define _ALIGN(type) offsetof(struct {char c; type v;},v) /* To be defined. */ static PyTypeObject PyDataType_Type; static PyTypeObject PyBaseArrayIter_Type; static PyTypeObject PyBaseArray_Type; /* Functions specific for data-types. */ typedef PyObject * (PyDataType_GetItemFunc) (void *, void *); typedef int (PyDataType_SetItemFunc)(PyObject *, void *, void *); typedef void (PyDataType_CopySwapFunc)(void *, void *, int, void *); typedef struct { /* Functions to get and set items with standard Python types. These are not numpy array scalars. */ PyDataType_GetItemFunc *getitem; PyDataType_SetItemFunc *setitem; /* Copy and/or swap data. Memory areas may not overlap. Use memmove first if possible */ PyDataType_CopySwapFunc *copyswap; } PyDataTypeFuncs; /* Data type object structure. */ typedef struct { PyObject_HEAD PyTypeObject *typeobj; /* Python type of the array elements. */ char kind; /* Character for the kind of data type. */ char byteorder; /* '>' (big-endian), '<' (little), '|' (not-applicable), or '=' (native). */ char hasobject; /* Non-zero if there are object arrays in the fields of this array. */ int elsize; /* Size of array elements for this datatype, counted in bytes. */ int alignment; /* For a basic C-type, this holds the alignment for the type. For the C-type of a type this data-type object represents, the alignment can be calculated as offsetof(struct{char c; v;},v). */ struct _arr_ *subarray; /* Non-NULL if the type is a C-contigouus array of some other type. */ PyObject *fields; /* A dictionary of names and fields - a field is a segment of a larger type that has its own data-type object. This dictionary is keyed by strings representing field names and returns a tuple of the form (data-type, offset[, label]), where data-type is the data-type object describing the type, offset is the offset in bytes to the start of that field, and label is the optional user-name of this field. The reason for having label is that the key might be a Python-acceptable name (such that could be used in attribute accesss, for example), but label is the definer's "official title", which may contain spaces, units, and so forth. */ PyObject *names; /* An ordered tuple of field names or NULL if no fields are defined. */ PyDataTypeFuncs *funcs; /* Table of functions specific for this datatype. */ } PyDataTypeObject; typedef struct _arr_ { PyDataTypeObject *base; /* The data-type this subarray refers to. */ PyObject *shape; /* Tuple with the shape of this subarray. */ } PyDataType_Array; #define PyDataType_CHECK(op) ((op)->ob_type == &PyDataType_Type || \ PyObject_TypeCheck((op), &PyDataType_Type)) /* Byte orders. */ #define PyDataType_LITTLE '<' #define PyDataType_BIG '>' #define PyDataType_NATIVE '=' #define PyDataType_SWAP 's' #define PyDataType_IGNORE '|' #ifdef WORDS_BIGENDIAN #define PyDataType_NATBYTE PyDataType_BIG #define PyDataType_OPPBYTE PyDataType_LITTLE #else #define PyDataType_NATBYTE PyDataType_LITTLE #define PyDataType_OPPBYTE PyDataType_BIG #endif #define PyDataType_ISNBO(arg) ((arg) != PyDataType_OPPBYTE) #define PyDataType_ISNOTSWAPPED(dt) PyDataType_ISNBO(dt->byteorder) /* Base array object structure. */ typedef struct PyBaseArrayObject { PyObject_HEAD void *data; /* Pointer to raw data buffer. */ int ndim; /* Number of dimensions. */ intp *dimensions; /* Size in each dimension. */ intp *strides; /* Bytes to jump to get to the next element in each dimension. */ PyDataTypeObject *datatype; /* Pointer to datatype object describing the data. */ int flags; /* Flags describing the data buffer */ PyObject *base; /* This object should be decref'd upon deletion of the array.*/ /* For creation from a buffer object it points to an object that should be decref'd upon deletion. */ PyObject *weakreflist; /* For weakreferences. */ } PyBaseArrayObject; #define PyBaseArray_CHECK(op) ((op)->ob_type == &PyBaseArray_Type || \ PyObject_TypeCheck((op), &PyBaseArray_Type)) /* Macros to define how array and dimension/strides data is allocated and freed. */ #define PyBaseArray_USE_PYMEM 0 #if PyBaseArray_USE_PYMEM == 1 #define _pybasearray_malloc PyObject_Malloc #define _pybasearray_free PyObject_Free #else #define _pybasearray_malloc malloc #define _pybasearray_free free #endif #define PyBaseArray_MALLOC(size) ((char *)malloc(size)) #define PyBaseArray_FREE(ptr) free(ptr) #define PyBaseArray_REALLOC(ptr,size) ((char *)realloc(ptr,size)) #define PyBaseArrayDim_MALLOC(size) \ ((intp *)_pybasearray_malloc(size*sizeof(intp))) #define PyBaseArrayDim_FREE(ptr) _pybasearray_free(ptr) #define PyBaseArrayDim_REALLOC(ptr,size)\ ((intp *)_pybasearray_realloc(ptr,size*sizeof(intp))) /* Definitions of C/FORTRAN/ANY array orders. */ typedef enum { PyBaseArray_ANYORDER=-1, PyBaseArray_CORDER=0, PyBaseArray_FORTRANORDER=1 } PyBaseArray_ORDER; /* ARRAY FLAGS */ /* Array flags hold information on how the memory area of the array is interpreted. Only UPDATEIFCOPY, WRITEABLE, and ALIGNED can be set by the user. Array flags cannot be set arbitrarily. UPDATEIFCOPY can only be set to False, ALIGNED can be set to true only if the data is aligned, and WRITEABLE can be set to True only is the array owns the memory ot the memory owner provides a writeable interface (or is a string). */ /* The array is reas as c-style contiguous, and the last index varies the fastest. Data elements come right after each other. */ #define CONTIGUOUS 0x0001 /* The array is a contiguous Fortran array, meaning the first index varies the fastest in memory, and the strides array is the reverse of C-contiguous arra). */ #define FORTRAN 0x0002 /* The array owns the memory data, and it will be freed when the array is deleted. If Flase, the array borrows memory from another object, and the base attribute provides a view of the source array. */ #define OWNDATA 0x0004 /* Array data is writeable. */ #define WRITEABLE 0x0400 /* Array data is aligned on the appropiate memory address for the type stored, according to how the compiler would align things. For example, an array of integers (4 bytes each) starts on a memory address that is a multiple of 4). */ #define ALIGNED 0x0100 /* Some logical combinations of flags. */ #define BEHAVED_FLAGS ALIGNED | WRITEABLE #define UPDATE_ALL_FLAGS CONTIGUOUS | FORTRAN | ALIGNED #define CARRAY_FLAGS CONTIGUOUS | BEHAVED_FLAGS #define CARRAY_FLAGS_RO CONTIGUOUS | ALIGNED #define FARRAY_FLAGS FORTRAN | BEHAVED_FLAGS #define FARRAY_FLAGS_RO FORTRAN | ALIGNED #define DEFAULT_FLAGS CARRAY_FLAGS #define PyBaseArray_ISONESEGMENT(m) ( (m)->ndim == 0 || ((m->flags) & CONTIGUOUS) || ((m->flags) & FORTRAN) ) /* Iterator structure used for looping over a basearray. */ typedef struct { PyObject_HEAD int nd_m1; /* Number of dimensions minus 1. */ intp index; /* Current 1D index into the array. */ intp size; /* Total size of the array. */ intp coordinates[MAX_DIMS]; /* N-dimensional index into the array. */ intp dims_m1[MAX_DIMS]; /* Size of the array minus 1 in each dimension. */ intp strides[MAX_DIMS]; /* Bytes to jump to get to the next element in each dimension. */ intp backstrides[MAX_DIMS]; /* Bytes to jump from the end of a dimension to its beginning. */ intp factors[MAX_DIMS]; /* Shape factors, for computing an ND index from a 1D index. */ PyBaseArrayObject *ao; /* The underlying basearray object this iterator refers to. */ char *dataptr; /* Pointer to the element indicated by this iterator. */ Bool contiguous; /* True only when *ao has the CONTIGUOUS flag set. */ } PyBaseArrayIterObject; /* Auxiliary structure used for interpreting the shape and stride of Python objects when they are converted to useful C objects. */ typedef struct { intp *ptr; /* Pointer to a list of intp representing array shape or strides. */ int len; /* The length of the list of integers pointed to above. */ } PyBaseArray_Dims; /* Auxiliary structure for representing a memory segment, the equivalent of the Python buffer object. */ typedef struct { PyObject_HEAD PyObject *base; /* _ython object this memory segment comes from. */ void *ptr; /* Pointer to the beginning of the memory segment. */ intp len; /* Length of the segment in bytes. */ int flags; /* Data flags to interpret the memory. */ } PyBaseArray_Chunk; /* Functions called before defined in basearray.c */ static int PyBaseArray_DataTypeConverter(PyObject *obj, PyDataTypeObject **at); static int PyBaseArray_IntpConverter(PyObject *obj, PyBaseArray_Dims *seq); static PyObject * PyBaseArray_NewFromDataType(PyTypeObject *subtype, PyDataTypeObject *descr, int nd, intp *dims, intp *strides, void *data, int flags, PyObject *obj); static void PyBaseArray_UpdateFlags(PyBaseArrayObject *ret, int flagmask); static PyObject * PyBaseArrayIter_New(PyObject *obj); static void PyBaseArrayIter_Next(PyBaseArrayIterObject *it); /* Data-type object instances supported by basearray. */ enum PyDataType_KINDS { PyDataType_BOOL='b', PyDataType_INT='i', PyDataType_FLOAT='f', PyDataType_COMPLEX='c', PyDataType_STRING='S', PyDataType_UNICODE='U', PyDataType_OBJECT='O', PyDataType_VOID='V', PyDataType_NOTYPE='X', }; #define PyDataType_DEFAULT PyDataType_FLOAT /* Functions getitem specific for the supported datatypes. */ static PyObject * PyDataTypeGetitem_Bool(char *ip, PyBaseArrayObject *ap) { Bool t1; int notswapped = PyDataType_ISNOTSWAPPED(ap->datatype); if ( (ap == NULL) || (notswapped && (ap->flags & ALIGNED)) ) { t1 = *((Bool *)ip); return PyBool_FromLong((long)t1); } else { ap->datatype->funcs->copyswap(&t1, ip, !notswapped, ap); return PyBool_FromLong((long)t1); } } static PyObject * PyDataTypeGetitem_Int(char *ip, PyBaseArrayObject *ap) { int t1, notswapped = PyDataType_ISNOTSWAPPED(ap->datatype); if ( (ap == NULL) || (notswapped && (ap->flags & ALIGNED)) ) { t1 = *((int *)ip); return PyInt_FromLong((long)t1); } else { ap->datatype->funcs->copyswap(&t1, ip, !notswapped, ap); return PyInt_FromLong((long)t1); } } static PyObject * PyDataTypeGetitem_Float(char *ip, PyBaseArrayObject *ap) { float t1; int notswapped = PyDataType_ISNOTSWAPPED(ap->datatype); if ( (ap == NULL) || (notswapped && (ap->flags & ALIGNED)) ) { t1 = *((float *)ip); return PyFloat_FromDouble((float)t1); } else { ap->datatype->funcs->copyswap(&t1, ip, !notswapped, ap); return PyFloat_FromDouble((float)t1); } } static void _strided_byte_swap(void *p, intp stride, intp n, int size) { char *a, *b, c=0; int j,m; m = size / 2; for (a = (char *)p ; n > 0; n--, a += stride-m) { b = a + (size-1); for (j=0; j 1, then dst must be contiguous. */ static void copy_and_swap(void *dst, void *src, int itemsize, intp numitems, intp srcstrides, int swap) { int i; char *s1 = (char *)src, *d1 = (char *)dst; if ((numitems == 1) || (itemsize == srcstrides)) memcpy(d1, s1, itemsize*numitems); else { for (i = 0; i < numitems; i++) { memcpy(d1, s1, itemsize); d1 += itemsize; s1 += srcstrides; } } if (swap) byte_swap_vector(d1, numitems, itemsize); } static PyObject * PyDataTypeGetitem_Complex(char *ip, PyBaseArrayObject *ap) { float t1, t2; int notswapped = PyDataType_ISNOTSWAPPED(ap->datatype); if ( (ap == NULL) || (notswapped && (ap->flags & ALIGNED)) ) { return PyComplex_FromDoubles( (double)((float *)ip)[0], (double)((float *)ip)[1] ); } else { int size = sizeof(float); copy_and_swap(&t1, ip, size, 1, 0, !notswapped); copy_and_swap(&t2, ip+size, size, 1, 0, !notswapped); return PyComplex_FromDoubles((double)t1, (double)t2); } } /* Can handle both NULL-terminated and not NULL-terminated cases. */ static PyObject * PyDataTypeGetitem_String(char *ip, PyBaseArrayObject *ap) { if (ip[ap->datatype->elsize-1]) return PyString_FromStringAndSize(ip,ap->datatype->elsize); else return PyString_FromString(ip); } static PyObject * PyDataTypeGetitem_Unicode(char *ip, PyBaseArrayObject *ap) { PyObject *obj; int mysize; PyArray_UCS4 *dptr; char *buffer; int alloc=0; mysize = ap->descr->elsize >> 2; dptr = (PyArray_UCS4 *)ip + mysize-1; while(mysize > 0 && *dptr-- == 0) mysize--; if (!PyArray_ISBEHAVED(ap)) { buffer = _pya_malloc(mysize << 2); if (buffer == NULL) return PyErr_NoMemory(); alloc = 1; memcpy(buffer, ip, mysize << 2); if (!PyArray_ISNOTSWAPPED(ap)) { byte_swap_vector(buffer, mysize, 4); } } else buffer = ip; #ifdef Py_UNICODE_WIDE obj = PyUnicode_FromUnicode((const Py_UNICODE *)buffer, mysize); #else /* create new empty unicode object of length mysize*2 */ obj = MyPyUnicode_New(mysize*2); if (obj == NULL) {if (alloc) _pya_free(buffer); return obj;} mysize = PyUCS2Buffer_FromUCS4(((PyUnicodeObject *)obj)->str, (PyArray_UCS4 *)buffer, mysize); /* reset length of unicode object to ucs2size */ if (MyPyUnicode_Resize((PyUnicodeObject *)obj, mysize) < 0) { if (alloc) _pya_free(buffer); Py_DECREF(obj); return NULL; } #endif if (alloc) _pya_free(buffer); return obj; } static PyObject * PyDataTypeGetitem_Object(char *ip, PyBaseArrayObject *ap) { if (ap->flags & ALIGNED) { Py_INCREF(*(PyObject **)ip); return *(PyObject **)ip; } else { PyObject **obj; obj = (PyObject **)ip; Py_INCREF(*obj); return *obj; } } static PyObject * PyDataTypeGetitem_Void(char *ip, PyBaseArrayObject *ap) { PyObject *u=NULL; PyDataTypeObject *descr; int itemsize; descr = ap->datatype; if (descr->names) { PyObject *key, *names, *ret, *tup, *title; int i, n, offset, savedflags; PyDataTypeObject *new; /* get the names from the fields dictionary*/ names = descr->names; if (!names) goto finish; n = PyTuple_GET_SIZE(names); ret = PyTuple_New(n); savedflags = ap->flags; for (i=0; ifields, key); if (!PyArg_ParseTuple(tup, "Oi|O", &new, &offset, &title)) { Py_DECREF(ret); ap->datatype = descr; return NULL; } ap->datatype = new; /* update alignment based on offset */ if ((new->alignment > 1) && ((((intp)(ip+offset)) % new->alignment) != 0)) ap->flags &= ~ALIGNED; else ap->flags |= ALIGNED; PyTuple_SET_ITEM(ret, i, new->funcs->getitem(ip+offset, ap)); ap->flags = savedflags; } ap->datatype = descr; return ret; } if (descr->subarray) { /* return an array of the basic type */ PyBaseArray_Dims shape={NULL,-1}; PyObject *ret; if (!(PyBaseArray_IntpConverter(descr->subarray->shape, &shape))) { PyBaseArrayDim_FREE(shape.ptr); PyErr_SetString(PyExc_ValueError, "Invalid shape in fixed-type tuple."); return NULL; } Py_INCREF(descr->subarray->base); ret = PyBaseArray_NewFromDataType(&PyBaseArray_Type, descr->subarray->base, shape.len, shape.ptr, NULL, ip, ap->flags, NULL); PyBaseArrayDim_FREE(shape.ptr); if (!ret) return NULL; ((PyBaseArrayObject *)(ret))->base = (PyObject *)ap; Py_INCREF(ap); PyBaseArray_UpdateFlags((PyBaseArrayObject *)ret, UPDATE_ALL_FLAGS); return ret; } finish: itemsize=ap->datatype->elsize; if (ap->flags & WRITEABLE) u = PyBuffer_FromReadWriteMemory(ip, itemsize); else u = PyBuffer_FromMemory(ip, itemsize); if (u==NULL) goto fail; /* Default is to return a buffer object pointing to the current item. */ return u; fail: return NULL; } /* Functions setitem specific for the supported datatypes. */ static int PyDataTypeSetitem_Bool(PyObject *op, char *ov, PyBaseArrayObject *ap) { Bool temp; int notswapped = PyDataType_ISNOTSWAPPED(ap->datatype); temp = (Bool)PyObject_IsTrue(op); if (PyErr_Occurred()) return -1; if ( (ap == NULL) || (notswapped && (ap->flags & ALIGNED)) ) *((Bool *)ov)=temp; else { ap->datatype->funcs->copyswap(ov, &temp, !notswapped, ap); } return 0; } static int PyDataTypeSetitem_Int(PyObject *op, char *ov, PyBaseArrayObject *ap) { int temp, notswapped = PyDataType_ISNOTSWAPPED(ap->datatype); temp = (int)PyInt_AsLong(op); if (PyErr_Occurred()) return -1; if ( (ap == NULL) || (notswapped && (ap->flags & ALIGNED)) ) *((int *)ov)=temp; else { ap->datatype->funcs->copyswap(ov, &temp, !notswapped, ap); } return 0; } static int PyDataTypeSetitem_Float(PyObject *op, char *ov, PyBaseArrayObject *ap) { float temp; int notswapped = PyDataType_ISNOTSWAPPED(ap->datatype); temp = (float)PyFloat_AsDouble(op); if (PyErr_Occurred()) return -1; if ( (ap == NULL) || (notswapped && (ap->flags & ALIGNED)) ) *((float *)ov)=temp; else { ap->datatype->funcs->copyswap(ov, &temp, !notswapped, ap); } return 0; } static int PyDataTypeSetitem_Complex(PyObject *op, char *ov, PyBaseArrayObject *ap) { Py_complex oop; PyObject *op2; cfloat temp; int rsize, notswapped = PyDataType_ISNOTSWAPPED(ap->datatype); if (PyBaseArray_CHECK(op) && (((PyBaseArrayObject *)(op))->ndim==0)) { op2 = ((PyBaseArrayObject *)op)->datatype->funcs-> \ getitem(((PyBaseArrayObject *)op)->data, (PyBaseArrayObject *)op); } else { op2 = op; Py_INCREF(op); } if (op2 == Py_None) { oop.real = oop.imag = NAN; } Py_DECREF(op2); if (PyErr_Occurred()) return -1; temp.real = (float) oop.real; temp.imag = (float) oop.imag; memcpy(ov, &temp, ap->datatype->elsize); if (!notswapped) byte_swap_vector(ov, 2, sizeof(float)); rsize = sizeof(float); copy_and_swap(ov, &temp, rsize, 2, rsize, !notswapped); return 0; } static int PyDataTypeSetitem_String(PyObject *op, char *ov, PyBaseArrayObject *ap) { char *ptr; int len; PyObject *temp=PyObject_Str(op); if (temp == NULL) return -1; if (PyString_AsStringAndSize(temp, &ptr, &len) == -1) { Py_DECREF(temp); return -1; } memcpy(ov, ptr, _MIN(ap->datatype->elsize,len)); if (ap->datatype->elsize > len) { memset(ov + len, 0, (ap->datatype->elsize - len)); } Py_DECREF(temp); return 0; } static int PyDataTypeSetitem_Object(PyObject *op, char *ov, PyBaseArrayObject *ap) { Py_INCREF(op); if (ap->flags & ALIGNED) { Py_XDECREF(*(PyObject **)ov); *(PyObject **)ov = op; } else { PyObject **obj; obj = (PyObject **)ov; Py_XDECREF(*obj); memcpy(ov, &op, sizeof(PyObject *)); } return PyErr_Occurred() ? -1:0; } static int PyDataTypeSetitem_Void(PyObject *op, char *ip, PyBaseArrayObject *ap) { PyDataTypeObject* descr; int res, itemsize=ap->datatype->elsize; descr = ap->datatype; if (descr->names && PyTuple_Check(op)) { PyObject *key, *names, *tup, *title; int i, n; PyDataTypeObject *new; int offset, savedflags; res = -1; /* Get the names from the fields dictionary. */ names = descr->names; n = PyTuple_GET_SIZE(names); if (PyTuple_GET_SIZE(op) != n) { PyErr_SetString(PyExc_ValueError, "Size of tuple must match number of fields."); return -1; } savedflags = ap->flags; for (i=0; ifields, key); if (!PyArg_ParseTuple(tup, "Oi|O", &new, &offset, &title)) { ap->datatype = descr; return -1; } ap->datatype = new; /* remember to update alignment flags */ if ((new->alignment > 1) && \ ((((intp)(ip+offset)) % new->alignment) != 0)) ap->flags &= ~ALIGNED; else ap->flags |= ALIGNED; res = new->funcs->setitem(PyTuple_GET_ITEM(op, i), ip+offset, ap); ap->flags = savedflags; if (res < 0) break; } ap->datatype = descr; return res; } if (descr->subarray) { /* copy into an array of the same basic type */ PyBaseArray_Dims shape={NULL,-1}; PyObject *ret; if (!(PyBaseArray_IntpConverter(descr->subarray->shape, &shape))) { PyBaseArrayDim_FREE(shape.ptr); PyErr_SetString(PyExc_ValueError, "invalid shape in fixed-type tuple."); return -1; } Py_INCREF(descr->subarray->base); ret = PyBaseArray_NewFromDataType(&PyBaseArray_Type, descr->subarray->base, shape.len, shape.ptr, NULL, ip, ap->flags, NULL); PyBaseArrayDim_FREE(shape.ptr); if (!ret) return -1; ((PyBaseArrayObject *)(ret))->base = (PyObject *)ap; Py_INCREF(ap); PyBaseArray_UpdateFlags((PyBaseArrayObject *)ret, UPDATE_ALL_FLAGS); /* res = PyArray_CopyObject((PyArrayObject *)ret, op); */ Py_DECREF(ret); return res; } /* Default is to use buffer interface to set item */ const void *buffer; int buflen; res = PyObject_AsReadBuffer(op, &buffer, &buflen); if (res == -1) goto fail; memcpy(ip, buffer, _MIN(buflen, itemsize)); return 0; fail: return -1; } /* Functions copyswap specific for the supported datatypes. */ static void PyDataTypeCopyswap_Bool(void *dst, void *src, int swap, void *arr) { /* Copy first if needed, otherwise ignore swap. */ if (src != NULL) memcpy(dst, src, sizeof(Bool)); } static void PyDataTypeCopyswap_Int (void *dst, void *src, int swap, void *arr) { int s = sizeof(int); /* Copy first if needed. */ if (src != NULL) memcpy(dst, src, s); if (swap) { register char *a, *b, c; a = (char *)dst; register int i, nn; b = a + s-1; nn = s / 2; for (i=0; idatatype->elsize); } } #define __ALIGNED(obj, sz) ((((size_t) obj) % (sz))==0) static void PyDataTypeCopyswap_Object(PyObject **dst, PyObject **src, int swap, void *arr) { if (src != NULL) { if ( __ALIGNED(dst,sizeof(PyObject **)) && __ALIGNED(src,sizeof(PyObject **)) ) { Py_INCREF(*src); Py_XDECREF(*dst); *dst = *src; } else { PyObject **dp=dst, **sp=src; Py_INCREF(*sp); Py_XDECREF(*dp); memcpy(dst, src, sizeof(PyObject *)); } } } static void PyDataTypeCopyswap_Void(char *dst, char *src, int swap, PyBaseArrayObject *arr) { if (arr==NULL) return; if (arr->datatype->fields) { PyObject *key, *value, *title=NULL; PyDataTypeObject *new, *descr; int offset, pos=0; descr = arr->datatype; while (PyDict_Next(descr->fields, &pos, &key, &value)) { if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) { arr->datatype=descr; return; } arr->datatype = new; new->funcs->copyswap(dst+offset, src+offset, swap, arr); } arr->datatype = descr; return; } if (src != NULL) { memcpy(dst, src, arr->datatype->elsize); } return; } /* Datatype-specific function structures. */ static PyDataTypeFuncs PyDataTypeFuncs_Bool = { (PyDataType_GetItemFunc *)PyDataTypeGetitem_Bool, (PyDataType_SetItemFunc *)PyDataTypeSetitem_Bool, (PyDataType_CopySwapFunc *)PyDataTypeCopyswap_Bool, }; static PyDataTypeFuncs PyDataTypeFuncs_Int = { (PyDataType_GetItemFunc *)PyDataTypeGetitem_Int, (PyDataType_SetItemFunc *)PyDataTypeSetitem_Int, (PyDataType_CopySwapFunc *)PyDataTypeCopyswap_Int, }; static PyDataTypeFuncs PyDataTypeFuncs_Float = { (PyDataType_GetItemFunc *)PyDataTypeGetitem_Float, (PyDataType_SetItemFunc *)PyDataTypeSetitem_Float, (PyDataType_CopySwapFunc *)PyDataTypeCopyswap_Float, }; static PyDataTypeFuncs PyDataTypeFuncs_Complex = { (PyDataType_GetItemFunc *)PyDataTypeGetitem_Complex, (PyDataType_SetItemFunc *)PyDataTypeSetitem_Complex, (PyDataType_CopySwapFunc *)PyDataTypeCopyswap_Complex, }; static PyDataTypeFuncs PyDataTypeFuncs_String = { (PyDataType_GetItemFunc *)PyDataTypeGetitem_String, (PyDataType_SetItemFunc *)PyDataTypeSetitem_String, (PyDataType_CopySwapFunc *)PyDataTypeCopyswap_String, }; static PyDataTypeFuncs PyDataTypeFuncs_Object = { (PyDataType_GetItemFunc *)PyDataTypeGetitem_Object, (PyDataType_SetItemFunc *)PyDataTypeSetitem_Object, (PyDataType_CopySwapFunc *)PyDataTypeCopyswap_Object, }; static PyDataTypeFuncs PyDataTypeFuncs_Void = { (PyDataType_GetItemFunc *)PyDataTypeGetitem_Void, (PyDataType_SetItemFunc *)PyDataTypeSetitem_Void, (PyDataType_CopySwapFunc *)PyDataTypeCopyswap_Void, }; /* Definitions of the supported datatypes. */ static PyDataTypeObject PyDataType_Bool = { PyObject_HEAD_INIT(&PyDataType_Type) &(Py_True->ob_type), /* PyTypeObject * typeobj */ PyDataType_BOOL, /* char kind */ PyDataType_IGNORE, /* char byteorder */ 0, /* char hasobject */ sizeof(Bool), /* int elsize */ _ALIGN(Bool), /* int alignment */ NULL, /* struct _arr_ *subarray */ NULL, /* PyObject * fields */ NULL, /* PyObject * names */ &PyDataTypeFuncs_Bool, /* PyDataTypeFuncs * funcs */ }; static PyDataTypeObject PyDataType_Int = { PyObject_HEAD_INIT(&PyDataType_Type) &PyInt_Type, /* PyTypeObject * typeobj */ PyDataType_INT, /* char kind */ PyDataType_NATIVE, /* char byteorder */ 0, /* char hasobject */ sizeof(int), /* int elsize */ _ALIGN(int), /* int alignment */ NULL, /* struct _arr_ *subarray */ NULL, /* PyObject * fields */ NULL, /* PyObject * names */ &PyDataTypeFuncs_Int, /* PyDataTypeFuncs * funcs */ }; static PyDataTypeObject PyDataType_Float = { PyObject_HEAD_INIT(&PyDataType_Type) &PyFloat_Type, /* PyTypeObject * typeobj */ PyDataType_FLOAT, /* char kind */ PyDataType_NATIVE, /* char byteorder */ 0, /* char hasobject */ sizeof(float), /* int elsize */ _ALIGN(float), /* int alignment */ NULL, /* struct _arr_ *subarray */ NULL, /* PyObject * fields */ NULL, /* PyObject * names */ &PyDataTypeFuncs_Float, /* PyDataTypeFuncs * funcs */ }; static PyDataTypeObject PyDataType_Complex = { PyObject_HEAD_INIT(&PyDataType_Type) &PyComplex_Type, /* PyTypeObject * typeobj */ PyDataType_COMPLEX, /* char kind */ PyDataType_NATIVE, /* char byteorder */ 0, /* char hasobject */ sizeof(cfloat), /* int elsize */ _ALIGN(cfloat), /* int alignment */ NULL, /* struct _arr_ *subarray */ NULL, /* PyObject * fields */ NULL, /* PyObject * names */ &PyDataTypeFuncs_Complex, /* PyDataTypeFuncs * funcs */ }; static PyDataTypeObject PyDataType_String = { PyObject_HEAD_INIT(&PyDataType_Type) &PyString_Type, /* PyTypeObject * typeobj */ PyDataType_STRING, /* char kind */ PyDataType_IGNORE, /* char byteorder */ 0, /* char hasobject */ sizeof(PyStringObject), /* int elsize */ _ALIGN(PyStringObject), /* int alignment */ NULL, /* struct _arr_ *subarray */ NULL, /* PyObject * fields */ NULL, /* PyObject * names */ &PyDataTypeFuncs_String /* PyDataTypeFuncs * funcs */ }; static PyDataTypeObject PyDataType_Object = { PyObject_HEAD_INIT(&PyDataType_Type) &PyType_Type, /* PyTypeObject * typeobj */ PyDataType_OBJECT, /* char kind */ PyDataType_IGNORE, /* char byteorder */ 1, /* char hasobject */ sizeof(PyObject), /* int elsize */ _ALIGN(PyObject), /* int alignment */ NULL, /* struct _arr_ *subarray */ NULL, /* PyObject * fields */ NULL, /* PyObject * names */ &PyDataTypeFuncs_Object, /* PyDataTypeFuncs * funcs */ }; static PyDataTypeObject PyDataType_Void = { PyObject_HEAD_INIT(&PyDataType_Type) &PyBuffer_Type, /* PyTypeObject * typeobj */ PyDataType_VOID, /* char kind */ PyDataType_IGNORE, /* char byteorder */ 0, /* char hasobject */ 0, /* int elsize */ 0, /* int alignment */ NULL, /* struct _arr_ *subarray */ NULL, /* PyObject * fields */ NULL, /* PyObject * names */ &PyDataTypeFuncs_Void, /* PyDataTypeFuncs * funcs */ }; /* Conversion functions. */ static PyDataTypeObject * PyDataType_FromKind(char kind) { if (kind == PyDataType_BOOL) return &PyDataType_Bool; if (kind == PyDataType_INT) return &PyDataType_Int; if (kind == PyDataType_FLOAT) return &PyDataType_Float; if (kind == PyDataType_COMPLEX) return &PyDataType_Complex; if (kind == PyDataType_STRING) return &PyDataType_String; if (kind == PyDataType_OBJECT) return &PyDataType_Object; if (kind == PyDataType_NOTYPE) return NULL; return &PyDataType_Void; }; #endif