| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,15 +11,16 @@ steps: | |||
| 11 | 11 | mkdir build | |
| 12 | 12 | cd build | |
| 13 | 13 | cmake -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -DPYTHON_EXECUTABLE=`which python` -DDOWNLOAD_GTEST=ON $(Build.SourcesDirectory) | |
| 14 | + make install | ||
| 14 | 15 | displayName: Configure xtensor-python | |
| 15 | 16 | workingDirectory: $(Build.BinariesDirectory) | |
| 16 | - | ||
| 17 | + | ||
| 17 | 18 | - script: | | |
| 18 | 19 | source activate xtensor-python | |
| 19 | 20 | make -j2 test_xtensor_python | |
| 20 | 21 | displayName: Build xtensor-python | |
| 21 | 22 | workingDirectory: $(Build.BinariesDirectory)/build | |
| 22 | - | ||
| 23 | + | ||
| 23 | 24 | - script: | | |
| 24 | 25 | source activate xtensor-python | |
| 25 | 26 | cd test | |
@@ -32,3 +33,19 @@ steps: | |||
| 32 | 33 | py.test -s | |
| 33 | 34 | displayName: Test xtensor-python (Python) | |
| 34 | 35 | workingDirectory: $(Build.SourcesDirectory) | |
| 36 | + | ||
| 37 | + - script: | | ||
| 38 | + source activate xtensor-python | ||
| 39 | + cmake . -DPYTHON_EXECUTABLE=`which python` | ||
| 40 | + cmake --build . | ||
| 41 | + python example.py | ||
| 42 | + displayName: Example - readme 1 | ||
| 43 | + workingDirectory: $(Build.SourcesDirectory)/docs/source/examples/readme_example_1 | ||
| 44 | + | ||
| 45 | + - script: | | ||
| 46 | + source activate xtensor-python | ||
| 47 | + cmake . -DPYTHON_EXECUTABLE=`which python` | ||
| 48 | + cmake --build . | ||
| 49 | + python example.py | ||
| 50 | + displayName: Example - SFINAE | ||
| 51 | + workingDirectory: $(Build.SourcesDirectory)/docs/source/examples/sfinae | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -49,10 +49,10 @@ Both containers enable the numpy-style APIs of xtensor (see [the numpy to xtenso | |||
| 49 | 49 | ||
| 50 | 50 | ```cpp | |
| 51 | 51 | #include <numeric> // Standard library import for std::accumulate | |
| 52 | - #include "pybind11/pybind11.h" // Pybind11 import to define Python bindings | ||
| 53 | - #include "xtensor/xmath.hpp" // xtensor import for the C++ universal functions | ||
| 52 | + #include <pybind11/pybind11.h> // Pybind11 import to define Python bindings | ||
| 53 | + #include <xtensor/xmath.hpp> // xtensor import for the C++ universal functions | ||
| 54 | 54 | #define FORCE_IMPORT_ARRAY | |
| 55 | - #include "xtensor-python/pyarray.hpp" // Numpy bindings | ||
| 55 | + #include <xtensor-python/pyarray.hpp> // Numpy bindings | ||
| 56 | 56 | ||
| 57 | 57 | double sum_of_sines(xt::pyarray<double>& m) | |
| 58 | 58 | { | |
@@ -77,7 +77,7 @@ import xtensor_python_test as xt | |||
| 77 | 77 | ||
| 78 | 78 | v = np.arange(15).reshape(3, 5) | |
| 79 | 79 | s = xt.sum_of_sines(v) | |
| 80 | - s | ||
| 80 | + print(s) | ||
| 81 | 81 | ``` | |
| 82 | 82 | ||
| 83 | 83 | **Outputs** | |
@@ -86,14 +86,22 @@ s | |||
| 86 | 86 | 1.2853996391883833 | |
| 87 | 87 | ``` | |
| 88 | 88 | ||
| 89 | + **Working example** | ||
| 90 | + | ||
| 91 | + Get the working example here: | ||
| 92 | + | ||
| 93 | + * [`CMakeLists.txt`](docs/source/examples/readme_example_1/CMakeLists.txt) | ||
| 94 | + * [`main.cpp`](docs/source/examples/readme_example_1/main.cpp) | ||
| 95 | + * [`example.py`](docs/source/examples/readme_example_1/example.py) | ||
| 96 | + | ||
| 89 | 97 | ### Example 2: Create a universal function from a C++ scalar function | |
| 90 | 98 | ||
| 91 | 99 | **C++ code** | |
| 92 | 100 | ||
| 93 | 101 | ```cpp | |
| 94 | - #include "pybind11/pybind11.h" | ||
| 102 | + #include <pybind11/pybind11.h> | ||
| 95 | 103 | #define FORCE_IMPORT_ARRAY | |
| 96 | - #include "xtensor-python/pyvectorize.hpp" | ||
| 104 | + #include <xtensor-python/pyvectorize.hpp> | ||
| 97 | 105 | #include <numeric> | |
| 98 | 106 | #include <cmath> | |
| 99 | 107 | ||
@@ -122,7 +130,7 @@ import xtensor_python_test as xt | |||
| 122 | 130 | x = np.arange(15).reshape(3, 5) | |
| 123 | 131 | y = [1, 2, 3, 4, 5] | |
| 124 | 132 | z = xt.vectorized_func(x, y) | |
| 125 | - z | ||
| 133 | + print(z) | ||
| 126 | 134 | ``` | |
| 127 | 135 | ||
| 128 | 136 | **Outputs** | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,100 @@ | |||
| 1 | + | ||
| 2 | + **************** | ||
| 3 | + (CMake) Examples | ||
| 4 | + **************** | ||
| 5 | + | ||
| 6 | + Basic example (from readme) | ||
| 7 | + =========================== | ||
| 8 | + | ||
| 9 | + Consider the following C++ code: | ||
| 10 | + | ||
| 11 | + :download:`main.cpp <examples/readme_example_1/main.cpp>` | ||
| 12 | + | ||
| 13 | + .. literalinclude:: examples/readme_example_1/main.cpp | ||
| 14 | + :language: cpp | ||
| 15 | + | ||
| 16 | + There are several options to build the module, | ||
| 17 | + whereby we will CMake here with the following ``CMakeLists.txt``: | ||
| 18 | + | ||
| 19 | + :download:`CMakeLists.txt <examples/readme_example_1/CMakeLists.txt>` | ||
| 20 | + | ||
| 21 | + .. literalinclude:: examples/readme_example_1/CMakeLists.txt | ||
| 22 | + :language: cmake | ||
| 23 | + | ||
| 24 | + Then we can test the module: | ||
| 25 | + | ||
| 26 | + :download:`example.py <examples/readme_example_1/example.py>` | ||
| 27 | + | ||
| 28 | + .. literalinclude:: examples/readme_example_1/example.py | ||
| 29 | + :language: cmake | ||
| 30 | + | ||
| 31 | + .. note:: | ||
| 32 | + | ||
| 33 | + Since we did not install the module, | ||
| 34 | + we should compile and run the example from the same folder. | ||
| 35 | + To install, please consult | ||
| 36 | + `this pybind11 / CMake example <https://github.com/pybind/cmake_example>`_. | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + Type restriction with SFINAE | ||
| 40 | + ============================ | ||
| 41 | + | ||
| 42 | + .. seealso:: | ||
| 43 | + | ||
| 44 | + `Medium post by Johan Mabille <https://medium.com/@johan.mabille/designing-language-bindings-with-xtensor-f32aa0f20db>`__ | ||
| 45 | + This example covers "Option 4". | ||
| 46 | + | ||
| 47 | + In this example we will design a module with a function that accepts an ``xt::xtensor`` as argument, | ||
| 48 | + but in such a way that an ``xt::pyxtensor`` can be accepted in the Python module. | ||
| 49 | + This is done by having a templated function | ||
| 50 | + | ||
| 51 | + .. code-block:: cpp | ||
| 52 | + | ||
| 53 | + template <class T> | ||
| 54 | + void times_dimension(T& t); | ||
| 55 | + | ||
| 56 | + As this might be a bit too permissive for your liking, we will show you how to limit the | ||
| 57 | + scope to *xtensor* types, and allow other overloads using the principle of SFINAE | ||
| 58 | + (Substitution Failure Is Not An Error). | ||
| 59 | + In particular: | ||
| 60 | + | ||
| 61 | + :download:`mymodule.hpp <examples/sfinae/mymodule.hpp>` | ||
| 62 | + | ||
| 63 | + .. literalinclude:: examples/sfinae/mymodule.hpp | ||
| 64 | + :language: cpp | ||
| 65 | + | ||
| 66 | + Consequently from C++, the interaction with the module's function is trivial | ||
| 67 | + | ||
| 68 | + :download:`main.cpp <examples/sfinae/main.cpp>` | ||
| 69 | + | ||
| 70 | + .. literalinclude:: examples/sfinae/main.cpp | ||
| 71 | + :language: cpp | ||
| 72 | + | ||
| 73 | + For the Python module we just have to specify the template to be | ||
| 74 | + ``xt::pyarray`` or ``xt::pytensor``. E.g. | ||
| 75 | + | ||
| 76 | + :download:`src/python.cpp <examples/sfinae/python.cpp>` | ||
| 77 | + | ||
| 78 | + .. literalinclude:: examples/sfinae/python.cpp | ||
| 79 | + :language: cpp | ||
| 80 | + | ||
| 81 | + We will again use CMake to compile, with the following ``CMakeLists.txt``: | ||
| 82 | + | ||
| 83 | + :download:`CMakeLists.txt <examples/sfinae/CMakeLists.txt>` | ||
| 84 | + | ||
| 85 | + .. literalinclude:: examples/sfinae/CMakeLists.txt | ||
| 86 | + :language: cmake | ||
| 87 | + | ||
| 88 | + Then we can test the module: | ||
| 89 | + | ||
| 90 | + :download:`example.py <examples/readme_example_1/example.py>` | ||
| 91 | + | ||
| 92 | + .. literalinclude:: examples/readme_example_1/example.py | ||
| 93 | + :language: cmake | ||
| 94 | + | ||
| 95 | + .. note:: | ||
| 96 | + | ||
| 97 | + Since we did not install the module, | ||
| 98 | + we should compile and run the example from the same folder. | ||
| 99 | + To install, please consult | ||
| 100 | + `this pybind11 / CMake example <https://github.com/pybind/cmake_example>`_. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,13 @@ | |||
| 1 | + cmake_minimum_required(VERSION 3.1..3.19) | ||
| 2 | + | ||
| 3 | + project(mymodule) | ||
| 4 | + | ||
| 5 | + find_package(pybind11 CONFIG REQUIRED) | ||
| 6 | + find_package(xtensor REQUIRED) | ||
| 7 | + find_package(xtensor-python REQUIRED) | ||
| 8 | + find_package(Python REQUIRED COMPONENTS NumPy) | ||
| 9 | + | ||
| 10 | + pybind11_add_module(mymodule main.cpp) | ||
| 11 | + target_link_libraries(mymodule PUBLIC pybind11::module xtensor-python Python::NumPy) | ||
| 12 | + | ||
| 13 | + target_compile_definitions(mymodule PRIVATE VERSION_INFO=0.1.0) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,6 @@ | |||
| 1 | + import mymodule | ||
| 2 | + import numpy as np | ||
| 3 | + | ||
| 4 | + a = np.array([1, 2, 3]) | ||
| 5 | + assert np.isclose(np.sum(np.sin(a)), mymodule.sum_of_sines(a)) | ||
| 6 | + | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,18 @@ | |||
| 1 | + #include <numeric> | ||
| 2 | + #include <xtensor.hpp> | ||
| 3 | + #include <pybind11/pybind11.h> | ||
| 4 | + #define FORCE_IMPORT_ARRAY | ||
| 5 | + #include <xtensor-python/pyarray.hpp> | ||
| 6 | + | ||
| 7 | + double sum_of_sines(xt::pyarray<double>& m) | ||
| 8 | + { | ||
| 9 | + auto sines = xt::sin(m); // sines does not actually hold values. | ||
| 10 | + return std::accumulate(sines.begin(), sines.end(), 0.0); | ||
| 11 | + } | ||
| 12 | + | ||
| 13 | + PYBIND11_MODULE(mymodule, m) | ||
| 14 | + { | ||
| 15 | + xt::import_numpy(); | ||
| 16 | + m.doc() = "Test module for xtensor python bindings"; | ||
| 17 | + m.def("sum_of_sines", sum_of_sines, "Sum the sines of the input values"); | ||
| 18 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,16 @@ | |||
| 1 | + cmake_minimum_required(VERSION 3.1..3.19) | ||
| 2 | + | ||
| 3 | + project(mymodule) | ||
| 4 | + | ||
| 5 | + find_package(pybind11 CONFIG REQUIRED) | ||
| 6 | + find_package(xtensor REQUIRED) | ||
| 7 | + find_package(xtensor-python REQUIRED) | ||
| 8 | + find_package(Python REQUIRED COMPONENTS NumPy) | ||
| 9 | + | ||
| 10 | + pybind11_add_module(mymodule python.cpp) | ||
| 11 | + target_link_libraries(mymodule PUBLIC pybind11::module xtensor-python Python::NumPy) | ||
| 12 | + | ||
| 13 | + target_compile_definitions(mymodule PRIVATE VERSION_INFO=0.1.0) | ||
| 14 | + | ||
| 15 | + add_executable(myexec main.cpp) | ||
| 16 | + target_link_libraries(myexec PUBLIC xtensor) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,8 @@ | |||
| 1 | + import mymodule | ||
| 2 | + import numpy as np | ||
| 3 | + | ||
| 4 | + a = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64) | ||
| 5 | + b = np.array(a, copy=True) | ||
| 6 | + mymodule.times_dimension(b) # changing in-place! | ||
| 7 | + assert np.allclose(2 * a, b) | ||
| 8 | + | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,10 @@ | |||
| 1 | + #include "mymodule.hpp" | ||
| 2 | + #include <xtensor/xio.hpp> | ||
| 3 | + | ||
| 4 | + int main() | ||
| 5 | + { | ||
| 6 | + xt::xtensor<size_t, 2> a = xt::arange<size_t>(2 * 3).reshape({2, 3}); | ||
| 7 | + mymodule::times_dimension(a); | ||
| 8 | + std::cout << a << std::endl; | ||
| 9 | + return 0; | ||
| 10 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,32 @@ | |||
| 1 | + #include <xtensor/xtensor.hpp> | ||
| 2 | + | ||
| 3 | + namespace mymodule { | ||
| 4 | + | ||
| 5 | + template <class T> | ||
| 6 | + struct is_std_vector | ||
| 7 | + { | ||
| 8 | + static const bool value = false; | ||
| 9 | + }; | ||
| 10 | + | ||
| 11 | + template <class T> | ||
| 12 | + struct is_std_vector<std::vector<T> > | ||
| 13 | + { | ||
| 14 | + static const bool value = true; | ||
| 15 | + }; | ||
| 16 | + | ||
| 17 | + // any xtensor object | ||
| 18 | + template <class T, std::enable_if_t<xt::is_xexpression<T>::value, bool> = true> | ||
| 19 | + void times_dimension(T& t) | ||
| 20 | + { | ||
| 21 | + using value_type = typename T::value_type; | ||
| 22 | + t *= (value_type)(t.dimension()); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + // an std::vector | ||
| 26 | + template <class T, std::enable_if_t<is_std_vector<T>::value, bool> = true> | ||
| 27 | + void times_dimension(T& t) | ||
| 28 | + { | ||
| 29 | + // do nothing | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments