new working adaptive_storage

This commit is contained in:
hans.dembinski@gmail.com
2017-03-27 15:13:16 +02:00
parent 12003ce3f1
commit f38085daa9
7 changed files with 524 additions and 1605 deletions

View File

@@ -282,58 +282,84 @@ std::string histogram_repr(const dynamic_histogram<> &h) {
return os.str();
}
struct storage_access {
#ifdef HAVE_NUMPY
using mp_int = adaptive_storage<>::mp_int;
using weight = adaptive_storage<>::weight;
template <typename T>
using array = adaptive_storage<>::array<T>;
struct dtype_visitor : public static_visitor<std::pair<unsigned, python::object>> {
template <typename Array>
std::pair<unsigned, python::object> operator()(const Array& /*unused*/) const {
std::pair<unsigned, python::object> p;
p.first = sizeof(typename Array::value_type);
p.second = python::str("|u") + python::str(p.first);
return p;
}
std::pair<unsigned, python::object> operator()(const array<void>& /*unused*/) const {
return std::pair<unsigned, python::object>();
}
std::pair<unsigned, python::object> operator()(const array<mp_int>& /*unused*/) const {
std::pair<unsigned, python::object> p;
p.first = sizeof(double);
p.second = python::str("|f") + python::str(p.first);
return p;
}
std::pair<unsigned, python::object> operator()(const array<weight>& /*unused*/) const {
std::pair<unsigned, python::object> p;
p.first = sizeof(double);
p.second = python::str("|f") + python::str(p.first);
return p;
}
};
struct data_visitor : public static_visitor<python::object> {
const python::list& shapes;
const python::list& strides;
data_visitor(const python::list& sh, const python::list& st) : shapes(sh), strides(st) {}
template <typename Array>
python::object operator()(const Array& b) const {
return python::make_tuple(reinterpret_cast<uintptr_t>(b.begin()), false);
}
python::object operator()(const array<void>& /*unused*/) const {
return python::object();
}
python::object operator()(const array<mp_int>& b) const {
// cannot pass cpp_int to numpy; make new
// double array, fill it and pass it
int dim = python::len(shapes);
npy_intp shapes2[BOOST_HISTOGRAM_AXIS_LIMIT];
for (int i = 0; i < dim; ++i) {
shapes2[i] = python::extract<npy_intp>(shapes[i]);
}
PyObject *ptr = PyArray_SimpleNew(dim, shapes2, NPY_DOUBLE);
for (int i = 0; i < dim; ++i) {
PyArray_STRIDES((PyArrayObject *)ptr)[i] = python::extract<npy_intp>(strides[i]);
}
auto *buf = (double *)PyArray_DATA((PyArrayObject *)ptr);
for (int i = 0; i < b.size; ++i)
buf[i] = static_cast<double>(b[i]);
return python::object(python::handle<>(ptr));
}
};
static python::object array_interface(dynamic_histogram<> &self) {
auto &b = self.storage_.buffer_;
if (b.type_.id_ == 0) {
if (auto* pa = get<array<void>>(&b)) {
// buffer not created yet, do that now
b.template initialize<uint8_t>();
b = array<uint8_t>(pa->size);
}
python::dict d;
python::list shapes;
python::list strides;
std::size_t stride = 1;
if (b.type_.id_ == 5) {
// cannot pass cpp_int to numpy; make new
// double array, fill it and pass it
npy_intp shapes2[BOOST_HISTOGRAM_AXIS_LIMIT];
stride = sizeof(double);
d["typestr"] = python::str("|f") + python::str(stride);
for (unsigned i = 0; i < self.dim(); ++i) {
const auto s = shape(self.axis(i));
shapes2[i] = s;
shapes.append(s);
strides.append(stride);
stride *= s;
}
PyObject *ptr = PyArray_SimpleNew(self.dim(), shapes2, NPY_DOUBLE);
stride = sizeof(double);
for (unsigned i = 0; i < self.dim(); ++i) {
const auto s = shape(self.axis(i));
PyArray_STRIDES((PyArrayObject *)ptr)[i] = stride;
stride *= s;
}
double *buf = (double *)PyArray_DATA((PyArrayObject *)ptr);
for (unsigned i = 0; i < b.size_; ++i)
buf[i] = static_cast<double>(b.template at<detail::mp_int>(i));
d["shape"] = python::tuple(shapes);
d["strides"] = python::tuple(strides);
d["data"] = python::object(python::handle<>(ptr));
return d;
}
if (b.type_.id_ == 6) {
stride *= sizeof(double);
d["typestr"] = python::str("|f") + python::str(stride);
auto dtype = apply_visitor(dtype_visitor(), b);
auto stride = dtype.first;
if (get<array<weight>>(&b)) {
strides.append(stride);
stride *= 2;
shapes.append(2);
} else {
stride *= b.type_.depth_;
d["typestr"] = python::str("|u") + python::str(stride);
}
for (unsigned i = 0; i < self.dim(); ++i) {
const auto s = shape(self.axis(i));
@@ -343,7 +369,8 @@ struct storage_access {
}
d["shape"] = python::tuple(shapes);
d["strides"] = python::tuple(strides);
d["data"] = python::make_tuple(reinterpret_cast<uintptr_t>(b.ptr_), false);
d["typestr"] = dtype.second;
d["data"] = apply_visitor(data_visitor(shapes, strides), b);
return d;
}
#endif