void utils_interp_array(Lattice *lat, PyObject *rObj, PyObject * vObj) { PyArrayObject *rArrayObj, *vArrayObj; int num, n; /* Single position of and force */ double *r, *v; int rNext, vNext; if (!arrayOK(rObj) || !arrayOK(vObj)) return; rArrayObj = (PyArrayObject *)rObj; vArrayObj = (PyArrayObject *)vObj; /* get number of pos/force pairs */ num = PyArray_DIM(rArrayObj, 0); /* check forceArrayObj has the same number */ if (PyArray_DIM(vArrayObj, 0) != num) { PyErr_Format(PyExc_ValueError, "rArrayObj and vArrayObj must have the same length"); return; } r = (double *)PyArray_DATA(rArrayObj); v = (double *)PyArray_DATA(vArrayObj); rNext = PyArray_STRIDE(rArrayObj, 0)/sizeof(double); vNext = PyArray_STRIDE(vArrayObj, 0)/sizeof(double); for (n=0; n<num; ++n) { utils_interp_single(lat, r, v); r += rNext; v += vNext; } /* n */ }
static int strides_to_terms(PyArrayObject *arr, diophantine_term_t *terms, unsigned int *nterms, int skip_empty) { unsigned int i; for (i = 0; i < PyArray_NDIM(arr); ++i) { if (skip_empty) { if (PyArray_DIM(arr, i) <= 1 || PyArray_STRIDE(arr, i) == 0) { continue; } } terms[*nterms].a = PyArray_STRIDE(arr, i); if (terms[*nterms].a < 0) { terms[*nterms].a = -terms[*nterms].a; } if (terms[*nterms].a < 0) { /* integer overflow */ return 1; } terms[*nterms].ub = PyArray_DIM(arr, i) - 1; ++*nterms; } return 0; }
static void construct(PyObject* obj_ptr, converter::rvalue_from_python_stage1_data* data) { const int R = MatType::RowsAtCompileTime; const int C = MatType::ColsAtCompileTime; PyArrayObject *array = reinterpret_cast<PyArrayObject*>(obj_ptr); int flags = PyArray_FLAGS(array); if (!(flags & NPY_ARRAY_C_CONTIGUOUS) || !(flags & NPY_ARRAY_ALIGNED)) throw std::invalid_argument("Contiguous and aligned array required!"); const int ndims = PyArray_NDIM(array); const int dtype_size = (PyArray_DESCR(array))->elsize; const int s1 = PyArray_STRIDE(array, 0), s2 = ndims > 1 ? PyArray_STRIDE(array, 1) : 0; int nrows=1, ncols=1; if( R==1 || C==1 ) { // Vector nrows = R==1 ? 1 : PyArray_SIZE2(array); ncols = C==1 ? 1 : PyArray_SIZE2(array); } else { nrows = (R == Dynamic) ? PyArray_DIMS(array)[0] : R; if ( ndims > 1 ) ncols = (R == Dynamic) ? PyArray_DIMS(array)[1] : R; } T* raw_data = reinterpret_cast<T*>(PyArray_DATA(array)); typedef Map< Matrix<T,Dynamic,Dynamic,RowMajor>,Aligned,Stride<Dynamic, Dynamic> > MapType; void* storage=((converter::rvalue_from_python_storage<MatType>*)(data))->storage.bytes; new (storage) MatType; MatType* emat = (MatType*)storage; *emat = MapType(raw_data, nrows, ncols,Stride<Dynamic, Dynamic>(s1/dtype_size, s2/dtype_size)); data->convertible = storage; }
static blitz::Array<T,1> np_to_blitz_1d( PyObject *ovec, std::string const &vname, std::array<int,1> dims) { // Check that it's type PyArrayObject if (!PyArray_Check(ovec)) { (*icebin_error)(-1, "check_dimensions: Object %s is not a Numpy array", vname.c_str()); } PyArrayObject *vec = (PyArrayObject *)ovec; // Set up shape and strides int const T_size = sizeof(T); size_t len = 1; auto min_stride = PyArray_STRIDE(vec, 0); for (int i=0;i<PyArray_NDIM(vec); ++i) { len *= PyArray_DIM(vec, i); // Python/Numpy strides are in bytes, Blitz++ in sizeof(T) units. min_stride = std::min(min_stride, PyArray_STRIDE(vec, i) / T_size); } assert(T_size == PyArray_ITEMSIZE(vec)); blitz::TinyVector<int,1> shape(0); shape[0] = len; blitz::TinyVector<int,1> strides(0); strides[0] = min_stride; return blitz::Array<T,1>((T*) PyArray_DATA(vec),shape,strides, blitz::neverDeleteData); }
fff_array* fff_array_fromPyArray(const PyArrayObject* x) { fff_array* y; fff_datatype datatype; unsigned int nbytes; size_t dimX = 1, dimY = 1, dimZ = 1, dimT = 1; size_t offX = 0, offY = 0, offZ = 0, offT = 0; size_t ndims = (size_t)PyArray_NDIM(x); /* Check that the input array has less than four dimensions */ if (ndims > 4) { FFF_ERROR("Input array has more than four dimensions", EINVAL); return NULL; } /* Check that the input array is aligned */ if (! PyArray_ISALIGNED(x)) { FFF_ERROR("Input array is not aligned", EINVAL); return NULL; } /* Match the data type */ datatype = fff_datatype_fromNumPy(PyArray_TYPE(x)); if (datatype == FFF_UNKNOWN_TYPE) { FFF_ERROR("Unrecognized data type", EINVAL); return NULL; } /* Dimensions and offsets */ nbytes = fff_nbytes(datatype); dimX = PyArray_DIM(x, 0); offX = PyArray_STRIDE(x, 0)/nbytes; if (ndims > 1) { dimY = PyArray_DIM(x, 1); offY = PyArray_STRIDE(x, 1)/nbytes; if (ndims > 2) { dimZ = PyArray_DIM(x, 2); offZ = PyArray_STRIDE(x, 2)/nbytes; if (ndims > 3) { dimT = PyArray_DIM(x, 3); offT = PyArray_STRIDE(x, 3)/nbytes; } } } /* Create array (not owner) */ y = (fff_array*)malloc(sizeof(fff_array)); *y = fff_array_view(datatype, (void*) PyArray_DATA(x), dimX, dimY, dimZ, dimT, offX, offY, offZ, offT); return y; }
NRT_adapt_ndarray_from_python(PyObject *obj, arystruct_t* arystruct) { PyArrayObject *ndary; int i, ndim; npy_intp *p; void *data; if (!PyArray_Check(obj)) { return -1; } ndary = (PyArrayObject*)obj; ndim = PyArray_NDIM(ndary); data = PyArray_DATA(ndary); arystruct->meminfo = meminfo_new_from_pyobject((void*)data, obj); arystruct->data = data; arystruct->nitems = PyArray_SIZE(ndary); arystruct->itemsize = PyArray_ITEMSIZE(ndary); arystruct->parent = obj; p = arystruct->shape_and_strides; for (i = 0; i < ndim; i++, p++) { *p = PyArray_DIM(ndary, i); } for (i = 0; i < ndim; i++, p++) { *p = PyArray_STRIDE(ndary, i); } NRT_Debug(nrt_debug_print("NRT_adapt_ndarray_from_python %p\n", arystruct->meminfo)); return 0; }
/* * Return non-zero if a type is aligned in each item in the given array, * AND, the descr element size is a multiple of the alignment, * AND, the array data is positioned to alignment granularity. */ static int _is_natively_aligned_at(PyArray_Descr *descr, PyArrayObject *arr, Py_ssize_t offset) { int k; if ((Py_ssize_t)(PyArray_DATA(arr)) % descr->alignment != 0) { return 0; } if (offset % descr->alignment != 0) { return 0; } if (descr->elsize % descr->alignment) { return 0; } for (k = 0; k < PyArray_NDIM(arr); ++k) { if (PyArray_DIM(arr, k) > 1) { if (PyArray_STRIDE(arr, k) % descr->alignment != 0) { return 0; } } } return 1; }
/* save a pgm image */ static PyObject * save_pgm(PyObject *self, PyObject *args) { int status; const char *filename; unsigned w, h, stride; PyArrayObject* array = NULL; if (!PyArg_ParseTuple(args, "sO", &filename, &array)) return NULL; CHECK_CONTIGUOUS(array); w = PyArray_DIM(array, 1); h = PyArray_DIM(array, 0); stride = PyArray_STRIDE(array, 0); Py_BEGIN_ALLOW_THREADS; status = _save_pgm(filename, w, h, stride, PyArray_DATA(array)); Py_END_ALLOW_THREADS; if (status != 0) { PyErr_SetString(FleaError, "pgm save failed"); return NULL; } Py_RETURN_NONE; }
/* initialize iterations over single array elements: */ int NI_InitPointIterator(PyArrayObject *array, NI_Iterator *iterator) { int ii; iterator->rank_m1 = PyArray_NDIM(array) - 1; for(ii = 0; ii < PyArray_NDIM(array); ii++) { /* adapt dimensions for use in the macros: */ iterator->dimensions[ii] = PyArray_DIM(array, ii) - 1; /* initialize coordinates: */ iterator->coordinates[ii] = 0; /* initialize strides: */ iterator->strides[ii] = PyArray_STRIDE(array, ii); /* calculate the strides to move back at the end of an axis: */ iterator->backstrides[ii] = PyArray_STRIDE(array, ii) * iterator->dimensions[ii]; } return 1; }
static PyObject * chameleon_capture(PyObject *self, PyObject *args) { int handle = -1; int timeout_ms = 0; struct chameleon_camera* cam = NULL; PyArrayObject* array = NULL; if (!PyArg_ParseTuple(args, "iiO", &handle, &timeout_ms, &array)) return NULL; CHECK_CONTIGUOUS(array); if (handle >= 0 && handle < NUM_CAMERA_HANDLES && cameras[handle]) { cam = cameras[handle]; } else { PyErr_SetString(ChameleonError, "Invalid handle"); return NULL; } int ndim = PyArray_NDIM(array); //printf("ndim=%d\n", ndim); if (ndim != 2){ PyErr_SetString(ChameleonError, "Array has invalid number of dimensions"); return NULL; } int w = PyArray_DIM(array, 1); int h = PyArray_DIM(array, 0); int stride = PyArray_STRIDE(array, 0); //printf("w=%d, h=%d, stride=%d\n", w,h,stride); if (w != 1280 || h != 960){ PyErr_SetString(ChameleonError, "Invalid array dimensions should be 960x1280"); return NULL; } void* buf = PyArray_DATA(array); int status; float frame_time=0; uint32_t frame_counter=0; Py_BEGIN_ALLOW_THREADS; status = capture_wait(cam, &shutters[handle], buf, stride, stride*h, timeout_ms, &frame_time, &frame_counter); Py_END_ALLOW_THREADS; if (status < 0) { PyErr_SetString(ChameleonError, "Failed to capture"); return NULL; } return Py_BuildValue("flf", frame_time, (long)frame_counter, shutters[handle]); }
/* Fetch vector data from an iterator (view or copy) */ void _fff_vector_sync_with_PyArrayIter(fff_vector* y, const PyArrayIterObject* it, npy_intp axis) { if (y->owner) { PyArrayObject* ao = (PyArrayObject*) it->ao; COPY_BUFFER(y, PyArray_ITER_DATA(it), PyArray_STRIDE(ao, axis), PyArray_TYPE(ao), PyArray_ITEMSIZE(ao)); } else y->data = (double*) PyArray_ITER_DATA(it); return; }
void init_from_array(PyArrayObject* a) throw() { /* Upon calling init_from_array, a should already have been incref'd for ownership by this object. */ /* Store a reference to the Numpy array so we can DECREF it in the destructor. */ array = a; /* Point the boost::array at the Numpy array data. We don't need to worry about free'ing this pointer, because it will always point to memory allocated as part of the data of a Numpy array. That memory is managed by Python reference counting. */ super::base_ = (TPtr)PyArray_DATA(a); /* Set the storage order. It would seem like we would want to choose C or Fortran ordering here based on the flags in the Numpy array. However, those flags are purely informational, the actually information about storage order is recorded in the strides. */ super::storage_ = boost::c_storage_order(); /* Copy the dimensions from the Numpy array to the boost::array. */ boost::detail::multi_array::copy_n(PyArray_DIMS(a), NDims, super::extent_list_.begin()); /* Copy the strides from the Numpy array to the boost::array. Numpy strides are in bytes. boost::array strides are in elements, so we need to divide. */ for (size_t i = 0; i < NDims; ++i) { super::stride_list_[i] = PyArray_STRIDE(a, i) / sizeof(T); } /* index_base_list_ stores the bases of the indices in each dimension. Since we want C-style and Numpy-style zero-based indexing, just fill it with zeros. */ std::fill_n(super::index_base_list_.begin(), NDims, 0); /* We don't want any additional offsets. If they exist, Numpy has already handled that for us when calculating the data pointer and strides. */ super::origin_offset_ = 0; super::directional_offset_ = 0; /* Calculate the number of elements. This has nothing to do with memory layout. */ super::num_elements_ = std::accumulate(super::extent_list_.begin(), super::extent_list_.end(), size_type(1), std::multiplies<size_type>()); }
static int set_vector_from_array(int n, double *dest, PyArrayObject *obj) { int i; if (PyArray_DESCR(obj) != PyArray_DescrFromType(NPY_DOUBLE)) { PyErr_SetString(PyExc_TypeError, "Expected a double precision numpy array."); return -1; } if (PyArray_NDIM(obj) == 1) { if (PyArray_DIM(obj,0) !=n) { PyErr_SetString(PyExc_TypeError, "Invalid number of elements."); return -1; } for (i=0;i<n;i++) { char *data = PyArray_BYTES(obj) + PyArray_STRIDE(obj,0)*i; dest[i] = *((double *) data); } return 0; } if (PyArray_NDIM(obj) == 2) { if (PyArray_DIM(obj,0)==n && PyArray_DIM(obj,1)==1) { for (i=0;i<n;i++) { char *data = PyArray_BYTES(obj) + PyArray_STRIDE(obj,0)*i; dest[i] = *((double *) data); } return 0; } if (PyArray_DIM(obj,0)==1 && PyArray_DIM(obj,1)==n) { for (i=0;i<n;i++) { char *data = PyArray_BYTES(obj) + PyArray_STRIDE(obj,1)*i; dest[i] = *((double *) data); } return 0; } PyErr_SetString(PyExc_TypeError, "Invalid number of elements."); return -1; } PyErr_SetString(PyExc_TypeError, "Expected a one-dimensional numpy array."); return -1; }
static PyObject* py_chebyfwd(PyObject *obj, PyObject *args, PyObject *kwds) { PyArrayObject *data = NULL; PyArrayObject *coef = NULL; int numdata, error; int numcoef = MAXCOEF; npy_intp t; static char *kwlist[] = {"data", "numcoef", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist, PyConverter_AnyDoubleArray, &data, &numcoef)) return NULL; if (PyArray_NDIM(data) != 1) { PyErr_Format(PyExc_ValueError, "not a one dimensional array"); goto _fail; } numdata = (int)PyArray_DIM(data, 0); if (numcoef > numdata) numcoef = numdata; if (numcoef > MAXCOEF) numcoef = MAXCOEF; t = numcoef; coef = (PyArrayObject *)PyArray_SimpleNew(1, &t, NPY_DOUBLE); if (coef == NULL) { PyErr_Format(PyExc_MemoryError, "unable to allocate coef array"); goto _fail; } error = chebyfwd( (char *)PyArray_DATA(data), (int)PyArray_STRIDE(data, 0), numdata, (double *)PyArray_DATA(coef), numcoef); if (error != 0) { PyErr_Format(PyExc_ValueError, "chebyfwd() failed with error code %i", error); goto _fail; } Py_DECREF(data); return PyArray_Return(coef); _fail: Py_XDECREF(data); Py_XDECREF(coef); return NULL; }
void local_histogram(double* H, unsigned int clamp, PyArrayIterObject* iter, const unsigned int* size) { PyArrayObject *block, *im = iter->ao; PyArrayIterObject* block_iter; unsigned int i, left, right, center, halfsize, dim, offset=0; npy_intp block_dims[3]; UPDATE_ITERATOR_COORDS(iter); /* Compute block corners */ for (i=0; i<3; i++) { center = iter->coordinates[i]; halfsize = size[i]/2; dim = PyArray_DIM(im, i); /* Left handside corner */ if (center<halfsize) left = 0; else left = center-halfsize; /* Right handside corner (plus one)*/ right = center+halfsize+1; if (right>dim) right = dim; /* Block properties */ offset += left*PyArray_STRIDE(im, i); block_dims[i] = right-left; } /* Create the block as a vew and the block iterator */ block = (PyArrayObject*)PyArray_New(&PyArray_Type, 3, block_dims, PyArray_TYPE(im), PyArray_STRIDES(im), (void*)(PyArray_DATA(im)+offset), PyArray_ITEMSIZE(im), NPY_BEHAVED, NULL); block_iter = (PyArrayIterObject*)PyArray_IterNew((PyObject*)block); /* Compute block histogram */ histogram(H, clamp, block_iter); /* Free memory */ Py_XDECREF(block_iter); Py_XDECREF(block); return; }
/* Create an fff_vector from a PyArrayIter object */ fff_vector* _fff_vector_new_from_PyArrayIter(const PyArrayIterObject* it, npy_intp axis) { fff_vector* y; char* data = PyArray_ITER_DATA(it); PyArrayObject* ao = (PyArrayObject*) it->ao; npy_intp dim = PyArray_DIM(ao, axis); npy_intp stride = PyArray_STRIDE(ao, axis); int type = PyArray_TYPE(ao); int itemsize = PyArray_ITEMSIZE(ao); y = _fff_vector_new_from_buffer(data, dim, stride, type, itemsize); return y; }
static int set_matrix_from_array(int m,int ms,int n, double *dest, PyArrayObject *obj) { int i,j; if (PyArray_DESCR(obj) != PyArray_DescrFromType(NPY_DOUBLE)) { PyErr_SetString(PyExc_TypeError, "Expected a double precision numpy array."); return -1; } if (PyArray_NDIM(obj) != 2) { PyErr_SetString(PyExc_TypeError, "Expected a two-dimensional numpy array (matrix)."); return -1; } if (PyArray_DIM(obj,0) !=m || PyArray_DIM(obj,1) !=n ) { PyErr_SetString(PyExc_TypeError, "Number of columns or rows do not match."); return -1; } for (j=0;j<n;j++) { for (i=0;i<m;i++) { char *data = PyArray_BYTES(obj) + PyArray_STRIDE(obj,0)*i + PyArray_STRIDE(obj,1)*j; dest[i+j*ms] = *((double *) data); } } return 0; }
void utils_addForceAtPosition_array(Lattice *lat, PyObject *FObj, PyObject *rObj) { PyArrayObject *FArrayObj, *rArrayObj; int num; /* Single position of and force */ double *r, *F; int rNext, FNext; int n; if (!arrayOK(FObj) || !arrayOK(rObj)) return; rArrayObj = (PyArrayObject *)rObj; FArrayObj = (PyArrayObject *)FObj; /* get number of pos/force pairs */ num = PyArray_DIM(rArrayObj, 0); /* check forceArrayObj has the same number */ if (PyArray_DIM(FArrayObj, 0) != num) { PyErr_Format(PyExc_ValueError, "FArrayObj and rArrayObj must have the same length"); return; } r = (double *)PyArray_DATA(rArrayObj); F = (double *)PyArray_DATA(FArrayObj); rNext = PyArray_STRIDE(rArrayObj, 0)/sizeof(double); FNext = PyArray_STRIDE(FArrayObj, 0)/sizeof(double); for (n=0; n<num; ++n) { utils_addForceAtPosition_single(lat, F, r); r += rNext; F += FNext; } }
static PyObject *get_array_from_matrix(int m, int ms, int n, const double *data) { int i; npy_intp dims[2]; PyArrayObject *matout; dims[0] = m; dims[1] = n; matout = (PyArrayObject *) PyArray_NewFromDescr(&PyArray_Type, PyArray_DescrFromType(NPY_DOUBLE), 2, dims, NULL, NULL, 1, NULL); for (i=0;i<n;i++) { memcpy(matout->data + i*PyArray_STRIDE(matout,1), data + i*ms, sizeof(double) * m); } return PyArray_Return(matout); }
double cubic_spline_sample1d (double x, const PyArrayObject* Coef, int mode) { unsigned int dim = PyArray_DIM(Coef, 0); unsigned int offset = PyArray_STRIDE(Coef, 0)/sizeof(double); double *coef = PyArray_DATA(Coef); unsigned int ddim = dim-1; unsigned int two_ddim = 2*ddim; double *buf; int nx, px, xx; double s; double bspx[4]; int posx[4]; double *buf_bspx; int *buf_posx; double w = 1; BOUNDARY_CONDITIONS(mode, x, w, ddim, dim); COMPUTE_NEIGHBORS(x, ddim, nx, px); /* Compute the B-spline values as well as the image positions where to find the B-spline coefficients (including mirror conditions) */ buf_bspx = (double*)bspx; buf_posx = (int*)posx; for (xx = nx; xx <= px; xx ++, buf_bspx ++, buf_posx ++) { *buf_bspx = cubic_spline_basis(x-(double)xx); *buf_posx = CUBIC_SPLINE_MIRROR(xx, ddim, two_ddim); } /* Compute the interpolated value incrementally */ s = 0.0; buf_bspx = (double*)bspx; buf_posx = (int*)posx; for (xx = nx; xx <= px; xx ++, buf_bspx ++, buf_posx ++) { /* Point towards the coefficient value at position xx */ buf = coef + (*buf_posx)*offset; /* Update signal value */ s += (*buf) * (*buf_bspx); } return w*s; }
fff_vector* fff_vector_fromPyArray(const PyArrayObject* x) { fff_vector* y; int ok; npy_intp axis = _PyArray_main_axis(x, &ok); if (!ok) { FFF_ERROR("Input array is not a vector", EINVAL); return NULL; } y = _fff_vector_new_from_buffer(PyArray_DATA(x), PyArray_DIM(x, axis), PyArray_STRIDE(x, axis), PyArray_TYPE(x), PyArray_ITEMSIZE(x)); return y; }
static void _cubic_spline_transform(PyArrayObject* res, int axis, double* work) { PyArrayIterObject* iter; unsigned int dim, stride; /* Instantiate iterator and views */ iter = (PyArrayIterObject*)PyArray_IterAllButAxis((PyObject*)res, &axis); dim = PyArray_DIM((PyArrayObject*)iter->ao, axis); stride = PyArray_STRIDE((PyArrayObject*)iter->ao, axis)/sizeof(double); /* Apply the cubic spline transform along given axis */ while(iter->index < iter->size) { _copy_double_buffer(work, PyArray_ITER_DATA(iter), dim, stride); _cubic_spline_transform1d(PyArray_ITER_DATA(iter), work, dim, stride, 1); PyArray_ITER_NEXT(iter); } /* Free local structures */ Py_DECREF(iter); return; }
/* Initialize a line buffer */ int NI_InitLineBuffer(PyArrayObject *array, int axis, npy_intp size1, npy_intp size2, npy_intp buffer_lines, double *buffer_data, NI_ExtendMode extend_mode, double extend_value, NI_LineBuffer *buffer) { npy_intp line_length = 0, array_lines = 0, size; size = PyArray_SIZE(array); /* check if the buffer is big enough: */ if (size > 0 && buffer_lines < 1) { PyErr_SetString(PyExc_RuntimeError, "buffer too small"); return 0; } /* Initialize a line iterator to move over the array: */ if (!NI_InitPointIterator(array, &(buffer->iterator))) return 0; if (!NI_LineIterator(&(buffer->iterator), axis)) return 0; line_length = PyArray_NDIM(array) > 0 ? PyArray_DIM(array, axis) : 1; if (line_length > 0) { array_lines = line_length > 0 ? size / line_length : 1; } /* initialize the buffer structure: */ buffer->array_data = (void *)PyArray_DATA(array); buffer->buffer_data = buffer_data; buffer->buffer_lines = buffer_lines; buffer->array_type = NI_CanonicalType(PyArray_TYPE(array)); buffer->array_lines = array_lines; buffer->next_line = 0; buffer->size1 = size1; buffer->size2 = size2; buffer->line_length = line_length; buffer->line_stride = PyArray_NDIM(array) > 0 ? PyArray_STRIDE(array, axis) : 0; buffer->extend_mode = extend_mode; buffer->extend_value = extend_value; return 1; }
Domi::MDArrayRCP< T > convertToMDArrayRCP(PyArrayObject * pyArray) { // Get the number of dimensions and initialize the dimensions and // strides arrays int numDims = PyArray_NDIM(pyArray); Teuchos::Array< Domi::dim_type > dims( numDims); Teuchos::Array< Domi::size_type > strides(numDims); // Set the dimensions and strides for (int axis = 0; axis < numDims; ++axis) { dims[ axis] = (Domi::dim_type ) PyArray_DIM( pyArray, axis); strides[axis] = (Domi::size_type) PyArray_STRIDE(pyArray, axis); } // Get the data pointer and layout T * data = (T*) PyArray_DATA(pyArray); Domi::Layout layout = PyArray_IS_C_CONTIGUOUS(pyArray) ? Domi::C_ORDER : Domi::FORTRAN_ORDER; // Return the result return Domi::MDArrayRCP< T >(dims, strides, data, layout); }
npy_intp raw_stride(npy_intp i) const { return PyArray_STRIDE(this->array_, i); }
/* * digitize(x, bins, right=False) returns an array of integers the same length * as x. The values i returned are such that bins[i - 1] <= x < bins[i] if * bins is monotonically increasing, or bins[i - 1] > x >= bins[i] if bins * is monotonically decreasing. Beyond the bounds of bins, returns either * i = 0 or i = len(bins) as appropriate. If right == True the comparison * is bins [i - 1] < x <= bins[i] or bins [i - 1] >= x > bins[i] */ NPY_NO_EXPORT PyObject * arr_digitize(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds) { PyObject *obj_x = NULL; PyObject *obj_bins = NULL; PyArrayObject *arr_x = NULL; PyArrayObject *arr_bins = NULL; PyObject *ret = NULL; npy_intp len_bins; int monotonic, right = 0; NPY_BEGIN_THREADS_DEF static char *kwlist[] = {"x", "bins", "right", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i", kwlist, &obj_x, &obj_bins, &right)) { goto fail; } /* PyArray_SearchSorted will make `x` contiguous even if we don't */ arr_x = (PyArrayObject *)PyArray_FROMANY(obj_x, NPY_DOUBLE, 0, 0, NPY_ARRAY_CARRAY_RO); if (arr_x == NULL) { goto fail; } /* TODO: `bins` could be strided, needs change to check_array_monotonic */ arr_bins = (PyArrayObject *)PyArray_FROMANY(obj_bins, NPY_DOUBLE, 1, 1, NPY_ARRAY_CARRAY_RO); if (arr_bins == NULL) { goto fail; } len_bins = PyArray_SIZE(arr_bins); if (len_bins == 0) { PyErr_SetString(PyExc_ValueError, "bins must have non-zero length"); goto fail; } NPY_BEGIN_THREADS_THRESHOLDED(len_bins) monotonic = check_array_monotonic((const double *)PyArray_DATA(arr_bins), len_bins); NPY_END_THREADS if (monotonic == 0) { PyErr_SetString(PyExc_ValueError, "bins must be monotonically increasing or decreasing"); goto fail; } /* PyArray_SearchSorted needs an increasing array */ if (monotonic == - 1) { PyArrayObject *arr_tmp = NULL; npy_intp shape = PyArray_DIM(arr_bins, 0); npy_intp stride = -PyArray_STRIDE(arr_bins, 0); void *data = (void *)(PyArray_BYTES(arr_bins) - stride * (shape - 1)); arr_tmp = (PyArrayObject *)PyArray_New(&PyArray_Type, 1, &shape, NPY_DOUBLE, &stride, data, 0, PyArray_FLAGS(arr_bins), NULL); if (!arr_tmp) { goto fail; } if (PyArray_SetBaseObject(arr_tmp, (PyObject *)arr_bins) < 0) { Py_DECREF(arr_tmp); goto fail; } arr_bins = arr_tmp; } ret = PyArray_SearchSorted(arr_bins, (PyObject *)arr_x, right ? NPY_SEARCHLEFT : NPY_SEARCHRIGHT, NULL); if (!ret) { goto fail; } /* If bins is decreasing, ret has bins from end, not start */ if (monotonic == -1) { npy_intp *ret_data = (npy_intp *)PyArray_DATA((PyArrayObject *)ret); npy_intp len_ret = PyArray_SIZE((PyArrayObject *)ret); NPY_BEGIN_THREADS_THRESHOLDED(len_ret) while (len_ret--) { *ret_data = len_bins - *ret_data; ret_data++; } NPY_END_THREADS }
Py::Object _path_module::affine_transform(const Py::Tuple& args) { args.verify_length(2); Py::Object vertices_obj = args[0]; Py::Object transform_obj = args[1]; PyArrayObject* vertices = NULL; PyArrayObject* transform = NULL; PyArrayObject* result = NULL; try { vertices = (PyArrayObject*)PyArray_FromObject (vertices_obj.ptr(), PyArray_DOUBLE, 1, 2); if (!vertices || (PyArray_NDIM(vertices) == 2 && PyArray_DIM(vertices, 0) != 0 && PyArray_DIM(vertices, 1) != 2) || (PyArray_NDIM(vertices) == 1 && PyArray_DIM(vertices, 0) != 2 && PyArray_DIM(vertices, 0) != 0)) { throw Py::ValueError("Invalid vertices array."); } transform = (PyArrayObject*) PyArray_FromObject (transform_obj.ptr(), PyArray_DOUBLE, 2, 2); if (!transform || PyArray_DIM(transform, 0) != 3 || PyArray_DIM(transform, 1) != 3) { throw Py::ValueError("Invalid transform."); } double a, b, c, d, e, f; { size_t stride0 = PyArray_STRIDE(transform, 0); size_t stride1 = PyArray_STRIDE(transform, 1); char* row0 = PyArray_BYTES(transform); char* row1 = row0 + stride0; a = *(double*)(row0); row0 += stride1; c = *(double*)(row0); row0 += stride1; e = *(double*)(row0); b = *(double*)(row1); row1 += stride1; d = *(double*)(row1); row1 += stride1; f = *(double*)(row1); } result = (PyArrayObject*)PyArray_SimpleNew (PyArray_NDIM(vertices), PyArray_DIMS(vertices), PyArray_DOUBLE); if (result == NULL) { throw Py::MemoryError("Could not allocate memory for path"); } if (PyArray_NDIM(vertices) == 2) { size_t n = PyArray_DIM(vertices, 0); char* vertex_in = PyArray_BYTES(vertices); double* vertex_out = (double*)PyArray_DATA(result); size_t stride0 = PyArray_STRIDE(vertices, 0); size_t stride1 = PyArray_STRIDE(vertices, 1); double x; double y; for (size_t i = 0; i < n; ++i) { x = *(double*)(vertex_in); y = *(double*)(vertex_in + stride1); *vertex_out++ = a * x + c * y + e; *vertex_out++ = b * x + d * y + f; vertex_in += stride0; } } else if (PyArray_DIM(vertices, 0) != 0) { char* vertex_in = PyArray_BYTES(vertices); double* vertex_out = (double*)PyArray_DATA(result); size_t stride0 = PyArray_STRIDE(vertices, 0); double x; double y; x = *(double*)(vertex_in); y = *(double*)(vertex_in + stride0); *vertex_out++ = a * x + c * y + e; *vertex_out++ = b * x + d * y + f; } } catch (...) { Py_XDECREF(vertices); Py_XDECREF(transform); Py_XDECREF(result); throw; } Py_XDECREF(vertices); Py_XDECREF(transform); return Py::Object((PyObject*)result, true); }
static PyObject * PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out, int axis, int otype) { PyArrayObject *op[2]; PyArray_Descr *op_dtypes[2] = {NULL, NULL}; int op_axes_arrays[2][NPY_MAXDIMS]; int *op_axes[2] = {op_axes_arrays[0], op_axes_arrays[1]}; npy_uint32 op_flags[2]; int idim, ndim, otype_final; int needs_api, need_outer_iterator; NpyIter *iter = NULL, *iter_inner = NULL; /* The selected inner loop */ PyUFuncGenericFunction innerloop = NULL; void *innerloopdata = NULL; const char *ufunc_name = ufunc->name ? ufunc->name : "(unknown)"; /* These parameters come from extobj= or from a TLS global */ int buffersize = 0, errormask = 0; NPY_BEGIN_THREADS_DEF; NPY_UF_DBG_PRINT1("\nEvaluating ufunc %s.accumulate\n", ufunc_name); #if 0 printf("Doing %s.accumulate on array with dtype : ", ufunc_name); PyObject_Print((PyObject *)PyArray_DESCR(arr), stdout, 0); printf("\n"); #endif if (_get_bufsize_errmask(NULL, "accumulate", &buffersize, &errormask) < 0) { return NULL; } /* Take a reference to out for later returning */ Py_XINCREF(out); otype_final = otype; if (get_binary_op_function(ufunc, &otype_final, &innerloop, &innerloopdata) < 0) { PyArray_Descr *dtype = PyArray_DescrFromType(otype); PyErr_Format(PyExc_ValueError, "could not find a matching type for %s.accumulate, " "requested type has type code '%c'", ufunc_name, dtype ? dtype->type : '-'); Py_XDECREF(dtype); goto fail; } ndim = PyArray_NDIM(arr); /* * Set up the output data type, using the input's exact * data type if the type number didn't change to preserve * metadata */ if (PyArray_DESCR(arr)->type_num == otype_final) { if (PyArray_ISNBO(PyArray_DESCR(arr)->byteorder)) { op_dtypes[0] = PyArray_DESCR(arr); Py_INCREF(op_dtypes[0]); } else { op_dtypes[0] = PyArray_DescrNewByteorder(PyArray_DESCR(arr), NPY_NATIVE); } } else { op_dtypes[0] = PyArray_DescrFromType(otype_final); } if (op_dtypes[0] == NULL) { goto fail; } #if NPY_UF_DBG_TRACING printf("Found %s.accumulate inner loop with dtype : ", ufunc_name); PyObject_Print((PyObject *)op_dtypes[0], stdout, 0); printf("\n"); #endif /* Set up the op_axes for the outer loop */ for (idim = 0; idim < ndim; ++idim) { op_axes_arrays[0][idim] = idim; op_axes_arrays[1][idim] = idim; } /* The per-operand flags for the outer loop */ op_flags[0] = NPY_ITER_READWRITE | NPY_ITER_NO_BROADCAST | NPY_ITER_ALLOCATE | NPY_ITER_NO_SUBTYPE; op_flags[1] = NPY_ITER_READONLY; op[0] = out; op[1] = arr; need_outer_iterator = (ndim > 1); /* We can't buffer, so must do UPDATEIFCOPY */ if (!PyArray_ISALIGNED(arr) || (out && !PyArray_ISALIGNED(out)) || !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(arr)) || (out && !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(out)))) { need_outer_iterator = 1; } if (need_outer_iterator) { int ndim_iter = 0; npy_uint32 flags = NPY_ITER_ZEROSIZE_OK| NPY_ITER_REFS_OK; PyArray_Descr **op_dtypes_param = NULL; /* * The way accumulate is set up, we can't do buffering, * so make a copy instead when necessary. */ ndim_iter = ndim; flags |= NPY_ITER_MULTI_INDEX; /* Add some more flags */ op_flags[0] |= NPY_ITER_UPDATEIFCOPY|NPY_ITER_ALIGNED; op_flags[1] |= NPY_ITER_COPY|NPY_ITER_ALIGNED; op_dtypes_param = op_dtypes; op_dtypes[1] = op_dtypes[0]; NPY_UF_DBG_PRINT("Allocating outer iterator\n"); iter = NpyIter_AdvancedNew(2, op, flags, NPY_KEEPORDER, NPY_UNSAFE_CASTING, op_flags, op_dtypes_param, ndim_iter, op_axes, NULL, 0); if (iter == NULL) { goto fail; } /* In case COPY or UPDATEIFCOPY occurred */ op[0] = NpyIter_GetOperandArray(iter)[0]; op[1] = NpyIter_GetOperandArray(iter)[1]; if (PyArray_SIZE(op[0]) == 0) { if (out == NULL) { out = op[0]; Py_INCREF(out); } goto finish; } if (NpyIter_RemoveAxis(iter, axis) != NPY_SUCCEED) { goto fail; } if (NpyIter_RemoveMultiIndex(iter) != NPY_SUCCEED) { goto fail; } } /* Get the output */ if (out == NULL) { if (iter) { op[0] = out = NpyIter_GetOperandArray(iter)[0]; Py_INCREF(out); } else { PyArray_Descr *dtype = op_dtypes[0]; Py_INCREF(dtype); op[0] = out = (PyArrayObject *)PyArray_NewFromDescr( &PyArray_Type, dtype, ndim, PyArray_DIMS(op[1]), NULL, NULL, 0, NULL); if (out == NULL) { goto fail; } } } /* * If the reduction axis has size zero, either return the reduction * unit for UFUNC_REDUCE, or return the zero-sized output array * for UFUNC_ACCUMULATE. */ if (PyArray_DIM(op[1], axis) == 0) { goto finish; } else if (PyArray_SIZE(op[0]) == 0) { goto finish; } if (iter && NpyIter_GetIterSize(iter) != 0) { char *dataptr_copy[3]; npy_intp stride_copy[3]; npy_intp count_m1, stride0, stride1; NpyIter_IterNextFunc *iternext; char **dataptr; int itemsize = op_dtypes[0]->elsize; /* Get the variables needed for the loop */ iternext = NpyIter_GetIterNext(iter, NULL); if (iternext == NULL) { goto fail; } dataptr = NpyIter_GetDataPtrArray(iter); /* Execute the loop with just the outer iterator */ count_m1 = PyArray_DIM(op[1], axis)-1; stride0 = 0, stride1 = PyArray_STRIDE(op[1], axis); NPY_UF_DBG_PRINT("UFunc: Reduce loop with just outer iterator\n"); stride0 = PyArray_STRIDE(op[0], axis); stride_copy[0] = stride0; stride_copy[1] = stride1; stride_copy[2] = stride0; needs_api = NpyIter_IterationNeedsAPI(iter); NPY_BEGIN_THREADS_NDITER(iter); do { dataptr_copy[0] = dataptr[0]; dataptr_copy[1] = dataptr[1]; dataptr_copy[2] = dataptr[0]; /* * Copy the first element to start the reduction. * * Output (dataptr[0]) and input (dataptr[1]) may point to * the same memory, e.g. np.add.accumulate(a, out=a). */ if (otype == NPY_OBJECT) { /* * Incref before decref to avoid the possibility of the * reference count being zero temporarily. */ Py_XINCREF(*(PyObject **)dataptr_copy[1]); Py_XDECREF(*(PyObject **)dataptr_copy[0]); *(PyObject **)dataptr_copy[0] = *(PyObject **)dataptr_copy[1]; } else { memmove(dataptr_copy[0], dataptr_copy[1], itemsize); } if (count_m1 > 0) { /* Turn the two items into three for the inner loop */ dataptr_copy[1] += stride1; dataptr_copy[2] += stride0; NPY_UF_DBG_PRINT1("iterator loop count %d\n", (int)count_m1); innerloop(dataptr_copy, &count_m1, stride_copy, innerloopdata); } } while (iternext(iter)); NPY_END_THREADS; } else if (iter == NULL) { char *dataptr_copy[3]; npy_intp stride_copy[3]; int itemsize = op_dtypes[0]->elsize; /* Execute the loop with no iterators */ npy_intp count = PyArray_DIM(op[1], axis); npy_intp stride0 = 0, stride1 = PyArray_STRIDE(op[1], axis); NPY_UF_DBG_PRINT("UFunc: Reduce loop with no iterators\n"); if (PyArray_NDIM(op[0]) != PyArray_NDIM(op[1]) || !PyArray_CompareLists(PyArray_DIMS(op[0]), PyArray_DIMS(op[1]), PyArray_NDIM(op[0]))) { PyErr_SetString(PyExc_ValueError, "provided out is the wrong size " "for the reduction"); goto fail; } stride0 = PyArray_STRIDE(op[0], axis); stride_copy[0] = stride0; stride_copy[1] = stride1; stride_copy[2] = stride0; /* Turn the two items into three for the inner loop */ dataptr_copy[0] = PyArray_BYTES(op[0]); dataptr_copy[1] = PyArray_BYTES(op[1]); dataptr_copy[2] = PyArray_BYTES(op[0]); /* * Copy the first element to start the reduction. * * Output (dataptr[0]) and input (dataptr[1]) may point to the * same memory, e.g. np.add.accumulate(a, out=a). */ if (otype == NPY_OBJECT) { /* * Incref before decref to avoid the possibility of the * reference count being zero temporarily. */ Py_XINCREF(*(PyObject **)dataptr_copy[1]); Py_XDECREF(*(PyObject **)dataptr_copy[0]); *(PyObject **)dataptr_copy[0] = *(PyObject **)dataptr_copy[1]; } else { memmove(dataptr_copy[0], dataptr_copy[1], itemsize); } if (count > 1) { --count; dataptr_copy[1] += stride1; dataptr_copy[2] += stride0; NPY_UF_DBG_PRINT1("iterator loop count %d\n", (int)count); needs_api = PyDataType_REFCHK(op_dtypes[0]); if (!needs_api) { NPY_BEGIN_THREADS_THRESHOLDED(count); } innerloop(dataptr_copy, &count, stride_copy, innerloopdata); NPY_END_THREADS; } } finish: Py_XDECREF(op_dtypes[0]); NpyIter_Deallocate(iter); NpyIter_Deallocate(iter_inner); return (PyObject *)out; fail: Py_XDECREF(out); Py_XDECREF(op_dtypes[0]); NpyIter_Deallocate(iter); NpyIter_Deallocate(iter_inner); return NULL; }
int NI_GeometricTransform(PyArrayObject *input, int (*map)(npy_intp*, double*, int, int, void*), void* map_data, PyArrayObject* matrix_ar, PyArrayObject* shift_ar, PyArrayObject *coordinates, PyArrayObject *output, int order, int mode, double cval) { char *po, *pi, *pc = NULL; npy_intp **edge_offsets = NULL, **data_offsets = NULL, filter_size; npy_intp ftmp[NPY_MAXDIMS], *fcoordinates = NULL, *foffsets = NULL; npy_intp cstride = 0, kk, hh, ll, jj; npy_intp size; double **splvals = NULL, icoor[NPY_MAXDIMS]; npy_intp idimensions[NPY_MAXDIMS], istrides[NPY_MAXDIMS]; NI_Iterator io, ic; npy_double *matrix = matrix_ar ? (npy_double*)PyArray_DATA(matrix_ar) : NULL; npy_double *shift = shift_ar ? (npy_double*)PyArray_DATA(shift_ar) : NULL; int irank = 0, orank; NPY_BEGIN_THREADS_DEF; NPY_BEGIN_THREADS; for(kk = 0; kk < PyArray_NDIM(input); kk++) { idimensions[kk] = PyArray_DIM(input, kk); istrides[kk] = PyArray_STRIDE(input, kk); } irank = PyArray_NDIM(input); orank = PyArray_NDIM(output); /* if the mapping is from array coordinates: */ if (coordinates) { /* initialize a line iterator along the first axis: */ if (!NI_InitPointIterator(coordinates, &ic)) goto exit; cstride = ic.strides[0]; if (!NI_LineIterator(&ic, 0)) goto exit; pc = (void *)(PyArray_DATA(coordinates)); } /* offsets used at the borders: */ edge_offsets = malloc(irank * sizeof(npy_intp*)); data_offsets = malloc(irank * sizeof(npy_intp*)); if (NPY_UNLIKELY(!edge_offsets || !data_offsets)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) data_offsets[jj] = NULL; for(jj = 0; jj < irank; jj++) { data_offsets[jj] = malloc((order + 1) * sizeof(npy_intp)); if (NPY_UNLIKELY(!data_offsets[jj])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } } /* will hold the spline coefficients: */ splvals = malloc(irank * sizeof(double*)); if (NPY_UNLIKELY(!splvals)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) splvals[jj] = NULL; for(jj = 0; jj < irank; jj++) { splvals[jj] = malloc((order + 1) * sizeof(double)); if (NPY_UNLIKELY(!splvals[jj])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } } filter_size = 1; for(jj = 0; jj < irank; jj++) filter_size *= order + 1; /* initialize output iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; /* get data pointers: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); /* make a table of all possible coordinates within the spline filter: */ fcoordinates = malloc(irank * filter_size * sizeof(npy_intp)); /* make a table of all offsets within the spline filter: */ foffsets = malloc(filter_size * sizeof(npy_intp)); if (NPY_UNLIKELY(!fcoordinates || !foffsets)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) ftmp[jj] = 0; kk = 0; for(hh = 0; hh < filter_size; hh++) { for(jj = 0; jj < irank; jj++) fcoordinates[jj + hh * irank] = ftmp[jj]; foffsets[hh] = kk; for(jj = irank - 1; jj >= 0; jj--) { if (ftmp[jj] < order) { ftmp[jj]++; kk += istrides[jj]; break; } else { ftmp[jj] = 0; kk -= istrides[jj] * order; } } } size = PyArray_SIZE(output); for(kk = 0; kk < size; kk++) { double t = 0.0; int constant = 0, edge = 0; npy_intp offset = 0; if (map) { NPY_END_THREADS; /* call mappint functions: */ if (!map(io.coordinates, icoor, orank, irank, map_data)) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "unknown error in mapping function"); goto exit; } NPY_BEGIN_THREADS; } else if (matrix) { /* do an affine transformation: */ npy_double *p = matrix; for(hh = 0; hh < irank; hh++) { icoor[hh] = 0.0; for(ll = 0; ll < orank; ll++) icoor[hh] += io.coordinates[ll] * *p++; icoor[hh] += shift[hh]; } } else if (coordinates) { /* mapping is from an coordinates array: */ char *p = pc; switch (PyArray_TYPE(coordinates)) { CASE_MAP_COORDINATES(NPY_BOOL, npy_bool, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_UBYTE, npy_ubyte, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_USHORT, npy_ushort, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_UINT, npy_uint, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_ULONG, npy_ulong, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_ULONGLONG, npy_ulonglong, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_BYTE, npy_byte, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_SHORT, npy_short, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_INT, npy_int, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_LONG, npy_long, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_LONGLONG, npy_longlong, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_FLOAT, npy_float, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_DOUBLE, npy_double, p, icoor, irank, cstride); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "coordinate array data type not supported"); goto exit; } } /* iterate over axes: */ for(hh = 0; hh < irank; hh++) { /* if the input coordinate is outside the borders, map it: */ double cc = map_coordinate(icoor[hh], idimensions[hh], mode); if (cc > -1.0) { /* find the filter location along this axis: */ npy_intp start; if (order & 1) { start = (npy_intp)floor(cc) - order / 2; } else { start = (npy_intp)floor(cc + 0.5) - order / 2; } /* get the offset to the start of the filter: */ offset += istrides[hh] * start; if (start < 0 || start + order >= idimensions[hh]) { /* implement border mapping, if outside border: */ edge = 1; edge_offsets[hh] = data_offsets[hh]; for(ll = 0; ll <= order; ll++) { npy_intp idx = start + ll; npy_intp len = idimensions[hh]; if (len <= 1) { idx = 0; } else { npy_intp s2 = 2 * len - 2; if (idx < 0) { idx = s2 * (int)(-idx / s2) + idx; idx = idx <= 1 - len ? idx + s2 : -idx; } else if (idx >= len) { idx -= s2 * (int)(idx / s2); if (idx >= len) idx = s2 - idx; } } /* calculate and store the offests at this edge: */ edge_offsets[hh][ll] = istrides[hh] * (idx - start); } } else { /* we are not at the border, use precalculated offsets: */ edge_offsets[hh] = NULL; } spline_coefficients(cc, order, splvals[hh]); } else { /* we use the constant border condition: */ constant = 1; break; } } if (!constant) { npy_intp *ff = fcoordinates; const int type_num = PyArray_TYPE(input); t = 0.0; for(hh = 0; hh < filter_size; hh++) { double coeff = 0.0; npy_intp idx = 0; if (NPY_UNLIKELY(edge)) { for(ll = 0; ll < irank; ll++) { if (edge_offsets[ll]) idx += edge_offsets[ll][ff[ll]]; else idx += ff[ll] * istrides[ll]; } } else { idx = foffsets[hh]; } idx += offset; switch (type_num) { CASE_INTERP_COEFF(NPY_BOOL, npy_bool, coeff, pi, idx); CASE_INTERP_COEFF(NPY_UBYTE, npy_ubyte, coeff, pi, idx); CASE_INTERP_COEFF(NPY_USHORT, npy_ushort, coeff, pi, idx); CASE_INTERP_COEFF(NPY_UINT, npy_uint, coeff, pi, idx); CASE_INTERP_COEFF(NPY_ULONG, npy_ulong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_ULONGLONG, npy_ulonglong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_BYTE, npy_byte, coeff, pi, idx); CASE_INTERP_COEFF(NPY_SHORT, npy_short, coeff, pi, idx); CASE_INTERP_COEFF(NPY_INT, npy_int, coeff, pi, idx); CASE_INTERP_COEFF(NPY_LONG, npy_long, coeff, pi, idx); CASE_INTERP_COEFF(NPY_LONGLONG, npy_longlong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_FLOAT, npy_float, coeff, pi, idx); CASE_INTERP_COEFF(NPY_DOUBLE, npy_double, coeff, pi, idx); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } /* calculate the interpolated value: */ for(ll = 0; ll < irank; ll++) if (order > 0) coeff *= splvals[ll][ff[ll]]; t += coeff; ff += irank; } } else { t = cval; } /* store output value: */ switch (PyArray_TYPE(output)) { CASE_INTERP_OUT(NPY_BOOL, npy_bool, po, t); CASE_INTERP_OUT_UINT(UBYTE, npy_ubyte, po, t); CASE_INTERP_OUT_UINT(USHORT, npy_ushort, po, t); CASE_INTERP_OUT_UINT(UINT, npy_uint, po, t); CASE_INTERP_OUT_UINT(ULONG, npy_ulong, po, t); CASE_INTERP_OUT_UINT(ULONGLONG, npy_ulonglong, po, t); CASE_INTERP_OUT_INT(BYTE, npy_byte, po, t); CASE_INTERP_OUT_INT(SHORT, npy_short, po, t); CASE_INTERP_OUT_INT(INT, npy_int, po, t); CASE_INTERP_OUT_INT(LONG, npy_long, po, t); CASE_INTERP_OUT_INT(LONGLONG, npy_longlong, po, t); CASE_INTERP_OUT(NPY_FLOAT, npy_float, po, t); CASE_INTERP_OUT(NPY_DOUBLE, npy_double, po, t); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } if (coordinates) { NI_ITERATOR_NEXT2(io, ic, po, pc); } else { NI_ITERATOR_NEXT(io, po); } } exit: NPY_END_THREADS; free(edge_offsets); if (data_offsets) { for(jj = 0; jj < irank; jj++) free(data_offsets[jj]); free(data_offsets); } if (splvals) { for(jj = 0; jj < irank; jj++) free(splvals[jj]); free(splvals); } free(foffsets); free(fcoordinates); return PyErr_Occurred() ? 0 : 1; }
int NI_ZoomShift(PyArrayObject *input, PyArrayObject* zoom_ar, PyArrayObject* shift_ar, PyArrayObject *output, int order, int mode, double cval) { char *po, *pi; npy_intp **zeros = NULL, **offsets = NULL, ***edge_offsets = NULL; npy_intp ftmp[NPY_MAXDIMS], *fcoordinates = NULL, *foffsets = NULL; npy_intp jj, hh, kk, filter_size, odimensions[NPY_MAXDIMS]; npy_intp idimensions[NPY_MAXDIMS], istrides[NPY_MAXDIMS]; npy_intp size; double ***splvals = NULL; NI_Iterator io; npy_double *zooms = zoom_ar ? (npy_double*)PyArray_DATA(zoom_ar) : NULL; npy_double *shifts = shift_ar ? (npy_double*)PyArray_DATA(shift_ar) : NULL; int rank = 0; NPY_BEGIN_THREADS_DEF; NPY_BEGIN_THREADS; for (kk = 0; kk < PyArray_NDIM(input); kk++) { idimensions[kk] = PyArray_DIM(input, kk); istrides[kk] = PyArray_STRIDE(input, kk); odimensions[kk] = PyArray_DIM(output, kk); } rank = PyArray_NDIM(input); /* if the mode is 'constant' we need some temps later: */ if (mode == NI_EXTEND_CONSTANT) { zeros = malloc(rank * sizeof(npy_intp*)); if (NPY_UNLIKELY(!zeros)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) zeros[jj] = NULL; for(jj = 0; jj < rank; jj++) { zeros[jj] = malloc(odimensions[jj] * sizeof(npy_intp)); if (NPY_UNLIKELY(!zeros[jj])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } } } /* store offsets, along each axis: */ offsets = malloc(rank * sizeof(npy_intp*)); /* store spline coefficients, along each axis: */ splvals = malloc(rank * sizeof(double**)); /* store offsets at all edges: */ edge_offsets = malloc(rank * sizeof(npy_intp**)); if (NPY_UNLIKELY(!offsets || !splvals || !edge_offsets)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) { offsets[jj] = NULL; splvals[jj] = NULL; edge_offsets[jj] = NULL; } for(jj = 0; jj < rank; jj++) { offsets[jj] = malloc(odimensions[jj] * sizeof(npy_intp)); splvals[jj] = malloc(odimensions[jj] * sizeof(double*)); edge_offsets[jj] = malloc(odimensions[jj] * sizeof(npy_intp*)); if (NPY_UNLIKELY(!offsets[jj] || !splvals[jj] || !edge_offsets[jj])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(hh = 0; hh < odimensions[jj]; hh++) { splvals[jj][hh] = NULL; edge_offsets[jj][hh] = NULL; } } /* precalculate offsets, and offsets at the edge: */ for(jj = 0; jj < rank; jj++) { double shift = 0.0, zoom = 0.0; if (shifts) shift = shifts[jj]; if (zooms) zoom = zooms[jj]; for(kk = 0; kk < odimensions[jj]; kk++) { double cc = (double)kk; if (shifts) cc += shift; if (zooms) cc *= zoom; cc = map_coordinate(cc, idimensions[jj], mode); if (cc > -1.0) { npy_intp start; if (zeros && zeros[jj]) zeros[jj][kk] = 0; if (order & 1) { start = (npy_intp)floor(cc) - order / 2; } else { start = (npy_intp)floor(cc + 0.5) - order / 2; } offsets[jj][kk] = istrides[jj] * start; if (start < 0 || start + order >= idimensions[jj]) { edge_offsets[jj][kk] = malloc((order + 1) * sizeof(npy_intp)); if (NPY_UNLIKELY(!edge_offsets[jj][kk])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(hh = 0; hh <= order; hh++) { npy_intp idx = start + hh; npy_intp len = idimensions[jj]; if (len <= 1) { idx = 0; } else { npy_intp s2 = 2 * len - 2; if (idx < 0) { idx = s2 * (npy_intp)(-idx / s2) + idx; idx = idx <= 1 - len ? idx + s2 : -idx; } else if (idx >= len) { idx -= s2 * (npy_intp)(idx / s2); if (idx >= len) idx = s2 - idx; } } edge_offsets[jj][kk][hh] = istrides[jj] * (idx - start); } } if (order > 0) { splvals[jj][kk] = malloc((order + 1) * sizeof(double)); if (NPY_UNLIKELY(!splvals[jj][kk])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } spline_coefficients(cc, order, splvals[jj][kk]); } } else { zeros[jj][kk] = 1; } } } filter_size = 1; for(jj = 0; jj < rank; jj++) filter_size *= order + 1; if (!NI_InitPointIterator(output, &io)) goto exit; pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); /* store all coordinates and offsets with filter: */ fcoordinates = malloc(rank * filter_size * sizeof(npy_intp)); foffsets = malloc(filter_size * sizeof(npy_intp)); if (NPY_UNLIKELY(!fcoordinates || !foffsets)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) ftmp[jj] = 0; kk = 0; for(hh = 0; hh < filter_size; hh++) { for(jj = 0; jj < rank; jj++) fcoordinates[jj + hh * rank] = ftmp[jj]; foffsets[hh] = kk; for(jj = rank - 1; jj >= 0; jj--) { if (ftmp[jj] < order) { ftmp[jj]++; kk += istrides[jj]; break; } else { ftmp[jj] = 0; kk -= istrides[jj] * order; } } } size = PyArray_SIZE(output); for(kk = 0; kk < size; kk++) { double t = 0.0; npy_intp edge = 0, oo = 0, zero = 0; for(hh = 0; hh < rank; hh++) { if (zeros && zeros[hh][io.coordinates[hh]]) { /* we use constant border condition */ zero = 1; break; } oo += offsets[hh][io.coordinates[hh]]; if (edge_offsets[hh][io.coordinates[hh]]) edge = 1; } if (!zero) { npy_intp *ff = fcoordinates; const int type_num = PyArray_TYPE(input); t = 0.0; for(hh = 0; hh < filter_size; hh++) { npy_intp idx = 0; double coeff = 0.0; if (NPY_UNLIKELY(edge)) { /* use precalculated edge offsets: */ for(jj = 0; jj < rank; jj++) { if (edge_offsets[jj][io.coordinates[jj]]) idx += edge_offsets[jj][io.coordinates[jj]][ff[jj]]; else idx += ff[jj] * istrides[jj]; } idx += oo; } else { /* use normal offsets: */ idx += oo + foffsets[hh]; } switch (type_num) { CASE_INTERP_COEFF(NPY_BOOL, npy_bool, coeff, pi, idx); CASE_INTERP_COEFF(NPY_UBYTE, npy_ubyte, coeff, pi, idx); CASE_INTERP_COEFF(NPY_USHORT, npy_ushort, coeff, pi, idx); CASE_INTERP_COEFF(NPY_UINT, npy_uint, coeff, pi, idx); CASE_INTERP_COEFF(NPY_ULONG, npy_ulong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_ULONGLONG, npy_ulonglong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_BYTE, npy_byte, coeff, pi, idx); CASE_INTERP_COEFF(NPY_SHORT, npy_short, coeff, pi, idx); CASE_INTERP_COEFF(NPY_INT, npy_int, coeff, pi, idx); CASE_INTERP_COEFF(NPY_LONG, npy_long, coeff, pi, idx); CASE_INTERP_COEFF(NPY_LONGLONG, npy_longlong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_FLOAT, npy_float, coeff, pi, idx); CASE_INTERP_COEFF(NPY_DOUBLE, npy_double, coeff, pi, idx); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } /* calculate interpolated value: */ for(jj = 0; jj < rank; jj++) if (order > 0) coeff *= splvals[jj][io.coordinates[jj]][ff[jj]]; t += coeff; ff += rank; } } else { t = cval; } /* store output: */ switch (PyArray_TYPE(output)) { CASE_INTERP_OUT(NPY_BOOL, npy_bool, po, t); CASE_INTERP_OUT_UINT(UBYTE, npy_ubyte, po, t); CASE_INTERP_OUT_UINT(USHORT, npy_ushort, po, t); CASE_INTERP_OUT_UINT(UINT, npy_uint, po, t); CASE_INTERP_OUT_UINT(ULONG, npy_ulong, po, t); CASE_INTERP_OUT_UINT(ULONGLONG, npy_ulonglong, po, t); CASE_INTERP_OUT_INT(BYTE, npy_byte, po, t); CASE_INTERP_OUT_INT(SHORT, npy_short, po, t); CASE_INTERP_OUT_INT(INT, npy_int, po, t); CASE_INTERP_OUT_INT(LONG, npy_long, po, t); CASE_INTERP_OUT_INT(LONGLONG, npy_longlong, po, t); CASE_INTERP_OUT(NPY_FLOAT, npy_float, po, t); CASE_INTERP_OUT(NPY_DOUBLE, npy_double, po, t); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } NI_ITERATOR_NEXT(io, po); } exit: NPY_END_THREADS; if (zeros) { for(jj = 0; jj < rank; jj++) free(zeros[jj]); free(zeros); } if (offsets) { for(jj = 0; jj < rank; jj++) free(offsets[jj]); free(offsets); } if (splvals) { for(jj = 0; jj < rank; jj++) { if (splvals[jj]) { for(hh = 0; hh < odimensions[jj]; hh++) free(splvals[jj][hh]); free(splvals[jj]); } } free(splvals); } if (edge_offsets) { for(jj = 0; jj < rank; jj++) { if (edge_offsets[jj]) { for(hh = 0; hh < odimensions[jj]; hh++) free(edge_offsets[jj][hh]); free(edge_offsets[jj]); } } free(edge_offsets); } free(foffsets); free(fcoordinates); return PyErr_Occurred() ? 0 : 1; }