##// END OF EJS Templates
Added cpp_utils as subproject and removed few warnings...
Added cpp_utils as subproject and removed few warnings Signed-off-by: Alexis Jeandet <alexis.jeandet@member.fsf.org>

File last commit:

r1485:4f6ae2f1ca26
r1485:4f6ae2f1ca26
Show More
numpy_wrappers.h
265 lines | 7.0 KiB | text/x-c | CLexer
#ifndef NUMPY_WRAPPERS_H
#define NUMPY_WRAPPERS_H
#include <Data/ScalarTimeSerie.h>
#include <Data/VectorTimeSerie.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#if defined(slots) && (defined(__GNUC__) || defined(_MSC_VER) || defined(__clang__))
#pragma push_macro("slots")
#undef slots
extern "C"
{
/*
* Python 2 uses the "register" keyword, which is deprecated in C++ 11
* and forbidden in C++17.
*/
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-register"
#endif
#include <Python.h>
#include <numpy/arrayobject.h>
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
#else
#include <Python.h>
#include <numpy/arrayobject.h>
#endif
#include <assert.h>
#include <map>
#include <warnings.h>
inline int init_numpy()
{
DISABLE_WARNING_PUSH
DISABLE_WARNING_CONVERSION_NULL
import_array(); // PyError if not successful
DISABLE_WARNING_POP
return 0;
}
const static int numpy_initialized = init_numpy();
template <typename dest_type = PyObject>
struct PyObjectWrapper
{
private:
PyObject* _py_obj = nullptr;
void inc_refcount() { Py_XINCREF(_py_obj); }
void dec_refcount()
{
Py_XDECREF(_py_obj);
_py_obj = nullptr;
}
public:
PyObjectWrapper() : _py_obj { nullptr } {}
PyObjectWrapper(const PyObjectWrapper& other) : _py_obj { other._py_obj } { inc_refcount(); }
PyObjectWrapper(PyObjectWrapper&& other) : _py_obj { other._py_obj } { inc_refcount(); }
explicit PyObjectWrapper(PyObject* obj) : _py_obj { obj } { inc_refcount(); }
~PyObjectWrapper() { dec_refcount(); }
PyObjectWrapper& operator=(PyObjectWrapper&& other)
{
dec_refcount();
this->_py_obj = other._py_obj;
inc_refcount();
return *this;
}
PyObjectWrapper& operator=(const PyObjectWrapper& other)
{
dec_refcount();
this->_py_obj = other._py_obj;
inc_refcount();
return *this;
}
PyObject* py_object() { return _py_obj; }
inline dest_type* get() { return reinterpret_cast<dest_type*>(_py_obj); }
inline bool is_null() { return _py_obj == nullptr; }
};
struct NpArray_view
{
private:
PyObjectWrapper<PyArrayObject> _py_obj;
NpArray_view(const NpArray_view&& other) = delete;
public:
static bool isNpArray(PyObject* obj)
{
auto arr = reinterpret_cast<PyArrayObject*>(obj);
auto is_c_aray = obj && PyArray_Check(arr) && PyArray_ISCARRAY(arr);
return is_c_aray;
}
NpArray_view() : _py_obj { nullptr } {}
NpArray_view(const NpArray_view& other) : _py_obj { other._py_obj } {}
NpArray_view(NpArray_view&& other) : _py_obj { other._py_obj } {}
explicit NpArray_view(PyObject* obj) : _py_obj { obj }
{
assert(isNpArray(obj));
assert(PyArray_ISFLOAT(_py_obj.get()));
}
NpArray_view& operator=(const NpArray_view& other)
{
this->_py_obj = other._py_obj;
return *this;
}
NpArray_view& operator=(NpArray_view&& other)
{
this->_py_obj = other._py_obj;
return *this;
}
std::vector<std::size_t> shape()
{
std::vector<std::size_t> shape;
if (!_py_obj.is_null())
{
if (int ndim = PyArray_NDIM(_py_obj.get()); ndim > 0)
{
if (ndim < 10)
{
shape.resize(ndim);
std::copy_n(PyArray_SHAPE(_py_obj.get()), ndim, std::begin(shape));
}
}
}
return shape;
}
std::size_t ndim()
{
if (!_py_obj.is_null())
{
return static_cast<std::size_t>(PyArray_NDIM(_py_obj.get()));
}
return 0;
}
std::size_t size(std::size_t index = 0)
{
if (!_py_obj.is_null())
{
if (index < static_cast<std::size_t>(PyArray_NDIM(_py_obj.get())))
{
return PyArray_SHAPE(_py_obj.get())[index];
}
}
return 0;
}
std::size_t flat_size()
{
auto s = this->shape();
return std::accumulate(
std::cbegin(s), std::cend(s), 1, [](const auto& a, const auto& b) { return a * b; });
}
double data(std::size_t pos)
{
if (!_py_obj.is_null())
{
return reinterpret_cast<double*>(PyArray_DATA(_py_obj.get()))[pos];
}
return nan("NAN");
}
std::vector<double> to_std_vect()
{
assert(!this->_py_obj.is_null());
auto sz = flat_size();
std::vector<double> v(sz);
auto d_ptr = reinterpret_cast<double*>(PyArray_DATA(_py_obj.get()));
std::copy(d_ptr, d_ptr + sz, std::begin(v));
return v;
}
std::vector<VectorTimeSerie::raw_value_type> to_std_vect_vect()
{
auto sz = size(0);
std::vector<VectorTimeSerie::raw_value_type> v(sz);
if (sz)
{
assert(ndim() == 2);
assert(size(1) == 3);
auto d_ptr
= reinterpret_cast<VectorTimeSerie::raw_value_type*>(PyArray_DATA(_py_obj.get()));
std::copy(d_ptr, d_ptr + sz, std::begin(v));
}
return v;
}
PyObject* py_object() { return _py_obj.py_object(); }
};
struct NpArray
{
std::vector<std::size_t> shape;
std::vector<double> data;
static bool isNpArray(PyObject* obj) { return NpArray_view::isNpArray(obj); }
NpArray() = default;
explicit NpArray(PyObject* obj)
{
if (obj)
{
NpArray_view view { obj };
shape = view.shape();
data = view.to_std_vect();
}
}
inline std::size_t ndim() { return shape.size(); }
std::size_t size(std::size_t index = 0)
{
if (index < shape.size())
return shape[index];
return 0;
}
std::size_t flat_size()
{
return std::accumulate(std::cbegin(shape), std::cend(shape), 1,
[](const auto& a, const auto& b) { return a * b; });
}
// TODO temporary hack should find a way to avoid this copy
std::vector<VectorTimeSerie::raw_value_type> to_std_vect_vect()
{
auto sz = size(0);
std::vector<VectorTimeSerie::raw_value_type> v(sz);
if (sz)
{
assert(ndim() == 2);
assert(size(1) == 3);
auto d_ptr = reinterpret_cast<VectorTimeSerie::raw_value_type*>(data.data());
std::copy(d_ptr, d_ptr + sz, std::begin(v));
}
return v;
}
// TODO maybe ;)
PyObject* py_object() { return nullptr; }
};
inline int test_np_array(NpArray& arr)
{
auto shape = arr.shape;
std::cout << "len(shape)=" << shape.size() << std::endl;
std::for_each(std::cbegin(shape), std::cend(shape), [](auto sz) {
static int i = 0;
std::cout << "shape[" << i++ << "]=" << sz << std::endl;
});
auto flatsize = std::accumulate(std::cbegin(shape), std::cend(shape), 0);
for (auto i = 0; i < flatsize; i++)
{
std::cout << "data[" << i << "]=" << arr.data[i] << std::endl;
}
return 1;
}
#endif //#ifndef NUMPY_WRAPPERS_H