/** * Scans through the types, and tries to view data * for 'tp'/'arrmeta' as 'view_tp'. For this to be * possible, one must be able to construct * arrmeta for 'tp' corresponding to the same data. * * \param tp The type of the data. * \param arrmeta The array arrmeta of the data. * \param view_tp The type the data should be viewed as. * \param view_arrmeta The array arrmeta of the view, which should be populated. * \param embedded_reference The containing memory block in case the data was embedded. * * \returns If it worked, returns true, otherwise false. */ static bool try_view(const ndt::type &tp, const char *arrmeta, const ndt::type &view_tp, char *view_arrmeta, dynd::memory_block_data *embedded_reference) { switch (tp.get_type_id()) { case fixed_dim_type_id: { // All the strided dim types share the same arrmeta, so can be // treated uniformly here const ndt::base_dim_type *sdt = tp.extended<ndt::base_dim_type>(); const fixed_dim_type_arrmeta *md = reinterpret_cast<const fixed_dim_type_arrmeta *>(arrmeta); switch (view_tp.get_type_id()) { case fixed_dim_type_id: { // strided as fixed const ndt::fixed_dim_type *view_fdt = view_tp.extended<ndt::fixed_dim_type>(); // The size must match exactly in this case if (md->dim_size != view_fdt->get_fixed_dim_size()) { return false; } fixed_dim_type_arrmeta *view_md = reinterpret_cast<fixed_dim_type_arrmeta *>(view_arrmeta); if (try_view(sdt->get_element_type(), arrmeta + sizeof(fixed_dim_type_arrmeta), view_fdt->get_element_type(), view_arrmeta + sizeof(fixed_dim_type_arrmeta), embedded_reference)) { *view_md = *md; return true; } else { return false; } } default: // other cases cannot be handled return false; } } default: if (tp == view_tp) { // require equal types otherwise if (tp.get_arrmeta_size() > 0) { tp.extended()->arrmeta_copy_construct(view_arrmeta, arrmeta, embedded_reference); } return true; } else if (tp.is_pod() && view_tp.is_pod() && tp.get_data_size() == view_tp.get_data_size() && tp.get_data_alignment() >= view_tp.get_data_alignment()) { // POD types with matching properties if (view_tp.get_arrmeta_size() > 0) { view_tp.extended()->arrmeta_default_construct(view_arrmeta, true); } return true; } else { return false; } } }
void dynd::typed_data_copy(const ndt::type& tp, const char *dst_arrmeta, char *dst_data, const char *src_arrmeta, const char *src_data) { size_t data_size = tp.get_data_size(); if (tp.is_pod()) { memcpy(dst_data, src_data, data_size); } else { unary_ckernel_builder k; make_assignment_kernel(&k, 0, tp, dst_arrmeta, tp, src_arrmeta, kernel_request_single, &eval::default_eval_context); k(dst_data, src_data); } }
view_type::view_type(const ndt::type& value_type, const ndt::type& operand_type) : base_expression_type(view_type_id, expression_kind, operand_type.get_data_size(), operand_type.get_data_alignment(), inherited_flags(value_type.get_flags(), operand_type.get_flags()), operand_type.get_metadata_size()), m_value_type(value_type), m_operand_type(operand_type) { if (value_type.get_data_size() != operand_type.value_type().get_data_size()) { std::stringstream ss; ss << "view_type: Cannot view " << operand_type.value_type() << " as " << value_type << " because they have different sizes"; throw std::runtime_error(ss.str()); } if (!value_type.is_pod()) { throw std::runtime_error("view_type: Only POD types are supported"); } }
void dynd::typed_data_copy(const ndt::type &tp, const char *dst_arrmeta, char *dst_data, const char *src_arrmeta, const char *src_data) { if (tp.get_type_id() == option_type_id) { return typed_data_copy(tp.extended<ndt::option_type>()->get_value_type(), dst_arrmeta, dst_data, src_arrmeta, src_data); } size_t data_size = tp.get_data_size(); if (tp.is_pod()) { memcpy(dst_data, src_data, data_size); } else { ckernel_builder<kernel_request_host> k; make_assignment_kernel(&k, 0, tp, dst_arrmeta, tp, src_arrmeta, kernel_request_single, &eval::default_eval_context); expr_single_t fn = k.get()->get_function<expr_single_t>(); char *src = const_cast<char *>(src_data); fn(dst_data, &src, k.get()); } }
size_t dynd::make_tuple_identical_assignment_kernel( void *ckb, intptr_t ckb_offset, const ndt::type &val_tup_tp, const char *dst_arrmeta, const char *src_arrmeta, kernel_request_t kernreq, const eval::eval_context *ectx) { if (val_tup_tp.get_kind() != tuple_kind && val_tup_tp.get_kind() != struct_kind) { stringstream ss; ss << "make_tuple_identical_assignment_kernel: provided type " << val_tup_tp << " is not of tuple or struct kind"; throw runtime_error(ss.str()); } if (val_tup_tp.is_pod()) { // For POD structs, get a trivial memory copy kernel return make_pod_typed_data_assignment_kernel( ckb, ckb_offset, val_tup_tp.get_data_size(), val_tup_tp.get_data_alignment(), kernreq); } auto sd = val_tup_tp.extended<ndt::base_tuple_type>(); intptr_t field_count = sd->get_field_count(); const uintptr_t *arrmeta_offsets = sd->get_arrmeta_offsets_raw(); shortvector<const char *> dst_fields_arrmeta(field_count); for (intptr_t i = 0; i != field_count; ++i) { dst_fields_arrmeta[i] = dst_arrmeta + arrmeta_offsets[i]; } shortvector<const char *> src_fields_arrmeta(field_count); for (intptr_t i = 0; i != field_count; ++i) { src_fields_arrmeta[i] = src_arrmeta + arrmeta_offsets[i]; } return make_tuple_unary_op_ckernel( nd::copy::get().get(), nd::copy::get().get_type(), ckb, ckb_offset, field_count, sd->get_data_offsets(dst_arrmeta), sd->get_field_types_raw(), dst_fields_arrmeta.get(), sd->get_data_offsets(src_arrmeta), sd->get_field_types_raw(), src_fields_arrmeta.get(), kernreq, ectx); }