/** * This function promotes the requested `axis` from * a strided dim to a var dim. It modifies `shape`, `coord`, * `elem`, and `arr` to point to a new array, and * copies the data over. */ static void promote_nd_arr_dim(std::vector<intptr_t> &shape, std::vector<afpd_coordentry> &coord, afpd_dtype &elem, nd::array &arr, intptr_t axis, bool copy_final_coord) { vector<afpd_coordentry> newcoord; afpd_dtype newelem; newelem.dtp = elem.dtp; // Convert the axis into a var dim shape[axis] = -1; // Create the new array nd::array newarr = allocate_nd_arr(shape, newcoord, newelem, axis); // Copy the data up to, but not including, the current `coord` // from the old `arr` to the new one. The recursion stops // at `axis`, where all subsequent dimensions are handled by the // created kernel. ckernel_builder<kernel_request_host> k; if (elem.dtp.get_type_id() != uninitialized_type_id) { make_assignment_kernel(&k, 0, newcoord[axis].tp, newcoord[axis].arrmeta_ptr, coord[axis].tp, coord[axis].arrmeta_ptr, kernel_request_strided, &eval::default_eval_context); } copy_to_promoted_nd_arr(shape, newarr.get_readwrite_originptr(), newcoord, newelem, arr.get_readonly_originptr(), coord, elem, k, 0, axis, copy_final_coord, true); arr.swap(newarr); coord.swap(newcoord); elem.swap(newelem); }
inline static bool run(nd::array &a) { const ndt::type &tp = a.get_type(); if (a.is_immutable() && tp.get_type_id() == fixed_dim_type_id) { // It's immutable and "N * <something>" const ndt::type &et = tp.extended<fixed_dim_type>()->get_element_type(); const fixed_dim_type_arrmeta *md = reinterpret_cast<const fixed_dim_type_arrmeta *>(a.get_arrmeta()); if (et.get_type_id() == type_type_id && md->stride == sizeof(ndt::type)) { // It also has the right type and is contiguous, // so no modification necessary. return true; } } // We have to make a copy, check that it's a 1D array, and that // it has the same array kind as the requested type. if (tp.get_ndim() == 1) { // It's a 1D array const ndt::type &et = tp.get_type_at_dimension(NULL, 1).value_type(); if (et.get_type_id() == type_type_id) { // It also has the same array type as requested nd::array tmp = nd::empty(a.get_dim_size(), ndt::make_type()); tmp.vals() = a; tmp.flag_as_immutable(); a.swap(tmp); return true; } } // It's not compatible, so return false return false; }
/** * This function promotes the dtype the array currently has with * `tp`, allocates a new one, then copies all the data up to the * current index in `coord`. This modifies coord and elem in place. */ static void promote_nd_arr_dtype(const std::vector<intptr_t> &shape, std::vector<afpd_coordentry> &coord, afpd_dtype &elem, nd::array &arr, const ndt::type &tp) { intptr_t ndim = shape.size(); vector<afpd_coordentry> newcoord; afpd_dtype newelem; if (elem.dtp.get_type_id() == uninitialized_type_id) { // If the `elem` dtype is uninitialized, it means a dummy // array was created to capture dimensional structure until // the first value is encountered newelem.dtp = tp; } else { newelem.dtp = promote_types_arithmetic(elem.dtp, tp); } // Create the new array nd::array newarr = allocate_nd_arr(shape, newcoord, newelem, ndim); // Copy the data up to, but not including, the current `coord` // from the old `arr` to the new one ckernel_builder<kernel_request_host> k; if (elem.dtp.get_type_id() != uninitialized_type_id) { make_assignment_kernel(&k, 0, newelem.dtp, newelem.arrmeta_ptr, elem.dtp, elem.arrmeta_ptr, kernel_request_strided, &eval::default_eval_context); } else { // An assignment kernel which copies one byte - will only // be called with count==0 when dtp is uninitialized make_assignment_kernel(&k, 0, ndt::type::make<char>(), NULL, ndt::type::make<char>(), NULL, kernel_request_strided, &eval::default_eval_context); } copy_to_promoted_nd_arr(shape, newarr.get_readwrite_originptr(), newcoord, newelem, arr.get_readonly_originptr(), coord, elem, k, 0, ndim, false, true); arr.swap(newarr); coord.swap(newcoord); elem.swap(newelem); }
inline void swap(nd::arrfunc &rhs) { m_value.swap(rhs.m_value); }