Skip to content

Commit

Permalink
Changed NpyArrayNeighborhoodIterObject to no longer call PyArray_One …
Browse files Browse the repository at this point in the history
…or PyArray_Zero.
  • Loading branch information
swarts committed Jul 19, 2010
1 parent f8c46da commit 16a059b
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 112 deletions.
6 changes: 6 additions & 0 deletions numpy/core/include/numpy/_neighborhood_iterator_imp.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef _NPY_INCLUDE_NEIGHBORHOOD_IMP
#error You should not include this header directly
#endif

#ifndef _NEIGHBORHOOD_ITERATOR_IMP_H_
#define _NEIGHBORHOOD_ITERATOR_IMP_H_

/*
* Private API (here for inline)
*/
Expand Down Expand Up @@ -88,3 +92,5 @@ NpyArrayNeighborhoodIter_Reset(NpyArrayNeighborhoodIterObject* iter)

return 0;
}

#endif
21 changes: 5 additions & 16 deletions numpy/core/include/numpy/ndarraytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -879,30 +879,19 @@ typedef struct {
NpyArrayNeighborhoodIterObject* iter;
} PyArrayNeighborhoodIterObject;

#if 0
/*
* Neighborhood iterator API
*/

/* General: those work for any mode */
static NPY_INLINE int
PyArrayNeighborhoodIter_Reset(PyArrayNeighborhoodIterObject* iter);
static NPY_INLINE int
PyArrayNeighborhoodIter_Next(PyArrayNeighborhoodIterObject* iter);
#if 0
static NPY_INLINE int
PyArrayNeighborhoodIter_Next2D(PyArrayNeighborhoodIterObject* iter);
#endif

/*
* Include inline implementations - functions defined there are not
* considered public API
*/
#define _NPY_INCLUDE_NEIGHBORHOOD_IMP
#include "_neighborhood_iterator_imp.h"
#undef _NPY_INCLUDE_NEIGHBORHOOD_IMP

#endif
#define PyArrayNeighborhoodIter_Reset(iter) \
NpyArrayNeighborhoodIter_Reset((iter)->iter)

#define PyArrayNeighborhoodIter_Next(iter) \
NpyArrayNeighborhoodIter_Next((iter)->iter)

