From 131729cd9a638a2a4c33c83f9cd757cce1a62eba Mon Sep 17 00:00:00 2001 From: Tom de Geus Date: Sat, 9 Nov 2019 16:57:57 +0100 Subject: [PATCH] Adding examples (full-working) --- docs/source/examples.rst | 52 ++++++++++++++++++++++ docs/source/examples/sfinae/CMakeLists.txt | 32 +++++++++++++ docs/source/examples/sfinae/main.cpp | 9 ++++ docs/source/examples/sfinae/src/foobar.hpp | 27 +++++++++++ docs/source/examples/sfinae/src/python.cpp | 19 ++++++++ docs/source/index.rst | 10 ++--- 6 files changed, 144 insertions(+), 5 deletions(-) create mode 100644 docs/source/examples.rst create mode 100644 docs/source/examples/sfinae/CMakeLists.txt create mode 100644 docs/source/examples/sfinae/main.cpp create mode 100644 docs/source/examples/sfinae/src/foobar.hpp create mode 100644 docs/source/examples/sfinae/src/python.cpp diff --git a/docs/source/examples.rst b/docs/source/examples.rst new file mode 100644 index 0000000..02d192e --- /dev/null +++ b/docs/source/examples.rst @@ -0,0 +1,52 @@ + +******** +Examples +******** + +.. seealso:: + + `Medium post by Johan Mabille `__ + +Option 4: type restriction with SFINAE +====================================== + +In this example we will design a module with a function that accepts an ``xt::xtensor`` as argument, but in such a way that an ``xt::pyxtensor`` can be accepted in the Python module. We will achieve this with the principle of SFINAE (Substitution Failure Is Not An Error). + +Our example has the following file-structure. + +.. code-block:: none + + examples/sfinae + |- src + | |- foobar.hpp + | |- python.cpp + |- CMakeLists.txt + |- main.cpp + +The module has one function that accepts an ``xt::xtensor`` as argument: + +:download:`src/foobar.hpp ` + +.. literalinclude:: examples/sfinae/src/foobar.hpp + :language: cpp + +Consequently from C++, the interaction with the module's function is trivial + +:download:`main.cpp ` + +.. literalinclude:: examples/sfinae/main.cpp + :language: cpp + +From the Python module, we will add an additional overload to the template + +:download:`src/python.cpp ` + +.. literalinclude:: examples/sfinae/src/python.cpp + :language: cpp + +There are several options to build the module. Using cmake we can use the following ``CMakeLists.txt``: + +:download:`CMakeLists.txt ` + +.. literalinclude:: examples/sfinae/CMakeLists.txt + :language: cmake diff --git a/docs/source/examples/sfinae/CMakeLists.txt b/docs/source/examples/sfinae/CMakeLists.txt new file mode 100644 index 0000000..67120ad --- /dev/null +++ b/docs/source/examples/sfinae/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.1) + +project(foobar) + +find_package(xtl REQUIRED) +find_package(xtensor REQUIRED) +find_package(pybind11 REQUIRED) +find_package(xtensor-python REQUIRED) + +add_library(foobar src/python.cpp) + +if(MSVC) + target_compile_options(foobar PRIVATE /EHsc /MP /bigobj) + set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO) +endif() + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR + CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR + (CMAKE_CXX_COMPILER_ID MATCHES "Intel" AND NOT WIN32)) + target_compile_options(foobar PRIVATE -march=native -std=c++14) +endif() + +target_link_libraries(foobar + PRIVATE + pybind11::pybind11 + xtensor + xtensor-python) + +set_target_properties(foobar + PROPERTIES + PREFIX "${PYTHON_MODULE_PREFIX}" + SUFFIX "${PYTHON_MODULE_EXTENSION}") diff --git a/docs/source/examples/sfinae/main.cpp b/docs/source/examples/sfinae/main.cpp new file mode 100644 index 0000000..94ab07b --- /dev/null +++ b/docs/source/examples/sfinae/main.cpp @@ -0,0 +1,9 @@ +#include "src/foobar.hpp" + +int main() +{ + xt::xtensor a = xt::arange(2 * 3).reshape({2, 3}); + foobar::compute(a); + std::cout << a << std::endl; + return 0; +} diff --git a/docs/source/examples/sfinae/src/foobar.hpp b/docs/source/examples/sfinae/src/foobar.hpp new file mode 100644 index 0000000..4e32af5 --- /dev/null +++ b/docs/source/examples/sfinae/src/foobar.hpp @@ -0,0 +1,27 @@ +#include +#include + +namespace foobar { + +template +struct is_tensor : std::false_type +{ +}; + +template +struct is_tensor> : std::true_type +{ +}; + +template class C, class T> +using check_constraints = std::enable_if_t::value, bool>; + +template class C = is_tensor, + check_constraints = true> +void compute(T& t) +{ + using value_type = typename T::value_type; + t *= (value_type)(2); +} + +} diff --git a/docs/source/examples/sfinae/src/python.cpp b/docs/source/examples/sfinae/src/python.cpp new file mode 100644 index 0000000..3cd7334 --- /dev/null +++ b/docs/source/examples/sfinae/src/python.cpp @@ -0,0 +1,19 @@ +#include +#define FORCE_IMPORT_ARRAY +#include + +namespace foobar { + +template +struct is_tensor> : std::true_type +{ +}; + +} + +PYBIND11_MODULE(foobar, m) +{ + xt::import_numpy(); + + m.def("compute", &foobar::compute>); +} diff --git a/docs/source/index.rst b/docs/source/index.rst index 950559f..2412e67 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -16,7 +16,7 @@ What are ``xtensor`` and ``xtensor-python``? - ``xtensor`` is a C++ library for multi-dimensional arrays enabling numpy-style broadcasting and lazy computing. - ``xtensor-python`` enables inplace use of numpy arrays with all the benefits from ``xtensor`` - - C++ universal functions and broadcasting + - C++ universal functions and broadcasting - STL - compliant APIs. @@ -54,7 +54,6 @@ This software is licensed under the BSD-3-Clause license. See the LICENSE file f installation - .. toctree:: :caption: USAGE :maxdepth: 2 @@ -63,6 +62,7 @@ This software is licensed under the BSD-3-Clause license. See the LICENSE file f array_tensor numpy_capi cookiecutter + examples .. toctree:: :caption: API REFERENCE @@ -78,7 +78,7 @@ This software is licensed under the BSD-3-Clause license. See the LICENSE file f .. _NumPy: http://www.numpy.org .. _`Buffer Protocol`: https://docs.python.org/3/c-api/buffer.html -.. _`numpy to xtensor cheat sheet`: http://xtensor.readthedocs.io/en/latest/numpy.html +.. _`numpy to xtensor cheat sheet`: http://xtensor.readthedocs.io/en/latest/numpy.html .. _xtensor: https://github.com/QuantStack/xtensor -.. _pybind11: https://github.com/pybind/pybind11 -.. _xtensor-python-cookiecutter: https://github.com/QuantStack/xtensor-python-cookiecutter +.. _pybind11: https://github.com/pybind/pybind11 +.. _xtensor-python-cookiecutter: https://github.com/QuantStack/xtensor-python-cookiecutter