# Related projects

## xtensor-python

The xtensor-python project provides the implementation of container types compatible with `xtensor`‘s expression system, `pyarray` and `pytensor` which effectively wrap numpy arrays, allowing operating on numpy arrays inplace.

### Example 1: Use an algorithm of the C++ library on a numpy array inplace

C++ code

    #include <numeric>                        // Standard library import for std::accumulate
    #include "pybind11/pybind11.h"            // Pybind11 import to define Python bindings
    #include "xtensor/xmath.hpp"              // xtensor import for the C++ universal functions
    #define FORCE_IMPORT_ARRAY                // numpy C api loading
    #include "xtensor-python/pyarray.hpp"     // Numpy bindings

    double sum_of_sines(xt::pyarray<double> &m)
    {
        auto sines = xt::sin(m);
        // sines does not actually hold any value
        return std::accumulate(sines.cbegin(), sines.cend(), 0.0);
    }

    PYBIND11_PLUGIN(xtensor_python_test)
    {
        xt::import_numpy();
        pybind11::module m("xtensor_python_test", "Test module for xtensor python bindings");

        m.def("sum_of_sines", sum_of_sines,
            "Sum the sines of the input values");

        return m.ptr();
    }

Python code

    Python Code

    import numpy as np
    import xtensor_python_test as xt

    a = np.arange(15).reshape(3, 5)
    s = xt.sum_of_sines(v)
    s

Outputs

    1.2853996391883833

### Example 2: Create a universal function from a C++ scalar function

C++ code

    #include "pybind11/pybind11.h"
    #define FORCE_IMPORT_ARRAY
    #include "xtensor-python/pyvectorize.hpp"
    #include <numeric>
    #include <cmath>

    namespace py = pybind11;

    double scalar_func(double i, double j)
    {
        return std::sin(i) - std::cos(j);
    }

    PYBIND11_PLUGIN(xtensor_python_test)
    {
        xt::import_numpy();
        py::module m("xtensor_python_test", "Test module for xtensor python bindings");

        m.def("vectorized_func", xt::pyvectorize(scalar_func), "");

        return m.ptr();
    }

Python code

    import numpy as np
    import xtensor_python_test as xt

    x = np.arange(15).reshape(3, 5)
    y = [1, 2, 3, 4, 5]
    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]]

## xtensor-python-cookiecutter

The xtensor-python-cookiecutter project helps extension authors create Python extension modules making use of xtensor.

It takes care of the initial work of generating a project skeleton with

- A complete setup.py compiling the extension module

A few examples included in the resulting project including

- A universal function defined from C++
- A function making use of an algorithm from the STL on a numpy array
- Unit tests
- The generation of the HTML documentation with sphinx

## xtensor-julia

The xtensor-julia project provides the implementation of container types compatible with `xtensor`‘s expression system, `jlarray` and `jltensor` which effectively wrap Julia arrays, allowing operating on Julia arrays inplace.

### Example 1: Use an algorithm of the C++ library with a Julia array

C++ code

    #include <numeric>                        // Standard library import for std::accumulate
    #include <cxx_wrap.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);
    }

    JULIA_CPP_MODULE_BEGIN(registry)
        cxx_wrap::Module mod = registry.create_module("xtensor_julia_test");
        mod.method("sum_of_sines", sum_of_sines);
    JULIA_CPP_MODULE_END

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 <cxx_wrap.hpp>
    #include "xtensor-julia/jlvectorize.hpp"

    double scalar_func(double i, double j)
    {
        return std::sin(i) - std::cos(j);
    }

    JULIA_CPP_MODULE_BEGIN(registry)
        cxx_wrap::Module mod = registry.create_module("xtensor_julia_test");
        mod.method("vectorized_func", xt::jlvectorize(scalar_func));
    JULIA_CPP_MODULE_END

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]]

## xtensor-julia-cookiecutter

The xtensor-julia-cookiecutter project helps extension authors create Julia extension modules making use of xtensor.

It takes care of the initial work of generating a project skeleton with

- A complete read-to-use Julia package

A few examples included in the resulting project including

- A numpy-style universal function defined from C++
- A function making use of an algorithm from the STL on a numpy array
- Unit tests
- The generation of the HTML documentation with sphinx

## xtensor-r

The xtensor-r project provides the implementation of container types compatible with `xtensor`‘s expression system, `rarray` and `rtensor` which effectively wrap R arrays, allowing operating on R arrays inplace.

## xtensor-blas

The xtensor-blas project is an extension to the xtensor library, offering bindings to BLAS and LAPACK libraries through cxxblas and cxxlapack from the FLENS project. `xtensor-blas` powers the `xt::linalg` functionalities, which are the counterpart to numpy’s `linalg` module.