/* The default array type */
#define NPY_DEFAULT_TYPE NPY_DOUBLE
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/include/numpy/npy_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,6 @@ enum NPY_TYPES { NPY_BOOL=0,
#define NpyArray_ISNBO(arg) ((arg) != NPY_OPPBYTE)
#define NpyArray_IsNativeByteOrder NpyArray_ISNBO

typedef void (*npy_free_func)(void*);

#endif
7 changes: 6 additions & 1 deletion numpy/core/include/numpy/npy_iterators.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ typedef struct {

} NpyArrayMapIterObject;

/*
* TODO: We should have both PY and NPY level modes since the
* NPY level doesn't support 0 and 1.
*/
enum {
NPY_NEIGHBORHOOD_ITER_ZERO_PADDING,
NPY_NEIGHBORHOOD_ITER_ONE_PADDING,
Expand Down Expand Up @@ -346,6 +350,7 @@ typedef struct {
* for constant padding
*/
char* constant;
npy_free_func constant_free;

int mode;
} NpyArrayNeighborhoodIterObject;
Expand All @@ -359,7 +364,7 @@ extern _NpyTypeObject NpyArrayNeighborhoodIter_Type;

NpyArrayNeighborhoodIterObject*
NpyArray_NeighborhoodIterNew(NpyArrayIterObject *x, npy_intp *bounds,
int mode, struct PyArrayObject *fill);
int mode, void *fill, npy_free_func fillfree);

/* General: those work for any mode */
static NPY_INLINE int
Expand Down
90 changes: 25 additions & 65 deletions numpy/core/src/libnumpy/npy_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,39 +508,6 @@ NpyArray_MultiIterFromArrays(NpyArray **mps, int n, int nadd, ...)

/*========================= Neighborhood iterator ======================*/

static char* _set_constant(NpyArrayNeighborhoodIterObject* iter,
NpyArray *fill)
{
char *ret;
NpyArrayIterObject *ar = iter->_internal_iter;
int storeflags, st;

ret = (char *)NpyArray_malloc(ar->ao->descr->elsize);
if (ret == NULL) {
NpyErr_SetNone(NpyExc_MemoryError);
return NULL;
}

if (NpyArray_ISOBJECT(ar->ao)) { /* TODO: Double check this case, memcpy of a pointer? Is ISOBJECT still correct? */
memcpy(ret, fill->data, sizeof(PyObject*));
Npy_Interface_INCREF(*(PyObject**)ret); /* TODO: What are the possible object types for ret? */
} else {
/* Non-object types */

storeflags = ar->ao->flags;
ar->ao->flags |= NPY_BEHAVED;
st = ar->ao->descr->f->setitem((PyObject*)fill, ret, ar->ao);
ar->ao->flags = storeflags;

if (st < 0) {
NpyArray_free(ret);
return NULL;
}
}

return ret;
}

#define _INF_SET_PTR(c) \
bd = coordinates[c] + p->coordinates[c]; \
if (bd < p->limits[c][0] || bd > p->limits[c][1]) { \
Expand Down Expand Up @@ -665,14 +632,14 @@ get_ptr_circular(NpyArrayIterObject* _iter, npy_intp *coordinates)
*/
NpyArrayNeighborhoodIterObject*
NpyArray_NeighborhoodIterNew(NpyArrayIterObject *x, npy_intp *bounds,
int mode, NpyArray *fill)
int mode, void* fill, npy_free_func fillfree)
{
int i;
NpyArrayNeighborhoodIterObject *ret;
NpyArrayNeighborhoodIterObject *ret = NULL;

ret = NpyArray_malloc(sizeof(*ret));
if (ret == NULL) {
return NULL;
goto fail;
}
_NpyObject_Init((_NpyObject *)ret, &NpyArrayNeighborhoodIter_Type);
ret->magic_number = NPY_VALID_MAGIC;
Expand Down Expand Up @@ -708,42 +675,26 @@ NpyArray_NeighborhoodIterNew(NpyArrayIterObject *x, npy_intp *bounds,
ret->dimensions[i] - 1;
ret->limits_sizes[i] = (ret->limits[i][1] - ret->limits[i][0]) + 1;
}

ret->constant = fill;
ret->constant_free = fillfree;
ret->mode = mode;

switch (mode) {
case NPY_NEIGHBORHOOD_ITER_ZERO_PADDING:
ret->constant = PyArray_Zero(x->ao);
ret->mode = mode;
ret->translate = &get_ptr_constant;
break;
case NPY_NEIGHBORHOOD_ITER_ONE_PADDING:
ret->constant = PyArray_One(x->ao);
ret->mode = mode;
ret->translate = &get_ptr_constant;
break;
case NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING:
/* New reference in returned value of _set_constant if array
* object */
assert(NpyArray_EquivArrTypes(x->ao, fill) == NPY_TRUE);
ret->constant = _set_constant(ret, fill);
if (ret->constant == NULL) {
goto clean_x;
}
ret->mode = mode;
ret->translate = &get_ptr_constant;
break;
case NPY_NEIGHBORHOOD_ITER_MIRROR_PADDING:
ret->mode = mode;
ret->constant = NULL;
ret->translate = &get_ptr_mirror;
break;
case NPY_NEIGHBORHOOD_ITER_CIRCULAR_PADDING:
ret->mode = mode;
ret->constant = NULL;
ret->translate = &get_ptr_circular;
break;
case NPY_NEIGHBORHOOD_ITER_ZERO_PADDING:
case NPY_NEIGHBORHOOD_ITER_ONE_PADDING:
default:
NpyErr_SetString(NpyExc_ValueError, "Unsupported padding mode");
goto clean_x;
goto fail;
}

/*
Expand All @@ -754,16 +705,24 @@ NpyArray_NeighborhoodIterNew(NpyArrayIterObject *x, npy_intp *bounds,

NpyArrayNeighborhoodIter_Reset(ret);
if (NPY_FALSE == NpyInterface_NeighborhoodIterNewWrapper(ret, &ret->nob_interface)) {
if (fill && fillfree) {
(*fillfree)(fill);
}
Npy_INTERFACE(ret) = NULL;
_Npy_DECREF(ret);
return NULL;
}

return ret;

clean_x:
_Npy_DECREF(ret->_internal_iter);
/* TODO: Free ret here once we add a level of indirection */
fail:
if (fill && fillfree) {
(*fillfree)(fill);
}
if (ret) {
_Npy_DECREF(ret->_internal_iter);
/* TODO: Free ret here once we add a level of indirection */
}
return NULL;
}

Expand All @@ -777,11 +736,12 @@ static void neighiter_dealloc(NpyArrayNeighborhoodIterObject* iter)
Py_DECREF(*(PyObject**)iter->constant);
}
}
if (iter->constant != NULL) {
PyDataMem_FREE(iter->constant);
}
_Npy_DECREF(iter->_internal_iter);

