CARMA is a header only library providing conversions between Numpy arrays and Armadillo matrices. Examples and reference documentation can be found at carma.readthedocs.io.
CARMA provides fast bidirectional conversions between Numpy arrays and Armadillo matrices, vectors and cubes, much like RcppArmadillo does for R and Armadillo.
The library relies heavily on the impressive pybind11 library and is largely inspired by their Eigen conversion albeit with a less conservative approach to memory management. For details on pybind11 and Armadillo refer to their respective documentation.
Carma is a header only library that relies on two other header only libraries, Armadillo and Pybind11.
Both libraries are linked as submodule in the third_party
directory.
In order to achieve fast conversions the default behaviour is avoid copying both from and to Numpy whenever possible and reasonable. This allows very low overhead conversions but it impacts memory safety and requires user vigilance.
A second consideration is memory layout. Armadillo is optimised for column-major (Fortran order) memory whereas Numpy defaults to row-major (C order). The default behaviour is to automatically convert, read copy, C-order arrays to F-order arrays upon conversion to Armadillo. Users should note that the library will not convert back to C-order when returning, this has consequences for matrices and cubes.
For details see the documentation section Memory Management.
On a high level Carma provides three ways to work Numpy arrays in Armadillo:
The easiest way to use Carma is manual conversion, it gives you the most control over when to copy or not. You pass a Numpy array as an argument and/or as the return type and call the respective conversion function.
#include <armadillo>
#include <carma/carma.h>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
py::array_t<double> manual_example(py::array_t<double> & arr) {
// convert to armadillo matrix without copying.
arma::Mat<double> mat = carma::arr_to_mat<double>(arr);
// normally you do something useful here ...
arma::Mat<double> result = arma::Mat<double>(
arr.shape(0),
arr.shape(1),
arma::fill::randu
);
// convert to Numpy array and return
return carma::mat_to_arr(result);
}
#include <armadillo>
#include <carma/carma.h>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
void update_example(py::array_t<double> & arr) {
// convert to armadillo matrix without copying.
arma::Mat<double> mat = carma::arr_to_mat<double>(arr);
// normally you do something useful here with mat ...
mat += arma::Mat<double>(arr.shape(0), arr.shape(1), arma::fill::randu);
// update Numpy array buffer
carma::update_array(mat, arr);
}
#include <armadillo>
#include <carma/carma.h>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
arma::Mat<double> automatic_example(arma::Mat<double> & mat) {
// normally you do something useful here with mat ...
arma::Mat<double> rand = arma::Mat<double>(mat.n_rows, mat.n_cols, arma::fill::randu);
arma::Mat<double> result = mat + rand;
// type caster will take care of casting `result` to a Numpy array.
return result;
}
The repository contains tests, examples and CMake build instructions that can be used as an reference. For manual compilation see the documentation section Usage.
carma
has been tested with:
- armadillo-9.800.1
- pybind11-2.4.3
The repository contains tests, examples and CMake build instructions that can be used as an reference. For manual compilation see the documentation section Usage.
Compiler requirements through pybind11
- Clang/LLVM 3.3 or newer (for Apple Xcode's clang, this is 5.0.0 or newer)
- GCC 4.8 or newer
- Microsoft Visual Studio 2015 Update 3 or newer
- Intel C++ compiler 17 or newer
- Cygwin/GCC (tested on 2.5.1)
This project was created by Ralph Urlus. Significant improvements to the project have been contributed by Pascal H.
carma is provided under a Apache 2.0 license that can be found in the LICENSE file. By using, distributing, or contributing to this project, you agree to the terms and conditions of this license.