Skip to content

Commit 509eb8d

Browse files
committed
Fixes for issues exposed by the blaze tests
1 parent 1ca7b43 commit 509eb8d

File tree

4 files changed

+84
-6
lines changed

4 files changed

+84
-6
lines changed

dynd/tests/test_numpy_interop.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,22 @@ def assign_to(x,y):
345345
self.assertRaises(RuntimeError, nd.view, a, access='rw')
346346

347347
class TestAsNumpy(unittest.TestCase):
348+
def test_struct_as_numpy(self):
349+
# Aligned cstruct
350+
a = nd.array([[1, 2], [3, 4]], dtype='{x : int32, y: int64}')
351+
b = nd.as_numpy(a)
352+
self.assertEqual(b.dtype,
353+
np.dtype([('x', np.int32), ('y', np.int64)], align=True))
354+
self.assertEqual(nd.as_py(a.x), b['x'].tolist())
355+
self.assertEqual(nd.as_py(a.y), b['y'].tolist())
356+
# Unaligned cstruct
357+
a = nd.array([[1, 2], [3, 4]],
358+
dtype='{x : unaligned[int32], y: unaligned[int64]}')
359+
b = nd.as_numpy(a)
360+
self.assertEqual(b.dtype, np.dtype([('x', np.int32), ('y', np.int64)]))
361+
self.assertEqual(nd.as_py(a.x), b['x'].tolist())
362+
self.assertEqual(nd.as_py(a.y), b['y'].tolist())
363+
348364
def test_cstruct_as_numpy(self):
349365
# Aligned cstruct
350366
a = nd.array([[1, 2], [3, 4]], dtype='c{x : int32, y: int64}')
@@ -377,6 +393,18 @@ def test_cstruct_via_pep3118(self):
377393
self.assertEqual(nd.as_py(a.x), b['x'].tolist())
378394
self.assertEqual(nd.as_py(a.y), b['y'].tolist())
379395

396+
def test_fixed_dim(self):
397+
a = nd.array([1, 3, 5], type='3 * int32')
398+
b = nd.as_numpy(a)
399+
self.assertEqual(b.dtype, np.dtype('int32'))
400+
self.assertEqual(b.tolist(), [1, 3, 5])
401+
402+
def test_fixed_dim_via_pep3118(self):
403+
a = nd.array([1, 3, 5], type='3 * int32')
404+
b = np.asarray(a)
405+
self.assertEqual(b.dtype, np.dtype('int32'))
406+
self.assertEqual(b.tolist(), [1, 3, 5])
407+
380408
class TestNumpyScalarInterop(unittest.TestCase):
381409
def test_numpy_scalar_conversion_dtypes(self):
382410
self.assertEqual(nd.dtype_of(nd.array(np.bool_(True))), ndt.bool)

include/ndt_type.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ cdef extern from "dynd/type.hpp" namespace "dynd::ndt":
6969
type_id_t type_id()
7070
type_kind_t get_kind()
7171
size_t get_data_size()
72+
size_t get_default_data_size(intptr_t, intptr_t*)
7273
size_t get_data_alignment()
7374
size_t get_metadata_size()
7475
base_type* extended()

src/_pydynd.pyx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,16 @@ cdef class w_type:
173173
else:
174174
return None
175175

