11#pragma once
22
3- #include < dynd/callables/base_callable.hpp>
43#include " kernels/assign_to_pyarrayobject_kernel.hpp"
4+ #include < dynd/callables/base_callable.hpp>
55
66/* *
77 * This sets up a ckernel to copy from a dynd array
@@ -22,127 +22,128 @@ class assign_to_pyarrayobject_callable : public dynd::nd::base_callable {
2222 return dst_tp;
2323 }
2424
25- /*
26- void instantiate(char *data, dynd::nd::kernel_builder *ckb, const dynd::ndt::type &dst_tp, const char *dst_arrmeta,
27- intptr_t nsrc, const dynd::ndt::type *src_tp, const char *const *src_arrmeta,
28- dynd::kernel_request_t kernreq, intptr_t nkwd, const dynd::nd::array *kwds,
29- const std::map<std::string, dynd::ndt::type> &tp_vars)
30- {
31- PyObject *dst_obj = *reinterpret_cast<PyObject *const *>(dst_arrmeta);
32- uintptr_t dst_alignment = reinterpret_cast<const uintptr_t *>(dst_arrmeta)[1];
25+ /*
26+ void instantiate(char *data, dynd::nd::kernel_builder *ckb, const dynd::ndt::type &dst_tp, const char *dst_arrmeta,
27+ intptr_t nsrc, const dynd::ndt::type *src_tp, const char *const *src_arrmeta,
28+ dynd::kernel_request_t kernreq, intptr_t nkwd, const dynd::nd::array *kwds,
29+ const std::map<std::string, dynd::ndt::type> &tp_vars)
30+ {
31+ PyObject *dst_obj = *reinterpret_cast<PyObject *const *>(dst_arrmeta);
32+ uintptr_t dst_alignment = reinterpret_cast<const uintptr_t *>(dst_arrmeta)[1];
3333
34- PyArray_Descr *dtype = reinterpret_cast<PyArray_Descr *>(dst_obj);
35-
36- // If there is no object type in the numpy type, get the dynd equivalent
37- // type and use it to do the copying
38- if (!PyDataType_FLAGCHK(dtype, NPY_ITEM_HASOBJECT)) {
39- dynd::ndt::type dst_view_tp = pydynd::_type_from_numpy_dtype(dtype, dst_alignment);
40- nd::array error_mode = assign_error_fractional;
41- nd::assign->instantiate(node, NULL, ckb, dst_view_tp, NULL, 1, src_tp, src_arrmeta, kernreq, 1, &error_mode,
42- std::map<std::string, ndt::type>());
43- return;
44- }
34+ PyArray_Descr *dtype = reinterpret_cast<PyArray_Descr *>(dst_obj);
4535
46- if (PyDataType_ISOBJECT(dtype)) {
47- dynd::nd::assign->instantiate(node, NULL, ckb, dynd::ndt::make_type<pyobject_type>(), NULL, nsrc, src_tp,
48- src_arrmeta, kernreq, 0, NULL, tp_vars);
49- return;
50- }
51-
52- if (PyDataType_HASFIELDS(dtype)) {
53- if (src_tp[0].get_id() != dynd::struct_id && src_tp[0].get_id() != dynd::tuple_id) {
54- std::stringstream ss;
55- pydynd::pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype));
56- ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type "
57- << pydynd::pystring_as_string(dtype_str.get());
58- throw std::invalid_argument(ss.str());
36+ // If there is no object type in the numpy type, get the dynd equivalent
37+ // type and use it to do the copying
38+ if (!PyDataType_FLAGCHK(dtype, NPY_ITEM_HASOBJECT)) {
39+ dynd::ndt::type dst_view_tp = pydynd::_type_from_numpy_dtype(dtype, dst_alignment);
40+ nd::array error_mode = assign_error_fractional;
41+ nd::assign->instantiate(node, NULL, ckb, dst_view_tp, NULL, 1, src_tp, src_arrmeta, kernreq, 1, &error_mode,
42+ std::map<std::string, ndt::type>());
43+ return;
5944 }
6045
61- // Get the fields out of the numpy dtype
62- std::vector<PyArray_Descr *> field_dtypes_orig;
63- std::vector<std::string> field_names_orig;
64- std::vector<size_t> field_offsets_orig;
65- pydynd::extract_fields_from_numpy_struct(dtype, field_dtypes_orig, field_names_orig, field_offsets_orig);
66- intptr_t field_count = field_dtypes_orig.size();
67- if (field_count != src_tp[0].extended<dynd::ndt::tuple_type>()->get_field_count()) {
68- std::stringstream ss;
69- pydynd::pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype));
70- ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type "
71- << pydynd::pystring_as_string(dtype_str.get());
72- throw std::invalid_argument(ss.str());
46+ if (PyDataType_ISOBJECT(dtype)) {
47+ dynd::nd::assign->instantiate(node, NULL, ckb, dynd::ndt::make_type<pyobject_type>(), NULL, nsrc, src_tp,
48+ src_arrmeta, kernreq, 0, NULL, tp_vars);
49+ return;
7350 }
7451
75- // Permute the numpy fields to match with the dynd fields
76- std::vector<PyArray_Descr *> field_dtypes;
77- std::vector<size_t> field_offsets;
78- if (src_tp[0].get_id() == dynd::struct_id) {
79- field_dtypes.resize(field_count);
80- field_offsets.resize(field_count);
81- for (intptr_t i = 0; i < field_count; ++i) {
82- intptr_t src_i = src_tp[0].extended<dynd::ndt::struct_type>()->get_field_index(field_names_orig[i]);
83- if (src_i >= 0) {
84- field_dtypes[src_i] = field_dtypes_orig[i];
85- field_offsets[src_i] = field_offsets_orig[i];
86- }
87- else {
88- std::stringstream ss;
89- pydynd::pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype));
90- ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type "
91- << pydynd::pystring_as_string(dtype_str.get());
92- throw std::invalid_argument(ss.str());
52+ if (PyDataType_HASFIELDS(dtype)) {
53+ if (src_tp[0].get_id() != dynd::struct_id && src_tp[0].get_id() != dynd::tuple_id) {
54+ std::stringstream ss;
55+ pydynd::py_ref dtype_str = capture_if_not_null(PyObject_Str((PyObject *)dtype));
56+ ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type "
57+ << pydynd::pystring_as_string(dtype_str.get());
58+ throw std::invalid_argument(ss.str());
59+ }
60+
61+ // Get the fields out of the numpy dtype
62+ std::vector<PyArray_Descr *> field_dtypes_orig;
63+ std::vector<std::string> field_names_orig;
64+ std::vector<size_t> field_offsets_orig;
65+ pydynd::extract_fields_from_numpy_struct(dtype, field_dtypes_orig, field_names_orig, field_offsets_orig);
66+ intptr_t field_count = field_dtypes_orig.size();
67+ if (field_count != src_tp[0].extended<dynd::ndt::tuple_type>()->get_field_count()) {
68+ std::stringstream ss;
69+ pydynd::py_ref dtype_str = capture_if_not_null(PyObject_Str((PyObject *)dtype));
70+ ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type "
71+ << pydynd::pystring_as_string(dtype_str.get());
72+ throw std::invalid_argument(ss.str());
73+ }
74+
75+ // Permute the numpy fields to match with the dynd fields
76+ std::vector<PyArray_Descr *> field_dtypes;
77+ std::vector<size_t> field_offsets;
78+ if (src_tp[0].get_id() == dynd::struct_id) {
79+ field_dtypes.resize(field_count);
80+ field_offsets.resize(field_count);
81+ for (intptr_t i = 0; i < field_count; ++i) {
82+ intptr_t src_i = src_tp[0].extended<dynd::ndt::struct_type>()->get_field_index(field_names_orig[i]);
83+ if (src_i >= 0) {
84+ field_dtypes[src_i] = field_dtypes_orig[i];
85+ field_offsets[src_i] = field_offsets_orig[i];
86+ }
87+ else {
88+ std::stringstream ss;
89+ pydynd::py_ref dtype_str = capture_if_not_null(PyObject_Str((PyObject *)dtype));
90+ ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type "
91+ << pydynd::pystring_as_string(dtype_str.get());
92+ throw std::invalid_argument(ss.str());
93+ }
9394 }
9495 }
95- }
96- else {
97- // In the tuple case, use position instead of name
98- field_dtypes.swap(field_dtypes_orig);
99- field_offsets.swap(field_offsets_orig);
100- }
96+ else {
97+ // In the tuple case, use position instead of name
98+ field_dtypes.swap(field_dtypes_orig);
99+ field_offsets.swap(field_offsets_orig);
100+ }
101101
102- std::vector<dynd::ndt::type> dst_fields_tp(field_count, dynd::ndt::make_type<void>());
103- std::vector<copy_to_numpy_arrmeta> dst_arrmeta_values(field_count);
104- std::vector<const char *> dst_fields_arrmeta(field_count);
105- for (intptr_t i = 0; i < field_count; ++i) {
106- dst_arrmeta_values[i].dst_dtype = field_dtypes[i];
107- dst_arrmeta_values[i].dst_alignment = dst_alignment | field_offsets[i];
108- dst_fields_arrmeta[i] = reinterpret_cast<const char *>(&dst_arrmeta_values[i]);
109- }
102+ std::vector<dynd::ndt::type> dst_fields_tp(field_count, dynd::ndt::make_type<void>());
103+ std::vector<copy_to_numpy_arrmeta> dst_arrmeta_values(field_count);
104+ std::vector<const char *> dst_fields_arrmeta(field_count);
105+ for (intptr_t i = 0; i < field_count; ++i) {
106+ dst_arrmeta_values[i].dst_dtype = field_dtypes[i];
107+ dst_arrmeta_values[i].dst_alignment = dst_alignment | field_offsets[i];
108+ dst_fields_arrmeta[i] = reinterpret_cast<const char *>(&dst_arrmeta_values[i]);
109+ }
110110
111- const uintptr_t *src_arrmeta_offsets = src_tp[0].extended<dynd::ndt::tuple_type>()->get_arrmeta_offsets_raw();
112- dynd::shortvector<const char *> src_fields_arrmeta(field_count);
113- for (intptr_t i = 0; i != field_count; ++i) {
114- src_fields_arrmeta[i] = src_arrmeta[0] + src_arrmeta_offsets[i];
115- }
111+ const uintptr_t *src_arrmeta_offsets = src_tp[0].extended<dynd::ndt::tuple_type>()->get_arrmeta_offsets_raw();
112+ dynd::shortvector<const char *> src_fields_arrmeta(field_count);
113+ for (intptr_t i = 0; i != field_count; ++i) {
114+ src_fields_arrmeta[i] = src_arrmeta[0] + src_arrmeta_offsets[i];
115+ }
116116
117- // Todo: Remove this
118- dynd::nd::callable af = dynd::nd::make_callable<assign_to_pyarrayobject_callable>();
117+ // Todo: Remove this
118+ dynd::nd::callable af = dynd::nd::make_callable<assign_to_pyarrayobject_callable>();
119119
120- const std::vector<ndt::type> &src_field_tp = src_tp[0].extended<dynd::ndt::tuple_type>()->get_field_types();
121- const uintptr_t *src_data_offsets = src_tp[0].extended<dynd::ndt::tuple_type>()->get_data_offsets(src_arrmeta[0]);
120+ const std::vector<ndt::type> &src_field_tp = src_tp[0].extended<dynd::ndt::tuple_type>()->get_field_types();
121+ const uintptr_t *src_data_offsets =
122+ src_tp[0].extended<dynd::ndt::tuple_type>()->get_data_offsets(src_arrmeta[0]);
122123
123- intptr_t self_offset = ckb->size();
124- ckb->emplace_back<nd::tuple_unary_op_ck>(kernreq);
125- nd::tuple_unary_op_ck *self = ckb->get_at<nd::tuple_unary_op_ck>(self_offset);
126- self->m_fields.resize(field_count);
127- for (intptr_t i = 0; i < field_count; ++i) {
128- self = ckb->get_at<nd::tuple_unary_op_ck>(self_offset);
129- nd::tuple_unary_op_item &field = self->m_fields[i];
130- field.child_kernel_offset = ckb->size() - self_offset;
131- field.dst_data_offset = field_offsets[i];
132- field.src_data_offset = src_data_offsets[i];
133- nd::array error_mode = ndt::traits<assign_error_mode>::na();
134- af->instantiate(node, NULL, ckb, dst_fields_tp[i], dst_fields_arrmeta[i], 1, &src_field_tp[i],
135- &src_fields_arrmeta[i], kernel_request_single, 1, &error_mode,
136- std::map<std::string, ndt::type>());
124+ intptr_t self_offset = ckb->size();
125+ ckb->emplace_back<nd::tuple_unary_op_ck>(kernreq);
126+ nd::tuple_unary_op_ck *self = ckb->get_at<nd::tuple_unary_op_ck>(self_offset);
127+ self->m_fields.resize(field_count);
128+ for (intptr_t i = 0; i < field_count; ++i) {
129+ self = ckb->get_at<nd::tuple_unary_op_ck>(self_offset);
130+ nd::tuple_unary_op_item &field = self->m_fields[i];
131+ field.child_kernel_offset = ckb->size() - self_offset;
132+ field.dst_data_offset = field_offsets[i];
133+ field.src_data_offset = src_data_offsets[i];
134+ nd::array error_mode = ndt::traits<assign_error_mode>::na();
135+ af->instantiate(node, NULL, ckb, dst_fields_tp[i], dst_fields_arrmeta[i], 1, &src_field_tp[i],
136+ &src_fields_arrmeta[i], kernel_request_single, 1, &error_mode,
137+ std::map<std::string, ndt::type>());
138+ }
139+ return;
140+ }
141+ else {
142+ std::stringstream ss;
143+ ss << "TODO: implement assign from source dynd type " << src_tp[0] << " to numpy type "
144+ << pydynd::pyobject_repr((PyObject *)dtype);
145+ throw std::invalid_argument(ss.str());
137146 }
138- return;
139- }
140- else {
141- std::stringstream ss;
142- ss << "TODO: implement assign from source dynd type " << src_tp[0] << " to numpy type "
143- << pydynd::pyobject_repr((PyObject *)dtype);
144- throw std::invalid_argument(ss.str());
145147 }
146- }
147- */
148+ */
148149};
0 commit comments