summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorDavid Cournapeau <cournape@gmail.com>2009-08-07 13:23:24 +0000
committerDavid Cournapeau <cournape@gmail.com>2009-08-07 13:23:24 +0000
commit1f9788da60bfee39e5b95f67d08a2b52cd842498 (patch)
treee780db36734af4a746343bc77867b70809c6e070 /numpy
parent61a88ebe58f740704d6294f289c10ff104c6832a (diff)
downloadnumpy-1f9788da60bfee39e5b95f67d08a2b52cd842498.tar.gz
BUG: Fix neighborhood iterators when the neighborhood was strictly within the array.
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/include/numpy/ndarrayobject.h6
-rw-r--r--numpy/core/src/multiarray/iterators.c40
-rw-r--r--numpy/core/tests/test_multiarray.py23
3 files changed, 51 insertions, 18 deletions
diff --git a/numpy/core/include/numpy/ndarrayobject.h b/numpy/core/include/numpy/ndarrayobject.h
index c91e79446..b6c366cdd 100644
--- a/numpy/core/include/numpy/ndarrayobject.h
+++ b/numpy/core/include/numpy/ndarrayobject.h
@@ -698,7 +698,8 @@ struct PyArrayIterObject_tag {
npy_bool contiguous;
npy_intp bounds[NPY_MAXDIMS][2];
- npy_intp bounds_size[NPY_MAXDIMS];
+ npy_intp limits[NPY_MAXDIMS][2];
+ npy_intp limits_sizes[NPY_MAXDIMS];
npy_iter_get_dataptr_t translate;
} ;
@@ -950,7 +951,8 @@ typedef struct {
npy_bool contiguous;
npy_intp bounds[NPY_MAXDIMS][2];
- npy_intp bounds_size[NPY_MAXDIMS];
+ npy_intp limits[NPY_MAXDIMS][2];
+ npy_intp limits_sizes[NPY_MAXDIMS];
npy_iter_get_dataptr_t translate;
/*
diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c
index 2c48c8657..bf4e52364 100644
--- a/numpy/core/src/multiarray/iterators.c
+++ b/numpy/core/src/multiarray/iterators.c
@@ -315,7 +315,9 @@ array_iter_base_init(PyArrayIterObject *it, PyArrayObject *ao)
}
it->bounds[i][0] = 0;
it->bounds[i][1] = ao->dimensions[i] - 1;
- it->bounds_size[i] = ao->dimensions[i];
+ it->limits[i][0] = 0;
+ it->limits[i][1] = ao->dimensions[i] - 1;
+ it->limits_sizes[i] = it->limits[i][1] - it->limits[i][0] + 1;
}
it->translate = &get_ptr_simple;
@@ -1796,7 +1798,7 @@ static char* _set_constant(PyArrayNeighborhoodIterObject* iter,
#define _INF_SET_PTR(c) \
bd = coordinates[c] + p->coordinates[c]; \
- if (bd < p->bounds[c][0] || bd > p->bounds[c][1]) { \
+ if (bd < p->limits[c][0] || bd > p->limits[c][1]) { \
return niter->constant; \
} \
_coordinates[c] = bd;
@@ -1814,7 +1816,6 @@ get_ptr_constant(PyArrayIterObject* _iter, npy_intp *coordinates)
_INF_SET_PTR(i)
}
- // printf("%s: coordinates is %ld, ptr is %f\n", __func__, _coordinates[0], *((double*)p->translate(p, _coordinates)));
return p->translate(p, _coordinates);
}
#undef _INF_SET_PTR
@@ -1853,9 +1854,9 @@ __npy_pos_remainder(npy_intp i, npy_intp n)
#undef _NPY_IS_EVEN
#define _INF_SET_PTR_MIRROR(c) \
- lb = p->bounds[c][0]; \
+ lb = p->limits[c][0]; \
bd = coordinates[c] + p->coordinates[c] - lb; \
- _coordinates[c] = lb + __npy_pos_remainder(bd, p->bounds_size[c]);
+ _coordinates[c] = lb + __npy_pos_remainder(bd, p->limits_sizes[c]);
/* set the dataptr from its current coordinates */
static char*
@@ -1888,9 +1889,9 @@ __npy_euclidean_division(npy_intp i, npy_intp n)
}
#define _INF_SET_PTR_CIRCULAR(c) \
- lb = p->bounds[c][0]; \
+ lb = p->limits[c][0]; \
bd = coordinates[c] + p->coordinates[c] - lb; \
- _coordinates[c] = lb + __npy_euclidean_division(bd, p->bounds_size[c]);
+ _coordinates[c] = lb + __npy_euclidean_division(bd, p->limits_sizes[c]);
static char*
get_ptr_circular(PyArrayIterObject* _iter, npy_intp *coordinates)
@@ -1931,17 +1932,30 @@ PyArray_NeighborhoodIterNew(PyArrayIterObject *x, intp *bounds,
ret->nd = x->ao->nd;
+ for (i = 0; i < ret->nd; ++i) {
+ ret->dimensions[i] = x->ao->dimensions[i];
+ }
+
/* Compute the neighborhood size and copy the shape */
ret->size = 1;
for (i = 0; i < ret->nd; ++i) {
ret->bounds[i][0] = bounds[2 * i];
ret->bounds[i][1] = bounds[2 * i + 1];
- ret->bounds_size[i] = (bounds[2*i+1] - bounds[2*i]) + 1;
- ret->size *= ret->bounds_size[i];
- }
-
- for (i = 0; i < ret->nd; ++i) {
- ret->dimensions[i] = x->ao->dimensions[i];
+ ret->size *= (ret->bounds[i][1] - ret->bounds[i][0]) + 1;
+
+ /* limits keep track of valid ranges for the neighborhood: if a bound
+ * of the neighborhood is outside the array, then limits is the same as
+ * boundaries. On the contrary, if a bound is strictly inside the
+ * array, then limits correspond to the array range. For example, for
+ * an array [1, 2, 3], if bounds are [-1, 3], limits will be [-1, 3],
+ * but if bounds are [1, 2], then limits will be [0, 2].
+ *
+ * This is used by neighborhood iterators stacked on top of this one */
+ ret->limits[i][0] = ret->bounds[i][0] < 0 ? ret->bounds[i][0] : 0;
+ ret->limits[i][1] = ret->bounds[i][1] >= ret->dimensions[i] - 1 ?
+ ret->bounds[i][1] :
+ ret->dimensions[i] - 1;
+ ret->limits_sizes[i] = (ret->limits[i][1] - ret->limits[i][0]) + 1;
}
switch (mode) {
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 133a67f3c..57f1bd4c6 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1358,11 +1358,28 @@ class TestStackedNeighborhoodIter(TestCase):
# being strictly within the array
def test_simple_strict_within(self):
dt = np.float64
- # Stacking zero on top of mirror
+ # Stacking zero on top of zero, first neighborhood strictly inside the
+ # array
x = np.array([1, 2, 3], dtype=dt)
- r = [np.array([1, 2, 3], dtype=dt)]
+ r = [np.array([1, 2, 3, 0], dtype=dt)]
l = test_neighborhood_iterator_oob(x, [1, 1], NEIGH_MODE['zero'],
- [-1, 1], NEIGH_MODE['zero'])
+ [-1, 2], NEIGH_MODE['zero'])
+ assert_array_equal(l, r)
+
+ # Stacking mirror on top of zero, first neighborhood strictly inside the
+ # array
+ x = np.array([1, 2, 3], dtype=dt)
+ r = [np.array([1, 2, 3, 3], dtype=dt)]
+ l = test_neighborhood_iterator_oob(x, [1, 1], NEIGH_MODE['zero'],
+ [-1, 2], NEIGH_MODE['mirror'])
+ assert_array_equal(l, r)
+
+ # Stacking mirror on top of zero, first neighborhood strictly inside the
+ # array
+ x = np.array([1, 2, 3], dtype=dt)
+ r = [np.array([1, 2, 3, 1], dtype=dt)]
+ l = test_neighborhood_iterator_oob(x, [1, 1], NEIGH_MODE['zero'],
+ [-1, 2], NEIGH_MODE['circular'])
assert_array_equal(l, r)
if __name__ == "__main__":
run_module_suite()