std::string pydynd::ndt_type_repr(const dynd::ndt::type& d) { std::stringstream ss; if (d.is_builtin() && d.get_type_id() != dynd::complex_float32_type_id && d.get_type_id() != dynd::complex_float64_type_id) { ss << "ndt." << d; } else { switch (d.get_type_id()) { case complex_float32_type_id: ss << "ndt.complex_float32"; break; case complex_float64_type_id: ss << "ndt.complex_float64"; break; case date_type_id: ss << "ndt.date"; break; case time_type_id: if (d.tcast<time_type>()->get_timezone() == tz_abstract) { ss << "ndt.time"; } else { print_generic_type_repr(ss, d); } break; case datetime_type_id: if (d.tcast<datetime_type>()->get_timezone() == tz_abstract) { ss << "ndt.datetime"; } else if (d.tcast<datetime_type>()->get_timezone() == tz_utc) { ss << "ndt.datetimeutc"; } else { print_generic_type_repr(ss, d); } break; case json_type_id: ss << "ndt.json"; break; case bytes_type_id: if (d.tcast<bytes_type>()->get_target_alignment() == 1) { ss << "ndt.bytes"; } else { print_generic_type_repr(ss, d); } break; case string_type_id: if (d.tcast<string_type>()->get_encoding() == string_encoding_utf_8) { ss << "ndt.string"; } else { print_generic_type_repr(ss, d); } break; default: print_generic_type_repr(ss, d); break; } } return ss.str(); }
/** * This sets up a ckernel to copy from a dynd array * to a numpy array. The destination numpy array is * represented by dst_tp being ``void`` and the dst_arrmeta * being a pointer to the ``PyArray_Descr *`` of the type for the destination. */ intptr_t pydynd::copy_to_numpy_ck::instantiate( char *DYND_UNUSED(static_data), char *DYND_UNUSED(data), void *ckb, intptr_t ckb_offset, const dynd::ndt::type &dst_tp, const char *dst_arrmeta, intptr_t nsrc, const dynd::ndt::type *src_tp, const char *const *src_arrmeta, dynd::kernel_request_t kernreq, intptr_t nkwd, const dynd::nd::array *kwds, const std::map<std::string, dynd::ndt::type> &tp_vars) { if (dst_tp.get_type_id() != dynd::void_type_id) { stringstream ss; ss << "Cannot instantiate dynd::nd::callable with signature ("; ss << src_tp[0] << ") -> " << dst_tp; throw dynd::type_error(ss.str()); } PyObject *dst_obj = *reinterpret_cast<PyObject *const *>(dst_arrmeta); uintptr_t dst_alignment = reinterpret_cast<const uintptr_t *>(dst_arrmeta)[1]; PyArray_Descr *dtype = reinterpret_cast<PyArray_Descr *>(dst_obj); if (!PyDataType_FLAGCHK(dtype, NPY_ITEM_HASOBJECT)) { // If there is no object type in the numpy type, get the dynd equivalent // type and use it to do the copying dynd::ndt::type dst_view_tp = _type_from_numpy_dtype(dtype, dst_alignment); return dynd::make_assignment_kernel(ckb, ckb_offset, dst_view_tp, NULL, src_tp[0], src_arrmeta[0], kernreq, &dynd::eval::default_eval_context); } else if (PyDataType_ISOBJECT(dtype)) { dynd::nd::base_callable *af = const_cast<dynd::nd::base_callable *>( nd::copy_to_pyobject::get().get()); return af->instantiate(af->static_data(), NULL, ckb, ckb_offset, dynd::ndt::make_type<void>(), NULL, nsrc, src_tp, src_arrmeta, kernreq, 0, NULL, tp_vars); } else if (PyDataType_HASFIELDS(dtype)) { if (src_tp[0].get_kind() != dynd::struct_kind && src_tp[0].get_kind() != dynd::tuple_kind) { stringstream ss; pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype)); ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type " << pydynd::pystring_as_string(dtype_str.get()); throw invalid_argument(ss.str()); } // Get the fields out of the numpy dtype vector<PyArray_Descr *> field_dtypes_orig; vector<string> field_names_orig; vector<size_t> field_offsets_orig; pydynd::extract_fields_from_numpy_struct( dtype, field_dtypes_orig, field_names_orig, field_offsets_orig); intptr_t field_count = field_dtypes_orig.size(); if (field_count != src_tp[0].extended<dynd::ndt::tuple_type>()->get_field_count()) { stringstream ss; pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype)); ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type " << pydynd::pystring_as_string(dtype_str.get()); throw invalid_argument(ss.str()); } // Permute the numpy fields to match with the dynd fields vector<PyArray_Descr *> field_dtypes; vector<size_t> field_offsets; if (src_tp[0].get_kind() == dynd::struct_kind) { field_dtypes.resize(field_count); field_offsets.resize(field_count); for (intptr_t i = 0; i < field_count; ++i) { intptr_t src_i = src_tp[0].extended<dynd::ndt::struct_type>()->get_field_index( field_names_orig[i]); if (src_i >= 0) { field_dtypes[src_i] = field_dtypes_orig[i]; field_offsets[src_i] = field_offsets_orig[i]; } else { stringstream ss; pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype)); ss << "Cannot assign from source dynd type " << src_tp[0] << " to numpy type " << pydynd::pystring_as_string(dtype_str.get()); throw invalid_argument(ss.str()); } } } else { // In the tuple case, use position instead of name field_dtypes.swap(field_dtypes_orig); field_offsets.swap(field_offsets_orig); } vector<dynd::ndt::type> dst_fields_tp(field_count, dynd::ndt::make_type<void>()); vector<copy_to_numpy_arrmeta> dst_arrmeta_values(field_count); vector<const char *> dst_fields_arrmeta(field_count); for (intptr_t i = 0; i < field_count; ++i) { dst_arrmeta_values[i].dst_dtype = field_dtypes[i]; dst_arrmeta_values[i].dst_alignment = dst_alignment | field_offsets[i]; dst_fields_arrmeta[i] = reinterpret_cast<const char *>(&dst_arrmeta_values[i]); } const uintptr_t *src_arrmeta_offsets = src_tp[0].extended<dynd::ndt::tuple_type>()->get_arrmeta_offsets_raw(); dynd::shortvector<const char *> src_fields_arrmeta(field_count); for (intptr_t i = 0; i != field_count; ++i) { src_fields_arrmeta[i] = src_arrmeta[0] + src_arrmeta_offsets[i]; } // Todo: Remove this dynd::nd::callable af = dynd::nd::callable::make<copy_to_numpy_ck>( dynd::ndt::type("(Any) -> void"), 0); return make_tuple_unary_op_ckernel( af.get(), af.get_type(), ckb, ckb_offset, field_count, &field_offsets[0], &dst_fields_tp[0], &dst_fields_arrmeta[0], src_tp[0].extended<dynd::ndt::tuple_type>()->get_data_offsets( src_arrmeta[0]), src_tp[0].extended<dynd::ndt::tuple_type>()->get_field_types_raw(), src_fields_arrmeta.get(), kernreq); } else { stringstream ss; ss << "TODO: implement assign from source dynd type " << src_tp[0] << " to numpy type " << pyobject_repr((PyObject *)dtype); throw invalid_argument(ss.str()); } }