void pydynd::array_no_dim_broadcast_assign_from_py(
    const dynd::ndt::type &dst_tp, const char *dst_arrmeta, char *dst_data,
    PyObject *value, const dynd::eval::eval_context *ectx)
{
  // TODO: This is a hack, need a proper way to pass this dst param
  dynd::nd::array tmp_dst(
      dynd::make_array_memory_block(dst_tp.get_arrmeta_size()));
  tmp_dst.get()->tp = dst_tp;
  tmp_dst.get()->flags =
      dynd::nd::read_access_flag | dynd::nd::write_access_flag;
  if (dst_tp.get_arrmeta_size() > 0) {
    dst_tp.extended()->arrmeta_copy_construct(
        tmp_dst.get()->metadata(), dst_arrmeta,
        dynd::intrusive_ptr<dynd::memory_block_data>());
  }
  tmp_dst.get()->data = dst_data;
  dynd::ndt::type src_tp = dynd::ndt::type::make<void>();
  const char *src_arrmeta = NULL;
  char *src_data = reinterpret_cast<char *>(&value);
  const char *kwd_names[1] = {"broadcast"};
  dynd::nd::array kwd_values[1] = {false};
  (*pydynd::nd::copy_from_pyobject.get().get())(
      tmp_dst.get_type(), tmp_dst.get()->metadata(), tmp_dst.data(), 1, &src_tp,
      &src_arrmeta, &src_data, 1, kwd_values,
      std::map<std::string, dynd::ndt::type>());

  tmp_dst.get()->tp = dynd::ndt::type();
}
void pydynd::nd::array_copy_from_numpy(const dynd::ndt::type &dst_tp,
                                       const char *dst_arrmeta, char *dst_data,
                                       PyArrayObject *src_arr,
                                       const dynd::eval::eval_context *ectx)
{
  intptr_t src_ndim = PyArray_NDIM(src_arr);

  strided_of_numpy_arrmeta src_am_holder;
  const char *src_am = reinterpret_cast<const char *>(
      &src_am_holder.sdt[NPY_MAXDIMS - src_ndim]);
  // Fill in metadata for a multi-dim strided array, corresponding
  // to the numpy array, with a void type at the end for the numpy
  // specific data.
  uintptr_t src_alignment = reinterpret_cast<uintptr_t>(PyArray_DATA(src_arr));
  for (intptr_t i = 0; i < src_ndim; ++i) {
    dynd::fixed_dim_type_arrmeta &am =
        src_am_holder.sdt[NPY_MAXDIMS - src_ndim + i];
    am.dim_size = PyArray_DIM(src_arr, (int)i);
    am.stride = am.dim_size != 1 ? PyArray_STRIDE(src_arr, (int)i) : 0;
    src_alignment |= static_cast<uintptr_t>(am.stride);
  }
  dynd::ndt::type src_tp = dynd::ndt::make_type(
      src_ndim, PyArray_SHAPE(src_arr), dynd::ndt::type::make<void>());
  src_am_holder.am.src_dtype = PyArray_DTYPE(src_arr);
  src_am_holder.am.src_alignment = src_alignment;

  // TODO: This is a hack, need a proper way to pass this dst param
  dynd::nd::array tmp_dst(
      dynd::make_array_memory_block(dst_tp.get_arrmeta_size()));
  tmp_dst.get()->tp = dst_tp;
  tmp_dst.get()->flags =
      dynd::nd::read_access_flag | dynd::nd::write_access_flag;
  if (dst_tp.get_arrmeta_size() > 0) {
    dst_tp.extended()->arrmeta_copy_construct(
        tmp_dst.get()->metadata(), dst_arrmeta,
        dynd::intrusive_ptr<dynd::memory_block_data>());
  }
  tmp_dst.get()->data = dst_data;
  char *src_data = reinterpret_cast<char *>(PyArray_DATA(src_arr));
  const char *kwd_names[1] = {"broadcast"};
  dynd::nd::array kwd_values[1] = {true};
  (*pydynd::nd::copy_from_numpy::get().get())(
      tmp_dst.get_type(), tmp_dst.get()->metadata(), tmp_dst.data(), 1, &src_tp,
      &src_am, &src_data, 1, kwd_values,
      std::map<std::string, dynd::ndt::type>());

  tmp_dst.get()->tp = dynd::ndt::type();
}