static int
copy_double_double(PyArrayNeighborhoodIterObject *itx,
        PyArrayNeighborhoodIterObject *niterx,
        npy_intp *bounds,
        PyObject **out)
{
    npy_intp i, j;
    double *ptr;
    npy_intp odims[NPY_MAXDIMS];
    PyArrayObject *aout;

    /*
     * For each point in itx, copy the current neighborhood into an array which
     * is appended at the output list
     */
    PyArrayNeighborhoodIter_Reset(itx);
    for (i = 0; i < itx->size; ++i) {
        for (j = 0; j < PyArray_NDIM(itx->ao); ++j) {
            odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1;
        }
        aout = (PyArrayObject*)PyArray_SimpleNew(
                            PyArray_NDIM(itx->ao), odims, NPY_DOUBLE);
        if (aout == NULL) {
            return -1;
        }

        ptr = (double*)PyArray_DATA(aout);

        PyArrayNeighborhoodIter_Reset(niterx);
        for (j = 0; j < niterx->size; ++j) {
            *ptr = *((double*)niterx->dataptr);
            ptr += 1;
            PyArrayNeighborhoodIter_Next(niterx);
        }
        PyList_Append(*out, (PyObject*)aout);
        Py_DECREF(aout);
        PyArrayNeighborhoodIter_Next(itx);
    }
    return 0;
}
static int copy_int(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *niterx,
        npy_intp *bounds,
        PyObject **out)
{
    npy_intp i, j;
    int *ptr;
    npy_intp odims[NPY_MAXDIMS];
    PyArrayObject *aout;

    /*
     * For each point in itx, copy the current neighborhood into an array which
     * is appended at the output list
     */
    for (i = 0; i < itx->size; ++i) {
        PyArrayNeighborhoodIter_Reset(niterx);

        for (j = 0; j < itx->ao->nd; ++j) {
            odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1;
        }
        aout = (PyArrayObject*)PyArray_SimpleNew(itx->ao->nd, odims, NPY_INT);
        if (aout == NULL) {
            return -1;
        }

        ptr = (int*)aout->data;

        for (j = 0; j < niterx->size; ++j) {
            *ptr = *((int*)niterx->dataptr);
            PyArrayNeighborhoodIter_Next(niterx);
            ptr += 1;
        }

        PyList_Append(*out, (PyObject*)aout);
        Py_DECREF(aout);
        PyArray_ITER_NEXT(itx);
    }

    return 0;
}
static int copy_object(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *niterx,
        npy_intp *bounds,
        PyObject **out)
{
    npy_intp i, j;
    npy_intp odims[NPY_MAXDIMS];
    PyArrayObject *aout;
    PyArray_CopySwapFunc *copyswap = PyArray_DESCR(itx->ao)->f->copyswap;
    npy_int itemsize = PyArray_ITEMSIZE(itx->ao);

    /*
     * For each point in itx, copy the current neighborhood into an array which
     * is appended at the output list
     */
    for (i = 0; i < itx->size; ++i) {
        PyArrayNeighborhoodIter_Reset(niterx);

        for (j = 0; j < PyArray_NDIM(itx->ao); ++j) {
            odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1;
        }
        aout = (PyArrayObject*)PyArray_SimpleNew(PyArray_NDIM(itx->ao), odims, NPY_OBJECT);
        if (aout == NULL) {
            return -1;
        }

        for (j = 0; j < niterx->size; ++j) {
            copyswap(PyArray_BYTES(aout) + j * itemsize, niterx->dataptr, 0, NULL);
            PyArrayNeighborhoodIter_Next(niterx);
        }

        PyList_Append(*out, (PyObject*)aout);
        Py_DECREF(aout);
        PyArray_ITER_NEXT(itx);
    }

    return 0;
}