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()); } } }
nd::array nd::view(const nd::array& arr, const ndt::type& tp) { // If the types match exactly, simply return 'arr' if (arr.get_type() == tp) { return arr; } else if (arr.get_ndim() == tp.get_ndim()) { // Allocate a result array to attempt the view in it array result(make_array_memory_block(tp.get_metadata_size())); // Copy the fields result.get_ndo()->m_data_pointer = arr.get_ndo()->m_data_pointer; if (arr.get_ndo()->m_data_reference == NULL) { // Embedded data, need reference to the array result.get_ndo()->m_data_reference = arr.get_memblock().release(); } else { // Use the same data reference, avoid producing a chain result.get_ndo()->m_data_reference = arr.get_data_memblock().release(); } result.get_ndo()->m_type = ndt::type(tp).release(); result.get_ndo()->m_flags = arr.get_ndo()->m_flags; // Now try to copy the metadata as a view if (try_view(arr.get_type(), arr.get_ndo_meta(), tp, result.get_ndo_meta(), arr.get_memblock().get())) { // If it succeeded, return it return result; } // Otherwise fall through, let it get destructed, and raise an error } stringstream ss; ss << "Unable to view nd::array of type " << arr.get_type(); ss << "as type " << tp; throw type_error(ss.str()); }
inline base_uniform_dim_type(type_id_t type_id, const ndt::type& element_tp, size_t data_size, size_t alignment, size_t element_metadata_offset, flags_type flags) : base_type(type_id, uniform_dim_kind, data_size, alignment, flags, element_metadata_offset + element_tp.get_metadata_size(), 1 + element_tp.get_ndim()), m_element_tp(element_tp), m_element_metadata_offset(element_metadata_offset) { }
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) { }
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"); } }
/** * Scans through the types, and tries to view data * for 'tp'/'metadata' as 'view_tp'. For this to be * possible, one must be able to construct * metadata for 'tp' corresponding to the same data. * * \param tp The type of the data. * \param metadata The array metadata of the data. * \param view_tp The type the data should be viewed as. * \param view_metadata The array metadata 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 *metadata, const ndt::type &view_tp, char *view_metadata, dynd::memory_block_data *embedded_reference) { switch (tp.get_type_id()) { case strided_dim_type_id: { const strided_dim_type *sdt = static_cast<const strided_dim_type *>(tp.extended()); const strided_dim_type_metadata *md = reinterpret_cast<const strided_dim_type_metadata *>(metadata); switch (view_tp.get_type_id()) { case strided_dim_type_id: { // strided as strided const strided_dim_type *view_sdt = static_cast<const strided_dim_type *>(view_tp.extended()); strided_dim_type_metadata *view_md = reinterpret_cast<strided_dim_type_metadata *>(view_metadata); if (try_view(sdt->get_element_type(), metadata + sizeof(strided_dim_type_metadata), view_sdt->get_element_type(), view_metadata + sizeof(strided_dim_type_metadata), embedded_reference)) { view_md->size = md->size; view_md->stride = md->stride; return true; } else { return false; } } case fixed_dim_type_id: { // strided as fixed const fixed_dim_type *view_fdt = static_cast<const fixed_dim_type *>(view_tp.extended()); // The size and stride must match exactly in this case if (md->size != (intptr_t)view_fdt->get_fixed_dim_size() || md->stride != view_fdt->get_fixed_stride()) { return false; } return try_view(sdt->get_element_type(), metadata + sizeof(strided_dim_type_metadata), view_fdt->get_element_type(), view_metadata, embedded_reference); } default: // other cases cannot be handled return false; } } case fixed_dim_type_id: { const fixed_dim_type *fdt = static_cast<const fixed_dim_type *>(tp.extended()); switch (view_tp.get_type_id()) { case fixed_dim_type_id: { // fixed as fixed const fixed_dim_type *view_fdt = static_cast<const fixed_dim_type *>(view_tp.extended()); // The size and stride must match exactly in this case if (fdt->get_fixed_dim_size() != view_fdt->get_fixed_dim_size() || fdt->get_fixed_stride() != view_fdt->get_fixed_stride()) { return false; } return try_view(fdt->get_element_type(), metadata, view_fdt->get_element_type(), view_metadata, embedded_reference); } case strided_dim_type_id: { // fixed as strided const strided_dim_type *view_sdt = static_cast<const strided_dim_type *>(view_tp.extended()); strided_dim_type_metadata *view_md = reinterpret_cast<strided_dim_type_metadata *>(view_metadata); if (try_view(fdt->get_element_type(), metadata, view_sdt->get_element_type(), view_metadata + sizeof(strided_dim_type_metadata), embedded_reference)) { view_md->size = fdt->get_fixed_dim_size(); view_md->stride = fdt->get_fixed_stride(); return true; } else { return false; } } default: // other cases cannot be handled return false; } } default: // require equal types otherwise if (tp == view_tp) { if (tp.get_metadata_size() > 0) { tp.extended()->metadata_copy_construct(view_metadata, metadata, embedded_reference); } return true; } else { return false; } } }