From c3dabfc853269ffc52f4951debee65f2d4657472 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Tue, 11 Oct 2022 09:50:15 +0200 Subject: [PATCH] Added manual Armadillo - Numpy converters --- src/lasp/pybind11/arma_npy.h | 132 +++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/lasp/pybind11/arma_npy.h diff --git a/src/lasp/pybind11/arma_npy.h b/src/lasp/pybind11/arma_npy.h new file mode 100644 index 0000000..4fe8920 --- /dev/null +++ b/src/lasp/pybind11/arma_npy.h @@ -0,0 +1,132 @@ +#pragma once +#include "lasp_mathtypes.h" +#include +#include +#include + +namespace py = pybind11; + +template +using pyarray = py::array_t; +using dpyarray = pyarray; + + +/** + * @brief Convert Armadillo column vector to Numpy 1D array + * + * @tparam T Type (double, d, c, etc) + * @param data Input Armadillo array + * + * @return Numpy array with copied data + */ +template py::array_t ColToNpy(const arma::Col &data) { + + const us Tsize = sizeof(T); + + const auto nrows = static_cast(data.n_rows); + + const us size = nrows; + + py::array_t result({nrows}, {Tsize}); + + // Copy over memory + if (size > 0) { + memcpy(result.mutable_data(0), data.memptr(), sizeof(T) * nrows); + } + + return result; +} + +/** + * @brief Convert Armadillo 2D array Numpy 2D array + * + * @tparam T Type (double, d, c, etc) + * @param data Input Armadillo array + * + * @return Numpy array with copied data + */ +template py::array_t MatToNpy(const arma::Mat &data) { + + const us Tsize = sizeof(T); + + const auto nrows = static_cast(data.n_rows); + const auto ncols = static_cast(data.n_cols); + + const us size = nrows; + + py::array_t result({nrows, ncols}, {Tsize, nrows * Tsize}); + + // Copy over memory + if (size > 0) { + memcpy(result.mutable_data(0, 0), data.memptr(), sizeof(T) * nrows * ncols); + } + + return result; +} + +/** + * @brief Convert Armadillo Cube to Numpy 3D array + * + * @tparam T Type (double, d, c, etc) + * @param data Input Armadillo Array + * + * @return Numpy array with copied data + */ +template py::array_t CubeToNpy(const arma::Cube &data) { + + const us Tsize = sizeof(T); + + const auto nrows = static_cast(data.n_rows); + const auto ncols = static_cast(data.n_cols); + const auto nslices = static_cast(data.n_slices); + + const us size = nrows * ncols * nslices; + + py::array_t result({nrows, ncols, nslices}, + {Tsize, nrows * Tsize, nrows * ncols * Tsize}); + + // Copy over memory + if (size > 0) { + memcpy(result.mutable_data(0, 0, 0), data.memptr(), + sizeof(T) * nrows * ncols * nslices); + } + + return result; +} + +/// BACK converters + +/** + * @brief Wrap Numpy array to 2D Armadillo Mat + * + * @tparam T Type + * @tparam copy Whether to copy the data. If true, creates a copy + * @param data The Numpy array to convert + * + * @return Mat instance + */ +template +arma::Mat NpyToMat(pyarray data) { + if (data.ndim() != 2) { + throw std::runtime_error("Expects a 2D array"); + } + return arma::Mat(data.mutable_data(0,0), data.shape(0), data.shape(1), copy); +} + +/** + * @brief Wrap Numpy array to 1D Armadillo column vector + * + * @tparam T Type + * @tparam copy Whether to copy the data. If true, creates a copy + * @param data The Numpy array to convert + * + * @return Armadillo column instance + */ +template +arma::Mat NpyToCol(pyarray data) { + if (data.ndim() != 1) { + throw std::runtime_error("Expects a 1D array"); + } + return arma::Col(data.mutable_data(0), data.size(), copy); +} +