176+
property default_data_size:
177+
"""
178+
tp.default_data_size
179+
180+
The size, in bytes, of the data for a default-constructed
181+
instance of this dynd type.
182+
"""
183+
def __get__(self):
184+
return (GET(self.v)).get_default_data_size(0, <intptr_t *>0)
185+
176186
property data_alignment:
177187
"""
178188
tp.data_alignment

src/array_as_numpy.cpp

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "utility_functions.hpp"
1717

1818
#include <dynd/types/strided_dim_type.hpp>
19+
#include <dynd/types/fixed_dim_type.hpp>
1920
#include <dynd/types/cfixed_dim_type.hpp>
2021
#include <dynd/types/fixedstring_type.hpp>
2122
#include <dynd/types/base_struct_type.hpp>
@@ -122,22 +123,34 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype,
122123
#endif
123124
}
124125
case strided_dim_type_id:
126+
case fixed_dim_type_id:
125127
case cfixed_dim_type_id: {
126128
if (ndim > 0) {
127129
// If this is one of the array dimensions, it simply
128130
// becomes one of the numpy ndarray dimensions
129-
if (dt.get_type_id() == strided_dim_type_id) {
131+
switch (dt.get_type_id()) {
132+
case strided_dim_type_id: {
130133
const strided_dim_type *sad = dt.tcast<strided_dim_type>();
131134
make_numpy_dtype_for_copy(out_numpy_dtype,
132135
ndim - 1, sad->get_element_type(),
133136
metadata + sizeof(strided_dim_type_metadata));
134-
} else {
137+
return;
138+
}
139+
case fixed_dim_type_id: {
140+
const fixed_dim_type *fad = dt.tcast<fixed_dim_type>();
141+
make_numpy_dtype_for_copy(out_numpy_dtype,
142+
ndim - 1, fad->get_element_type(),
143+
metadata + sizeof(fixed_dim_type_metadata));
144+
return;
145+
}
146+
case cfixed_dim_type_id: {
135147
const cfixed_dim_type *fad = dt.tcast<cfixed_dim_type>();
136148
make_numpy_dtype_for_copy(out_numpy_dtype,
137149
ndim - 1, fad->get_element_type(),
138-
metadata + sizeof(strided_dim_type_metadata));
150+
metadata);
151+
return;
152+
}
139153
}
140-
return;
141154
} else {
142155
// If this isn't one of the array dimensions, it maps into
143156
// a numpy dtype with a shape
@@ -158,6 +171,12 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype,
158171
dim_size = sad->get_dim_size(metadata, NULL);
159172
element_tp = sad->get_element_type();
160173
metadata += sizeof(strided_dim_type_metadata);
174+
} else if (dt.get_type_id() == fixed_dim_type_id) {
175+
const fixed_dim_type *fad =
176+
element_tp.tcast<fixed_dim_type>();
177+
dim_size = fad->get_fixed_dim_size();
178+
element_tp = fad->get_element_type();
179+
metadata += sizeof(fixed_dim_type_metadata);
161180
} else if (dt.get_type_id() == cfixed_dim_type_id) {
162181
const cfixed_dim_type *fad =
163182
element_tp.tcast<cfixed_dim_type>();
@@ -372,6 +391,24 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir
372391
}
373392
break;
374393
}
394+
case fixed_dim_type_id: {
395+
const fixed_dim_type *fad = dt.tcast<fixed_dim_type>();
396+
if (ndim > 0) {
397+
// If this is one of the array dimensions, it simply
398+
// becomes one of the numpy ndarray dimensions
399+
as_numpy_analysis(out_numpy_dtype, out_requires_copy,
400+
ndim - 1, fad->get_element_type(),
401+
metadata + sizeof(fixed_dim_type_metadata));
402+
return;
403+
} else {
404+
// If this isn't one of the array dimensions, it maps into
405+
// a numpy dtype with a shape
406+
out_numpy_dtype->clear();
407+
*out_requires_copy = true;
408+
return;
409+
}
410+
break;
411+
}
375412
case cfixed_dim_type_id: {
376413
const cfixed_dim_type *fad = dt.tcast<cfixed_dim_type>();
377414
if (ndim > 0) {
@@ -481,13 +518,15 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir
481518
PyList_SET_ITEM((PyObject *)offsets_obj, i, PyLong_FromSize_t(offsets[i]));
482519
}
483520

484-
pyobject_ownref itemsize_obj(PyLong_FromSize_t(dt.get_data_size()));
485521

486522
pyobject_ownref dict_obj(PyDict_New());
487523
PyDict_SetItemString(dict_obj, "names", names_obj);
488524
PyDict_SetItemString(dict_obj, "formats", formats_obj);
489525
PyDict_SetItemString(dict_obj, "offsets", offsets_obj);
490-
PyDict_SetItemString(dict_obj, "itemsize", itemsize_obj);
526+
if (dt.get_data_size() > 0) {
527+
pyobject_ownref itemsize_obj(PyLong_FromSize_t(dt.get_data_size()));
528+
PyDict_SetItemString(dict_obj, "itemsize", itemsize_obj);
529+
}
491530

492531
PyArray_Descr *result = NULL;
493532
if (!PyArray_DescrConverter(dict_obj, &result)) {

0 commit comments

Comments
 (0)