static PyObject *softplus_(PyObject *self, PyObject *args) { PyArrayObject *input, *output; int i; if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &input, &PyArray_Type, &output)) return NULL; if ( (NULL == input) || (NULL == output) ) return NULL; if ( (input->descr->type_num != NPY_DOUBLE) || (output->descr->type_num != NPY_DOUBLE) || !PyArray_CHKFLAGS(input,NPY_C_CONTIGUOUS|NPY_ALIGNED) || !PyArray_CHKFLAGS(output,NPY_C_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) ) { PyErr_SetString(PyExc_ValueError, "In softplus_: all arguments must be of type double, C contiguous and aligned, and output should be writeable"); return NULL; } if ( (input->nd != output->nd) ) { PyErr_SetString(PyExc_ValueError, "In softplus_: both arguments should have the same dimensionality"); return NULL; } int tot_dim = 1; for (i=0; i<input->nd; i++) { if ( (input->dimensions[i] != output->dimensions[i]) ) { PyErr_SetString(PyExc_ValueError, "In softplus_: all dimensions of both arguments should be equal"); return NULL; } tot_dim *= input->dimensions[i]; } double * input_data_iter = (double *) input->data; double * output_data_iter = (double *) output->data; double input_data; for (i=0; i<tot_dim; i++) { input_data = *input_data_iter++; if(input_data > 0) *output_data_iter++ = input_data + log(1+exp(-input_data)); else *output_data_iter++ = log(1+exp(input_data)); // if(input_data > 35) // *output_data_iter++ = input_data; // else // if(input_data < -40) // *output_data_iter++ = 0; // else // *output_data_iter++ = log(1+exp(input_data)); } Py_RETURN_NONE; }
static PyObject *dreclin_(PyObject *self, PyObject *args) { PyArrayObject *output,*doutput,*dinput; int i; if (!PyArg_ParseTuple(args, "O!O!O!", &PyArray_Type, &output, &PyArray_Type, &doutput, &PyArray_Type, &dinput)) return NULL; if ( (NULL == output) || (NULL == doutput) || (NULL == dinput) ) return NULL; if ( (output->descr->type_num != NPY_DOUBLE) || (doutput->descr->type_num != NPY_DOUBLE) || (dinput->descr->type_num != NPY_DOUBLE) || !PyArray_CHKFLAGS(output,NPY_C_CONTIGUOUS|NPY_ALIGNED) || !PyArray_CHKFLAGS(doutput,NPY_C_CONTIGUOUS|NPY_ALIGNED) || !PyArray_CHKFLAGS(dinput,NPY_C_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) ) { PyErr_SetString(PyExc_ValueError, "In dreclin_: all arguments must be of type double, C contiguous and aligned, and output should be writeable"); return NULL; } if ( (dinput->nd != output->nd) || (doutput->nd != output->nd)) { PyErr_SetString(PyExc_ValueError, "In dreclin_: all arguments should have the same dimensionality"); return NULL; } int tot_dim = 1; for (i=0; i<output->nd; i++) { if ( (output->dimensions[i] != doutput->dimensions[i]) || (output->dimensions[i] != dinput->dimensions[i]) ) { PyErr_SetString(PyExc_ValueError, "In dreclin_: all dimensions of al arguments should be equal"); return NULL; } tot_dim *= output->dimensions[i]; } double * output_data_iter = (double *) output->data; double * doutput_data_iter = (double *) doutput->data; double * dinput_data_iter = (double *) dinput->data; for (i=0; i<tot_dim; i++) { if (*output_data_iter++<=0) *dinput_data_iter++ = 0; else *dinput_data_iter++ = *doutput_data_iter; doutput_data_iter++; } Py_RETURN_NONE; }
/* * check if in "alhs @op@ orhs" that alhs is a temporary (refcnt == 1) so we * can do in-place operations instead of creating a new temporary * "cannot" is set to true if it cannot be done even with swapped arguments */ static int can_elide_temp(PyArrayObject * alhs, PyObject * orhs, int * cannot) { /* * to be a candidate the array needs to have reference count 1, be an exact * array of a basic type, own its data and size larger than threshold */ if (Py_REFCNT(alhs) != 1 || !PyArray_CheckExact(alhs) || !PyArray_ISNUMBER(alhs) || !PyArray_CHKFLAGS(alhs, NPY_ARRAY_OWNDATA) || !PyArray_ISWRITEABLE(alhs) || PyArray_CHKFLAGS(alhs, NPY_ARRAY_UPDATEIFCOPY) || PyArray_CHKFLAGS(alhs, NPY_ARRAY_WRITEBACKIFCOPY) || PyArray_NBYTES(alhs) < NPY_MIN_ELIDE_BYTES) { return 0; } if (PyArray_CheckExact(orhs) || PyArray_CheckAnyScalar(orhs)) { PyArrayObject * arhs; /* create array from right hand side */ Py_INCREF(orhs); arhs = (PyArrayObject *)PyArray_EnsureArray(orhs); if (arhs == NULL) { return 0; } /* * if rhs is not a scalar dimensions must match * TODO: one could allow broadcasting on equal types */ if (!(PyArray_NDIM(arhs) == 0 || (PyArray_NDIM(arhs) == PyArray_NDIM(alhs) && PyArray_CompareLists(PyArray_DIMS(alhs), PyArray_DIMS(arhs), PyArray_NDIM(arhs))))) { Py_DECREF(arhs); return 0; } /* must be safe to cast (checks values for scalar in rhs) */ if (PyArray_CanCastArrayTo(arhs, PyArray_DESCR(alhs), NPY_SAFE_CASTING)) { Py_DECREF(arhs); return check_callers(cannot); } Py_DECREF(arhs); } return 0; }
static PyObject *solve_(PyObject *self, PyObject *args) { PyArrayObject *A, *B, *pivots; int n, nrhs, lda, ldb, info = 0; extern void dgesv_(int* n, int* nrhs, double * A, int* lda, int* ipiv, double *B, int *ldb, int* info); if (!PyArg_ParseTuple(args, "O!O!O!", &PyArray_Type, &A, &PyArray_Type, &B, &PyArray_Type, &pivots)) return NULL; if ( (NULL == A) || (NULL == B) || (NULL == pivots) ) return NULL; if ( (A->descr->type_num != NPY_DOUBLE) || (B->descr->type_num != NPY_DOUBLE) || (pivots->descr->type_num != NPY_INT) || !PyArray_CHKFLAGS(A,NPY_F_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) || !PyArray_CHKFLAGS(B,NPY_F_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) || !PyArray_CHKFLAGS(pivots,NPY_F_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) ) { PyErr_SetString(PyExc_ValueError, "In solve: some arguments are of invalid type"); return NULL; } n = A->dimensions[0]; nrhs = B->dimensions[1]; lda = n; ldb = B->dimensions[0]; dgesv_(&n, &nrhs, (double *) A->data, &lda, (int *) pivots->data, (double *) B->data, &ldb, &info); if ( info < 0 ) { /* Argument "-info" has illegal value */ PyErr_SetString(PyExc_ValueError, "In solve: dgesv error, one of the arguments has illegal value"); return NULL; } else if (info > 0 ) { PyErr_SetString(PyExc_ValueError, "In solve: dgesv error, solution could not be computed for value of A"); return NULL; } Py_RETURN_NONE; }
static PyObject *setdiag_(PyObject *self, PyObject *args) { PyArrayObject *matrix, *diag; int m, n; if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &matrix, &PyArray_Type, &diag)) return NULL; if ( (NULL == matrix) || (NULL == diag) ) return NULL; if ( (matrix->descr->type_num != NPY_DOUBLE) || (diag->descr->type_num != NPY_DOUBLE) || !PyArray_CHKFLAGS(matrix,NPY_ALIGNED|NPY_WRITEABLE) || !(PyArray_CHKFLAGS(matrix,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(matrix,NPY_F_CONTIGUOUS)) || !PyArray_CHKFLAGS(diag,NPY_C_CONTIGUOUS|NPY_ALIGNED)) { PyErr_SetString(PyExc_ValueError, "In setdiag: some arguments are of invalid type"); return NULL; } if ( (matrix->nd != 2) || (diag->nd != 1) ) { PyErr_SetString(PyExc_ValueError, "In setdiag: not all arguments have the right dimensionality"); return NULL; } m = matrix->dimensions[0]; n = matrix->dimensions[1]; int diagsize = (m<n?m:n); if ( diagsize != diag->dimensions[0] ) { PyErr_SetString(PyExc_ValueError, "In setdiag: input matrix and target vector dimensions are not compatible"); return NULL; } char * matrix_data_iter = matrix->data; int s1 = matrix->strides[0]; int s2 = matrix->strides[1]; double * diag_data_iter = (double *) diag->data; int i; for (i=0; i<diagsize; i++) { *((double *)matrix_data_iter) = *diag_data_iter++; matrix_data_iter += s1 + s2; } Py_RETURN_NONE; }
NPY_NO_EXPORT npy_bool _IsWriteable(PyArrayObject *ap) { PyObject *base=PyArray_BASE(ap); #if defined(NPY_PY3K) Py_buffer view; #else void *dummy; Py_ssize_t n; #endif /* If we own our own data, then no-problem */ if ((base == NULL) || (PyArray_FLAGS(ap) & NPY_ARRAY_OWNDATA)) { return NPY_TRUE; } /* * Get to the final base object * If it is a writeable array, then return TRUE * If we can find an array object * or a writeable buffer object as the final base object * or a string object (for pickling support memory savings). * - this last could be removed if a proper pickleable * buffer was added to Python. * * MW: I think it would better to disallow switching from READONLY * to WRITEABLE like this... */ while(PyArray_Check(base)) { if (PyArray_CHKFLAGS((PyArrayObject *)base, NPY_ARRAY_OWNDATA)) { return (npy_bool) (PyArray_ISWRITEABLE((PyArrayObject *)base)); } base = PyArray_BASE((PyArrayObject *)base); } /* * here so pickle support works seamlessly * and unpickled array can be set and reset writeable * -- could be abused -- */ if (PyString_Check(base)) { return NPY_TRUE; } #if defined(NPY_PY3K) if (PyObject_GetBuffer(base, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) { PyErr_Clear(); return NPY_FALSE; } PyBuffer_Release(&view); #else if (PyObject_AsWriteBuffer(base, &dummy, &n) < 0) { PyErr_Clear(); return NPY_FALSE; } #endif return NPY_TRUE; }
static Py_ssize_t array_getwritebuf(PyArrayObject *self, Py_ssize_t segment, void **ptrptr) { if (PyArray_CHKFLAGS(self, NPY_ARRAY_WRITEABLE)) { return array_getreadbuf(self, segment, (void **) ptrptr); } else { PyErr_SetString(PyExc_ValueError, "array cannot be " "accessed as a writeable buffer"); return -1; } }
/* try elide unary temporary */ NPY_NO_EXPORT int can_elide_temp_unary(PyArrayObject * m1) { int cannot; if (Py_REFCNT(m1) != 1 || !PyArray_CheckExact(m1) || !PyArray_ISNUMBER(m1) || !PyArray_CHKFLAGS(m1, NPY_ARRAY_OWNDATA) || !PyArray_ISWRITEABLE(m1) || PyArray_CHKFLAGS(m1, NPY_ARRAY_UPDATEIFCOPY) || PyArray_NBYTES(m1) < NPY_MIN_ELIDE_BYTES) { return 0; } if (check_callers(&cannot)) { #if NPY_ELIDE_DEBUG != 0 puts("elided temporary in unary op"); #endif return 1; } else { return 0; } }
void throw_array_conversion_error(PyObject* object, int flags, int rank_range, PyArray_Descr* descr) { if (!PyArray_Check(object)) PyErr_Format(PyExc_TypeError, "expected numpy array, got %s", object->ob_type->tp_name); else if (!PyArray_EquivTypes(PyArray_DESCR((PyArrayObject*)object), descr)) PyErr_Format(PyExc_TypeError, "expected array type %s, got %s", descr->typeobj->tp_name, PyArray_DESCR((PyArrayObject*)object)->typeobj->tp_name); else if (!PyArray_CHKFLAGS((PyArrayObject*)object,flags)){ if (flags&NPY_ARRAY_WRITEABLE && !PyArray_ISWRITEABLE((PyArrayObject*)object)) PyErr_SetString(PyExc_TypeError, "unwriteable array"); else if (flags&NPY_ARRAY_ALIGNED && !PyArray_ISALIGNED((PyArrayObject*)object)) PyErr_SetString(PyExc_TypeError, "unaligned array"); else if (flags&NPY_ARRAY_C_CONTIGUOUS && !PyArray_ISCONTIGUOUS((PyArrayObject*)object)) PyErr_SetString(PyExc_TypeError, "noncontiguous array"); else PyErr_SetString(PyExc_TypeError, "unknown array flag mismatch");} else if (rank_range>=0) PyErr_Format(PyExc_ValueError, "expected rank %d, got %d", rank_range, PyArray_NDIM((PyArrayObject*)object)); else PyErr_Format(PyExc_ValueError, "expected rank at least %d, got %d", -rank_range-1, PyArray_NDIM((PyArrayObject*)object)); throw PythonError(); }
/* * Retrieving buffers for ndarray */ static int array_getbuffer(PyObject *obj, Py_buffer *view, int flags) { PyArrayObject *self; _buffer_info_t *info = NULL; self = (PyArrayObject*)obj; /* Check whether we can provide the wanted properties */ if ((flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not Fortran contiguous"); goto fail; } if ((flags & PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS && !PyArray_ISONESEGMENT(self)) { PyErr_SetString(PyExc_ValueError, "ndarray is not contiguous"); goto fail; } if ((flags & PyBUF_STRIDES) != PyBUF_STRIDES && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { /* Non-strided N-dim buffers must be C-contiguous */ PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) { if (PyArray_FailUnlessWriteable(self, "buffer source array") < 0) { goto fail; } } /* * If a read-only buffer is requested on a read-write array, we return a * read-write buffer, which is dubious behavior. But that's why this call * is guarded by PyArray_ISWRITEABLE rather than (flags & * PyBUF_WRITEABLE). */ if (PyArray_ISWRITEABLE(self)) { if (array_might_be_written(self) < 0) { goto fail; } } if (view == NULL) { PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer"); goto fail; } /* Fill in information */ info = _buffer_get_info(obj); if (info == NULL) { goto fail; } view->buf = PyArray_DATA(self); view->suboffsets = NULL; view->itemsize = PyArray_ITEMSIZE(self); view->readonly = !PyArray_ISWRITEABLE(self); view->internal = NULL; view->len = PyArray_NBYTES(self); if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { view->format = info->format; } else { view->format = NULL; } if ((flags & PyBUF_ND) == PyBUF_ND) { view->ndim = info->ndim; view->shape = info->shape; } else { view->ndim = 0; view->shape = NULL; } if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { view->strides = info->strides; #ifdef NPY_RELAXED_STRIDES_CHECKING /* * If NPY_RELAXED_STRIDES_CHECKING is on, the array may be * contiguous, but it won't look that way to Python when it * tries to determine contiguity by looking at the strides * (since one of the elements may be -1). In that case, just * regenerate strides from shape. */ if (PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS) && !((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)) { Py_ssize_t sd = view->itemsize; int i; for (i = view->ndim-1; i >= 0; --i) { view->strides[i] = sd; sd *= view->shape[i]; } } else if (PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) { Py_ssize_t sd = view->itemsize; int i; for (i = 0; i < view->ndim; ++i) { view->strides[i] = sd; sd *= view->shape[i]; } } #endif } else { view->strides = NULL; } view->obj = (PyObject*)self; Py_INCREF(self); return 0; fail: return -1; }
static PyObject *multiple_row_accumulate_(PyObject *self, PyObject *args) { PyArrayObject *X, *rows, *Y; int i, j, m, n, o, r; if (!PyArg_ParseTuple(args, "O!O!O!", &PyArray_Type, &X, &PyArray_Type, &rows, &PyArray_Type, &Y)) return NULL; if ( (NULL == X) || (NULL == rows) || (NULL == Y) ) return NULL; if ( (X->descr->type_num != NPY_DOUBLE) || (Y->descr->type_num != NPY_DOUBLE) || (rows->descr->type_num != NPY_INT32) || !PyArray_CHKFLAGS(X,NPY_ALIGNED) || !PyArray_CHKFLAGS(X,NPY_C_CONTIGUOUS) || !PyArray_CHKFLAGS(rows,NPY_ALIGNED) || !PyArray_CHKFLAGS(rows,NPY_C_CONTIGUOUS) || !PyArray_CHKFLAGS(Y,NPY_C_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE)) { PyErr_SetString(PyExc_ValueError, "In multiple_row_accumulate: some arguments are of invalid type"); return NULL; } if ( (X->nd != 2) || (rows->nd != 1) || (Y->nd != 2) ) { PyErr_SetString(PyExc_ValueError, "In multiple_row_accumulate: not all arguments have the right dimensionality"); return NULL; } m = X->dimensions[0]; n = X->dimensions[1]; o = Y->dimensions[0]; if ( Y->dimensions[1] != n ) { PyErr_SetString(PyExc_ValueError, "In multiple_row_accumulate: X and Y matrices should have the same width"); return NULL; } if ( rows->dimensions[0] != m ) { PyErr_SetString(PyExc_ValueError, "In multiple_row_accumulate: X matrix and rows vector should have the same length"); return NULL; } double * X_data_iter = (double *) X->data; double * Y_data_iter = (double *) Y->data; double *Y_row_data_iter; int * rows_data_iter = (int *) rows->data; for (i=0; i<m; i++) { r = *rows_data_iter++; if ( r < 0 || r >= o ) { PyErr_SetString(PyExc_ValueError, "In multiple_row_accumulate: row indices in rows out of bound"); return NULL; } Y_row_data_iter = &Y_data_iter[r*n]; // Get rth row for (j=0; j<n; j++) { *Y_row_data_iter++ += *X_data_iter++; } } Py_RETURN_NONE; }
/*! @brief load an ANA f0 file data and header @param [in] filename @return [out] data, NULL on failure */ static PyObject *pyana_fzread(PyObject *self, PyObject *args) { // Function arguments char *filename; int debug=0; // Init ANA IO variables char *header = NULL; // ANA header (comments) uint8_t *anaraw = NULL; // Raw data int nd=-1, type=-1, *ds, size=-1, d; // Various properties // Data manipulation PyArrayObject *anadata; // Final ndarray // Parse arguments if (!PyArg_ParseTuple(args, "s|i", &filename, &debug)) { return NULL; } // Read ANA file if (debug == 1) printf("pyana_fzread(): Reading in ANA file\n"); anaraw = ana_fzread(filename, &ds, &nd, &header, &type, &size); if (NULL == anaraw) { PyErr_SetString(PyExc_ValueError, "In pyana_fzread: could not read ana file, data returned is NULL."); return NULL; } if (type == -1) { PyErr_SetString(PyExc_ValueError, "In pyana_fzread: could not read ana file, type invalid."); return NULL; } // Mold into numpy array npy_intp npy_dims[nd]; // Dimensions array int npy_type; // Numpy datatype // Calculate total datasize if (debug == 1) printf("pyana_fzread(): Dimensions: "); for (d=0; d<nd; d++) { if (debug == 1) printf("%d ", ds[d]); // ANA stores dimensions the other way around? //npy_dims[d] = ds[d]; npy_dims[nd-1-d] = ds[d]; } if (debug == 1) printf("\npyana_fzread(): Datasize: %d\n", size); // Convert datatype from ANA type to PyArray type switch (type) { case (INT8): npy_type = PyArray_INT8; break; case (INT16): npy_type = PyArray_INT16; break; case (INT32): npy_type = PyArray_INT32; break; case (FLOAT32): npy_type = PyArray_FLOAT32; break; case (FLOAT64): npy_type = PyArray_FLOAT64; break; case (INT64): npy_type = PyArray_INT64; break; default: PyErr_SetString(PyExc_ValueError, "In pyana_fzread: datatype of ana file unknown/unsupported."); return NULL; } if (debug == 1) printf("pyana_fzread(): Read %d bytes, %d dimensions\n", size, nd); // Create numpy array from the data anadata = (PyArrayObject*) PyArray_SimpleNewFromData(nd, npy_dims, npy_type, (void *) anaraw); // Make sure Python owns the data, so it will free the data after use PyArray_FLAGS(anadata) |= NPY_OWNDATA; if (!PyArray_CHKFLAGS(anadata, NPY_OWNDATA)) { PyErr_SetString(PyExc_RuntimeError, "In pyana_fzread: unable to own the data, will cause memory leak. Aborting"); return NULL; } // Return the data in a dict with some metainfo attached // NB: Use 'N' for PyArrayObject s, because when using 'O' it will create // another reference count such that the memory will never be deallocated. // See: // http://www.mail-archive.com/[email protected]/msg13354.html // ([Numpy-discussion] numpy CAPI questions) return Py_BuildValue("{s:N,s:{s:i,s:(ii),s:s}}", "data", anadata, "header", "size", size, "dims", ds[0], ds[1], "header", header); }
static int array_getbuffer(PyObject *obj, Py_buffer *view, int flags) { PyArrayObject *self; _buffer_info_t *info = NULL; self = (PyArrayObject*)obj; /* Check whether we can provide the wanted properties */ if ((flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not Fortran contiguous"); goto fail; } if ((flags & PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS && !PyArray_ISONESEGMENT(self)) { PyErr_SetString(PyExc_ValueError, "ndarray is not contiguous"); goto fail; } if ((flags & PyBUF_STRIDES) != PyBUF_STRIDES && (flags & PyBUF_ND) == PyBUF_ND && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { /* Non-strided N-dim buffers must be C-contiguous */ PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE && !PyArray_ISWRITEABLE(self)) { PyErr_SetString(PyExc_ValueError, "ndarray is not writeable"); goto fail; } if (view == NULL) { PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer"); goto fail; } /* Fill in information */ info = _buffer_get_info(obj); if (info == NULL) { goto fail; } view->buf = PyArray_DATA(self); view->suboffsets = NULL; view->itemsize = PyArray_ITEMSIZE(self); view->readonly = !PyArray_ISWRITEABLE(self); view->internal = NULL; view->len = PyArray_NBYTES(self); if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { view->format = info->format; } else { view->format = NULL; } if ((flags & PyBUF_ND) == PyBUF_ND) { view->ndim = info->ndim; view->shape = info->shape; } else { view->ndim = 0; view->shape = NULL; } if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { view->strides = info->strides; } else { view->strides = NULL; } view->obj = (PyObject*)self; Py_INCREF(self); return 0; fail: return -1; }
static PyObject *product_matrix_vector_(PyObject *self, PyObject *args) { PyArrayObject *matrix, *vector, *result; double alpha = 1.; double beta = 0.; int int_one = 1; int m, n; char trans[2] = "T"; extern void dgemv_(char *trans, int *m, int *n, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *Y, int *incy); if (!PyArg_ParseTuple(args, "O!O!O!", &PyArray_Type, &matrix, &PyArray_Type, &vector, &PyArray_Type, &result)) return NULL; if ( (NULL == matrix) || (NULL == vector) || (NULL == result) ) return NULL; if ( (matrix->descr->type_num != NPY_DOUBLE) || (vector->descr->type_num != NPY_DOUBLE) || (result->descr->type_num != NPY_DOUBLE) || !PyArray_CHKFLAGS(matrix,NPY_ALIGNED) || !(PyArray_CHKFLAGS(matrix,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(matrix,NPY_F_CONTIGUOUS)) || !PyArray_CHKFLAGS(vector,NPY_C_CONTIGUOUS|NPY_ALIGNED) || !PyArray_CHKFLAGS(result,NPY_C_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) ) { PyErr_SetString(PyExc_ValueError, "In product_matrix_vector: all arguments must be of type double, contiguous and aligned, and targets should be writeable"); return NULL; } if ( (matrix->nd != 2) || (vector->nd != 1) || (result->nd != 1) ) { PyErr_SetString(PyExc_ValueError, "In product_matrix_vector: not all arguments have the right dimensionality"); return NULL; } /* Figure out correct values for args to blas*/ if (PyArray_ISFORTRAN(matrix)) { m = matrix->dimensions[0]; n = matrix->dimensions[1]; trans[0] = 'N'; } else /*if (PyArray_ISCONTIGUOUS(matrix))*/ { /* Equivalent to matrix being the transposed of a Fortran matrix*/ m = matrix->dimensions[1]; n = matrix->dimensions[0]; } /* Check if dimensions are compatible */ if (matrix->dimensions[1] != vector->dimensions[0]) { PyErr_SetString(PyExc_ValueError, "In product_matrix_vector: input dimensions are not compatible"); return NULL; } if (result->dimensions[0] != matrix->dimensions[0]) { PyErr_SetString(PyExc_ValueError, "In product_matrix_vector: target dimension is not compatible"); return NULL; } dgemv_(trans, &m, &n, &alpha, (double *)matrix->data, &m, (double *)vector->data, &int_one, &beta, (double *)result->data, &int_one); Py_RETURN_NONE; }
static PyObject *lu_(PyObject *self, PyObject *args) { PyArrayObject *A, *pivots, *p, *L, *U; int m, n, lda, info = 0; extern void dgetrf_(int* m, int* n, double * A, int* lda, int* ipiv, int* info); if (!PyArg_ParseTuple(args, "O!O!O!O!O!", &PyArray_Type, &A, &PyArray_Type, &pivots, &PyArray_Type, &p, &PyArray_Type, &L, &PyArray_Type, &U)) return NULL; if ( (NULL == A) || (NULL == pivots) ) return NULL; if ( (A->descr->type_num != NPY_DOUBLE) || (pivots->descr->type_num != NPY_INT) || (p->descr->type_num != NPY_INT) || (U->descr->type_num != NPY_DOUBLE) || (L->descr->type_num != NPY_DOUBLE) || !PyArray_CHKFLAGS(A,NPY_F_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) || !PyArray_CHKFLAGS(pivots,NPY_F_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) || !PyArray_CHKFLAGS(p,NPY_C_CONTIGUOUS) || /* Contiguous vectors are for both C and fortran */ !(PyArray_CHKFLAGS(L,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(L,NPY_F_CONTIGUOUS)) || !(PyArray_CHKFLAGS(U,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(U,NPY_F_CONTIGUOUS)) || !PyArray_CHKFLAGS(p,NPY_ALIGNED|NPY_WRITEABLE) || !PyArray_CHKFLAGS(L,NPY_ALIGNED|NPY_WRITEABLE) || !PyArray_CHKFLAGS(U,NPY_ALIGNED|NPY_WRITEABLE) ) { PyErr_SetString(PyExc_ValueError, "In lu: some arguments are of invalid type"); return NULL; } m = A->dimensions[0]; n = A->dimensions[1]; lda = m; dgetrf_(&m, &n, (double *) A->data, &lda, (int *) pivots->data, &info); if ( info < 0 ) { /* Argument "-info" has illegal value */ PyErr_SetString(PyExc_ValueError, "In lu: dgetrf error, one of the arguments has illegal value"); return NULL; } else if (info > 0 ) { PyErr_SetString(PyExc_ValueError, "In lu: dgetrf error, solution could not be computed for value of A"); return NULL; } /* Rearrange the pivots in the right form*/ int * pivots_ptr, *p_ptr; int npivots = (m<n?m:n); int temp; int i, j; pivots_ptr = (int *)pivots->data; p_ptr = (int *)p->data; /* Init p */ for ( i=0; i<m; i++ ) *p_ptr++ = i; p_ptr = (int *)p->data; for ( i=0; i<npivots; i++ ) { temp = p_ptr[*pivots_ptr-1]; p_ptr[*pivots_ptr-1] = p_ptr[i]; p_ptr[i] = temp; pivots_ptr++; } /* Compute L */ double *A_ptr, *L_ptr; int Asi = A->strides[0]; int Asj = A->strides[1]; int Lsi = L->strides[0]; int Lsj = L->strides[1]; for ( i=0; i<m; i++ ) for ( j=0; j<npivots; j++ ) { A_ptr = (double *)(A->data + i*Asi + j*Asj); L_ptr = (double *)(L->data + i*Lsi + j*Lsj); if ( j < i ) { *L_ptr = *A_ptr; } else if ( j > i ) { *L_ptr = 0.; } else /* if ( j == i ) */ { *L_ptr = 1.; } } double *U_ptr; int Usi = U->strides[0]; int Usj = U->strides[1]; for ( i=0; i<npivots; i++ ) for ( j=0; j<n; j++ ) { A_ptr = (double *)(A->data + i*Asi + j*Asj); U_ptr = (double *)(U->data + i*Usi + j*Usj); if ( j < i ) { *U_ptr = 0.; } else { *U_ptr = *A_ptr; } } Py_RETURN_NONE; }
/*NUMPY_API * Clip */ NPY_NO_EXPORT PyObject * PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *out) { PyArray_FastClipFunc *func; int outgood = 0, ingood = 0; PyArrayObject *maxa = NULL; PyArrayObject *mina = NULL; PyArrayObject *newout = NULL, *newin = NULL; PyArray_Descr *indescr = NULL, *newdescr = NULL; char *max_data, *min_data; PyObject *zero; /* Treat None the same as NULL */ if (min == Py_None) { min = NULL; } if (max == Py_None) { max = NULL; } if ((max == NULL) && (min == NULL)) { PyErr_SetString(PyExc_ValueError, "array_clip: must set either max or min"); return NULL; } func = PyArray_DESCR(self)->f->fastclip; if (func == NULL || (min != NULL && !PyArray_CheckAnyScalar(min)) || (max != NULL && !PyArray_CheckAnyScalar(max)) || PyArray_ISBYTESWAPPED(self) || (out && PyArray_ISBYTESWAPPED(out))) { return _slow_array_clip(self, min, max, out); } /* Use the fast scalar clip function */ /* First we need to figure out the correct type */ if (min != NULL) { indescr = PyArray_DescrFromObject(min, NULL); if (indescr == NULL) { goto fail; } } if (max != NULL) { newdescr = PyArray_DescrFromObject(max, indescr); Py_XDECREF(indescr); indescr = NULL; if (newdescr == NULL) { goto fail; } } else { /* Steal the reference */ newdescr = indescr; indescr = NULL; } /* * Use the scalar descriptor only if it is of a bigger * KIND than the input array (and then find the * type that matches both). */ if (PyArray_ScalarKind(newdescr->type_num, NULL) > PyArray_ScalarKind(PyArray_DESCR(self)->type_num, NULL)) { indescr = PyArray_PromoteTypes(newdescr, PyArray_DESCR(self)); if (indescr == NULL) { goto fail; } func = indescr->f->fastclip; if (func == NULL) { Py_DECREF(indescr); return _slow_array_clip(self, min, max, out); } } else { indescr = PyArray_DESCR(self); Py_INCREF(indescr); } Py_DECREF(newdescr); newdescr = NULL; if (!PyDataType_ISNOTSWAPPED(indescr)) { PyArray_Descr *descr2; descr2 = PyArray_DescrNewByteorder(indescr, '='); Py_DECREF(indescr); indescr = NULL; if (descr2 == NULL) { goto fail; } indescr = descr2; } /* Convert max to an array */ if (max != NULL) { Py_INCREF(indescr); maxa = (PyArrayObject *)PyArray_FromAny(max, indescr, 0, 0, NPY_ARRAY_DEFAULT, NULL); if (maxa == NULL) { goto fail; } } /* * If we are unsigned, then make sure min is not < 0 * This is to match the behavior of _slow_array_clip * * We allow min and max to go beyond the limits * for other data-types in which case they * are interpreted as their modular counterparts. */ if (min != NULL) { if (PyArray_ISUNSIGNED(self)) { int cmp; zero = PyInt_FromLong(0); cmp = PyObject_RichCompareBool(min, zero, Py_LT); if (cmp == -1) { Py_DECREF(zero); goto fail; } if (cmp == 1) { min = zero; } else { Py_DECREF(zero); Py_INCREF(min); } } else { Py_INCREF(min); } /* Convert min to an array */ Py_INCREF(indescr); mina = (PyArrayObject *)PyArray_FromAny(min, indescr, 0, 0, NPY_ARRAY_DEFAULT, NULL); Py_DECREF(min); if (mina == NULL) { goto fail; } } /* * Check to see if input is single-segment, aligned, * and in native byteorder */ if (PyArray_ISONESEGMENT(self) && PyArray_CHKFLAGS(self, NPY_ARRAY_ALIGNED) && PyArray_ISNOTSWAPPED(self) && (PyArray_DESCR(self) == indescr)) { ingood = 1; } if (!ingood) { int flags; if (PyArray_ISFORTRAN(self)) { flags = NPY_ARRAY_FARRAY; } else { flags = NPY_ARRAY_CARRAY; } Py_INCREF(indescr); newin = (PyArrayObject *)PyArray_FromArray(self, indescr, flags); if (newin == NULL) { goto fail; } } else { newin = self; Py_INCREF(newin); } /* * At this point, newin is a single-segment, aligned, and correct * byte-order array of the correct type * * if ingood == 0, then it is a copy, otherwise, * it is the original input. */ /* * If we have already made a copy of the data, then use * that as the output array */ if (out == NULL && !ingood) { out = newin; } /* * Now, we know newin is a usable array for fastclip, * we need to make sure the output array is available * and usable */ if (out == NULL) { Py_INCREF(indescr); out = (PyArrayObject*)PyArray_NewFromDescr(Py_TYPE(self), indescr, PyArray_NDIM(self), PyArray_DIMS(self), NULL, NULL, PyArray_ISFORTRAN(self), (PyObject *)self); if (out == NULL) { goto fail; } outgood = 1; } else Py_INCREF(out); /* Input is good at this point */ if (out == newin) { outgood = 1; } /* make sure the shape of the output array is the same */ if (!PyArray_SAMESHAPE(newin, out)) { PyErr_SetString(PyExc_ValueError, "clip: Output array must have the" "same shape as the input."); goto fail; } if (!outgood && PyArray_EQUIVALENTLY_ITERABLE( self, out, PyArray_TRIVIALLY_ITERABLE_OP_READ, PyArray_TRIVIALLY_ITERABLE_OP_NOREAD) && PyArray_CHKFLAGS(out, NPY_ARRAY_ALIGNED) && PyArray_ISNOTSWAPPED(out) && PyArray_EquivTypes(PyArray_DESCR(out), indescr)) { outgood = 1; } /* * Do we still not have a suitable output array? * Create one, now. No matter why the array is not suitable a copy has * to be made. This may be just to avoid memory overlap though. */ if (!outgood) { int oflags; if (PyArray_ISFORTRAN(self)) { oflags = NPY_ARRAY_FARRAY; } else { oflags = NPY_ARRAY_CARRAY; } oflags |= (NPY_ARRAY_WRITEBACKIFCOPY | NPY_ARRAY_FORCECAST | NPY_ARRAY_ENSURECOPY); Py_INCREF(indescr); newout = (PyArrayObject*)PyArray_FromArray(out, indescr, oflags); if (newout == NULL) { goto fail; } } else { newout = out; Py_INCREF(newout); } /* Now we can call the fast-clip function */ min_data = max_data = NULL; if (mina != NULL) { min_data = PyArray_DATA(mina); } if (maxa != NULL) { max_data = PyArray_DATA(maxa); } func(PyArray_DATA(newin), PyArray_SIZE(newin), min_data, max_data, PyArray_DATA(newout)); /* Clean up temporary variables */ Py_XDECREF(indescr); Py_XDECREF(newdescr); Py_XDECREF(mina); Py_XDECREF(maxa); Py_DECREF(newin); /* Copy back into out if out was not already a nice array. */ PyArray_ResolveWritebackIfCopy(newout); Py_DECREF(newout); return (PyObject *)out; fail: Py_XDECREF(indescr); Py_XDECREF(newdescr); Py_XDECREF(maxa); Py_XDECREF(mina); Py_XDECREF(newin); PyArray_DiscardWritebackIfCopy(newout); Py_XDECREF(newout); return NULL; }
static PyObject *product_matrix_matrix_(PyObject *self, PyObject *args) { PyArrayObject *matrix1, *matrix2, *result, *A, *B; double alpha = 1.; double beta = 0.; int m, n, k; /* Watch out: m and n have a different meaning from that for dgemv, where it is the dimensionality BEFORE the transpose, whereas dgemm requires the dimensionality AFTER. */ int lda, ldb, ldc; char transa[2] = "T"; char transb[2] = "T"; extern void dgemm_(char* transa, char* transb, int* m, int* n, int* k, double *alpha, double *a, int* lda, double *b, int *ldb, double *beta, double *c, int* ldc); if (!PyArg_ParseTuple(args, "O!O!O!", &PyArray_Type, &matrix1, &PyArray_Type, &matrix2, &PyArray_Type, &result)) return NULL; if ( (NULL == matrix1) || (NULL == matrix2) || (NULL == result) ) return NULL; if ( (matrix1->descr->type_num != NPY_DOUBLE) || (matrix2->descr->type_num != NPY_DOUBLE) || (result->descr->type_num != NPY_DOUBLE) || !PyArray_CHKFLAGS(matrix1,NPY_ALIGNED) || !(PyArray_CHKFLAGS(matrix1,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(matrix1,NPY_F_CONTIGUOUS)) || !PyArray_CHKFLAGS(matrix2,NPY_ALIGNED) || !(PyArray_CHKFLAGS(matrix2,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(matrix2,NPY_F_CONTIGUOUS)) || !PyArray_CHKFLAGS(result,NPY_ALIGNED|NPY_WRITEABLE) || !(PyArray_CHKFLAGS(result,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(result,NPY_F_CONTIGUOUS)) ) { PyErr_SetString(PyExc_ValueError, "In product_matrix_matrix: all arguments must be of type double, contiguous and aligned, and targets should be writeable"); return NULL; } if ( (matrix1->nd != 2) || (matrix2->nd != 2) || (result->nd != 2) ) { PyErr_SetString(PyExc_ValueError, "In product_matrix_matrix: not all arguments have the right dimensionality"); return NULL; } /* Figure out correct values for args to blas*/ if (PyArray_ISFORTRAN(result)) { /* Matrix result has Fortran order */ A = matrix1; B = matrix2; m = matrix1->dimensions[0]; k = matrix1->dimensions[1]; if (PyArray_ISFORTRAN(matrix1)) { transa[0] = 'N'; lda = m; } else /*if (PyArray_ISCONTIGUOUS(matrix1))*/ { /* Equivalent to matrix being the transposed of a Fortran matrix*/ lda = k; } n = matrix2->dimensions[1]; k = matrix2->dimensions[0]; if (PyArray_ISFORTRAN(matrix2)) { transb[0] = 'N'; ldb = k; } else /*if (PyArray_ISCONTIGUOUS(matrix2))*/ { /* Equivalent to matrix being the transposed of a Fortran matrix*/ ldb = n; } } else /*if (PyArray_ISCONTIGUOUS(result))*/ { /* Matrix result has C order! Must be careful how blas is called! Must interchange matrix1 with matrix2, and interchange how the C and Fortran matrices are processed. */ A = matrix2; B = matrix1; m = matrix2->dimensions[1]; k = matrix2->dimensions[0]; if (PyArray_ISFORTRAN(matrix2)) { lda = k; } else /*if (PyArray_ISCONTIGUOUS(matrix2))*/ { /* Equivalent to matrix being the transposed of a Fortran matrix*/ transa[0] = 'N'; lda = m; } n = matrix1->dimensions[0]; k = matrix1->dimensions[1]; if (PyArray_ISFORTRAN(matrix1)) { ldb = n; } else /*if (PyArray_ISCONTIGUOUS(matrix1))*/ { /* Equivalent to matrix being the transposed of a Fortran matrix*/ transb[0] = 'N'; ldb = k; } } ldc = m; if ( matrix1->dimensions[1] != matrix2->dimensions[0] ) { PyErr_SetString(PyExc_ValueError, "In product_matrix_matrix: input matrices dimensions are not compatible"); return NULL; } if ( (matrix1->dimensions[0] != result->dimensions[0]) || (matrix2->dimensions[1] != result->dimensions[1]) ) { PyErr_SetString(PyExc_ValueError, "In product_matrix_matrix: target dimensions are not compatible"); return NULL; } dgemm_(transa, transb, &m, &n, &k, &alpha, (double *)A->data, &lda, (double *)B->data, &ldb, &beta, (double *)result->data, &ldc ); Py_RETURN_NONE; }
void check_numpy_conversion(PyObject* object, int flags, int rank_range, PyArray_Descr* descr) { const int rank = PyArray_NDIM((PyArrayObject*)object); const int min_rank = rank_range<0?-rank_range-1:rank_range,max_rank=rank_range<0?100:rank_range; if (!PyArray_CHKFLAGS((PyArrayObject*)object,flags) || min_rank>rank || rank>max_rank || !PyArray_EquivTypes(PyArray_DESCR((PyArrayObject*)object),descr)) throw_array_conversion_error(object,flags,rank_range,descr); }
static int array_getbuffer(PyObject *obj, Py_buffer *view, int flags) { PyArrayObject *self; _buffer_info_t *info = NULL; self = (PyArrayObject*)obj; /* Check whether we can provide the wanted properties */ if ((flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS && !PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) { PyErr_SetString(PyExc_ValueError, "ndarray is not Fortran contiguous"); goto fail; } if ((flags & PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS && !PyArray_ISONESEGMENT(self)) { PyErr_SetString(PyExc_ValueError, "ndarray is not contiguous"); goto fail; } if ((flags & PyBUF_STRIDES) != PyBUF_STRIDES && !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) { /* Non-strided N-dim buffers must be C-contiguous */ PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous"); goto fail; } if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) { if (PyArray_FailUnlessWriteable(self, "buffer source array") < 0) { goto fail; } } /* * If a read-only buffer is requested on a read-write array, we return a * read-write buffer, which is dubious behavior. But that's why this call * is guarded by PyArray_ISWRITEABLE rather than (flags & * PyBUF_WRITEABLE). */ if (PyArray_ISWRITEABLE(self)) { if (array_might_be_written(self) < 0) { goto fail; } } if (view == NULL) { PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer"); goto fail; } /* Fill in information */ info = _buffer_get_info(obj); if (info == NULL) { goto fail; } view->buf = PyArray_DATA(self); view->suboffsets = NULL; view->itemsize = PyArray_ITEMSIZE(self); view->readonly = !PyArray_ISWRITEABLE(self); view->internal = NULL; view->len = PyArray_NBYTES(self); if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { view->format = info->format; } else { view->format = NULL; } if ((flags & PyBUF_ND) == PyBUF_ND) { view->ndim = info->ndim; view->shape = info->shape; } else { view->ndim = 0; view->shape = NULL; } if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { view->strides = info->strides; } else { view->strides = NULL; } view->obj = (PyObject*)self; Py_INCREF(self); return 0; fail: return -1; }
static PyObject *softmax_vec_(PyObject *self, PyObject *args) { PyArrayObject *input, *output; int i; if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &input, &PyArray_Type, &output)) return NULL; if ( (NULL == input) || (NULL == output) ) return NULL; if ( (input->descr->type_num != NPY_DOUBLE) || (output->descr->type_num != NPY_DOUBLE) || !PyArray_CHKFLAGS(input,NPY_C_CONTIGUOUS|NPY_ALIGNED) || !PyArray_CHKFLAGS(output,NPY_C_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) ) { PyErr_SetString(PyExc_ValueError, "In softmax_vec_: all arguments must be of type double, C contiguous and aligned, and output should be writeable"); return NULL; } if ( (input->nd != output->nd) ) { PyErr_SetString(PyExc_ValueError, "In softmax_vec_: both arguments should have the same dimensionality"); return NULL; } int tot_dim = 1; for (i=0; i<input->nd; i++) { if ( (input->dimensions[i] != output->dimensions[i]) ) { PyErr_SetString(PyExc_ValueError, "In softmax_vec_: all dimensions of both arguments should be equal"); return NULL; } tot_dim *= input->dimensions[i]; } double * input_data_iter = (double *) input->data; double * output_data_iter = (double *) output->data; double max = *input_data_iter; for (i=0; i<tot_dim; i++) { if (max < *input_data_iter){ max = *input_data_iter; } input_data_iter++; } input_data_iter = (double *) input->data; output_data_iter = (double *) output->data; double sum = 0; for (i=0; i<tot_dim; i++) { *output_data_iter = exp(*input_data_iter++ - max); sum += *output_data_iter++; } output_data_iter = (double *) output->data; for (i=0; i<tot_dim; i++) { *output_data_iter++ /= sum; } Py_RETURN_NONE; }