summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/descriptor.c79
-rw-r--r--numpy/core/tests/test_dtype.py35
2 files changed, 51 insertions, 63 deletions
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 222ab9dd6..709b44472 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -22,9 +22,9 @@
* 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.
+ * that is divisible by 'alignment'. Because 'alignment'
+ * is a power of two and integers are twos-complement,
+ * it is possible to use some simple bit-fiddling to do this.
*/
#define NPY_NEXT_ALIGNED_OFFSET(offset, alignment) \
(((offset) + (alignment) - 1) & (-(alignment)))
@@ -2642,30 +2642,27 @@ static PyMethodDef arraydescr_methods[] = {
/*
* Checks whether the structured data type in 'dtype'
* has a simple layout, where all the fields are in order,
- * follow the alignment based on the NPY_ALIGNED_STRUCT flag,
- * and the total length ends just after the last field with
- * appropriate alignment padding.
+ * and follow each other with no alignment padding.
*
* When this returns true, the dtype can be reconstructed
- * from a list of the field names and dtypes, and an
- * alignment parameter.
+ * from a list of the field names and dtypes with no additional
+ * dtype parameters.
*
* Returns 1 if it has a simple layout, 0 otherwise.
*/
static int
-is_dtype_struct_simple_layout(PyArray_Descr *dtype)
+is_dtype_struct_simple_unaligned_layout(PyArray_Descr *dtype)
{
PyObject *names, *fields, *key, *tup, *title;
Py_ssize_t i, names_size;
PyArray_Descr *fld_dtype;
- int fld_offset, align;
+ int fld_offset;
npy_intp total_offset;
/* Get some properties from the dtype */
names = dtype->names;
names_size = PyTuple_GET_SIZE(names);
fields = dtype->fields;
- align = PyDataType_FLAGCHK(dtype, NPY_ALIGNED_STRUCT);
/* Start at offset zero */
total_offset = 0;
@@ -2683,16 +2680,6 @@ is_dtype_struct_simple_layout(PyArray_Descr *dtype)
PyErr_Clear();
return 0;
}
- /* If it's an aligned struct, apply the dtype alignment */
- if (align) {
- /*
- * Alignment is always a power of 2, so -alignment is
- * a bitmask which preserves everything but the undesired
- * bits.
- */
- total_offset = (total_offset + fld_dtype->alignment - 1) &
- (-fld_dtype->alignment);
- }
/* If this field doesn't follow the pattern, not a simple layout */
if (total_offset != fld_offset) {
return 0;
@@ -2701,19 +2688,8 @@ is_dtype_struct_simple_layout(PyArray_Descr *dtype)
total_offset += fld_dtype->elsize;
}
- /* If it's an aligned struct, apply the struct-level alignment */
- if (align) {
- /*
- * Alignment is always a power of 2, so -alignment is
- * a bitmask which preserves everything but the undesired
- * bits.
- */
- total_offset = (total_offset + dtype->alignment - 1) &
- (-dtype->alignment);
- }
-
/*
- * If the itemsize doesn't match the final aligned offset, it's
+ * If the itemsize doesn't match the final offset, it's
* not a simple layout.
*/
if (total_offset != dtype->elsize) {
@@ -2802,17 +2778,12 @@ arraydescr_struct_dict_str(PyArray_Descr *dtype)
Py_ssize_t i, names_size;
PyArray_Descr *fld_dtype;
int fld_offset, has_titles;
- int align, naturalsize;
names = dtype->names;
names_size = PyTuple_GET_SIZE(names);
fields = dtype->fields;
has_titles = 0;
- /* Used to determine whether the 'itemsize=' is needed */
- align = (dtype->flags&NPY_ALIGNED_STRUCT) != 0;
- naturalsize = 0;
-
/* Build up a string to make the dictionary */
/* First, the names */
@@ -2863,10 +2834,6 @@ arraydescr_struct_dict_str(PyArray_Descr *dtype)
if (i != names_size - 1) {
PyUString_ConcatAndDel(&ret, PyUString_FromString(","));
}
- /* Accumulate the natural size of the dtype */
- if (fld_offset + fld_dtype->elsize > naturalsize) {
- naturalsize = fld_offset + fld_dtype->elsize;
- }
}
/* Fourth, the titles */
if (has_titles) {
@@ -2889,18 +2856,9 @@ arraydescr_struct_dict_str(PyArray_Descr *dtype)
}
}
}
- /* The alignment is always a power of 2, so this works */
- if (align) {
- naturalsize = NPY_NEXT_ALIGNED_OFFSET(naturalsize, dtype->alignment);
- }
/* Finally, the itemsize */
- if (naturalsize == dtype->elsize) {
- PyUString_ConcatAndDel(&ret, PyUString_FromString("]}"));
- }
- else {
- PyUString_ConcatAndDel(&ret,
+ PyUString_ConcatAndDel(&ret,
PyUString_FromFormat("], 'itemsize':%d}", (int)dtype->elsize));
- }
return ret;
}
@@ -2909,7 +2867,7 @@ arraydescr_struct_dict_str(PyArray_Descr *dtype)
static PyObject *
arraydescr_struct_str(PyArray_Descr *dtype)
{
- if (is_dtype_struct_simple_layout(dtype)) {
+ if (is_dtype_struct_simple_unaligned_layout(dtype)) {
return arraydescr_struct_list_str(dtype);
}
else {
@@ -2979,13 +2937,16 @@ arraydescr_struct_repr(PyArray_Descr *dtype)
}
/*
- * This creates a shorter repr using the 'kind' and 'itemsize',
- * instead of the longer type name. This is the object you pass
- * as the first parameter to the dtype constructor.
+ * This creates a shorter repr using 'kind' and 'itemsize',
+ * instead of the longer type name. This is the object passed
+ * as the first parameter to the dtype constructor, and if no
+ * additional constructor parameters are given, will reproduce
+ * the exact memory layout.
*
- * This does not preserve the 'align=True' parameter
- * for structured arrays like the regular repr does, because
- * this flag is separate from the first dtype constructor parameter.
+ * This does not preserve the 'align=True' parameter or sticky
+ * NPY_ALIGNED_STRUCT flag for struct arrays like the regular
+ * repr does, because the 'align' flag is not part of first
+ * dtype constructor parameter.
*/
NPY_NO_EXPORT PyObject *
arraydescr_short_construction_repr(PyArray_Descr *dtype)
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index 70046cb72..ff13dcad6 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -299,14 +299,28 @@ class TestString(TestCase):
"(('Green pixel', 'g'), 'u1'), "
"(('Blue pixel', 'b'), 'u1')]")
+ dt = np.dtype({'names': ['rgba', 'r','g','b'],
+ 'formats': ['<u4', 'u1', 'u1', 'u1'],
+ 'offsets': [0, 0, 1, 2],
+ 'titles': ['Color', 'Red pixel',
+ 'Green pixel', 'Blue pixel']})
+ assert_equal(str(dt),
+ "{'names':['rgba','r','g','b'],"
+ " 'formats':['<u4','u1','u1','u1'],"
+ " 'offsets':[0,0,1,2],"
+ " 'titles':['Color','Red pixel',"
+ "'Green pixel','Blue pixel'],"
+ " 'itemsize':4}")
+
dt = np.dtype({'names': ['r','b'], 'formats': ['u1', 'u1'],
'offsets': [0, 2],
'titles': ['Red pixel', 'Blue pixel']})
assert_equal(str(dt),
- "{'names':['r','b'], "
- "'formats':['u1','u1'], "
- "'offsets':[0,2], "
- "'titles':['Red pixel','Blue pixel']}")
+ "{'names':['r','b'],"
+ " 'formats':['u1','u1'],"
+ " 'offsets':[0,2],"
+ " 'titles':['Red pixel','Blue pixel'],"
+ " 'itemsize':3}")
def test_complex_dtype_repr(self):
dt = np.dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)),
@@ -328,6 +342,19 @@ class TestString(TestCase):
"(('Green pixel', 'g'), 'u1'), "
"(('Blue pixel', 'b'), 'u1')], align=True)")
+ dt = np.dtype({'names': ['rgba', 'r','g','b'],
+ 'formats': ['<u4', 'u1', 'u1', 'u1'],
+ 'offsets': [0, 0, 1, 2],
+ 'titles': ['Color', 'Red pixel',
+ 'Green pixel', 'Blue pixel']}, align=True)
+ assert_equal(repr(dt),
+ "dtype({'names':['rgba','r','g','b'],"
+ " 'formats':['<u4','u1','u1','u1'],"
+ " 'offsets':[0,0,1,2],"
+ " 'titles':['Color','Red pixel',"
+ "'Green pixel','Blue pixel'],"
+ " 'itemsize':4}, align=True)")
+
dt = np.dtype({'names': ['r','b'], 'formats': ['u1', 'u1'],
'offsets': [0, 2],
'titles': ['Red pixel', 'Blue pixel'],