if (iter->constant && iter->constant_free) {
(*iter->constant_free)(iter->constant);
}

array_iter_base_dealloc((NpyArrayIterObject*)iter);
NpyArray_free(iter);
}
Expand Down
59 changes: 57 additions & 2 deletions numpy/core/src/multiarray/iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,37 @@ NPY_NO_EXPORT PyTypeObject PyArrayMultiIter_Type = {

/*========================= Neighborhood iterator ======================*/

static char* _set_constant(NpyArray* ao, NpyArray *fill)
{
char *ret;
int storeflags, st;

ret = (char *)PyDataMem_NEW(ao->descr->elsize);
if (ret == NULL) {
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}

if (NpyArray_ISOBJECT(ao)) { /* TODO: Double check this case, memcpy of a pointer? Is ISOBJECT still correct? */
memcpy(ret, fill->data, sizeof(PyObject*));
Py_INCREF(*(PyObject**)ret); /* TODO: What are the possible object types for ret? */
} else {
/* Non-object types */
storeflags = ao->flags;
ao->flags |= NPY_BEHAVED;
st = ao->descr->f->setitem((PyObject*)fill, ret, ao);
ao->flags = storeflags;

if (st < 0) {
PyDataMem_FREE(ret);
return NULL;
}
}

return ret;
}


/*
* fill and x->ao should have equivalent types
*/
Expand All @@ -1639,9 +1670,33 @@ PyArray_NeighborhoodIterNew(PyArrayIterObject *x, intp *bounds,
int mode, PyArrayObject* fill)
{
NpyArrayNeighborhoodIterObject *coreRet;

void *fillptr = NULL;
npy_free_func freefill = NULL;

switch (mode) {
case NPY_NEIGHBORHOOD_ITER_ZERO_PADDING:
fillptr = PyArray_Zero(x->iter->ao);
freefill = free;
mode = NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING;
break;
case NPY_NEIGHBORHOOD_ITER_ONE_PADDING:
fillptr = PyArray_One(x->iter->ao);
freefill = free;
mode = NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING;
break;
case NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING:
fillptr = _set_constant(x->iter->ao, PyArray_ARRAY(fill));
freefill = free;
break;
case NPY_NEIGHBORHOOD_ITER_MIRROR_PADDING:
case NPY_NEIGHBORHOOD_ITER_CIRCULAR_PADDING:
break;
default:
PyErr_SetString(PyExc_ValueError, "Unsupported padding mode");
return NULL;
}
coreRet = NpyArray_NeighborhoodIterNew(x->iter, bounds, mode,
PyArray_ARRAY(fill));
fillptr, freefill);
if (NULL == coreRet) {
return NULL;
}
Expand Down
Loading

0 comments on commit 16a059b

Please sign in to comment.