size_t bytes_type::make_assignment_kernel( void *ckb, intptr_t ckb_offset, const ndt::type &dst_tp, const char *dst_arrmeta, const ndt::type &src_tp, const char *src_arrmeta, kernel_request_t kernreq, const eval::eval_context *ectx) const { if (this == dst_tp.extended()) { switch (src_tp.get_type_id()) { case bytes_type_id: { return make_blockref_bytes_assignment_kernel(ckb, ckb_offset, get_data_alignment(), dst_arrmeta, src_tp.get_data_alignment(), src_arrmeta, kernreq, ectx); } case fixedbytes_type_id: { return make_fixedbytes_to_blockref_bytes_assignment_kernel(ckb, ckb_offset, get_data_alignment(), dst_arrmeta, src_tp.get_data_size(), src_tp.get_data_alignment(), kernreq, ectx); } default: { if (!src_tp.is_builtin()) { src_tp.extended()->make_assignment_kernel( ckb, ckb_offset, dst_tp, dst_arrmeta, src_tp, src_arrmeta, kernreq, ectx); } break; } } } stringstream ss; ss << "Cannot assign from " << src_tp << " to " << dst_tp; throw runtime_error(ss.str()); }
byteswap_type::byteswap_type(const ndt::type& value_type) : base_expr_type(byteswap_type_id, expr_kind, value_type.get_data_size(), value_type.get_data_alignment(), type_flag_scalar, 0), m_value_type(value_type), m_operand_type(ndt::make_fixedbytes(value_type.get_data_size(), value_type.get_data_alignment())) { if (!value_type.is_builtin()) { throw dynd::type_error("byteswap_type: Only built-in types are supported presently"); } }
size_t dynd::make_expression_comparison_kernel( ckernel_builder *out, size_t offset_out, const ndt::type& src0_dt, const char *src0_metadata, const ndt::type& src1_dt, const char *src1_metadata, comparison_type_t comptype, const eval::eval_context *ectx) { size_t current_offset = offset_out + sizeof(buffered_kernel_extra); out->ensure_capacity(current_offset); buffered_kernel_extra *e = out->get_at<buffered_kernel_extra>(offset_out); e->base.set_function<binary_single_predicate_t>(&buffered_kernel_extra::kernel); e->base.destructor = &buffered_kernel_extra::destruct; // Initialize the information for buffering the operands if (src0_dt.get_kind() == expression_kind) { e->init_buffer(0, src0_dt.value_type()); e->buf[0].kernel_offset = current_offset - offset_out; current_offset = make_assignment_kernel(out, current_offset, src0_dt.value_type(), e->buf[0].metadata, src0_dt, src0_metadata, kernel_request_single, assign_error_none, ectx); // Have to re-retrieve 'e', because creating another kernel may invalidate it e = out->get_at<buffered_kernel_extra>(offset_out); } if (src1_dt.get_kind() == expression_kind) { e->init_buffer(1, src1_dt.value_type()); e->buf[1].kernel_offset = current_offset - offset_out; current_offset = make_assignment_kernel(out, current_offset, src1_dt.value_type(), e->buf[1].metadata, src1_dt, src1_metadata, kernel_request_single, assign_error_none, ectx); // Have to re-retrieve 'e', because creating another kernel may invalidate it e = out->get_at<buffered_kernel_extra>(offset_out); } // Allocate the data for the buffers if (e->buf[0].kernel_offset != 0) { current_offset = inc_to_alignment(current_offset, src0_dt.get_data_alignment()); e->buf[0].data_offset = current_offset - offset_out; current_offset += e->buf[0].data_size; } if (e->buf[1].kernel_offset != 0) { current_offset = inc_to_alignment(current_offset, src1_dt.get_data_alignment()); e->buf[1].data_offset = current_offset - offset_out; current_offset += e->buf[1].data_size; } out->ensure_capacity(current_offset); // Have to re-retrieve 'e', because allocating the buffer data may invalidate it e = out->get_at<buffered_kernel_extra>(offset_out); e->cmp_kernel_offset = current_offset - offset_out; return make_comparison_kernel(out, current_offset, src0_dt.value_type(), (e->buf[0].kernel_offset != 0) ? e->buf[0].metadata : src0_metadata, src1_dt.value_type(), (e->buf[1].kernel_offset != 0) ? e->buf[1].metadata : src1_metadata, comptype, ectx); }
/** * 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; } } }
expr_type::expr_type(const ndt::type& value_type, const ndt::type& operand_type, const expr_kernel_generator *kgen) : base_expression_type(expr_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(), value_type.get_ndim()), m_value_type(value_type), m_operand_type(operand_type), m_kgen(kgen) { if (operand_type.get_type_id() != cstruct_type_id) { stringstream ss; ss << "expr_type can only be constructed with a cstruct as its operand, given "; ss << operand_type; throw runtime_error(ss.str()); } const cstruct_type *fsd = static_cast<const cstruct_type *>(operand_type.extended()); size_t field_count = fsd->get_field_count(); if (field_count == 1) { throw runtime_error("expr_type is for 2 or more operands, use unary_expr_type for 1 operand"); } const ndt::type *field_types = fsd->get_field_types(); for (size_t i = 0; i != field_count; ++i) { if (field_types[i].get_type_id() != pointer_type_id) { stringstream ss; ss << "each field of the expr_type's operand must be a pointer, field " << i; ss << " is " << field_types[i]; throw runtime_error(ss.str()); } } }
fixed_dim_type::fixed_dim_type(size_t dimension_size, const ndt::type& element_tp, intptr_t stride) : base_uniform_dim_type(fixed_dim_type_id, element_tp, 0, element_tp.get_data_alignment(), 0, type_flag_none), m_stride(stride), m_dim_size(dimension_size) { size_t child_element_size = element_tp.get_data_size(); if (child_element_size == 0) { stringstream ss; ss << "Cannot create dynd fixed_dim type with element type " << element_tp; ss << ", as it does not have a fixed size"; throw runtime_error(ss.str()); } if (dimension_size <= 1 && stride != 0) { stringstream ss; ss << "Cannot create dynd fixed_dim type with size " << dimension_size; ss << " and stride " << stride << ", as the stride must be zero when the dimension size is 1"; throw runtime_error(ss.str()); } if (dimension_size > 1 && stride == 0) { stringstream ss; ss << "Cannot create dynd fixed_dim type with size " << dimension_size; ss << " and stride 0, as the stride must be non-zero when the dimension size is > 1"; throw runtime_error(ss.str()); } m_members.data_size = m_stride * (m_dim_size-1) + child_element_size; // Propagate the zeroinit flag from the element m_members.flags |= (element_tp.get_flags()&type_flag_zeroinit); // Copy ndobject properties and functions from the first non-array dimension get_scalar_properties_and_functions(m_array_properties, m_array_functions); }
void dynd::typed_data_assign(const ndt::type& dst_tp, const char *dst_metadata, char *dst_data, const ndt::type& src_tp, const char *src_metadata, const char *src_data, assign_error_mode errmode, const eval::eval_context *ectx) { DYND_ASSERT_ALIGNED(dst, 0, dst_tp.get_data_alignment(), "dst type: " << dst_tp << ", src type: " << src_tp); DYND_ASSERT_ALIGNED(src, 0, src_dt.get_data_alignment(), "src type: " << src_tp << ", dst type: " << dst_tp); if (errmode == assign_error_default) { if (ectx != NULL) { if (dst_tp.get_dtype().get_type_id() == cuda_device_type_id && src_tp.get_dtype().get_type_id() == cuda_device_type_id) { errmode = ectx->default_cuda_device_errmode; } else { errmode = ectx->default_errmode; } } else if (dst_tp == src_tp) { errmode = assign_error_none; } else { stringstream ss; ss << "assignment from " << src_tp << " to " << dst_tp << " with default error mode requires an eval_context"; throw dynd::type_error(ss.str()); } } assignment_ckernel_builder k; make_assignment_kernel(&k, 0, dst_tp, dst_metadata, src_tp, src_metadata, kernel_request_single, errmode, ectx); k(dst_data, src_data); }
ndt::adapt_type::adapt_type(const ndt::type &value_tp, const ndt::type &storage_tp, const nd::callable &forward, const nd::callable &inverse) : base_expr_type(adapt_id, storage_tp.get_data_size(), storage_tp.get_data_alignment(), type_flag_none, storage_tp.get_arrmeta_size(), storage_tp.get_ndim()), m_value_tp(value_tp), m_storage_tp(storage_tp), m_forward(forward), m_inverse(inverse) { }
adapt_type::adapt_type(const ndt::type &operand_type, const ndt::type &value_type, const nd::string &op) : base_expr_type( adapt_type_id, expr_kind, operand_type.get_data_size(), operand_type.get_data_alignment(), inherited_flags(value_type.get_flags(), operand_type.get_flags()), 0), m_value_type(value_type), m_operand_type(operand_type), m_op(op) { if (!value_type.is_builtin() && value_type.extended()->adapt_type(operand_type.value_type(), op, m_forward, m_reverse)) { } else if (!operand_type.value_type().is_builtin() && operand_type.value_type().extended()->reverse_adapt_type( value_type, op, m_forward, m_reverse)) { } else { stringstream ss; ss << "Cannot create type "; print_type(ss); throw type_error(ss.str()); } // If the operand is an expression, make a buffering arrfunc if (m_operand_type.get_kind() == expr_kind && !m_forward.is_null() && m_operand_type != m_forward.get_type()->get_arg_type(0)) { m_forward = make_chain_arrfunc( make_arrfunc_from_assignment(m_forward.get_type()->get_arg_type(0), m_operand_type, assign_error_default), m_forward, m_forward.get_type()->get_arg_type(0)); } }
/** * Creates a result array for an elementwise * reduce operation. */ static ndarray_node_ptr make_elwise_reduce_result(const ndt::type& result_dt, uint32_t access_flags, bool keepdims, int ndim, const dynd_bool *reduce_axes, const intptr_t *src_shape, const int *src_axis_perm, char *&result_originptr, intptr_t *result_strides) { dimvector result_shape(ndim); // Calculate the shape and strides of the reduction result // without removing the dimensions intptr_t num_elements = 1; intptr_t stride = result_dt.get_data_size(); for (int i = 0; i < ndim; ++i) { int p = src_axis_perm[i]; if (reduce_axes[p]) { result_shape[p] = 1; result_strides[p] = 0; } else { intptr_t size = src_shape[p]; result_shape[p] = size; if (size == 1) { result_strides[p] = 0; } else { result_strides[p] = stride; stride *= size; num_elements *= size; } } } // Allocate the memoryblock for the data char *originptr = NULL; memory_block_ptr memblock = make_fixed_size_pod_memory_block(result_dt.get_data_size() * num_elements, result_dt.get_data_alignment(), &originptr, NULL, NULL); ndarray_node_ptr result; // Create the strided ndarray node, compressing the dimensions if requested if (!keepdims) { dimvector compressed_shape(ndim), compressed_strides(ndim); int compressed_ndim = 0; for (int i = 0; i < ndim; ++i) { if (!reduce_axes[i]) { compressed_shape[compressed_ndim] = result_shape[i]; compressed_strides[compressed_ndim] = result_strides[i]; ++compressed_ndim; } } result = make_strided_ndarray_node(result_dt, compressed_ndim, compressed_shape.get(), compressed_strides.get(), originptr, access_flags, memblock); } else { result = make_strided_ndarray_node(result_dt, ndim, result_shape.get(), result_strides, originptr, access_flags, memblock); } // Because we just allocated this buffer, we can write to it even though it // might be marked as readonly because the src memory block is readonly result_originptr = const_cast<char *>(result->get_readonly_originptr()); return DYND_MOVE(result); }
byteswap_type::byteswap_type(const ndt::type& value_type, const ndt::type& operand_type) : base_expr_type(byteswap_type_id, expr_kind, operand_type.get_data_size(), operand_type.get_data_alignment(), type_flag_scalar, 0), m_value_type(value_type), m_operand_type(operand_type) { // Only a bytes type be the operand to the byteswap if (operand_type.value_type().get_type_id() != fixedbytes_type_id) { std::stringstream ss; ss << "byteswap_type: The operand to the type must have a value type of bytes, not " << operand_type.value_type(); throw dynd::type_error(ss.str()); } // Automatically realign if needed if (operand_type.value_type().get_data_alignment() < value_type.get_data_alignment()) { m_operand_type = ndt::make_view(operand_type, ndt::make_fixedbytes(operand_type.get_data_size(), value_type.get_data_alignment())); } }
strided_dim_type::strided_dim_type(const ndt::type& element_tp) : base_dim_type(strided_dim_type_id, element_tp, 0, element_tp.get_data_alignment(), sizeof(strided_dim_type_arrmeta), type_flag_none, true) { // Propagate the inherited flags from the element m_members.flags |= (element_tp.get_flags() & ((type_flags_operand_inherited | type_flags_value_inherited) & ~type_flag_scalar)); }
unary_expr_type::unary_expr_type(const ndt::type& value_type, const ndt::type& operand_type, const expr_kernel_generator *kgen) : base_expression_type(unary_expr_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(), value_type.get_ndim()), m_value_type(value_type), m_operand_type(operand_type), m_kgen(kgen) { }
void dynd::typed_data_assign(const ndt::type &dst_tp, const char *dst_arrmeta, char *dst_data, const ndt::type &src_tp, const char *src_arrmeta, const char *src_data, const eval::eval_context *ectx) { DYND_ASSERT_ALIGNED(dst, 0, dst_tp.get_data_alignment(), "dst type: " << dst_tp << ", src type: " << src_tp); DYND_ASSERT_ALIGNED(src, 0, src_dt.get_data_alignment(), "src type: " << src_tp << ", dst type: " << dst_tp); unary_ckernel_builder k; make_assignment_kernel(&k, 0, dst_tp, dst_arrmeta, src_tp, src_arrmeta, kernel_request_single, ectx); 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_assign(const ndt::type &dst_tp, const char *dst_arrmeta, char *dst_data, const ndt::type &src_tp, const char *src_arrmeta, const char *src_data, const eval::eval_context *ectx) { DYND_ASSERT_ALIGNED(dst, 0, dst_tp.get_data_alignment(), "dst type: " << dst_tp << ", src type: " << src_tp); DYND_ASSERT_ALIGNED(src, 0, src_dt.get_data_alignment(), "src type: " << src_tp << ", dst type: " << dst_tp); ckernel_builder<kernel_request_host> k; make_assignment_kernel(&k, 0, dst_tp, dst_arrmeta, src_tp, src_arrmeta, kernel_request_single, ectx); expr_single_t fn = k.get()->get_function<expr_single_t>(); char *src = const_cast<char *>(src_data); fn(dst_data, &src, k.get()); }
memory_block_ptr dynd::make_zeroinit_memory_block(const ndt::type &element_tp, intptr_t initial_capacity_bytes) { // This is a temporary hack until the new bytes and string types are working size_t data_size; switch (element_tp.get_type_id()) { case bytes_type_id: case string_type_id: data_size = 1; break; default: data_size = element_tp.get_default_data_size(); } zeroinit_memory_block *pmb = new zeroinit_memory_block(data_size, element_tp.get_data_alignment(), initial_capacity_bytes); return memory_block_ptr(reinterpret_cast<memory_block_data *>(pmb), false); }
convert_type::convert_type(const ndt::type &value_type, const ndt::type &operand_type) : base_expr_type( convert_type_id, expr_kind, operand_type.get_data_size(), operand_type.get_data_alignment(), inherited_flags(value_type.get_flags(), operand_type.get_flags()), operand_type.get_arrmeta_size(), value_type.get_ndim()), m_value_type(value_type), m_operand_type(operand_type) { // An alternative to this error would be to use value_type.value_type(), cutting // away the expression part of the given value_type. if (m_value_type.get_kind() == expr_kind) { std::stringstream ss; ss << "convert_type: The destination type " << m_value_type; ss << " should not be an expr_kind"; throw dynd::type_error(ss.str()); } }
ndt::type ndt::make_unaligned(const ndt::type& value_type) { if (value_type.get_data_alignment() > 1) { // Only do something if it requires alignment if (value_type.get_kind() != expr_kind) { return ndt::make_view( value_type, ndt::make_fixed_bytes(value_type.get_data_size(), 1)); } else { const ndt::type &sdt = value_type.storage_type(); return ndt::type( value_type.extended<base_expr_type>()->with_replaced_storage_type( ndt::make_view(sdt, ndt::make_fixed_bytes(sdt.get_data_size(), 1)))); } } else { return value_type; } }
static nd::array view_as_bytes(const nd::array &arr, const ndt::type &tp) { if (arr.get_type().get_flags() & type_flag_destructor) { // Can't view arrays of object type return nd::array(); } // Get the essential components of the array to analyze memory_block_ptr data_ref = arr.get_data_memblock(); char *data_ptr = arr.get_ndo()->data.ptr; ndt::type data_tp = arr.get_type(); const char *data_meta = arr.get_arrmeta(); intptr_t data_dim_size = -1, data_stride = 0; // Repeatedly refine the data while (data_tp.get_type_id() != uninitialized_type_id) { refine_bytes_view(data_ref, data_ptr, data_tp, data_meta, data_dim_size, data_stride); } // Check that it worked, and that the resulting data pointer is aligned if (data_dim_size < 0 || !offset_is_aligned(reinterpret_cast<size_t>(data_ptr), tp.extended<ndt::bytes_type>()->get_target_alignment())) { // This signals we could not view the data as a // contiguous chunk of bytes return nd::array(); } char *result_data_ptr = NULL; nd::array result(make_array_memory_block(tp.extended()->get_arrmeta_size(), tp.get_data_size(), tp.get_data_alignment(), &result_data_ptr)); // Set the bytes extents ((char **)result_data_ptr)[0] = data_ptr; ((char **)result_data_ptr)[1] = data_ptr + data_dim_size; // Set the array arrmeta array_preamble *ndo = result.get_ndo(); ndo->m_type = ndt::type(tp).release(); ndo->data.ptr = result_data_ptr; ndo->data.ref = NULL; ndo->m_flags = arr.get_flags(); // Set the bytes arrmeta bytes_type_arrmeta *ndo_meta = reinterpret_cast<bytes_type_arrmeta *>(result.get_arrmeta()); ndo_meta->blockref = data_ref.release(); return result; }
fixed_dim_type::fixed_dim_type(size_t dimension_size, const ndt::type& element_tp) : base_uniform_dim_type(fixed_dim_type_id, element_tp, 0, element_tp.get_data_alignment(), 0, type_flag_none), m_dim_size(dimension_size) { size_t child_element_size = element_tp.get_data_size(); if (child_element_size == 0) { stringstream ss; ss << "Cannot create dynd fixed_dim type with element type " << element_tp; ss << ", as it does not have a fixed size"; throw runtime_error(ss.str()); } m_stride = m_dim_size > 1 ? element_tp.get_data_size() : 0; m_members.data_size = m_stride * (m_dim_size-1) + child_element_size; // Propagate the operand flags from the element m_members.flags |= (element_tp.get_flags()&type_flags_operand_inherited); // Copy ndobject properties and functions from the first non-array dimension get_scalar_properties_and_functions(m_array_properties, m_array_functions); }
size_t dynd::make_assignment_kernel( ckernel_builder *out, size_t offset_out, const ndt::type& dst_tp, const char *dst_metadata, const ndt::type& src_tp, const char *src_metadata, kernel_request_t kernreq, assign_error_mode errmode, const eval::eval_context *ectx) { if (errmode == assign_error_default && ectx != NULL) { errmode = ectx->default_errmode; } if (dst_tp.is_builtin()) { if (src_tp.is_builtin()) { // If the casting can be done losslessly, disable the error check to find faster code paths if (errmode != assign_error_none && is_lossless_assignment(dst_tp, src_tp)) { errmode = assign_error_none; } if (dst_tp.extended() == src_tp.extended()) { return make_pod_typed_data_assignment_kernel(out, offset_out, dst_tp.get_data_size(), dst_tp.get_data_alignment(), kernreq); } else { return make_builtin_type_assignment_kernel(out, offset_out, dst_tp.get_type_id(), src_tp.get_type_id(), kernreq, errmode); } } else { return src_tp.extended()->make_assignment_kernel(out, offset_out, dst_tp, dst_metadata, src_tp, src_metadata, kernreq, errmode, ectx); } } else { return dst_tp.extended()->make_assignment_kernel(out, offset_out, dst_tp, dst_metadata, src_tp, src_metadata, kernreq, errmode, ectx); } }
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); }
static nd::array view_from_bytes(const nd::array &arr, const ndt::type &tp) { if (tp.get_flags() & (type_flag_blockref | type_flag_destructor | type_flag_not_host_readable)) { // Bytes cannot be viewed as blockref types, types which require // destruction, or types not on host memory. return nd::array(); } const bytes_type_arrmeta *bytes_meta = reinterpret_cast<const bytes_type_arrmeta *>(arr.get_arrmeta()); bytes_type_data *bytes_d = reinterpret_cast<bytes_type_data *>(arr.get_ndo()->data.ptr); memory_block_ptr data_ref; if (bytes_meta->blockref != NULL) { data_ref = bytes_meta->blockref; } else { data_ref = arr.get_data_memblock(); } char *data_ptr = bytes_d->begin; intptr_t data_size = bytes_d->end - data_ptr; size_t tp_data_size = tp.get_data_size(); if (tp_data_size > 0) { // If the data type has a single chunk of POD memory, it's ok if ((intptr_t)tp_data_size == data_size && offset_is_aligned(reinterpret_cast<size_t>(data_ptr), tp.get_data_alignment())) { // Allocate a result array to attempt the view in it nd::array result(make_array_memory_block(tp.get_arrmeta_size())); // Initialize the fields result.get_ndo()->data.ptr = data_ptr; result.get_ndo()->data.ref = data_ref.release(); result.get_ndo()->m_type = ndt::type(tp).release(); result.get_ndo()->m_flags = arr.get_ndo()->m_flags; if (tp.get_arrmeta_size() > 0) { tp.extended()->arrmeta_default_construct(result.get_arrmeta(), true); } return result; } } else if (tp.get_type_id() == fixed_dim_type_id) { ndt::type arr_tp = tp; ndt::type el_tp = arr_tp.extended<ndt::base_dim_type>()->get_element_type(); size_t el_data_size = el_tp.get_data_size(); // If the element type has a single chunk of POD memory, and // it divides into the memory size, it's ok if (data_size % (intptr_t)el_data_size == 0 && offset_is_aligned(reinterpret_cast<size_t>(data_ptr), arr_tp.get_data_alignment())) { intptr_t dim_size = data_size / el_data_size; if (arr_tp.get_kind() != kind_kind) { if (arr_tp.extended<ndt::fixed_dim_type>()->get_fixed_dim_size() != dim_size) { return nd::array(); } } else { // Transform the symbolic fixed type into a concrete one arr_tp = ndt::make_fixed_dim(dim_size, el_tp); } // Allocate a result array to attempt the view in it nd::array result(make_array_memory_block(arr_tp.get_arrmeta_size())); // Initialize the fields result.get_ndo()->data.ptr = data_ptr; result.get_ndo()->data.ref = data_ref.release(); result.get_ndo()->m_type = ndt::type(arr_tp).release(); result.get_ndo()->m_flags = arr.get_ndo()->m_flags; if (el_tp.get_arrmeta_size() > 0) { el_tp.extended()->arrmeta_default_construct(result.get_arrmeta() + sizeof(fixed_dim_type_arrmeta), true); } fixed_dim_type_arrmeta *fixed_meta = reinterpret_cast<fixed_dim_type_arrmeta *>(result.get_arrmeta()); fixed_meta->dim_size = dim_size; fixed_meta->stride = el_data_size; return result; } } // No view could be produced return nd::array(); }
size_t dynd::make_expression_comparison_kernel(void *ckb, intptr_t ckb_offset, const ndt::type &src0_dt, const char *src0_arrmeta, const ndt::type &src1_dt, const char *src1_arrmeta, comparison_type_t comptype, const eval::eval_context *ectx) { intptr_t root_ckb_offset = ckb_offset; buffered_kernel_extra *e = reinterpret_cast<ckernel_builder<kernel_request_host> *>(ckb) ->alloc_ck<buffered_kernel_extra>(ckb_offset); e->base.function = reinterpret_cast<void *>(&buffered_kernel_extra::kernel); e->base.destructor = &buffered_kernel_extra::destruct; // Initialize the information for buffering the operands if (src0_dt.get_kind() == expr_kind) { e->init_buffer(0, src0_dt.value_type()); e->buf[0].kernel_offset = ckb_offset - root_ckb_offset; ckb_offset = make_assignment_kernel( ckb, ckb_offset, src0_dt.value_type(), e->buf[0].arrmeta, src0_dt, src0_arrmeta, kernel_request_single, ectx); // Have to re-retrieve 'e', because creating another kernel may invalidate // it e = reinterpret_cast<ckernel_builder<kernel_request_host> *>(ckb) ->get_at<buffered_kernel_extra>(root_ckb_offset); } if (src1_dt.get_kind() == expr_kind) { e->init_buffer(1, src1_dt.value_type()); e->buf[1].kernel_offset = ckb_offset - root_ckb_offset; ckb_offset = make_assignment_kernel( ckb, ckb_offset, src1_dt.value_type(), e->buf[1].arrmeta, src1_dt, src1_arrmeta, kernel_request_single, ectx); // Have to re-retrieve 'e', because creating another kernel may invalidate // it e = reinterpret_cast<ckernel_builder<kernel_request_host> *>(ckb) ->get_at<buffered_kernel_extra>(root_ckb_offset); } // Allocate the data for the buffers if (e->buf[0].kernel_offset != 0) { ckb_offset = inc_to_alignment(ckb_offset, src0_dt.get_data_alignment()); e->buf[0].data_offset = ckb_offset - root_ckb_offset; ckb_offset += e->buf[0].data_size; } if (e->buf[1].kernel_offset != 0) { ckb_offset = inc_to_alignment(ckb_offset, src1_dt.get_data_alignment()); e->buf[1].data_offset = ckb_offset - root_ckb_offset; ckb_offset += e->buf[1].data_size; } reinterpret_cast<ckernel_builder<kernel_request_host> *>(ckb) ->reserve(ckb_offset + sizeof(ckernel_prefix)); // Have to re-retrieve 'e', because allocating the buffer data may invalidate // it e = reinterpret_cast<ckernel_builder<kernel_request_host> *>(ckb) ->get_at<buffered_kernel_extra>(root_ckb_offset); e->cmp_kernel_offset = ckb_offset - root_ckb_offset; return make_comparison_kernel( ckb, ckb_offset, src0_dt.value_type(), (e->buf[0].kernel_offset != 0) ? e->buf[0].arrmeta : src0_arrmeta, src1_dt.value_type(), (e->buf[1].kernel_offset != 0) ? e->buf[1].arrmeta : src1_arrmeta, comptype, ectx); }
pod_memory_block(const ndt::type &tp, intptr_t initial_capacity_bytes = 2048) : pod_memory_block(tp.get_default_data_size(), tp.get_data_alignment(), initial_capacity_bytes) {}
intrusive_ptr<memory_block_data> dynd::make_pod_memory_block(const ndt::type &tp, intptr_t initial_capacity_bytes) { pod_memory_block *pmb = new pod_memory_block(tp.get_default_data_size(), tp.get_data_alignment(), initial_capacity_bytes); return intrusive_ptr<memory_block_data>(reinterpret_cast<memory_block_data *>(pmb), false); }