From ed4933995c2122531797da60894040515384c816 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 16 Jan 2015 20:11:38 +0100 Subject: [PATCH 1/8] Fix #5312: use an aligned allocator. Introduce two new functions, get_data_alignment() and set_data_alignment() which allow setting the guaranteed alignment at runtime. --- numpy/core/numeric.py | 40 +++++++- numpy/core/src/multiarray/alloc.c | 99 +++++++++++++++++++- numpy/core/src/multiarray/alloc.h | 7 ++ numpy/core/src/multiarray/multiarraymodule.c | 26 +++++ numpy/core/tests/test_multiarray.py | 27 ++++++ 5 files changed, 194 insertions(+), 5 deletions(-) diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index c1c55517222e..d7e423fb73a1 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -43,7 +43,8 @@ 'Inf', 'inf', 'infty', 'Infinity', 'nan', 'NaN', 'False_', 'True_', 'bitwise_not', 'CLIP', 'RAISE', 'WRAP', 'MAXDIMS', 'BUFSIZE', 'ALLOW_THREADS', - 'ComplexWarning', 'may_share_memory', 'full', 'full_like'] + 'ComplexWarning', 'may_share_memory', 'full', 'full_like', + 'get_data_alignment', 'set_data_alignment'] if sys.version_info[0] < 3: __all__.extend(['getbuffer', 'newbuffer']) @@ -2464,6 +2465,43 @@ def array_equiv(a1, a2): return bool(asarray(a1 == a2).all()) +def get_data_alignment(): + """ + Get the guaranteed alignment of array data allocated by Numpy. + + Returns + ------- + res : int + A power of two representing the current alignment, in bytes, enforced + when an array's data is allocated. + + See Also + -------- + set_data_alignment() + + """ + return multiarray._get_alignment() + + +def set_data_alignment(align): + """ + Set the guaranteed alignment of array data allocated by Numpy. + + Parameters + ---------- + align : int + A power of two representing the alignment, in bytes, to enforce + in future data allocations. + + Notes + ----- + ValueError is raised if the alignment is invalid (too small, or not + a power of two). + + """ + multiarray._set_alignment(align) + + _errdict = {"ignore":ERR_IGNORE, "warn":ERR_WARN, "raise":ERR_RAISE, diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c index 77eb0416bc34..0bb7e808f41b 100644 --- a/numpy/core/src/multiarray/alloc.c +++ b/numpy/core/src/multiarray/alloc.c @@ -59,6 +59,20 @@ _npy_free_cache(void * p, npy_uintp nelem, npy_uint msz, dealloc(p); } +/* + * clear all cache data in the given cache + */ +static void +_npy_clear_cache(npy_uint msz, cache_bucket * cache, void (*dealloc)(void *)) +{ + npy_intp i, nelem; + for (nelem = 0; nelem < msz; nelem++) { + for (i = 0; i < cache[nelem].available; i++) { + dealloc(cache[nelem].ptrs[i]); + } + cache[nelem].available = 0; + } +} /* * array data cache, sz is number of bytes to allocate @@ -162,6 +176,69 @@ PyDataMem_SetEventHook(PyDataMem_EventHookFunc *newhook, return temp; } + +/* Choose a minimum valid alignment for common data types */ +#define MIN_ALIGN 16 + +static size_t datamem_align = MIN_ALIGN; +static size_t datamem_align_mask = MIN_ALIGN - 1; + +static NPY_INLINE size_t +get_aligned_size(size_t size) +{ + return size + datamem_align; +} + +/* + * Align the given pointer to the guaranteed alignment, and remember + * the original pointer. + */ +static NPY_INLINE void * +align_pointer(void *ptr) +{ + /* Ensure a pointer can fit in the space before */ + npy_intp aligned_ptr = ((npy_intp) ptr + sizeof(void *) + datamem_align_mask) + & ~datamem_align_mask; + assert(aligned_ptr - (npy_intp) ptr >= sizeof(void *)); + ((void **) aligned_ptr)[-1] = ptr; + return (void *) aligned_ptr; +} + +/* + * Given an aligned pointer, get the start of the original allocation. + */ +static NPY_INLINE void * +get_original_pointer(void *aligned_ptr) +{ + return ((void **) aligned_ptr)[-1]; +} + +NPY_NO_EXPORT size_t +npy_datamem_get_align(void) +{ + return datamem_align; +} + +NPY_NO_EXPORT int +npy_datamem_set_align(size_t align) +{ + if (align < MIN_ALIGN) + return -1; + size_t align_mask = align - 1; + if ((align ^ align_mask) != (align | align_mask)) { + /* Not a power of two */ + return -1; + } + if (align > datamem_align) { + /* Alignment has increased, free all cached data areas as they may + not be aligned anymore. */ + _npy_clear_cache(NBUCKETS, datacache, &PyDataMem_FREE); + } + datamem_align = align; + datamem_align_mask = align_mask; + return 0; +} + /*NUMPY_API * Allocates memory for array data. */ @@ -169,8 +246,12 @@ NPY_NO_EXPORT void * PyDataMem_NEW(size_t size) { void *result; + size_t aligned_size = get_aligned_size(size); + + result = malloc(aligned_size); + if (result != NULL) + result = align_pointer(result); - result = malloc(size); if (_PyDataMem_eventhook != NULL) { NPY_ALLOW_C_API_DEF NPY_ALLOW_C_API @@ -190,8 +271,13 @@ NPY_NO_EXPORT void * PyDataMem_NEW_ZEROED(size_t size, size_t elsize) { void *result; + size_t aligned_size = get_aligned_size(size); + assert(elsize == 1); /* XXX */ + + result = calloc(aligned_size, elsize); + if (result != NULL) + result = align_pointer(result); - result = calloc(size, elsize); if (_PyDataMem_eventhook != NULL) { NPY_ALLOW_C_API_DEF NPY_ALLOW_C_API @@ -210,7 +296,8 @@ PyDataMem_NEW_ZEROED(size_t size, size_t elsize) NPY_NO_EXPORT void PyDataMem_FREE(void *ptr) { - free(ptr); + if (ptr != NULL) + free(get_original_pointer(ptr)); if (_PyDataMem_eventhook != NULL) { NPY_ALLOW_C_API_DEF NPY_ALLOW_C_API @@ -229,8 +316,12 @@ NPY_NO_EXPORT void * PyDataMem_RENEW(void *ptr, size_t size) { void *result; + size_t aligned_size = get_aligned_size(size); + void *original_ptr = get_original_pointer(ptr); - result = realloc(ptr, size); + result = realloc(original_ptr, aligned_size); + if (result != NULL) + result = align_pointer(result); if (_PyDataMem_eventhook != NULL) { NPY_ALLOW_C_API_DEF NPY_ALLOW_C_API diff --git a/numpy/core/src/multiarray/alloc.h b/numpy/core/src/multiarray/alloc.h index 8f6b167d0380..24b194253ad9 100644 --- a/numpy/core/src/multiarray/alloc.h +++ b/numpy/core/src/multiarray/alloc.h @@ -19,4 +19,11 @@ npy_alloc_cache_dim(npy_uintp sz); NPY_NO_EXPORT void npy_free_cache_dim(void * p, npy_uintp sd); +NPY_NO_EXPORT size_t +npy_datamem_get_align(void); + +NPY_NO_EXPORT int +npy_datamem_set_align(size_t); + + #endif diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index e6b317ed11c2..77115c244af0 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -58,6 +58,7 @@ NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0; #include "multiarraymodule.h" #include "cblasfuncs.h" #include "vdot.h" +#include "alloc.h" #include "templ_common.h" /* for npy_mul_with_overflow_intp */ /* Only here for API compatibility */ @@ -3881,6 +3882,25 @@ array_may_share_memory(PyObject *NPY_UNUSED(ignored), PyObject *args) } } +static PyObject * +get_alignment(PyObject *NPY_UNUSED(ignored), PyObject *NPY_UNUSED(args)) +{ + return PyLong_FromSsize_t(npy_datamem_get_align()); +} + +static PyObject * +set_alignment(PyObject *NPY_UNUSED(ignored), PyObject *args) +{ + int align; + if (!PyArg_ParseTuple(args, "i", &align)) { + return NULL; + } + if (npy_datamem_set_align(align)) { + PyErr_SetString(PyExc_ValueError, "invalid value for alignment"); + return NULL; + } + Py_RETURN_NONE; +} static struct PyMethodDef array_module_methods[] = { @@ -4029,6 +4049,12 @@ static struct PyMethodDef array_module_methods[] = { {"test_interrupt", (PyCFunction)test_interrupt, METH_VARARGS, NULL}, + {"_set_alignment", + (PyCFunction)set_alignment, + METH_VARARGS, NULL}, + {"_get_alignment", + (PyCFunction)get_alignment, + METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} /* sentinel */ }; diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 7ecb56cae73f..7a2f89398e45 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -4873,5 +4873,32 @@ def test_collections_hashable(self): self.assertFalse(isinstance(x, collections.Hashable)) +class TestAlignment(TestCase): + + def check_alignment(self, align): + for size in (0, 1, 7, 12, 135, 777): + e = np.empty(size, dtype='int8') + z = np.zeros(size, dtype='int8') + self.assertEqual(e.ctypes.data & (align - 1), 0, (size, align)) + self.assertEqual(z.ctypes.data & (align - 1), 0, (size, align)) + + def test_get_alignment(self): + a = get_data_alignment() + # Default alignment should probably be one of those. + self.assertIn(a, (4, 8, 16, 32)) + + def test_set_alignment(self): + old_align = get_data_alignment() + self.check_alignment(old_align) + try: + aligns = [16, 32, 64, 512] + for a in aligns: + set_data_alignment(a) + self.assertEqual(get_data_alignment(), a) + self.check_alignment(a) + finally: + set_data_alignment(old_align) + + if __name__ == "__main__": run_module_suite() From 18bd8948e4502da002d58c793596cefef2c7065d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 16 Jan 2015 20:25:55 +0100 Subject: [PATCH 2/8] Fix 2.6 compatibility --- numpy/core/tests/test_multiarray.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 7a2f89398e45..f0abbe0f9e7a 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -4885,7 +4885,7 @@ def check_alignment(self, align): def test_get_alignment(self): a = get_data_alignment() # Default alignment should probably be one of those. - self.assertIn(a, (4, 8, 16, 32)) + self.assertTrue(a in (8, 16, 32), a) def test_set_alignment(self): old_align = get_data_alignment() From d595e159b428116ad05ae59697562c6104209a60 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 16 Jan 2015 20:28:01 +0100 Subject: [PATCH 3/8] Fix C89 compatibility --- numpy/core/src/multiarray/alloc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c index 0bb7e808f41b..34d5293bb625 100644 --- a/numpy/core/src/multiarray/alloc.c +++ b/numpy/core/src/multiarray/alloc.c @@ -222,9 +222,11 @@ npy_datamem_get_align(void) NPY_NO_EXPORT int npy_datamem_set_align(size_t align) { - if (align < MIN_ALIGN) - return -1; size_t align_mask = align - 1; + if (align < MIN_ALIGN) { + /* Too small */ + return -1; + } if ((align ^ align_mask) != (align | align_mask)) { /* Not a power of two */ return -1; From d4fac8f1f50e33bdc9f64dc7ac7c1f0e9eb6e949 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 16 Jan 2015 21:13:52 +0100 Subject: [PATCH 4/8] Fix aligned allocation size. --- numpy/core/src/multiarray/alloc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c index 34d5293bb625..c4906e6205bc 100644 --- a/numpy/core/src/multiarray/alloc.c +++ b/numpy/core/src/multiarray/alloc.c @@ -186,7 +186,7 @@ static size_t datamem_align_mask = MIN_ALIGN - 1; static NPY_INLINE size_t get_aligned_size(size_t size) { - return size + datamem_align; + return size + sizeof(void *) + datamem_align_mask; } /* @@ -199,7 +199,6 @@ align_pointer(void *ptr) /* Ensure a pointer can fit in the space before */ npy_intp aligned_ptr = ((npy_intp) ptr + sizeof(void *) + datamem_align_mask) & ~datamem_align_mask; - assert(aligned_ptr - (npy_intp) ptr >= sizeof(void *)); ((void **) aligned_ptr)[-1] = ptr; return (void *) aligned_ptr; } @@ -273,10 +272,10 @@ NPY_NO_EXPORT void * PyDataMem_NEW_ZEROED(size_t size, size_t elsize) { void *result; - size_t aligned_size = get_aligned_size(size); - assert(elsize == 1); /* XXX */ + /* XXX this doesn't overflow-check */ + size_t aligned_size = get_aligned_size(size * elsize); - result = calloc(aligned_size, elsize); + result = calloc(aligned_size, 1); if (result != NULL) result = align_pointer(result); @@ -319,7 +318,7 @@ PyDataMem_RENEW(void *ptr, size_t size) { void *result; size_t aligned_size = get_aligned_size(size); - void *original_ptr = get_original_pointer(ptr); + void *original_ptr = (ptr != NULL) ? get_original_pointer(ptr) : ptr; result = realloc(original_ptr, aligned_size); if (result != NULL) From ad2e837835f18904f70621ee831f9811a04abb64 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 16 Jan 2015 21:36:21 +0100 Subject: [PATCH 5/8] Use npy_mul_with_overflow_intp() --- numpy/core/src/multiarray/alloc.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c index c4906e6205bc..682971ac0771 100644 --- a/numpy/core/src/multiarray/alloc.c +++ b/numpy/core/src/multiarray/alloc.c @@ -8,6 +8,7 @@ #include "numpy/arrayobject.h" #include #include "npy_config.h" +#include "templ_common.h" /* for npy_mul_with_overflow_intp */ #include @@ -247,9 +248,8 @@ NPY_NO_EXPORT void * PyDataMem_NEW(size_t size) { void *result; - size_t aligned_size = get_aligned_size(size); - result = malloc(aligned_size); + result = malloc(get_aligned_size(size)); if (result != NULL) result = align_pointer(result); @@ -269,21 +269,24 @@ PyDataMem_NEW(size_t size) * Allocates zeroed memory for array data. */ NPY_NO_EXPORT void * -PyDataMem_NEW_ZEROED(size_t size, size_t elsize) +PyDataMem_NEW_ZEROED(size_t nelems, size_t elsize) { void *result; - /* XXX this doesn't overflow-check */ - size_t aligned_size = get_aligned_size(size * elsize); + size_t size; - result = calloc(aligned_size, 1); - if (result != NULL) - result = align_pointer(result); + if (npy_mul_with_overflow_intp(&size, nelems, elsize)) + result = NULL; + else { + result = calloc(get_aligned_size(size), 1); + if (result != NULL) + result = align_pointer(result); + } if (_PyDataMem_eventhook != NULL) { NPY_ALLOW_C_API_DEF NPY_ALLOW_C_API if (_PyDataMem_eventhook != NULL) { - (*_PyDataMem_eventhook)(NULL, result, size * elsize, + (*_PyDataMem_eventhook)(NULL, result, nelems * elsize, _PyDataMem_eventhook_user_data); } NPY_DISABLE_C_API @@ -317,10 +320,9 @@ NPY_NO_EXPORT void * PyDataMem_RENEW(void *ptr, size_t size) { void *result; - size_t aligned_size = get_aligned_size(size); void *original_ptr = (ptr != NULL) ? get_original_pointer(ptr) : ptr; - result = realloc(original_ptr, aligned_size); + result = realloc(original_ptr, get_aligned_size(size)); if (result != NULL) result = align_pointer(result); if (_PyDataMem_eventhook != NULL) { From 900527d02a89f6f4adb54a62cb4fe50cfd594584 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 16 Jan 2015 23:05:35 +0100 Subject: [PATCH 6/8] Fix resizing when the base offset changes. --- numpy/core/src/multiarray/alloc.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c index 682971ac0771..7b9abc459c79 100644 --- a/numpy/core/src/multiarray/alloc.c +++ b/numpy/core/src/multiarray/alloc.c @@ -319,12 +319,26 @@ PyDataMem_FREE(void *ptr) NPY_NO_EXPORT void * PyDataMem_RENEW(void *ptr, size_t size) { - void *result; - void *original_ptr = (ptr != NULL) ? get_original_pointer(ptr) : ptr; + void *base_result, *result; + void *original_ptr = get_original_pointer(ptr); - result = realloc(original_ptr, get_aligned_size(size)); - if (result != NULL) - result = align_pointer(result); + base_result = realloc(original_ptr, get_aligned_size(size)); + if (base_result == NULL) + result = NULL; + else { + if (base_result == original_ptr) + result = ptr; + else { + size_t offset = (npy_intp) ptr - (npy_intp) original_ptr; + size_t new_offset; + result = align_pointer(base_result); + /* If the offset from base pointer changed, we must move + the data area ourselves */ + new_offset = (npy_intp) result - (npy_intp) base_result; + if (new_offset != offset) + memmove(result, (const char *) base_result + offset, size); + } + } if (_PyDataMem_eventhook != NULL) { NPY_ALLOW_C_API_DEF NPY_ALLOW_C_API From 920e6007321b778fb6295a90b0149bc93cb9b6ab Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 19 Jan 2015 12:22:16 +0100 Subject: [PATCH 7/8] Fix reallocation when the new alignment offset is larger than the old offset. Also some style fixes. --- numpy/core/src/multiarray/alloc.c | 73 ++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c index 7b9abc459c79..a741fce998e3 100644 --- a/numpy/core/src/multiarray/alloc.c +++ b/numpy/core/src/multiarray/alloc.c @@ -178,12 +178,16 @@ PyDataMem_SetEventHook(PyDataMem_EventHookFunc *newhook, } -/* Choose a minimum valid alignment for common data types */ +/* A minimum valid alignment for common data types */ #define MIN_ALIGN 16 static size_t datamem_align = MIN_ALIGN; static size_t datamem_align_mask = MIN_ALIGN - 1; +/* + * Get a safe size for an aligned allocation, taking into account the + * overhead of storing the base pointer. + */ static NPY_INLINE size_t get_aligned_size(size_t size) { @@ -191,28 +195,37 @@ get_aligned_size(size_t size) } /* - * Align the given pointer to the guaranteed alignment, and remember - * the original pointer. + * Align the given pointer to the guaranteed alignment. */ static NPY_INLINE void * -align_pointer(void *ptr) +get_aligned_pointer(void *ptr) { /* Ensure a pointer can fit in the space before */ npy_intp aligned_ptr = ((npy_intp) ptr + sizeof(void *) + datamem_align_mask) & ~datamem_align_mask; - ((void **) aligned_ptr)[-1] = ptr; return (void *) aligned_ptr; } /* - * Given an aligned pointer, get the start of the original allocation. + * Remember the base allocation start ahead of the aligned memory area. */ static NPY_INLINE void * -get_original_pointer(void *aligned_ptr) +store_base_pointer(void *aligned_ptr, void *ptr) +{ + ((void **) aligned_ptr)[-1] = ptr; +} + +/* + * Given an aligned pointer, get the start of the base allocation. + */ +static NPY_INLINE void * +get_base_pointer(void *aligned_ptr) { return ((void **) aligned_ptr)[-1]; } +/* Internal API for querying and changing the current alignement */ + NPY_NO_EXPORT size_t npy_datamem_get_align(void) { @@ -247,11 +260,13 @@ npy_datamem_set_align(size_t align) NPY_NO_EXPORT void * PyDataMem_NEW(size_t size) { - void *result; + void *base_result, *result = NULL; - result = malloc(get_aligned_size(size)); - if (result != NULL) - result = align_pointer(result); + base_result = malloc(get_aligned_size(size)); + if (base_result != NULL) { + result = get_aligned_pointer(base_result); + store_base_pointer(result, base_result); + } if (_PyDataMem_eventhook != NULL) { NPY_ALLOW_C_API_DEF @@ -271,15 +286,18 @@ PyDataMem_NEW(size_t size) NPY_NO_EXPORT void * PyDataMem_NEW_ZEROED(size_t nelems, size_t elsize) { - void *result; + void *base_result, *result = NULL; size_t size; - if (npy_mul_with_overflow_intp(&size, nelems, elsize)) + if (npy_mul_with_overflow_intp(&size, nelems, elsize)) { result = NULL; + } else { - result = calloc(get_aligned_size(size), 1); - if (result != NULL) - result = align_pointer(result); + base_result = calloc(get_aligned_size(size), 1); + if (base_result != NULL) { + result = get_aligned_pointer(base_result); + store_base_pointer(result, base_result); + } } if (_PyDataMem_eventhook != NULL) { @@ -300,8 +318,9 @@ PyDataMem_NEW_ZEROED(size_t nelems, size_t elsize) NPY_NO_EXPORT void PyDataMem_FREE(void *ptr) { - if (ptr != NULL) - free(get_original_pointer(ptr)); + if (ptr != NULL) { + free(get_base_pointer(ptr)); + } if (_PyDataMem_eventhook != NULL) { NPY_ALLOW_C_API_DEF NPY_ALLOW_C_API @@ -320,23 +339,27 @@ NPY_NO_EXPORT void * PyDataMem_RENEW(void *ptr, size_t size) { void *base_result, *result; - void *original_ptr = get_original_pointer(ptr); + void *base_ptr = get_base_pointer(ptr); - base_result = realloc(original_ptr, get_aligned_size(size)); - if (base_result == NULL) + base_result = realloc(base_ptr, get_aligned_size(size)); + if (base_result == NULL) { result = NULL; + } else { - if (base_result == original_ptr) + if (base_result == base_ptr) { result = ptr; + } else { - size_t offset = (npy_intp) ptr - (npy_intp) original_ptr; + size_t offset = (npy_intp) ptr - (npy_intp) base_ptr; size_t new_offset; - result = align_pointer(base_result); + result = get_aligned_pointer(base_result); /* If the offset from base pointer changed, we must move the data area ourselves */ new_offset = (npy_intp) result - (npy_intp) base_result; - if (new_offset != offset) + if (new_offset != offset) { memmove(result, (const char *) base_result + offset, size); + } + store_base_pointer(result, base_result); } } if (_PyDataMem_eventhook != NULL) { From 09ee1872a307fddb17280f95753b110e9989624a Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 19 Jan 2015 12:40:58 +0100 Subject: [PATCH 8/8] Simplify code a bit. --- numpy/core/src/multiarray/alloc.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c index a741fce998e3..be187d03dedc 100644 --- a/numpy/core/src/multiarray/alloc.c +++ b/numpy/core/src/multiarray/alloc.c @@ -289,10 +289,7 @@ PyDataMem_NEW_ZEROED(size_t nelems, size_t elsize) void *base_result, *result = NULL; size_t size; - if (npy_mul_with_overflow_intp(&size, nelems, elsize)) { - result = NULL; - } - else { + if (!npy_mul_with_overflow_intp(&size, nelems, elsize)) { base_result = calloc(get_aligned_size(size), 1); if (base_result != NULL) { result = get_aligned_pointer(base_result); @@ -338,14 +335,11 @@ PyDataMem_FREE(void *ptr) NPY_NO_EXPORT void * PyDataMem_RENEW(void *ptr, size_t size) { - void *base_result, *result; + void *base_result, *result = NULL; void *base_ptr = get_base_pointer(ptr); base_result = realloc(base_ptr, get_aligned_size(size)); - if (base_result == NULL) { - result = NULL; - } - else { + if (base_result != NULL) { if (base_result == base_ptr) { result = ptr; }