/* Python Multiarray Module -- A useful collection of functions for creating and operating on array objects. In an ideal world this would be called arraymodule.c, but this can't be used due to conflits with the existing python array module (which this should replace). Copyright (c) 1995, 1996, 1997 Jim Hugunin, hugunin@mit.edu See file COPYING for details. */ #include "Python.h" #include #include #include "Numeric/arrayobject.h" static PyObject *MultiArrayError; /*Sets the maximum number of dimensions in an array to 40. If you ever need to change this I'd love to know more about your arrays. */ #define MAX_DIMS 30 static int compare_lists(int *l1, int *l2, int n) { int i; for(i=0;ind; else { if (nd != mps[i]->nd) { PyErr_SetString(PyExc_ValueError, "arrays must have same number of dimensions"); goto fail; } if (!compare_lists(mps[0]->dimensions+1, mps[i]->dimensions+1, nd-1)) { PyErr_SetString(PyExc_ValueError, "array dimensions must agree except for d_0"); goto fail; } } if (nd == 0) { PyErr_SetString(PyExc_ValueError, "0d arrays can't be concatenated"); goto fail; } new_dim += mps[i]->dimensions[0]; } tmp = mps[0]->dimensions[0]; mps[0]->dimensions[0] = new_dim; ret = (PyArrayObject *)PyArray_FromDims(nd, mps[0]->dimensions, type_num); mps[0]->dimensions[0] = tmp; if (ret == NULL) goto fail; data = ret->data; for(i=0; idata, PyArray_NBYTES(mps[i])); data += PyArray_NBYTES(mps[i]); } PyArray_INCREF(ret); for(i=0; idescr->elsize; for (i = ap->nd-1; i >= 0; --i) { /* contiguous by definition */ if (ap->dimensions[i] == 0) return 1; if (ap->strides[i] != sd) return 0; sd *= ap->dimensions[i]; } return 1; } /* Changed to be able to deal with non-contiguous arrays. */ extern PyObject *PyArray_Transpose(PyArrayObject *ap, PyObject *op) { long *axes, axis; int i, n; int *permutation = NULL; PyArrayObject *ret = NULL; if (op == Py_None) { n = ap->nd; permutation = (int *)malloc(n*sizeof(int)); for(i=0; ind+axis; if (axis < 0 || axis >= ap->nd) { PyErr_SetString(PyExc_ValueError, "invalid axis for this array"); goto fail; } permutation[i] = axis; } } /* this allocates memory for dimensions and strides (but fills them incorrectly), sets up descr, and points data at ap->data. */ ret = (PyArrayObject *)PyArray_FromDimsAndData(n, permutation, ap->descr->type_num, ap->data); if (ret == NULL) goto fail; /* point at true owner of memory: */ ret->base = (PyObject *)ap; Py_INCREF(ap); for(i=0; idimensions[i] = ap->dimensions[permutation[i]]; ret->strides[i] = ap->strides[permutation[i]]; } if (array_really_contiguous(ret)) ret->flags |= CONTIGUOUS; else ret->flags &= ~CONTIGUOUS; if (op != Py_None) PyArray_Free(op, (char *)axes); free(permutation); return (PyObject *)ret; fail: Py_XDECREF(ret); if (permutation != NULL) free(permutation); if (op != Py_None) PyArray_Free(op, (char *)axes); return NULL; } extern PyObject *PyArray_Repeat(PyObject *aop, PyObject *op, int axis) { long *counts; int n, n_outer, i, j, k, chunk, total, tmp; PyArrayObject *ret=NULL, *ap; char *new_data, *old_data; ap = (PyArrayObject *)PyArray_ContiguousFromObject(aop, PyArray_NOTYPE, 0, 0); if (axis < 0) axis = ap->nd+axis; if (axis < 0 || axis >= ap->nd) { PyErr_SetString(PyExc_ValueError, "axis is invalid"); return NULL; } if (PyArray_As1D(&op, (char **)&counts, &n, PyArray_LONG) == -1) return NULL; if (n != ap->dimensions[axis]) { PyErr_SetString(PyExc_ValueError, "len(n) != a.shape[axis]"); goto fail; } total = 0; for(j=0; jdimensions[axis]; ap->dimensions[axis] = total; ret = (PyArrayObject *)PyArray_FromDims(ap->nd, ap->dimensions, ap->descr->type_num); ap->dimensions[axis] = tmp; if (ret == NULL) goto fail; new_data = ret->data; old_data = ap->data; chunk = ap->descr->elsize; for(i=axis+1; ind; i++) { chunk *= ap->dimensions[i]; } n_outer = 1; for(i=0; idimensions[i]; for(i=0; ind < mps[i]->nd) { PyErr_SetString(PyExc_ValueError, "too many dimensions"); goto fail; } if (!compare_lists(ap->dimensions+(ap->nd-mps[i]->nd), mps[i]->dimensions, mps[i]->nd)) { PyErr_SetString(PyExc_ValueError, "array dimensions must agree"); goto fail; } sizes[i] = PyArray_NBYTES(mps[i]); } ret = (PyArrayObject *)PyArray_FromDims(ap->nd, ap->dimensions, type_num); if (ret == NULL) goto fail; elsize = ret->descr->elsize; m = PyArray_SIZE(ret); self_data = (long *)ap->data; ret_data = ret->data; for (i=0; i= n) { PyErr_SetString(PyExc_ValueError, "invalid entry in choice array"); goto fail; } offset = i*elsize; if (offset >= sizes[mi]) {offset = offset % sizes[mi]; } memmove(ret_data, mps[mi]->data+offset, elsize); ret_data += elsize; self_data++; } PyArray_INCREF(ret); for(i=0; idescr->type_num]; if (compare_func == NULL) { PyErr_SetString(PyExc_TypeError, "compare not supported for type"); Py_XDECREF(ap); return NULL; } elsize = ap->descr->elsize; m = ap->dimensions[ap->nd-1]; if (m == 0) { return PyArray_Return(ap); } n = PyArray_SIZE(ap)/m; for (ip = ap->data, i=0; ind, ap->dimensions, PyArray_LONG); if (ret == NULL) goto fail; argsort_compare_func = compare_functions[ap->descr->type_num]; if (argsort_compare_func == NULL) { PyErr_SetString(PyExc_TypeError, "compare not supported for type"); goto fail; } ip = (long *)ret->data; argsort_elsize = ap->descr->elsize; m = ap->dimensions[ap->nd-1]; if (m == 0) { Py_XDECREF(ap); return PyArray_Return(ret); } n = PyArray_SIZE(ap)/m; argsort_data = ap->data; for (i=0; i 0) { if (compare(ip, vp+elsize*(--i)) != 0) { i = i+1; break; } } return i; } if (location < 0) { max_i = i; } else { min_i = i+1; } } return min_i; } extern PyObject *PyArray_BinarySearch(PyObject *op1, PyObject *op2) { PyArrayObject *ap1, *ap2, *ret; int m, n, i, elsize; char *ip; long *rp; CompareFunction compare_func; int typenum = 0; typenum = PyArray_ObjectType(op1, 0); typenum = PyArray_ObjectType(op2, typenum); ret = NULL; ap1 = (PyArrayObject *)PyArray_ContiguousFromObject(op1, typenum, 1, 1); if (ap1 == NULL) return NULL; ap2 = (PyArrayObject *)PyArray_ContiguousFromObject(op2, typenum, 0, 0); if (ap2 == NULL) goto fail; ret = (PyArrayObject *)PyArray_FromDims(ap2->nd, ap2->dimensions, PyArray_LONG); if (ret == NULL) goto fail; compare_func = compare_functions[ap2->descr->type_num]; if (compare_func == NULL) { PyErr_SetString(PyExc_TypeError, "compare not supported for type"); goto fail; } elsize = ap1->descr->elsize; m = ap1->dimensions[ap1->nd-1]; n = PyArray_Size((PyObject *)ap2); for (rp = (long *)ret->data, ip=ap2->data, i=0; idata, elsize, m, compare_func); } Py_DECREF(ap1); Py_DECREF(ap2); return PyArray_Return(ret); fail: Py_XDECREF(ap1); Py_XDECREF(ap2); Py_XDECREF(ret); return NULL; } /* Rather than build a generic inner product, this is just dot product. */ #define DOT_PRODUCT(name, number) \ static void name(char *ip1, int is1, char *ip2, int is2, char *op, int n) { \ number tmp=(number)0.0; int i; \ for(i=0;ind == 0 || ap2->nd == 0) { PyErr_SetString(PyExc_TypeError, "scalar arguments not allowed"); goto fail; } l = ap1->dimensions[ap1->nd-1]; if (ap2->dimensions[ap2->nd-1] != l) { PyErr_SetString(PyExc_ValueError, "matrices are not aligned"); goto fail; } if (l == 0) n1 = n2 = 0; else { n1 = PyArray_SIZE(ap1)/l; n2 = PyArray_SIZE(ap2)/l; } nd = ap1->nd+ap2->nd-2; j = 0; for(i=0; ind-1; i++) { dimensions[j++] = ap1->dimensions[i]; } for(i=0; ind-1; i++) { dimensions[j++] = ap2->dimensions[i]; } ret = (PyArrayObject *)PyArray_FromDims(nd, dimensions, typenum); if (ret == NULL) goto fail; dot = matrixMultiplyFunctions[(int)(ret->descr->type_num)]; if (dot == NULL) { PyErr_SetString(PyExc_ValueError, "matrixMultiply not available for this type"); goto fail; } is1 = ap1->strides[ap1->nd-1]; is2 = ap2->strides[ap2->nd-1]; op = ret->data; os = ret->descr->elsize; ip1 = ap1->data; for(i1=0; i1data; for(i2=0; i2nd == 0 || ap2->nd == 0) { /* handle the use of dot with scalers here */ PyErr_SetString(PyExc_TypeError, "scalar arguments not allowed"); goto fail; } l = ap1->dimensions[ap1->nd-1]; if (ap2->nd > 1) { matchDim = ap2->nd - 2; otherDim = ap2->nd - 1; } else { matchDim = 0; otherDim = 0; } /* fprintf(stderr, "ap1->nd=%d ap2->nd=%d\n", ap1->nd, ap2->nd); */ if (ap2->dimensions[matchDim] != l) { PyErr_SetString(PyExc_ValueError, "matrices are not aligned"); goto fail; } if (l == 0) n1 = n2 = 0; else { n1 = PyArray_SIZE(ap1)/l; n2 = PyArray_SIZE(ap2)/l; } nd = ap1->nd+ap2->nd-2; j = 0; for(i=0; ind-1; i++) { dimensions[j++] = ap1->dimensions[i]; } for(i=0; ind-2; i++) { dimensions[j++] = ap2->dimensions[i]; } if(ap2->nd > 1) { dimensions[j++] = ap2->dimensions[ap2->nd-1]; } /* fprintf(stderr, "nd=%d dimensions=", nd); for(i=0; idescr->type_num)]; if (dot == NULL) { PyErr_SetString(PyExc_ValueError, "matrixMultiply not available for this type"); goto fail; } is1 = ap1->strides[ap1->nd-1]; is2 = ap2->strides[matchDim]; if(ap1->nd > 1) is1r = ap1->strides[ap1->nd-2]; else is1r = ap1->strides[ap1->nd-1]; is2r = ap2->strides[otherDim]; /* fprintf(stderr, "n1=%d n2=%d is1=%d is2=%d\n", n1, n2, is1, is2); */ op = ret->data; os = ret->descr->elsize; ip1 = ap1->data; for(i1=0; i1data; for(i2=0; i2nd; if(nd == 1) { return PyArray_Copy(ap); } /* swap the dimensions and strides so that the copy will transpose */ t = ap->strides[0]; ap->strides[0] = ap->strides[1]; ap->strides[1] = t; t = ap->dimensions[0]; ap->dimensions[0] = ap->dimensions[1]; ap->dimensions[1] = t; /* create the copy and transposing */ ret = (PyArrayObject*)PyArray_Copy(ap); /* swap them back */ t = ap->strides[0]; ap->strides[0] = ap->strides[1]; ap->strides[1] = t; t = ap->dimensions[0]; ap->dimensions[0] = ap->dimensions[1]; ap->dimensions[1] = t; /* PyArray_Free(tmp); */ Py_DECREF(ap); return PyArray_Return(ret); } extern PyObject *PyArray_Correlate(PyObject *op1, PyObject *op2, int mode) { PyArrayObject *ap1, *ap2, *ret; int length; int i, n1, n2, n, n_left, n_right; int typenum; int is1, is2, os; char *ip1, *ip2, *op; DotFunction *dot; typenum = PyArray_ObjectType(op1, 0); typenum = PyArray_ObjectType(op2, typenum); ret = NULL; ap1 = (PyArrayObject *)PyArray_ContiguousFromObject(op1, typenum, 1, 1); if (ap1 == NULL) return NULL; ap2 = (PyArrayObject *)PyArray_ContiguousFromObject(op2, typenum, 1, 1); if (ap2 == NULL) goto fail; n1 = ap1->dimensions[ap1->nd-1]; n2 = ap2->dimensions[ap2->nd-1]; if (n1 < n2) { ret = ap1; ap1 = ap2; ap2 = ret; ret = NULL; i = n1;n1=n2;n2=i;} length = n1; n = n2; switch(mode) { case 0: length = length-n+1; n_left = n_right = 0; break; case 1: n_left = (int)(n/2); n_right = n-n_left-1; break; case 2: n_right = n-1; n_left = n-1; length = length+n-1; break; default: PyErr_SetString(PyExc_ValueError, "mode must be 0,1, or 2"); goto fail; } ret = (PyArrayObject *)PyArray_FromDims(1, &length, typenum); if (ret == NULL) goto fail; dot = matrixMultiplyFunctions[(int)(ret->descr->type_num)]; if (dot == NULL) { PyErr_SetString(PyExc_ValueError, "function not available for this type"); goto fail; } is1 = ap1->strides[ap1->nd-1]; is2 = ap2->strides[ap2->nd-1]; op = ret->data; os = ret->descr->elsize; ip1 = ap1->data; ip2 = ap2->data+n_left*is2; n = n-n_left; for(i=0; i) ARGFUNC(FLOAT_argmax, float, >) ARGFUNC(LONG_argmax, long, >) ARGFUNC(INT_argmax, int, >) ARGFUNC(UINT_argmax, int, >) ARGFUNC(SHORT_argmax, short, >) ARGFUNC(UNSIGNEDSHORT_argmax, unsigned short, >) ARGFUNC(BYTE_argmax, signed char, >) ARGFUNC(UNSIGNEDBYTE_argmax, unsigned char, >) int OBJECT_argmax(PyObject **ip, long n, long *ap) { long i; PyObject *mp=ip[0]; *ap=0; for(i=1; i 0) { mp = ip[i]; *ap=i; } } return 0; } static ArgFunction argmax_functions[] = { NULL, (ArgFunction) UNSIGNEDBYTE_argmax, (ArgFunction) BYTE_argmax, (ArgFunction)SHORT_argmax, (ArgFunction)UNSIGNEDSHORT_argmax, (ArgFunction)INT_argmax, (ArgFunction)UINT_argmax, (ArgFunction)LONG_argmax, (ArgFunction)FLOAT_argmax, (ArgFunction)DOUBLE_argmax, NULL, NULL, (ArgFunction)OBJECT_argmax }; extern PyObject *PyArray_ArgMax(PyObject *op) { PyArrayObject *ap, *rp; ArgFunction arg_func; char *ip; int i, n, m, elsize; rp = NULL; ap = (PyArrayObject *)PyArray_ContiguousFromObject(op, PyArray_NOTYPE, 1, 0); if (ap == NULL) return NULL; arg_func = argmax_functions[ap->descr->type_num]; if (arg_func == NULL) { PyErr_SetString(PyExc_TypeError, "type not ordered"); goto fail; } rp = (PyArrayObject *)PyArray_FromDims(ap->nd-1, ap->dimensions, PyArray_LONG); if (rp == NULL) goto fail; elsize = ap->descr->elsize; m = ap->dimensions[ap->nd-1]; if (m == 0) { PyErr_SetString(MultiArrayError, "Attempt to get argmax/argmin of an empty sequence??"); goto fail; } n = PyArray_SIZE(ap)/m; for (ip = ap->data, i=0; idata)+i); } Py_DECREF(ap); return PyArray_Return(rp); fail: Py_DECREF(ap); Py_XDECREF(rp); return NULL; } /************* ARGFUNC(DOUBLE_argmin, double, <) ARGFUNC(FLOAT_argmin, float, <) ARGFUNC(LONG_argmin, long, <) ARGFUNC(INT_argmin, int, <) ARGFUNC(UINT_argmin, int, <) ARGFUNC(SHORT_argmin, short, <) ARGFUNC(UNSIGNEDSHORT_argmin, unsigned short, <) int OBJECT_argmin(PyObject **ip, long n, PyObject **mp, long *ap) { long i; *mp=ip[0]; *ap=0; for(i=1; i 1) ) { PyErr_SetString(PyExc_TypeError, "typecode argument must be a valid type."); return NULL; } if (tp[0] == 0) type = PyArray_NOTYPE; else { type = tp[0]; if (!PyArray_ValidType(type)) { PyErr_SetString(PyExc_TypeError, "typecode argument must be a valid type."); return NULL; } } } /* fast exit if simple call */ if (PyArray_Check(op) && (copy==0) && (savespace==PyArray_ISSPACESAVER(op))) { if ((type == PyArray_NOTYPE) || (type == ((PyArrayObject *)op)->descr->type_num )) { Py_INCREF(op); return op; } } if (savespace != 0) type |= SAVESPACEBIT; if (copy) { if ((ret = PyArray_CopyFromObject(op, type, 0, 0)) == NULL) return NULL; } else { if ((ret = PyArray_FromObject(op, type, 0, 0)) == NULL) return NULL; } if (savespace |= 0 || (PyArray_Check(op) && PyArray_ISSPACESAVER(op))) ((PyArrayObject *)ret)->flags |= SAVESPACE; return ret; } static char doc_empty[] = "empty((d1,...,dn),typecode='l',savespace=0) will return a new array\n"\ "of shape (d1,...,dn) and given type with all its entries uninitialized. If savespace is\n" \ "nonzero, the array will be a spacesaver array. This can be faster than zeros."; static PyObject *array_empty(PyObject *ignored, PyObject *args, PyObject *kwds) { PyObject *sequence; char type='l'; int savespace=0; static char *kwlist[] = {"shape", "typecode", "savespace", NULL}; PyObject *op; PyArray_Descr *descr; int i, nd, n, dims[MAX_DIMS]; int sd; char *data; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ci", kwlist, &sequence, &type, &savespace)) { return NULL; } if ((descr = PyArray_DescrFromType((int)type)) == NULL) return NULL; if ((nd=PySequence_Length(sequence)) == -1) { PyErr_Clear(); nd = 1; dims[0] = PyArray_IntegerAsInt(sequence); if (PyErr_Occurred()) return NULL; } else { if (nd > MAX_DIMS) { fprintf(stderr, "Maximum number of dimensions = %d\n", MAX_DIMS); PyErr_SetString(PyExc_ValueError, "Number of dimensions is too large"); return NULL; } for(i=0; ielsize; for(i=nd-1;i>=0;i--) { if (dims[i] < 0) { PyErr_SetString(PyExc_ValueError, "negative dimensions are not allowed"); return NULL; } sd *= dims[i] ? dims[i] : 1; } /* Make sure we're alligned on ints. */ sd += sizeof(int) - sd%sizeof(int); /* allocate memory */ if ((data = (char *)malloc(sd)) == NULL) { PyErr_SetString(PyExc_MemoryError, "can't allocate memory for array"); return NULL; } if ((op = PyArray_FromDimsAndDataAndDescr(nd, dims, descr, data))==NULL) return NULL; /* we own the data (i.e. this informs the delete function to free the memory) */ ((PyArrayObject *)op)->flags |= OWN_DATA; if (savespace) ((PyArrayObject *)op)->flags |= SAVESPACE; if (descr->type_num == PyArray_OBJECT) { PyObject **optr; /* Fill it with Py_None */ n = PyArray_SIZE(((PyArrayObject *)op)); optr = (PyObject **)((PyArrayObject *)op)->data; for(i=0; i MAX_DIMS) { fprintf(stderr, "Maximum number of dimensions = %d\n", MAX_DIMS); PyErr_SetString(PyExc_ValueError, "Number of dimensions is too large"); return NULL; } for(i=0; idescr->zero, all_zero, ret->descr->elsize) == 0) { memset(ret->data,0,PyArray_Size((PyObject *)ret)*ret->descr->elsize); } else { dptr = ret->data; n = PyArray_SIZE(ret); for(i=0; idescr->zero, ret->descr->elsize); dptr += ret->descr->elsize; } } PyArray_INCREF(ret); if (savespace) ret->flags |= SAVESPACE; return (PyObject *)ret; } static char doc_fromString[] = "fromstring(string, typecode='l', count=-1) returns a new 1d array initialized from the raw binary data in string. If count is positive, the new array will have count elements, otherwise it's size is determined by the size of string."; static PyObject *array_fromString(PyObject *ignored, PyObject *args, PyObject *keywds) { PyArrayObject *ret; char *type_char = "l"; char *type; char *data; int s, n; PyObject* nobj; PyArray_Descr *descr; static char *kwlist[] = {"string", "typecode", "count", NULL}; nobj = (PyObject *) 0; type = type_char; n = -1; if (!PyArg_ParseTupleAndKeywords(args, keywds, "s#|si", kwlist, &data, &s, &type, &n)) { return NULL; } if ((descr = PyArray_DescrFromType(*type)) == NULL) { return NULL; } if (n < 0 ) { if (s % descr->elsize != 0) { PyErr_SetString(PyExc_ValueError, "string size must be a multiple of element size"); return NULL; } n = s/descr->elsize; } else { if (s < n*descr->elsize) { PyErr_SetString(PyExc_ValueError, "string is smaller than requested size"); return NULL; } } if ((ret = (PyArrayObject *)PyArray_FromDims(1, &n, *type)) == NULL) return NULL; memmove(ret->data, data, n*ret->descr->elsize); PyArray_INCREF(ret); return (PyObject *)ret; } static char doc_take[] = "take(a, indices, axis=0). Selects the elements in indices from array a along the given axis."; static PyObject *array_take(PyObject *dummy, PyObject *args, PyObject *kwds) { int dimension; PyObject *a, *indices, *ret; static char *kwlist[] = {"array", "indices", "axis", NULL}; dimension=0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i", kwlist, &a, &indices, &dimension)) return NULL; ret = PyArray_Take(a, indices, dimension); return ret; } static char doc_put[] = "put(a, indices, values) sets a.flat[n] = v[n] for each n in indices. v can be scalar or shorter than indices, will repeat."; static PyObject *array_put(PyObject *dummy, PyObject *args) { PyObject *a, *indices, *ret, *values; if (!PyArg_ParseTuple(args, "OOO", &a, &indices, &values)) return NULL; ret = PyArray_Put(a, indices, values); return ret; } static char doc_putmask[] = "putmask(a, mask, values) sets a.flat[n] = v[n] for each n where mask.flat[n] is true. v can be scalar."; static PyObject *array_putmask(PyObject *dummy, PyObject *args) { PyObject *a, *mask, *ret, *values; if (!PyArg_ParseTuple(args, "OOO", &a, &mask, &values)) return NULL; ret = PyArray_PutMask(a, mask, values); return ret; } static char doc_reshape[] = "reshape(a, (d1, d2, ..., dn)). Change the shape of a to be an n-dimensional array with dimensions given by d1...dn. Note: the size specified for the new array must be exactly equal to the size of the old one or an error will occur."; static PyObject *array_reshape(PyObject *dummy, PyObject *args) { PyObject *shape, *ret, *a0; PyArrayObject *a; if (!PyArg_ParseTuple(args, "OO", &a0, &shape)) return NULL; if ((a = (PyArrayObject *)PyArray_ContiguousFromObject(a0, PyArray_NOTYPE,0,0)) ==NULL) return NULL; ret = PyArray_Reshape(a, shape); Py_DECREF(a); return ret; } static char doc_concatenate[] = "concatenate((a1,a2,...))."; static PyObject *array_concatenate(PyObject *dummy, PyObject *args) { PyObject *a0; if (!PyArg_ParseTuple(args, "O", &a0)) return NULL; return PyArray_Concatenate(a0); } static char doc_transpose[] = "transpose(a, axes=None)"; static PyObject *array_transpose(PyObject *dummy, PyObject *args, PyObject *kwds) { PyObject *shape=Py_None, *ret, *a0; PyArrayObject *a; static char *kwlist[] = {"array", "axes", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &a0, &shape)) return NULL; if ((a = (PyArrayObject *)PyArray_FromObject(a0, PyArray_NOTYPE,0,0)) ==NULL) return NULL; ret = PyArray_Transpose(a, shape); Py_DECREF(a); return ret; } static char doc_repeat[] = "repeat(a, n, axis=0)"; static PyObject *array_repeat(PyObject *dummy, PyObject *args, PyObject *kwds) { PyObject *shape, *a0; int axis=0; static char *kwlist[] = {"array", "shape", "axis", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i", kwlist, &a0, &shape, &axis)) return NULL; return PyArray_Repeat(a0, shape, axis); } static char doc_choose[] = "choose(a, (b1,b2,...))"; static PyObject *array_choose(PyObject *dummy, PyObject *args) { PyObject *shape, *a0; if (!PyArg_ParseTuple(args, "OO", &a0, &shape)) return NULL; return PyArray_Choose(a0, shape); } static char doc_sort[] = "sort(a)"; static PyObject *array_sort(PyObject *dummy, PyObject *args) { PyObject *a0; if (!PyArg_ParseTuple(args, "O", &a0)) return NULL; return PyArray_Sort(a0); } static char doc_argsort[] = "argsort(a)"; static PyObject *array_argsort(PyObject *dummy, PyObject *args) { PyObject *a0; if (!PyArg_ParseTuple(args, "O", &a0)) return NULL; return PyArray_ArgSort(a0); } static char doc_binarysearch[] = "binarysearch(a,v)"; static PyObject *array_binarysearch(PyObject *dummy, PyObject *args) { PyObject *shape, *a0; if (!PyArg_ParseTuple(args, "OO", &a0, &shape)) return NULL; return PyArray_BinarySearch(a0, shape); } static char doc_innerproduct[] = "innerproduct(a,v)"; static PyObject *array_innerproduct(PyObject *dummy, PyObject *args) { PyObject *shape, *a0; if (!PyArg_ParseTuple(args, "OO", &a0, &shape)) return NULL; return PyArray_InnerProduct(a0, shape); } static char doc_matrixproduct[] = "matrixproduct(a,v)"; static PyObject *array_matrixproduct(PyObject *dummy, PyObject *args) { PyObject *shape, *a0; if (!PyArg_ParseTuple(args, "OO", &a0, &shape)) return NULL; return PyArray_MatrixProduct(a0, shape); } static char doc_fastCopyAndTranspose[] = "_fastCopyAndTranspose(a)"; static PyObject *array_fastCopyAndTranspose(PyObject *dummy, PyObject *args) { PyObject *a0; if (!PyArg_ParseTuple(args, "O", &a0)) return NULL; return PyArray_fastCopyAndTranspose(a0); } static char doc_correlate[] = "cross_correlate(a,v, mode=0)"; static PyObject *array_correlate(PyObject *dummy, PyObject *args, PyObject *kwds) { PyObject *shape, *a0; int mode=0; static char *kwlist[] = {"a", "v", "mode", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i", kwlist, &a0, &shape, &mode)) return NULL; return PyArray_Correlate(a0, shape, mode); } static char doc_argmax[] = "argmax(a)"; static PyObject *array_argmax(PyObject *dummy, PyObject *args) { PyObject *a0; if (!PyArg_ParseTuple(args, "O", &a0)) return NULL; return PyArray_ArgMax(a0); } static char doc_arange[] = "arange(start, stop=None, step=1, typecode=None)\n\n Just like range() except it returns an array whose type can be\n specified by the keyword argument typecode."; static PyObject * array_arange(PyObject *ignored, PyObject *args, PyObject *kws) { PyObject *o_start=NULL, *o_stop=Py_None, *o_step=NULL; PyObject *tpo=Py_None, *range; static char *kwd[]= {"start", "stop", "step", "typecode", NULL}; char *tp=NULL; char *rptr; int elsize; double start, stop, step, value; int type, length, i; int deftype = PyArray_LONG; PyArray_Descr *dbl_descr; if(!PyArg_ParseTupleAndKeywords(args, kws, "O|OOO", kwd, &o_start, &o_stop, &o_step, &tpo)) return NULL; deftype = PyArray_ObjectType(o_start, deftype); if (o_stop != Py_None) { deftype = PyArray_ObjectType(o_stop, deftype); } if (o_step != NULL) { deftype = PyArray_ObjectType(o_step, deftype); } if (tpo == Py_None) { type = deftype; } else { tp = PyString_AsString(tpo); if (tp == NULL) { PyErr_SetString(PyExc_TypeError, "typecode argument must be a string."); return NULL; } if (tp[0] == 0) type = deftype; else type = tp[0]; } start = PyFloat_AsDouble(o_start); if ((start == -1.0) && (PyErr_Occurred() != NULL)) return NULL; if (o_step == NULL) { step = 1; } else { step = PyFloat_AsDouble(o_step); if ((step == -1.0) && (PyErr_Occurred() != NULL)) return NULL; } if (o_stop == Py_None) { stop = start; start = 0; } else { stop = PyFloat_AsDouble(o_stop); if ((stop == -1.0) && (PyErr_Occurred() != NULL)) return NULL; } length = (int ) ceil((stop - start)/step); if (length <= 0) { length = 0; return PyArray_FromDims(1, &length, type); } range = PyArray_FromDims(1,&length, type); if (range == NULL) return NULL; dbl_descr = PyArray_DescrFromType(PyArray_DOUBLE); rptr = ((PyArrayObject *)range)->data; elsize = ((PyArrayObject *)range)->descr->elsize; type = ((PyArrayObject *)range)->descr->type_num; for (i=0; i < length; i++) { value = start + i*step; dbl_descr->cast[type]((char*)&value, 0, rptr, 0, 1); rptr += elsize; } return range; } /***** static char doc_arrayMap[] = "arrayMap(func, [a1,...,an])"; static PyObject *array_arrayMap(PyObject *dummy, PyObject *args) { PyObject *shape, *a0; if (PyArg_ParseTuple(args, "OO", &a0, &shape) == NULL) return NULL; return PyArray_Map(a0, shape); } *****/ static char doc_set_string_function[] = "set_string_function(f, repr=1) sets the python function f to be the function used to obtain a pretty printable string version of a array whenever a array is printed. f(M) should expect a array argument M, and should return a string consisting of the desired representation of M for printing."; static PyObject *array_set_string_function(PyObject *dummy, PyObject *args, PyObject *kwds) { PyObject *op; int repr=1; static char *kwlist[] = {"f", "repr", NULL}; if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &op, &repr)) return NULL; PyArray_SetStringFunction(op, repr); Py_INCREF(Py_None); return Py_None; } static struct PyMethodDef array_module_methods[] = { {"set_string_function", (PyCFunction)array_set_string_function, METH_VARARGS|METH_KEYWORDS, doc_set_string_function}, {"array", (PyCFunction)array_array, METH_VARARGS|METH_KEYWORDS, doc_array}, {"arange", (PyCFunction)array_arange, METH_VARARGS|METH_KEYWORDS, doc_arange}, {"zeros", (PyCFunction)array_zeros, METH_VARARGS|METH_KEYWORDS, doc_zeros}, {"empty", (PyCFunction)array_empty, METH_VARARGS|METH_KEYWORDS, doc_empty}, {"fromstring",(PyCFunction)array_fromString, METH_VARARGS|METH_KEYWORDS, doc_fromString}, {"take", (PyCFunction)array_take, METH_VARARGS|METH_KEYWORDS, doc_take}, {"put", (PyCFunction)array_put, METH_VARARGS, doc_put}, {"putmask", (PyCFunction)array_putmask, METH_VARARGS, doc_putmask}, {"reshape", (PyCFunction)array_reshape, METH_VARARGS, doc_reshape}, {"concatenate", (PyCFunction)array_concatenate, METH_VARARGS, doc_concatenate}, {"transpose", (PyCFunction)array_transpose, METH_VARARGS|METH_KEYWORDS, doc_transpose}, {"repeat", (PyCFunction)array_repeat, METH_VARARGS|METH_KEYWORDS, doc_repeat}, {"choose", (PyCFunction)array_choose, METH_VARARGS, doc_choose}, {"sort", (PyCFunction)array_sort, METH_VARARGS, doc_sort}, {"argsort", (PyCFunction)array_argsort, METH_VARARGS, doc_argsort}, {"binarysearch", (PyCFunction)array_binarysearch, METH_VARARGS, doc_binarysearch}, {"argmax", (PyCFunction)array_argmax, METH_VARARGS, doc_argmax}, {"innerproduct", (PyCFunction)array_innerproduct, METH_VARARGS, doc_innerproduct}, {"matrixproduct", (PyCFunction)array_matrixproduct, METH_VARARGS, doc_matrixproduct}, {"_fastCopyAndTranspose", (PyCFunction)array_fastCopyAndTranspose, METH_VARARGS, doc_fastCopyAndTranspose}, {"cross_correlate", (PyCFunction)array_correlate, METH_VARARGS | METH_KEYWORDS, doc_correlate}, /* {"arrayMap", (PyCFunction)array_arrayMap, 1, doc_arrayMap},*/ {NULL, NULL, 0} /* sentinel */ }; /* Initialization function for the module (*must* be called initArray) */ DL_EXPORT(void) initmultiarray(void) { PyObject *m, *d, *s, *one, *zero; int i; char *data; PyArray_Descr *descr; /* Create the module and add the functions */ m = Py_InitModule("multiarray", array_module_methods); /* Import the array object */ import_array(); /* Add some symbolic constants to the module */ d = PyModule_GetDict(m); MultiArrayError = PyErr_NewException("multiarray.error", NULL, NULL); PyDict_SetItemString (d, "error", MultiArrayError); s = PyString_FromString("0.30"); PyDict_SetItemString(d, "__version__", s); Py_DECREF(s); PyDict_SetItemString(d, "arraytype", (PyObject *)&PyArray_Type); /*Load up the zero and one values for the types.*/ one = PyInt_FromLong(1); zero = PyInt_FromLong(0); for(i=PyArray_CHAR; ielsize); memset(data, 0, descr->elsize); descr->setitem(one, data); descr->one = data; data = (char *)malloc(descr->elsize); memset(data, 0, descr->elsize); descr->setitem(zero, data); descr->zero = data; } Py_DECREF(zero); Py_DECREF(one); /* Check for errors */ if (PyErr_Occurred()) Py_FatalError("can't initialize module array"); }