Ejemplo n.º 1
0
std::string pydynd::ndt_type_repr(const dynd::ndt::type& d)
{
  std::stringstream ss;
  if (d.is_builtin() && d.get_type_id() != dynd::complex_float32_type_id &&
      d.get_type_id() != dynd::complex_float64_type_id) {
    ss << "ndt." << d;
  } else {
    switch (d.get_type_id()) {
    case complex_float32_type_id:
      ss << "ndt.complex_float32";
      break;
    case complex_float64_type_id:
      ss << "ndt.complex_float64";
      break;
    case date_type_id:
      ss << "ndt.date";
      break;
    case time_type_id:
      if (d.tcast<time_type>()->get_timezone() == tz_abstract) {
        ss << "ndt.time";
      } else {
        print_generic_type_repr(ss, d);
      }
      break;
    case datetime_type_id:
      if (d.tcast<datetime_type>()->get_timezone() == tz_abstract) {
        ss << "ndt.datetime";
      } else if (d.tcast<datetime_type>()->get_timezone() == tz_utc) {
        ss << "ndt.datetimeutc";
      } else {
        print_generic_type_repr(ss, d);
      }
      break;
    case json_type_id:
      ss << "ndt.json";
      break;
    case bytes_type_id:
      if (d.tcast<bytes_type>()->get_target_alignment() == 1) {
        ss << "ndt.bytes";
      } else {
        print_generic_type_repr(ss, d);
      }
      break;
    case string_type_id:
      if (d.tcast<string_type>()->get_encoding() == string_encoding_utf_8) {
        ss << "ndt.string";
      } else {
        print_generic_type_repr(ss, d);
      }
      break;
    default:
      print_generic_type_repr(ss, d);
      break;
    }
  }
  return ss.str();
}
Ejemplo n.º 2
0
/**
 * This sets up a ckernel to copy from a dynd array
 * to a numpy array. The destination numpy array is
 * represented by dst_tp being ``void`` and the dst_arrmeta
 * being a pointer to the ``PyArray_Descr *`` of the type for the destination.
 */
