summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/multiarray/descriptor.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index c611a1402..d1de37dcd 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -17,6 +17,18 @@
#include "common.h"
#include "descriptor.h"
+/*
+ * offset: A starting offset.
+ * alignment: A power-of-two alignment.
+ *
+ * This macro returns the smallest value >= 'offset'
+ * which is divisible by 'alignment'. Because 'alignment'
+ * is a power of two, and integers are twos-complement,
+ * can use some simple bit-fiddling to do this.
+ */
+#define NPY_NEXT_ALIGNED_OFFSET(offset, alignment) \
+ (((offset) + (alignment) - 1) & (-(alignment)))
+
static PyObject *typeDict = NULL; /* Must be explicitly loaded */
static PyArray_Descr *
@@ -408,8 +420,7 @@ _convert_from_array_descr(PyObject *obj, int align)
_align = conv->alignment;
if (_align > 1) {
- /* The alignment is always a power of 2, so this works */
- totalsize = (totalsize + _align - 1) & (-_align);
+ totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, _align);
}
maxalign = MAX(maxalign, _align);
}
@@ -444,8 +455,7 @@ _convert_from_array_descr(PyObject *obj, int align)
}
if (maxalign > 1) {
- /* The alignment is always a power of 2, so this works */
- totalsize = (totalsize + maxalign - 1) & (-maxalign);
+ totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, maxalign);
}
new = PyArray_DescrNewFromType(PyArray_VOID);
@@ -532,8 +542,7 @@ _convert_from_list(PyObject *obj, int align)
_align = conv->alignment;
if (_align > 1) {
- /* The alignment is always a power of 2, so this works */
- totalsize = (totalsize + _align - 1) & (-_align);
+ totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, _align);
}
maxalign = MAX(maxalign, _align);
}
@@ -548,8 +557,7 @@ _convert_from_list(PyObject *obj, int align)
new->names = nameslist;
new->flags = dtypeflags;
if (maxalign > 1) {
- /* The alignment is always a power of 2, so this works */
- totalsize = (totalsize + maxalign - 1) & (-maxalign);
+ totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, maxalign);
}
/* Structured arrays get a sticky aligned bit */
if (align) {
@@ -706,7 +714,6 @@ validate_object_field_overlap(PyArray_Descr *dtype)
Py_ssize_t i, j, names_size;
PyArray_Descr *fld_dtype, *fld2_dtype;
int fld_offset, fld2_offset, align;
- npy_intp total_offset;
/* Get some properties from the dtype */
names = dtype->names;
@@ -916,8 +923,7 @@ _convert_from_dict(PyObject *obj, int align)
}
else {
if (align && _align > 1) {
- /* The alignment is always a power of 2, so this works */
- totalsize = (totalsize + _align - 1) & (-_align);
+ totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, _align);
}
PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(totalsize));
totalsize += newdescr->elsize;
@@ -974,8 +980,7 @@ _convert_from_dict(PyObject *obj, int align)
goto fail;
}
if (maxalign > 1) {
- /* The alignment is always a power of 2, so this works */
- totalsize = (totalsize + maxalign - 1) & (-maxalign);
+ totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, maxalign);
}
if (align) {
new->alignment = maxalign;
@@ -2886,7 +2891,7 @@ arraydescr_struct_dict_str(PyArray_Descr *dtype)
}
/* The alignment is always a power of 2, so this works */
if (align) {
- naturalsize = (naturalsize + dtype->alignment - 1) & (-dtype->alignment);
+ naturalsize = NPY_NEXT_ALIGNED_OFFSET(naturalsize, dtype->alignment);
}
/* Finally, the itemsize */
if (naturalsize == dtype->elsize) {
@@ -2975,12 +2980,12 @@ arraydescr_struct_repr(PyArray_Descr *dtype)
/*
* This creates a shorter repr using the 'kind' and 'itemsize',
- * instead of the longer type name. It also creates the input
- * for constructing a dtype rather than the full dtype function
- * call.
+ * instead of the longer type name. This is the object you pass
+ * as the first parameter to the dtype constructor.
*
* This does not preserve the 'align=True' parameter
- * for structured arrays like the regular repr does.
+ * for structured arrays like the regular repr does, because
+ * this flag is separate from the first dtype constructor parameter.
*/
NPY_NO_EXPORT PyObject *
arraydescr_short_construction_repr(PyArray_Descr *dtype)