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()); } } }
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)); } }
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"); } }
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); }
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()); } }
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)); }
objectarray_memory_block(const ndt::type &dt, size_t arrmeta_size, const char *arrmeta, intptr_t stride, intptr_t initial_count) : m_dt(dt), arrmeta_size(arrmeta_size), m_arrmeta(arrmeta), m_stride(stride), m_total_allocated_count(0), m_finalized(false), m_memory_handles() { if ((dt.get_flags() & type_flag_destructor) == 0) { std::stringstream ss; ss << "Cannot create objectarray memory block with dynd type " << dt; ss << " because it does not have a destructor, use a POD memory block instead"; throw std::runtime_error(ss.str()); } append_memory(initial_count); }
~buffer_storage() { if (m_storage && m_type.get_flags()&type_flag_destructor) { m_type.extended()->data_destruct_strided(m_arrmeta, m_storage, m_stride, DYND_BUFFER_CHUNK_SIZE); } delete[] m_storage; if (m_arrmeta) { m_type.extended()->arrmeta_destruct(m_arrmeta); delete[] m_arrmeta; } }
char *resize(char *previous_allocated, size_t count) { memory_chunk *mc = &m_memory_handles.back(); size_t previous_index = (previous_allocated - mc->memory) / m_stride; size_t previous_count = mc->used_count - previous_index; char *result = previous_allocated; if (mc->capacity_count - previous_index < count) { append_memory(std::max(m_total_allocated_count, count)); memory_chunk *new_mc = &m_memory_handles.back(); // Move the old memory to the newly allocated block if (previous_count > 0) { // Subtract the previously used memory from the old chunk's count mc->used_count -= previous_count; memcpy(new_mc->memory, previous_allocated, previous_count); // If the old memory only had the memory being resized, // free it completely. if (previous_allocated == mc->memory) { free(mc->memory); // Remove the second-last element of the vector m_memory_handles.erase(m_memory_handles.begin() + m_memory_handles.size() - 2); } } mc = &m_memory_handles.back(); result = mc->memory; mc->used_count = count; } else { // Adjust the used count (this may mean to grow it or shrink it) if (count >= previous_count) { mc->used_count += (count - previous_count); } else { // Call the destructor on the elements no longer used m_dt.extended()->data_destruct_strided(m_arrmeta + arrmeta_size, previous_allocated + m_stride * count, m_stride, previous_count - count); mc->used_count -= (previous_count - count); } } if ((m_dt.get_flags() & type_flag_zeroinit) != 0) { // Zero-init the new memory intptr_t new_count = count - (intptr_t)previous_count; if (new_count > 0) { memset(mc->memory + m_stride * previous_count, 0, m_stride * new_count); } } else { // TODO: Add a default data constructor to base_type // as well, with a flag for it std::stringstream ss; ss << "Expected objectarray data to be zeroinit, but is not with dynd type " << m_dt; throw std::runtime_error(ss.str()); } return result; }
pointer_type::pointer_type(const ndt::type& target_tp) : base_expr_type(pointer_type_id, expr_kind, sizeof(void *), sizeof(void *), inherited_flags(target_tp.get_flags(), type_flag_zeroinit|type_flag_blockref), sizeof(pointer_type_arrmeta) + target_tp.get_arrmeta_size(), target_tp.get_ndim()), m_target_tp(target_tp) { // I'm not 100% sure how blockref pointer types should interact with // the computational subsystem, the details will have to shake out // when we want to actually do something with them. if (target_tp.get_kind() == expr_kind && target_tp.get_type_id() != pointer_type_id) { stringstream ss; ss << "A dynd pointer type's target cannot be the expression type "; ss << target_tp; throw dynd::type_error(ss.str()); } }
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); }
char *alloc(size_t count) { // cout << "allocating " << size_bytes << " of memory with alignment " << alignment << endl; // Allocate new POD memory of the requested size and alignment memory_chunk *mc = &m_memory_handles.back(); if (mc->capacity_count - mc->used_count < count) { append_memory(std::max(m_total_allocated_count, count)); mc = &m_memory_handles.back(); } char *result = mc->memory + m_stride * mc->used_count; mc->used_count += count; if ((m_dt.get_flags() & type_flag_zeroinit) != 0) { memset(result, 0, m_stride * count); } else { // TODO: Add a default data constructor to base_type // as well, with a flag for it std::stringstream ss; ss << "Expected objectarray data to be zeroinit, but is not with dynd type " << m_dt; throw std::runtime_error(ss.str()); } return result; }
cuda_host_type::cuda_host_type(const ndt::type& storage_tp, unsigned int cuda_host_flags) : base_memory_type(cuda_host_type_id, storage_tp, storage_tp.get_data_size(), get_cuda_device_data_alignment(storage_tp), 0, storage_tp.get_flags()), m_cuda_host_flags(cuda_host_flags) { }
ndt::cuda_device_type::cuda_device_type(type_id_t id, const ndt::type &element_tp) : base_memory_type(id, element_tp, element_tp.get_data_size(), get_cuda_device_data_alignment(element_tp), 0, element_tp.get_flags() | type_flag_not_host_readable) {}
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(); }