Julia bindings for the xtensor C++ multi-dimensional array library.
Introduction¶
xtensor
is a C++ library for multi-dimensional arrays enabling numpy-style broadcasting and lazy computing.
xtensor-julia
enables inplace use of julia arrays in C++ with all the benefits from xtensor
C++ universal function and broadcasting
STL - compliant APIs.
A broad coverage of numpy APIs (see the numpy to xtensor cheat sheet).
The Julia bindings for xtensor are based on the CxxWrap.jl C++ library.
Licensing¶
We use a shared copyright model that enables all contributors to maintain the copyright on their contributions.
This software is licensed under the BSD-3-Clause license. See the LICENSE file for details.
Basic Usage¶
Example 1: Use an algorithm of the C++ library with a Julia array¶
C++ code
#include <numeric> // Standard library import for std::accumulate
#include "jlcxx/jlcxx.hpp¨ // CxxWrap import to define Julia bindings
#include "xtensor-julia/jltensor.hpp" // Import the jltensor container definition
#include "xtensor/xmath.hpp" // xtensor import for the C++ universal functions
double sum_of_sines(xt::jltensor<double, 2> m)
{
auto sines = xt::sin(m); // sines does not actually hold values.
return std::accumulate(sines.cbegin(), sines.cend(), 0.0);
}
JLCXX_MODULE define_julia_module(jlcxx::Module& mod)
{
mod.method("sum_of_sines", sum_of_sines);
}
Julia code:
using xtensor_julia_test
arr = [[1.0 2.0]
[3.0 4.0]]
s = sum_of_sines(arr)
s
Outputs
1.2853996391883833
Example 2: Create a numpy-style universal function from a C++ scalar function¶
C++ code
#include "jlcxx/jlcxx.hpp"
#include "xtensor-julia/jlvectorize.hpp"
double scalar_func(double i, double j)
{
return std::sin(i) - std::cos(j);
}
JLCXX_MODULE define_julia_module(jlcxx::Module& mod)
{
mod.method("vectorized_func", xt::jlvectorize(scalar_func));
}
Julia code:
using xtensor_julia_test
x = [[ 0.0 1.0 2.0 3.0 4.0]
[ 5.0 6.0 7.0 8.0 9.0]
[10.0 11.0 12.0 13.0 14.0]]
y = [1.0, 2.0, 3.0, 4.0, 5.0]
z = xt.vectorized_func(x, y)
z
Outputs
[[-0.540302 1.257618 1.89929 0.794764 -1.040465],
[-1.499227 0.136731 1.646979 1.643002 0.128456],
[-1.084323 -0.583843 0.45342 1.073811 0.706945]]
Arrays and tensors¶
xtensor-julia
provides two container types wrapping Julia arrays: jlarray
and jltensor
. They are the counterparts
to xarray
and xtensor
containers.
jlarray¶
Like xarray
, jlarray
has a dynamic shape. This means that one can reshape the array on the C++ side and see this
change reflected on the Julia side. jlarray
doesn’t make a copy of the shape, but reads the values each time it
is needed. Therefore, if a reference on a jlarray
is kept in the C++ code and the corresponding Julia array is then reshaped
on the Julia side, this modification will reflect in the jlarray
.
jltensor¶
Like xtensor
, jltensor
has a static stack-allocated shape. This means that the shape of the Julia array is copied into
the shape of the jltensor
upon creation. As a consequence, reshapes are not reflected across languages. However, this drawback
is offset by a more effective iteration and broadcasting.
API reference¶
Containers¶
jlarray¶
-
template<class T>
class jlarray : public xt::jlcontainer<jlarray<T>>, public xcontainer_semantic<jlarray<T>>¶ Constructors
-
inline jlarray()¶
Allocates a jlarray that holds 1 element.
-
inline jlarray(const value_type &t)¶
Allocates a jlarray with a nested initializer list.
-
inline explicit jlarray(const shape_type &shape)¶
Allocates an uninitialized jlarray with the specified shape and layout.
- Parameters
shape – the shape of the jlarray
-
inline explicit jlarray(const shape_type &shape, const_reference value)¶
Allocates a jlarray with the specified shape and layout.
Elements are initialized to the specified value.
- Parameters
shape – the shape of the jlarray
value – the value of the elements
-
inline jlarray(jl_array_t *jl)¶
Allocates a jlarray that holds 1 element.
-
inline jlarray()¶
jltensor¶
-
template<class T, std::size_t N>
class jltensor : public xt::jlcontainer<jltensor<T, N>>, public xcontainer_semantic<jltensor<T, N>>¶ Constructors
-
inline jltensor()¶
Allocates a jltensor that holds 1 element.
-
inline jltensor(nested_initializer_list_t<T, N> t)¶
Allocates a jltensor with a nested initializer list.
-
inline explicit jltensor(const shape_type &shape)¶
Allocates an uninitialized jltensor with the specified shape and layout.
- Parameters
shape – the shape of the jltensor
-
inline explicit jltensor(const shape_type &shape, const_reference value)¶
Allocates a jltensor with the specified shape and layout.
Elements are initialized to the specified value.
- Parameters
shape – the shape of the jltensor
value – the value of the elements
-
inline jltensor(jl_array_t *jl)¶
Allocates a jltensor that holds 1 element.
-
inline jltensor()¶