intptr_t pydynd::copy_to_numpy_ck::instantiate(
    char *DYND_UNUSED(static_data), char *DYND_UNUSED(data), void *ckb,
    intptr_t ckb_offset, const dynd::ndt::type &dst_tp, const char *dst_arrmeta,
    intptr_t nsrc, const dynd::ndt::type *src_tp,
    const char *const *src_arrmeta, dynd::kernel_request_t kernreq,
    intptr_t nkwd, const dynd::nd::array *kwds,
    const std::map<std::string, dynd::ndt::type> &tp_vars)
{
  if (dst_tp.get_type_id() != dynd::void_type_id) {
    stringstream ss;
    ss << "Cannot instantiate dynd::nd::callable with signature (";
    ss << src_tp[0] << ") -> " << dst_tp;
    throw dynd::type_error(ss.str());
  }

  PyObject *dst_obj = *reinterpret_cast<PyObject *const *>(dst_arrmeta);
  uintptr_t dst_alignment = reinterpret_cast<const uintptr_t *>(dst_arrmeta)[1];

  PyArray_Descr *dtype = reinterpret_cast<PyArray_Descr *>(dst_obj);
  if (!PyDataType_FLAGCHK(dtype, NPY_ITEM_HASOBJECT)) {
    // If there is no object type in the numpy type, get the dynd equivalent
    // type and use it to do the copying
    dynd::ndt::type dst_view_tp = _type_from_numpy_dtype(dtype, dst_alignment);
    return dynd::make_assignment_kernel(ckb, ckb_offset, dst_view_tp, NULL,
                                        src_tp[0], src_arrmeta[0], kernreq,
                                        &dynd::eval::default_eval_context);
  }
  else if (PyDataType_ISOBJECT(dtype)) {
    dynd::nd::base_callable *af = const_cast<dynd::nd::base_callable *>(
        nd::copy_to_pyobject::get().get());
    return af->instantiate(af->static_data(), NULL, ckb, ckb_offset,
                           dynd::ndt::make_type<void>(), NULL, nsrc, src_tp,
                           src_arrmeta, kernreq, 0, NULL, tp_vars);
  }
  else if (PyDataType_HASFIELDS(dtype)) {
    if (src_tp[0].get_kind() != dynd::struct_kind &&
        src_tp[0].get_kind() != dynd::tuple_kind) {
      stringstream ss;
      pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype));
      ss << "Cannot assign from source dynd type " << src_tp[0]
         << " to numpy type " << pydynd::pystring_as_string(dtype_str.get());
      throw invalid_argument(ss.str());
    }

    // Get the fields out of the numpy dtype
    vector<PyArray_Descr *> field_dtypes_orig;
    vector<string> field_names_orig;
    vector<size_t> field_offsets_orig;
    pydynd::extract_fields_from_numpy_struct(
        dtype, field_dtypes_orig, field_names_orig, field_offsets_orig);
    intptr_t field_count = field_dtypes_orig.size();
    if (field_count !=
        src_tp[0].extended<dynd::ndt::tuple_type>()->get_field_count()) {
      stringstream ss;
      pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype));
      ss << "Cannot assign from source dynd type " << src_tp[0]
         << " to numpy type " << pydynd::pystring_as_string(dtype_str.get());
      throw invalid_argument(ss.str());
    }

    // Permute the numpy fields to match with the dynd fields
    vector<PyArray_Descr *> field_dtypes;
    vector<size_t> field_offsets;
    if (src_tp[0].get_kind() == dynd::struct_kind) {
      field_dtypes.resize(field_count);
      field_offsets.resize(field_count);
      for (intptr_t i = 0; i < field_count; ++i) {
        intptr_t src_i =
            src_tp[0].extended<dynd::ndt::struct_type>()->get_field_index(
                field_names_orig[i]);
        if (src_i >= 0) {
          field_dtypes[src_i] = field_dtypes_orig[i];
          field_offsets[src_i] = field_offsets_orig[i];
        }
        else {
          stringstream ss;
          pyobject_ownref dtype_str(PyObject_Str((PyObject *)dtype));
          ss << "Cannot assign from source dynd type " << src_tp[0]
             << " to numpy type "
             << pydynd::pystring_as_string(dtype_str.get());
          throw invalid_argument(ss.str());
        }
      }
    }
    else {
      // In the tuple case, use position instead of name
      field_dtypes.swap(field_dtypes_orig);
      field_offsets.swap(field_offsets_orig);
    }

    vector<dynd::ndt::type> dst_fields_tp(field_count,
                                          dynd::ndt::make_type<void>());
    vector<copy_to_numpy_arrmeta> dst_arrmeta_values(field_count);
    vector<const char *> dst_fields_arrmeta(field_count);
    for (intptr_t i = 0; i < field_count; ++i) {
      dst_arrmeta_values[i].dst_dtype = field_dtypes[i];
      dst_arrmeta_values[i].dst_alignment = dst_alignment | field_offsets[i];
      dst_fields_arrmeta[i] =
          reinterpret_cast<const char *>(&dst_arrmeta_values[i]);
    }

    const uintptr_t *src_arrmeta_offsets =
        src_tp[0].extended<dynd::ndt::tuple_type>()->get_arrmeta_offsets_raw();
    dynd::shortvector<const char *> src_fields_arrmeta(field_count);
    for (intptr_t i = 0; i != field_count; ++i) {
      src_fields_arrmeta[i] = src_arrmeta[0] + src_arrmeta_offsets[i];
    }

    // Todo: Remove this
    dynd::nd::callable af = dynd::nd::callable::make<copy_to_numpy_ck>(
        dynd::ndt::type("(Any) -> void"), 0);

    return make_tuple_unary_op_ckernel(
        af.get(), af.get_type(), ckb, ckb_offset, field_count,
        &field_offsets[0], &dst_fields_tp[0], &dst_fields_arrmeta[0],
        src_tp[0].extended<dynd::ndt::tuple_type>()->get_data_offsets(
            src_arrmeta[0]),
        src_tp[0].extended<dynd::ndt::tuple_type>()->get_field_types_raw(),
        src_fields_arrmeta.get(), kernreq);
  }
  else {
    stringstream ss;
    ss << "TODO: implement assign from source dynd type " << src_tp[0]
       << " to numpy type " << pyobject_repr((PyObject *)dtype);
    throw invalid_argument(ss.str());
  }
}