/*NUMPY_API * Update Several Flags at once. */ NPY_NO_EXPORT void PyArray_UpdateFlags(PyArrayObject *ret, int flagmask) { /* Always update both, as its not trivial to guess one from the other */ if (flagmask & (NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_C_CONTIGUOUS)) { _UpdateContiguousFlags(ret); } if (flagmask & NPY_ARRAY_ALIGNED) { if (_IsAligned(ret)) { PyArray_ENABLEFLAGS(ret, NPY_ARRAY_ALIGNED); } else { PyArray_CLEARFLAGS(ret, NPY_ARRAY_ALIGNED); } } /* * This is not checked by default WRITEABLE is not * part of UPDATE_ALL */ if (flagmask & NPY_ARRAY_WRITEABLE) { if (_IsWriteable(ret)) { PyArray_ENABLEFLAGS(ret, NPY_ARRAY_WRITEABLE); } else { PyArray_CLEARFLAGS(ret, NPY_ARRAY_WRITEABLE); } } return; }
/*NUMPY_API * Update Several Flags at once. */ NPY_NO_EXPORT void PyArray_UpdateFlags(PyArrayObject *ret, int flagmask) { if (flagmask & NPY_ARRAY_F_CONTIGUOUS) { if (_IsFortranContiguous(ret)) { PyArray_ENABLEFLAGS(ret, NPY_ARRAY_F_CONTIGUOUS); if (PyArray_NDIM(ret) > 1) { PyArray_CLEARFLAGS(ret, NPY_ARRAY_C_CONTIGUOUS); } } else { PyArray_CLEARFLAGS(ret, NPY_ARRAY_F_CONTIGUOUS); } } if (flagmask & NPY_ARRAY_C_CONTIGUOUS) { if (_IsContiguous(ret)) { PyArray_ENABLEFLAGS(ret, NPY_ARRAY_C_CONTIGUOUS); if (PyArray_NDIM(ret) > 1) { PyArray_CLEARFLAGS(ret, NPY_ARRAY_F_CONTIGUOUS); } } else { PyArray_CLEARFLAGS(ret, NPY_ARRAY_C_CONTIGUOUS); } } if (flagmask & NPY_ARRAY_ALIGNED) { if (_IsAligned(ret)) { PyArray_ENABLEFLAGS(ret, NPY_ARRAY_ALIGNED); } else { PyArray_CLEARFLAGS(ret, NPY_ARRAY_ALIGNED); } } /* * This is not checked by default WRITEABLE is not * part of UPDATE_ALL */ if (flagmask & NPY_ARRAY_WRITEABLE) { if (_IsWriteable(ret)) { PyArray_ENABLEFLAGS(ret, NPY_ARRAY_WRITEABLE); } else { PyArray_CLEARFLAGS(ret, NPY_ARRAY_WRITEABLE); } } return; }
NRT_adapt_ndarray_to_python(arystruct_t* arystruct, int ndim, int writeable, PyArray_Descr *descr) { PyArrayObject *array; MemInfoObject *miobj = NULL; PyObject *args; npy_intp *shape, *strides; int flags = 0; if (!PyArray_DescrCheck(descr)) { PyErr_Format(PyExc_TypeError, "expected dtype object, got '%.200s'", Py_TYPE(descr)->tp_name); return NULL; } if (arystruct->parent) { PyObject *obj = try_to_return_parent(arystruct, ndim, descr); if (obj) { /* Release NRT reference to the numpy array */ NRT_MemInfo_release(arystruct->meminfo); return obj; } } if (arystruct->meminfo) { /* wrap into MemInfoObject */ miobj = PyObject_New(MemInfoObject, &MemInfoType); args = PyTuple_New(1); /* SETITEM steals reference */ PyTuple_SET_ITEM(args, 0, PyLong_FromVoidPtr(arystruct->meminfo)); /* Note: MemInfo_init() does not incref. This function steals the * NRT reference. */ if (MemInfo_init(miobj, args, NULL)) { return NULL; } Py_DECREF(args); } shape = arystruct->shape_and_strides; strides = shape + ndim; Py_INCREF((PyObject *) descr); array = (PyArrayObject *) PyArray_NewFromDescr(&PyArray_Type, descr, ndim, shape, strides, arystruct->data, flags, (PyObject *) miobj); if (array == NULL) return NULL; /* Set writable */ #if NPY_API_VERSION >= 0x00000007 if (writeable) { PyArray_ENABLEFLAGS(array, NPY_ARRAY_WRITEABLE); } else { PyArray_CLEARFLAGS(array, NPY_ARRAY_WRITEABLE); } #else if (writeable) { array->flags |= NPY_WRITEABLE; } else { array->flags &= ~NPY_WRITEABLE; } #endif if (miobj) { /* Set the MemInfoObject as the base object */ #if NPY_API_VERSION >= 0x00000007 if (-1 == PyArray_SetBaseObject(array, (PyObject *) miobj)) { Py_DECREF(array); Py_DECREF(miobj); return NULL; } #else PyArray_BASE(array) = (PyObject *) miobj; #endif } return (PyObject *) array; }
/* * Check whether the given array is stored contiguously * in memory. And update the passed in ap flags appropriately. * * The traditional rule is that for an array to be flagged as C contiguous, * the following must hold: * * strides[-1] == itemsize * strides[i] == shape[i+1] * strides[i + 1] * * And for an array to be flagged as F contiguous, the obvious reversal: * * strides[0] == itemsize * strides[i] == shape[i - 1] * strides[i - 1] * * According to these rules, a 0- or 1-dimensional array is either both * C- and F-contiguous, or neither; and an array with 2+ dimensions * can be C- or F- contiguous, or neither, but not both. Though there * there are exceptions for arrays with zero or one item, in the first * case the check is relaxed up to and including the first dimension * with shape[i] == 0. In the second case `strides == itemsize` will * can be true for all dimensions and both flags are set. * * When NPY_RELAXED_STRIDES_CHECKING is set, we use a more accurate * definition of C- and F-contiguity, in which all 0-sized arrays are * contiguous (regardless of dimensionality), and if shape[i] == 1 * then we ignore strides[i] (since it has no affect on memory layout). * With these new rules, it is possible for e.g. a 10x1 array to be both * C- and F-contiguous -- but, they break downstream code which assumes * that for contiguous arrays strides[-1] (resp. strides[0]) always * contains the itemsize. */ static void _UpdateContiguousFlags(PyArrayObject *ap) { npy_intp sd; npy_intp dim; int i; npy_bool is_c_contig = 1; sd = PyArray_ITEMSIZE(ap); for (i = PyArray_NDIM(ap) - 1; i >= 0; --i) { dim = PyArray_DIMS(ap)[i]; #if NPY_RELAXED_STRIDES_CHECKING /* contiguous by definition */ if (dim == 0) { PyArray_ENABLEFLAGS(ap, NPY_ARRAY_C_CONTIGUOUS); PyArray_ENABLEFLAGS(ap, NPY_ARRAY_F_CONTIGUOUS); return; } if (dim != 1) { if (PyArray_STRIDES(ap)[i] != sd) { is_c_contig = 0; } sd *= dim; } #else /* not NPY_RELAXED_STRIDES_CHECKING */ if (PyArray_STRIDES(ap)[i] != sd) { is_c_contig = 0; break; } /* contiguous, if it got this far */ if (dim == 0) { break; } sd *= dim; #endif /* not NPY_RELAXED_STRIDES_CHECKING */ } if (is_c_contig) { PyArray_ENABLEFLAGS(ap, NPY_ARRAY_C_CONTIGUOUS); } else { PyArray_CLEARFLAGS(ap, NPY_ARRAY_C_CONTIGUOUS); } /* check if fortran contiguous */ sd = PyArray_ITEMSIZE(ap); for (i = 0; i < PyArray_NDIM(ap); ++i) { dim = PyArray_DIMS(ap)[i]; #if NPY_RELAXED_STRIDES_CHECKING if (dim != 1) { if (PyArray_STRIDES(ap)[i] != sd) { PyArray_CLEARFLAGS(ap, NPY_ARRAY_F_CONTIGUOUS); return; } sd *= dim; } #else /* not NPY_RELAXED_STRIDES_CHECKING */ if (PyArray_STRIDES(ap)[i] != sd) { PyArray_CLEARFLAGS(ap, NPY_ARRAY_F_CONTIGUOUS); return; } if (dim == 0) { break; } sd *= dim; #endif /* not NPY_RELAXED_STRIDES_CHECKING */ } PyArray_ENABLEFLAGS(ap, NPY_ARRAY_F_CONTIGUOUS); return; }
static PyObject * enz_vnmpocnp(PyObject *self, PyObject *args, PyObject *keywds) { static char *kwlist[] = { "r", "f", "n", "m", "L_max", "bessel_name", "ncpus", "verb", NULL }; long syscpus = sysconf(_SC_NPROCESSORS_ONLN); PyObject *r_o, *f_o, *n_o, *m_o; PyObject *r = NULL; PyObject *f = NULL; PyObject *n = NULL; PyObject *m = NULL; const char *error = NULL; npy_intp r_n, f_n, beta_n; PyObject *vnm = NULL; npy_intp vnm_dims[3]; double *datar = NULL; complex double *dataf = NULL; int *datan = NULL; int *datam = NULL; complex double *datap = NULL; int kL_max = 35; int kncpus = -1; int kverb = 0; char *kbessel_name = "jn"; int ret; if (syscpus <= 0) syscpus = 1; if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!O!O!O!|isii", kwlist, &PyArray_Type, &r_o, &PyArray_Type, &f_o, &PyArray_Type, &n_o, &PyArray_Type, &m_o, &kL_max, &kbessel_name, &kncpus, &kverb)) { PyErr_SetString(PyExc_SyntaxError, "failed to parse args"); return NULL; } r = PyArray_FROM_OTF(r_o, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY); f = PyArray_FROM_OTF(f_o, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY); n = PyArray_FROM_OTF(n_o, NPY_INT64, NPY_ARRAY_IN_ARRAY); m = PyArray_FROM_OTF(m_o, NPY_INT64, NPY_ARRAY_IN_ARRAY); if (!r) { PyErr_SetString(PyExc_ValueError, "cannot convert r to PyArray"); return NULL; } if (!f) { PyErr_SetString(PyExc_ValueError, "cannot convert f to PyArray"); return NULL; } if (!n) { PyErr_SetString(PyExc_ValueError, "cannot convert n to PyArray"); return NULL; } if (!m) { PyErr_SetString(PyExc_ValueError, "cannot convert m to PyArray"); return NULL; } if (!r || not_vect(r) || PyArray_TYPE((PyArrayObject*)r) != NPY_FLOAT64) { error = "r is not a vector of doubles"; goto exit_decrement; } r_n = PyArray_DIM((PyArrayObject*)r, 0); if (!f || not_vect(f) || PyArray_TYPE((PyArrayObject*)f) != NPY_COMPLEX128) { error = "f is not a vector of complex numbers"; goto exit_decrement; } f_n = PyArray_DIM((PyArrayObject*)f, 0); if (!n || not_vect(n) || PyArray_TYPE((PyArrayObject*)n) != NPY_INT64) { error = "n is not a vector of integers"; goto exit_decrement; } if (!m || not_vect(m) || PyArray_TYPE((PyArrayObject*)m) != NPY_INT64) { error = "m is not a vector of integers"; goto exit_decrement; } if (PyArray_DIM((PyArrayObject*)n, 0) != PyArray_DIM((PyArrayObject*)m, 0)) { error = "n and m must have the same length"; goto exit_decrement; } beta_n = PyArray_DIM((PyArrayObject*)n, 0); vnm_dims[0] = r_n; vnm_dims[1] = f_n; vnm_dims[2] = beta_n; vnm = PyArray_New(&PyArray_Type, 3, vnm_dims, NPY_COMPLEX128, NULL, NULL, 0, NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_ALIGNED, NULL); if (!vnm) { error = "cannot create vnm"; goto exit_decrement; } PyArray_CLEARFLAGS((PyArrayObject*)vnm, NPY_ARRAY_C_CONTIGUOUS); assert(PyArray_Size(vnm) == (r_n * f_n * beta_n)); assert(PyArray_NBYTES(vnm) == (r_n * f_n * beta_n * sizeof(double complex))); datap = PyArray_DATA((PyArrayObject*)vnm); if (kncpus < 0) kncpus = beta_n < syscpus ? beta_n : syscpus; else kncpus = kncpus > syscpus ? syscpus : kncpus; if ((r_n * f_n * beta_n) != 0) { datar = PyArray_DATA((PyArrayObject*)r); dataf = PyArray_DATA((PyArrayObject*)f); datan = PyArray_DATA((PyArrayObject*)n); datam = PyArray_DATA((PyArrayObject*)m); Py_BEGIN_ALLOW_THREADS ret = vnmpocnp(r_n, datar, f_n, dataf, beta_n, datan, datam, kL_max, kbessel_name, kncpus, kverb, datap, &error); Py_END_ALLOW_THREADS if (ret) { Py_XDECREF(vnm); goto exit_decrement; } }