pax_global_header00006660000000000000000000000064131465513640014522gustar00rootroot0000000000000052 comment=5dd44aa0a146c2e6910a3dd112bf4ab544ee4c41 xtensor-0.10.11/000077500000000000000000000000001314655136400133645ustar00rootroot00000000000000xtensor-0.10.11/.appveyor.yml000066400000000000000000000022161314655136400160330ustar00rootroot00000000000000build: false os: Visual Studio 2015 platform: - x64 - x86 environment: MINICONDA: C:\xtensor-conda matrix: - COLUMN_MAJOR_LAYOUT: OFF - COLUMN_MAJOR_LAYOUT: ON matrix: allow_failures: - COLUMN_MAJOR_LAYOUT: ON init: - "ECHO %MINICONDA%" - C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\vcvarsall.bat %PLATFORM% - ps: if($env:Platform -eq "x64"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe' C:\Miniconda.exe; echo "Done"} - ps: if($env:Platform -eq "x86"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86.exe' C:\Miniconda.exe; echo "Done"} - cmd: C:\Miniconda.exe /S /D=C:\xtensor-conda - "set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%MINICONDA%\\Library\\bin;%PATH%" install: - conda config --set always_yes yes --set changeps1 no - conda update -q conda - conda info -a - conda install gtest cmake -c conda-forge - cmake -G "NMake Makefiles" -D CMAKE_INSTALL_PREFIX=%MINICONDA%\\LIBRARY -DBUILD_TESTS=ON -DDEFAULT_COLUMN_MAJOR=%COLUMN_MAJOR_LAYOUT% . - nmake test_xtensor - cd test build_script: - .\test_xtensor xtensor-0.10.11/.gitignore000066400000000000000000000010341314655136400153520ustar00rootroot00000000000000# Prerequisites *.d # Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app # Vim tmp files *.swp # Build directory build/ # Test build artefacts test/test_xtensor test/CMakeCache.txt test/Makefile test/CMakeFiles/ test/cmake_install.cmake # Documentation build artefacts docs/CMakeCache.txt docs/xml/ docs/build/ # Jupyter artefacts .ipynb_checkpoints/ # Generated files *.pc xtensor-0.10.11/.travis.yml000066400000000000000000000060231314655136400154760ustar00rootroot00000000000000language: cpp dist: precise matrix: include: - os: linux addons: apt: sources: - ubuntu-toolchain-r-test packages: - g++-4.9 env: COMPILER=gcc GCC=4.9 - os: linux addons: apt: sources: - ubuntu-toolchain-r-test packages: - g++-5 env: COMPILER=gcc GCC=5 - os: linux addons: apt: sources: - ubuntu-toolchain-r-test packages: - g++-6 env: COMPILER=gcc GCC=6 - os: linux addons: apt: sources: - ubuntu-toolchain-r-test packages: - g++-6 env: COMPILER=gcc GCC=6 BOUND_CHECKS=1 - os: linux addons: apt: sources: - ubuntu-toolchain-r-test - llvm-toolchain-precise-3.6 packages: - clang-3.6 env: COMPILER=clang CLANG=3.6 - os: linux addons: apt: sources: - ubuntu-toolchain-r-test - llvm-toolchain-precise-3.7 packages: - clang-3.7 env: COMPILER=clang CLANG=3.7 - os: linux addons: apt: sources: - ubuntu-toolchain-r-test - llvm-toolchain-precise-3.8 packages: - clang-3.8 env: COMPILER=clang CLANG=3.8 - os: linux addons: apt: sources: - ubuntu-toolchain-r-test - llvm-toolchain-precise-3.9 packages: - clang-3.9 env: COMPILER=clang CLANG=3.9 - os: osx osx_image: xcode8 compiler: clang env: global: - MINCONDA_VERSION="latest" - MINCONDA_LINUX="Linux-x86_64" - MINCONDA_OSX="MacOSX-x86_64" before_install: - | # Configure build variables if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then if [[ "$COMPILER" == "gcc" ]]; then export CXX=g++-$GCC CC=gcc-$GCC; fi if [[ "$COMPILER" == "clang" ]]; then export CXX=clang++-$CLANG CC=clang-$CLANG; fi elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export CXX=clang++ CC=clang; fi install: # Define the version of miniconda to download - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then MINCONDA_OS=$MINCONDA_LINUX; elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then MINCONDA_OS=$MINCONDA_OSX; fi - wget "http://repo.continuum.io/miniconda/Miniconda3-$MINCONDA_VERSION-$MINCONDA_OS.sh" -O miniconda.sh; - bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH" - hash -r - conda config --set always_yes yes --set changeps1 no - conda update -q conda - conda install gtest cmake -c conda-forge # Testing - mkdir build - cd build - if [[ "$BOUND_CHECKS" == 1 ]]; then cmake -DXTENSOR_ENABLE_ASSERT=ON -DDOWNLOAD_GTEST=ON ..; else cmake -DBUILD_TESTS=ON ..; fi - make -j2 test_xtensor - cd test script: - ./test_xtensor xtensor-0.10.11/CMakeLists.txt000066400000000000000000000127551314655136400161360ustar00rootroot00000000000000############################################################################ # Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht # # # # Distributed under the terms of the BSD 3-Clause License. # # # # The full license is in the file LICENSE, distributed with this software. # ############################################################################ cmake_minimum_required(VERSION 3.1) project(xtensor) set(XTENSOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) # Versionning # =========== file(STRINGS "${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_config.hpp" xtensor_version_defines REGEX "#define XTENSOR_VERSION_(MAJOR|MINOR|PATCH)") foreach(ver ${xtensor_version_defines}) if(ver MATCHES "#define XTENSOR_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$") set(XTENSOR_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") endif() endforeach() set(${PROJECT_NAME}_VERSION ${XTENSOR_VERSION_MAJOR}.${XTENSOR_VERSION_MINOR}.${XTENSOR_VERSION_PATCH}) message(STATUS "xtensor v${${PROJECT_NAME}_VERSION}") # Build # ===== set(XTENSOR_HEADERS ${XTENSOR_INCLUDE_DIR}/xtensor/xadapt.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xarray.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xassign.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xaxis_iterator.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xbroadcast.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xbuffer_adaptor.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xbuilder.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xcomplex.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xcontainer.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xcsv.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xeval.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xexception.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xexpression.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xfunction.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xfunctorview.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xgenerator.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xindexview.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xinfo.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xio.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xiterable.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xiterator.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xlayout.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xmath.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xmissing.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xnoalias.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xoffsetview.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xoperation.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xoptional.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xrandom.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xreducer.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xscalar.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xsemantic.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xstridedview.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xslice.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xstorage.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xstrides.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xtensor.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_config.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_forward.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xutils.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xvectorize.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xview.hpp ${XTENSOR_INCLUDE_DIR}/xtensor/xview_utils.hpp ) OPTION(XTENSOR_ENABLE_ASSERT "xtensor bound check" OFF) OPTION(BUILD_TESTS "xtensor test suite" OFF) OPTION(BUILD_BENCHMARK "xtensor benchmark" OFF) OPTION(DOWNLOAD_GTEST "build gtest from downloaded sources" OFF) OPTION(DEFAULT_COLUMN_MAJOR "set default layout to column major" OFF) if(DOWNLOAD_GTEST OR GTEST_SRC_DIR) set(BUILD_TESTS ON) endif() if(XTENSOR_ENABLE_ASSERT) add_definitions(-DXTENSOR_ENABLE_ASSERT) endif() if(DEFAULT_COLUMN_MAJOR) add_definitions(-DDEFAULT_LAYOUT=layout_type::column_major) endif() if(BUILD_TESTS) add_subdirectory(test) endif() if(BUILD_BENCHMARK) add_subdirectory(benchmark) endif() # Installation # ============ include(GNUInstallDirs) include(CMakePackageConfigHelpers) install(FILES ${XTENSOR_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xtensor) set(XTENSOR_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for xtensorConfig.cmake") configure_package_config_file(${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION ${XTENSOR_CMAKECONFIG_INSTALL_DIR}) # xtensor is header-only and does not depend on the architecture. # Remove CMAKE_SIZEOF_VOID_P from xtensorConfigVersion.cmake so that an xtensorConfig.cmake # generated for a 64 bit target can be used for 32 bit targets and vice versa. set(_XTENSOR_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) unset(CMAKE_SIZEOF_VOID_P) write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${${PROJECT_NAME}_VERSION} COMPATIBILITY AnyNewerVersion) set(CMAKE_SIZEOF_VOID_P ${_XTENSOR_CMAKE_SIZEOF_VOID_P}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake DESTINATION ${XTENSOR_CMAKECONFIG_INSTALL_DIR}) configure_file(${PROJECT_NAME}.pc.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") xtensor-0.10.11/LICENSE000066400000000000000000000027461314655136400144020ustar00rootroot00000000000000Copyright (c) 2016, Johan Mabille and Sylvain Corlay All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. xtensor-0.10.11/README.md000066400000000000000000000236431314655136400146530ustar00rootroot00000000000000# ![xtensor](http://quantstack.net/assets/images/xtensor.svg) [![Travis](https://travis-ci.org/QuantStack/xtensor.svg?branch=master)](https://travis-ci.org/QuantStack/xtensor) [![Appveyor](https://ci.appveyor.com/api/projects/status/quf1hllkedr0rxbk?svg=true)](https://ci.appveyor.com/project/QuantStack/xtensor) [![Documentation Status](http://readthedocs.org/projects/xtensor/badge/?version=latest)](https://xtensor.readthedocs.io/en/latest/?badge=latest) [![Binder](https://img.shields.io/badge/launch-binder-brightgreen.svg)](http://mybinder.org/repo/QuantStack/xtensor/notebooks/notebooks/xtensor.ipynb) [![Join the Gitter Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/QuantStack/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Multi-dimensional arrays with broadcasting and lazy computing. ## Introduction `xtensor` is a C++ library meant for numerical analysis with multi-dimensional array expressions. `xtensor` provides - an extensible expression system enabling **lazy broadcasting**. - an API following the idioms of the **C++ standard library**. - tools to manipulate array expressions and build upon `xtensor`. Containers of `xtensor` are inspired by [NumPy](http://www.numpy.org), the Python array programming library. **Adaptors** for existing data structures to be plugged into our expression system can easily be written. In fact, `xtensor` can be used to **process `numpy` data structures inplace** using Python's [buffer protocol](https://docs.python.org/3/c-api/buffer.html). Similarly, we can operate on Julia and R arrays. For more details on the numpy, Julia and R bindings, check out the [xtensor-python](https://github.com/QuantStack/xtensor-python), [xtensor-julia](https://github.com/QuantStack/Xtensor.jl) and [xtensor-r](https://github.com/QuantStack/xtensor-r) projects respectively. `xtensor` requires a modern C++ compiler supporting C++14. The following C++ compilers are supported: - On Windows platforms, Visual C++ 2015 Update 2, or more recent - On Unix platforms, gcc 4.9 or a recent version of Clang ## Installation `xtensor` is a header-only library. We provide a package for the conda package manager. ```bash conda install -c conda-forge xtensor ``` Or you can directly install it from the sources: ```bash cmake -D CMAKE_INSTALL_PREFIX=your_install_prefix make install ``` ## Usage ### Basic usage **Initialize a 2-D array and compute the sum of one of its rows and a 1-D array.** ```cpp #include #include "xtensor/xarray.hpp" #include "xtensor/xio.hpp" xt::xarray arr1 {{1.0, 2.0, 3.0}, {2.0, 5.0, 7.0}, {2.0, 5.0, 7.0}}; xt::xarray arr2 {5.0, 6.0, 7.0}; xt::xarray res = xt::view(arr1, 1) + arr2; std::cout << res; ``` Outputs: ``` {7, 11, 14} ``` **Initialize a 1-D array and reshape it inplace.** ```cpp #include #include "xtensor/xarray.hpp" #include "xtensor/xio.hpp" xt::xarray arr {1, 2, 3, 4, 5, 6, 7, 8, 9}; arr.reshape({3, 3}); std::cout << arr; ``` Outputs: ``` {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} ``` ## The numpy to xtensor cheat sheet If you are familiar with numpy APIs, and you are interested in xtensor, you can check out the [numpy to xtensor cheat sheet](https://xtensor.readthedocs.io/en/latest/numpy.html) provided in the documentation. ## Lazy broadcasting with `xtensor` We can operate on arrays of different shapes of dimensions in an elementwise fashion. Broadcasting rules of xtensor are similar to those of [numpy](http://www.numpy.org) and [libdynd](http://libdynd.org). ### Broadcasting rules In an operation involving two arrays of different dimensions, the array with the lesser dimensions is broadcast across the leading dimensions of the other. For example, if `A` has shape `(2, 3)`, and `B` has shape `(4, 2, 3)`, the result of a broadcasted operation with `A` and `B` has shape `(4, 2, 3)`. ``` (2, 3) # A (4, 2, 3) # B --------- (4, 2, 3) # Result ``` The same rule holds for scalars, which are handled as 0-D expressions. If `A` is a scalar, the equation becomes: ``` () # A (4, 2, 3) # B --------- (4, 2, 3) # Result ``` If matched up dimensions of two input arrays are different, and one of them has size `1`, it is broadcast to match the size of the other. Let's say B has the shape `(4, 2, 1)` in the previous example, so the broadcasting happens as follows: ``` (2, 3) # A (4, 2, 1) # B --------- (4, 2, 3) # Result ``` ### Universal functions, laziness and vectorization With `xtensor`, if `x`, `y` and `z` are arrays of *broadcastable shapes*, the return type of an expression such as `x + y * sin(z)` is **not an array**. It is an `xexpression` object offering the same interface as an N-dimensional array, which does not hold the result. **Values are only computed upon access or when the expression is assigned to an xarray object**. This allows to operate symbolically on very large arrays and only compute the result for the indices of interest. We provide utilities to **vectorize any scalar function** (taking multiple scalar arguments) into a function that will perform on `xexpression`s, applying the lazy broadcasting rules which we just described. These functions are called *xfunction*s. They are `xtensor`'s counterpart to numpy's universal functions. In `xtensor`, arithmetic operations (`+`, `-`, `*`, `/`) and all special functions are *xfunction*s. ### Iterating over `xexpression`s and broadcasting Iterators All `xexpression`s offer two sets of functions to retrieve iterator pairs (and their `const` counterpart). - `begin()` and `end()` provide instances of `xiterator`s which can be used to iterate over all the elements of the expression. The order in which elements are listed is `row-major` in that the index of last dimension is incremented first. - `xbegin(shape)` and `xend(shape)` are similar but take a *broadcasting shape* as an argument. Elements are iterated upon in a row-major way, but certain dimensions are repeated to match the provided shape as per the rules described above. For an expression `e`, `e.xbegin(e.shape())` and `e.begin()` are equivalent. ### Runtime vs compile-time dimensionality Two container classes implementing multi-dimensional arrays are provided: `xarray` and `xtensor`. - `xarray` can be reshaped dynamically to any number of dimensions. It is the container that is the most similar to numpy arrays. - `xtensor` has a dimension set at compilation time, which enables many optimizations. For example, shapes and strides of `xtensor` instances are allocated on the stack instead of the heap. `xarray` and `xtensor` container are both `xexpression`s and can be involved and mixed in universal functions, assigned to each other etc... Besides, two access operators are provided: - The variadic template `operator()` which can take multiple integral arguments or none. - And the `operator[]` which takes a single multi-index argument, which can be of size determined at runtime. `operator[]` also supports access with braced initializers. ### Performance The dynamic nature of `xarray` over `xtensor` has a cost. Since the dimension is unknown at build time, the sequences holding shape and strides of `xarray` instances are heap-allocated, which makes it significantly more expansive than `xtensor`. Shape and strides of `xtensor` are stack allocated which makes them more efficient. More generally, the library implement a `promote_shape` mechanism at build time to determine the optimal sequence type to hold the shape of an expression. The shape type of a broadcasting expression whose members have a dimensionality determined at compile time will have a stack allocated shape. If a single member of a broadcasting expression has a dynamic dimension (for example an `xarray`), it bubbles up to entire broadcasting expression which will have a heap allocated shape. The same hold for views, broadcast expressions, etc... Therefore, when building an application with xtensor, we recommend using statically dimensioned containers whenever possible to improve the overall performance of the application. ## Python bindings The [xtensor-python](https://github.com/QuantStack/xtensor-python) project provides the implementation of two `xtensor` containers, `pyarray` and `pytensor` which effectively wrap numpy arrays, allowing inplace modification, including reshapes. ## Building and running the tests Building the tests requires the [GTest](https://github.com/google/googletest) testing framework and [cmake](https://cmake.org). gtest and cmake are available as a packages for most linux distributions. Besides, they can also be installed with the `conda` package manager (even on windows): ```bash conda install -c conda-forge gtest cmake ``` Once `gtest` and `cmake` are installed, you can build and run the tests: ```bash mkdir build cd build cmake -DBUILD_TESTS=ON ../ make xtest ``` You can also use CMake to download the source of `gtest`, build it, and use the generated libraries: ```bash mkdir build cd build cmake -DBUILD_TESTS=ON -DDOWNLOAD_GTEST=ON ../ make xtest ``` In the context of continuous integration with Travis CI, tests are run in a `conda` environment, which can be activated with ```bash cd test conda env create -f ./test-environment.yml source activate test-xtensor cd .. cmake -DBUILD_TESTS=ON . make xtest ``` ## Building the HTML documentation xtensor's documentation is built with three tools - [doxygen](http://www.doxygen.org) - [sphinx](http://www.sphinx-doc.org) - [breathe](https://breathe.readthedocs.io) While doxygen must be installed separately, you can install breathe by typing ```bash pip install breathe ``` Breathe can also be installed with `conda` ```bash conda install -c conda-forge breathe ``` Finally, build the documentation with ```bash make html ``` from the `docs` subdirectory. ## License 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](LICENSE) file for details. xtensor-0.10.11/benchmark/000077500000000000000000000000001314655136400153165ustar00rootroot00000000000000xtensor-0.10.11/benchmark/CMakeLists.txt000066400000000000000000000060351314655136400200620ustar00rootroot00000000000000############################################################################ # Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht # # # # Distributed under the terms of the BSD 3-Clause License. # # # # The full license is in the file LICENSE, distributed with this software. # ############################################################################ cmake_minimum_required(VERSION 3.1) if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(xtensor-benchmark) find_package(xtensor REQUIRED CONFIG) set(XTENSOR_INCLUDE_DIR ${xtensor_INCLUDE_DIR}) endif () message(STATUS "Forcing tests build type to Release") set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) include(CheckCXXCompilerFlag) string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wunused-parameter -Wextra -Wreorder -Wconversion") CHECK_CXX_COMPILER_FLAG("-std=c++14" HAS_CPP14_FLAG) if (HAS_CPP14_FLAG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") else() message(FATAL_ERROR "Unsupported compiler -- xtensor requires C++14 support!") endif() # Enable link time optimization and set the default symbol # visibility to hidden (very important to obtain small binaries) if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) # Default symbol visibility set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") # Check for Link Time Optimization support # (GCC/Clang) CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG) if (HAS_LTO_FLAG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto") endif() # Intel equivalent to LTO is called IPO if (CMAKE_CXX_COMPILER_ID MATCHES "Intel") CHECK_CXX_COMPILER_FLAG("-ipo" HAS_IPO_FLAG) if (HAS_IPO_FLAG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ipo") endif() endif() endif() endif() if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /MP /bigobj") set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO) foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}") endforeach() endif() include_directories(${XTENSOR_INCLUDE_DIR}) set(XTENSOR_BENCHMARK benchmark_assign.hpp benchmark_container.hpp benchmark_math.hpp benchmark_views.hpp main.cpp ) set(XTENSOR_BENCHMARK_TARGET benchmark_xtensor) add_executable(${XTENSOR_BENCHMARK_TARGET} EXCLUDE_FROM_ALL ${XTENSOR_BENCHMARK} ${XTENSOR_HEADERS}) add_custom_target(xbenchmark COMMAND benchmark_xtensor DEPENDS ${XTENSOR_BENCHMARK_TARGET}) xtensor-0.10.11/benchmark/benchmark_assign.hpp000066400000000000000000000113721314655136400213310ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef BENCHMARK_ASSIGN_HPP #define BENCHMARK_ASSIGN_HPP #include #include #include "xtensor/xnoalias.hpp" #include "xtensor/xtensor.hpp" namespace xt { namespace assign { using duration_type = std::chrono::duration; /**************************** * Benchmark initialization * ****************************/ template inline void init_benchmark_data(V& lhs, V& rhs, std::size_t size0, std::size_t size1) { using T = typename V::value_type; for (std::size_t i = 0; i < size0; ++i) { for (std::size_t j = 0; j < size1; ++j) { lhs(i, j) = T(0.5) * T(j) / T(j + 1) + std::sqrt(T(i)) * T(9.) / T(size1); rhs(i, j) = T(10.2) / T(i + 2) + T(0.25) * T(j); } } } template inline void init_xtensor_benchmark(V& lhs, V& rhs, V& res, std::size_t size0, size_t size1) { lhs.reshape({ size0, size1 }); rhs.reshape({ size0, size1 }); res.reshape({ size0, size1 }); init_benchmark_data(lhs, rhs, size0, size1); } template inline void init_dl_xtensor_benchmark(V& lhs, V& rhs, V& res, std::size_t size0, size_t size1) { using strides_type = typename V::strides_type; strides_type str = { size1, 1 }; lhs.reshape({ size0, size1 }, str); rhs.reshape({ size0, size1 }, str); res.reshape({ size0, size1 }, str); init_benchmark_data(lhs, rhs, size0, size1); } template inline auto benchmark_c_loop(const E& x, const E& y, E& res, std::size_t count) { duration_type t_res = duration_type::max(); using size_type = typename E::size_type; for (std::size_t i = 0; i < count; ++i) { auto start = std::chrono::steady_clock::now(); size_type csize = x.size(); for (size_type i = 0; i < csize; ++i) { res.data()[i] = 3 * x.data()[i] - 2 * y.data()[i]; } auto end = std::chrono::steady_clock::now(); auto tmp = end - start; t_res = tmp < t_res ? tmp : t_res; } return t_res; } template inline auto benchmark_xtensor(const E& x, const E& y, E& res, std::size_t count) { duration_type t_res = duration_type::max(); for (std::size_t i = 0; i < count; ++i) { auto start = std::chrono::steady_clock::now(); xt::noalias(res) = 3 * x - 2 * y; auto end = std::chrono::steady_clock::now(); auto tmp = end - start; t_res = tmp < t_res ? tmp : t_res; } return t_res; } template inline void benchmark(OS& out) { std::size_t count = 10; std::size_t size0 = 20, size1 = 500; xtensor lhs_r, rhs_r, res_r; init_xtensor_benchmark(lhs_r, rhs_r, res_r, size0, size1); xtensor lhs_d, rhs_d, res_d; init_dl_xtensor_benchmark(lhs_d, rhs_d, res_d, size0, size1); duration_type c_loop_assign = benchmark_c_loop(lhs_d, rhs_d, res_d, count); duration_type iterator_assign = benchmark_xtensor(lhs_d, rhs_d, res_d, count); duration_type index_assign = benchmark_xtensor(lhs_r, rhs_r, res_r, count); out << "********************" << std::endl; out << "* ASSIGN BENCHMARK *" << std::endl; out << "********************" << std::endl; out << "c loop assign : " << c_loop_assign.count() << "ms" << std::endl; out << "iterator assign: " << iterator_assign.count() << "ms" << std::endl; out << "index assign : " << index_assign.count() << "ms" << std::endl; out << std::endl; } } } #endif xtensor-0.10.11/benchmark/benchmark_container.hpp000066400000000000000000000246471314655136400220400ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef BENCHMARK_CONTAINER_HPP #define BENCHMARK_CONTAINER_HPP #include "xtensor/xarray.hpp" #include "xtensor/xtensor.hpp" #include #include #include namespace xt { template std::string get_container_name(const std::vector&) { return "std::vector"; } template std::string get_container_name(const uvector&) { return "xt::uvector"; } namespace axpy_1d { template inline auto benchmark_iteration(const E& x, const E& y, E& res, typename E::value_type a, std::size_t number) { auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < number; ++i) { auto iterx = x.begin(); auto itery = y.begin(); for (auto iter = res.begin(); iter != res.end(); ++iter, ++iterx, ++itery) { *iter = a * (*iterx) + (*itery); } } auto end = std::chrono::steady_clock::now(); auto diff = end - start; return diff; } template inline auto benchmark_xiteration(const E& x, const E& y, E& res, typename E::value_type a, std::size_t number) { auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < number; ++i) { auto iterx = x.xbegin(); auto itery = y.xbegin(); for (auto iter = res.xbegin(); iter != res.xend(); ++iter, ++iterx, ++itery) { *iter = a * (*iterx) + (*itery); } } auto end = std::chrono::steady_clock::now(); auto diff = end - start; return diff; } template inline auto benchmark_indexing(const E& x, const E& y, E& res, typename E::value_type a, std::size_t number) { using size_type = typename E::size_type; auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < number; ++i) { size_type n = x.size(); for (size_type i = 0; i < n; ++i) { res(i) = a * x(i) + y(i); } } auto end = std::chrono::steady_clock::now(); auto diff = end - start; return diff; } template inline void init_benchmark(E& x, E& y, E& res, typename E::size_type size) { x.reshape({ size }); y.reshape({ size }); res.reshape({ size }); using value_type = typename E::value_type; using size_type = typename E::size_type; for (size_type i = 0; i < size; ++i) { x(i) = 0.5 + value_type(i); y(i) = 0.25 * value_type(i); } } template void benchmark(OS& out) { using duration_type = std::chrono::duration; using size_type = xarray::size_type; constexpr size_type size = 1000; constexpr size_type number = 10000; double a = 2.7; using array_type = xarray_container; array_type ax, ay, ares; init_benchmark(ax, ay, ares, size); using tensor_type = xtensor_container; tensor_type tx, ty, tres; init_benchmark(tx, ty, tres, size); duration_type aiter = benchmark_iteration(ax, ay, ares, a, number); duration_type titer = benchmark_iteration(tx, ty, tres, a, number); duration_type axiter = benchmark_xiteration(ax, ay, ares, a, number); duration_type txiter = benchmark_xiteration(tx, ty, tres, a, number); duration_type aindex = benchmark_indexing(ax, ay, ares, a, number); duration_type tindex = benchmark_indexing(tx, ty, tres, a, number); std::string cname = get_container_name(C()); out << "************************" << std::string(cname.size(), '*') << std::endl; out << "* AXPY 1D BENCHMARK : " << cname << " *" << std::endl; out << "************************" << std::string(cname.size(), '*') << std::endl << std::endl; out << "xarray iteration: " << aiter.count() << "ms" << std::endl; out << "xtensor iteration: " << titer.count() << "ms" << std::endl; out << "xarray xiteration: " << axiter.count() << "ms" << std::endl; out << "xtensor xiteration: " << txiter.count() << "ms" << std::endl; out << "xarray indexing: " << aindex.count() << "ms" << std::endl; out << "xtensor indexing: " << tindex.count() << "ms" << std::endl; out << std::endl; } } namespace func { template inline auto benchmark_assign(const E& x, const E& y, const E& z, E& res, std::size_t number) { auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < number; ++i) { res = 3 * x - 2 * y * z; } auto end = std::chrono::steady_clock::now(); auto diff = end - start; return diff; } template inline void init_benchmark(E& x, E& y, E& z, E& res) { using value_type = typename E::value_type; using size_type = typename E::size_type; using shape_type = typename E::shape_type; shape_type shape = { 4, 3, 5 }; x.reshape(shape); y.reshape(shape); z.reshape(shape); res.reshape(shape); for (size_type i = 0; i < shape[0]; ++i) { for (size_type j = 0; j < shape[1]; ++j) { for (size_type k = 0; k < shape[2]; ++k) { x(i, j, k) = 0.25 * value_type(i) + 0.5 * value_type(j) - 0.01 * value_type(k); y(i, j, k) = 0.31 * value_type(i) - 0.2 * value_type(j) + 0.07 * value_type(k); z(i, j, k) = 0.27 * value_type(i) + 0.4 * value_type(j) - 0.03 * value_type(k); } } } } template void benchmark(OS& out) { using duration_type = std::chrono::duration; std::size_t number = 2000; using array_type = xarray_container; array_type ax, ay, az, ares; init_benchmark(ax, ay, az, ares); using tensor_type = xtensor_container; tensor_type tx, ty, tz, tres; init_benchmark(tx, ty, tz, tres); duration_type aassign = benchmark_assign(ax, ay, az, ares, number); duration_type tassign = benchmark_assign(tx, ty, tz, tres, number); std::string cname = get_container_name(C()); out << "*********************************" << std::string(cname.size(), '*') << std::endl; out << "* XFUNCTION ASSIGN BENCHMARK : " << cname << " *" << std::endl; out << "*********************************" << std::string(cname.size(), '*') << std::endl << std::endl; out << "benchmark: res = 3 * x - 2 * y * z; - res resized out of the benchmark" << std::endl; out << "xarray : " << aassign.count() << "ms" << std::endl; out << "xtensor: " << tassign.count() << "ms" << std::endl; out << std::endl; } } namespace sum_assign { template inline auto benchmark_assign(const E& x, const E& y, E& res) { auto start = std::chrono::steady_clock::now(); res = 3 * x - 2 * y; auto end = std::chrono::steady_clock::now(); auto diff = end - start; return diff; } template inline void init_benchmark(E& x, E& y) { using value_type = typename E::value_type; using size_type = typename E::size_type; using shape_type = typename E::shape_type; shape_type shape = { 100, 100 }; x.reshape(shape); y.reshape(shape); for (size_type i = 0; i < shape[0]; ++i) { for (size_type j = 0; j < shape[1]; ++j) { x(i, j) = 0.25 * value_type(i) + 0.5 * value_type(j); y(i, j) = 0.31 * value_type(i) - 0.2 * value_type(j); } } } template void benchmark(OS& out) { using duration_type = std::chrono::duration; std::size_t number = 2000; using array_type = xarray_container; array_type ax, ay, ares; init_benchmark(ax, ay); using tensor_type = xtensor_container; tensor_type tx, ty, tres; init_benchmark(tx, ty); duration_type aassign = benchmark_assign(ax, ay, ares); duration_type tassign = benchmark_assign(tx, ty, tres); std::string cname = get_container_name(C()); out << "***************************************" << std::string(cname.size(), '*') << std::endl; out << "* XFUNCTION FULL ASSIGN BENCHMARK : " << cname << " *" << std::endl; out << "***************************************" << std::string(cname.size(), '*') << std::endl << std::endl; out << "benchmark: res = 3 * x - 2 * y; - res resized inside the benchmark" << std::endl; out << "xarray : " << aassign.count() << "ms" << std::endl; out << "xtensor: " << tassign.count() << "ms" << std::endl; out << std::endl; } } } #endif xtensor-0.10.11/benchmark/benchmark_math.hpp000066400000000000000000000320511314655136400207730ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef BENCHMARK_MATH_HPP #define BENCHMARK_MATH_HPP #include #include #include #include #include "xtensor/xarray.hpp" #include "xtensor/xnoalias.hpp" #include "xtensor/xtensor.hpp" namespace xt { namespace math { using duration_type = std::chrono::duration; /**************************** * Benchmark initialization * ****************************/ template inline void init_benchmark_data(V& lhs, V& rhs, std::size_t size0, std::size_t size1) { using T = typename V::value_type; for (std::size_t i = 0; i < size0; ++i) { for (std::size_t j = 0; j < size1; ++j) { lhs(i, j) = T(0.5) * T(j) / T(j + 1) + std::sqrt(T(i)) * T(9.) / T(size1); rhs(i, j) = T(10.2) / T(i + 2) + T(0.25) * T(j); } } } template inline void init_xtensor_benchmark(V& lhs, V& rhs, V& res, std::size_t size0, size_t size1) { lhs.reshape({ size0, size1 }); rhs.reshape({ size0, size1 }); res.reshape({ size0, size1 }); init_benchmark_data(lhs, rhs, size0, size1); } template inline void init_ext_benchmark(V& lhs, V& rhs, V& res, std::size_t size0, size_t size1) { lhs.resize(size0, size1); rhs.resize(size0, size1); res.resize(size0, size1); init_benchmark_data(lhs, rhs, size0, size1); } /*********************** * Benchmark functions * ***********************/ template inline duration_type benchmark_xtensor_ref(F f, const V& lhs, V& res, std::size_t number) { size_t size = lhs.shape()[0] * lhs.shape()[1]; duration_type t_res = duration_type::max(); for (std::size_t count = 0; count < number; ++count) { auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < size; ++i) { res.data()[i] = f(lhs.data()[i]); } auto end = std::chrono::steady_clock::now(); auto tmp = end - start; t_res = tmp < t_res ? tmp : t_res; } return t_res; } template inline duration_type benchmark_xtensor_ref(F f, const V& lhs, const V& rhs, V& res, std::size_t number) { size_t size = lhs.shape()[0] * lhs.shape()[1]; duration_type t_res = duration_type::max(); for (std::size_t count = 0; count < number; ++count) { auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < size; ++i) { res.data()[i] = f(lhs.data()[i], rhs.data()[i]); } auto end = std::chrono::steady_clock::now(); auto tmp = end - start; t_res = tmp < t_res ? tmp : t_res; } return t_res; } template inline duration_type benchmark_xtensor(F f, const V& lhs, V& res, std::size_t number) { size_t s0 = lhs.shape()[0]; size_t s1 = lhs.shape()[1]; duration_type t_res = duration_type::max(); for (std::size_t count = 0; count < number; ++count) { auto start = std::chrono::steady_clock::now(); xt::noalias(res) = f(lhs); auto end = std::chrono::steady_clock::now(); auto tmp = end - start; t_res = tmp < t_res ? tmp : t_res; } return t_res; } template inline duration_type benchmark_xtensor(F f, const V& lhs, const V& rhs, V& res, std::size_t number) { size_t s0 = lhs.shape()[0]; size_t s1 = lhs.shape()[1]; duration_type t_res = duration_type::max(); for (std::size_t count = 0; count < number; ++count) { auto start = std::chrono::steady_clock::now(); xt::noalias(res) = f(lhs, rhs); auto end = std::chrono::steady_clock::now(); auto tmp = end - start; t_res = tmp < t_res ? tmp : t_res; } return t_res; } /********************* * Benchmark runners * *********************/ template void run_benchmark_1op(F f, OS& out, std::size_t size0, std::size_t size1, std::size_t iter) { xtensor lhs, rhs, res; init_xtensor_benchmark(lhs, rhs, res, size0, size1); duration_type ref_time = benchmark_xtensor_ref(f, lhs, res, iter); duration_type xt_time = benchmark_xtensor(f, lhs, res, iter); out << "=====================" << std::endl; out << F::name() << std::endl; out << "reference: " << ref_time.count() << "ms" << std::endl; out << "xtensor : " << xt_time.count() << "ms" << std::endl; out << "=====================" << std::endl; } template void run_benchmark_2op(F f, OS& out, std::size_t size0, std::size_t size1, std::size_t iter) { xtensor lhs, rhs, res; init_xtensor_benchmark(lhs, rhs, res, size0, size1); duration_type ref_time = benchmark_xtensor_ref(f, lhs, rhs, res, iter); duration_type xt_time = benchmark_xtensor(f, lhs, rhs, res, iter); out << "=====================" << std::endl; out << F::name() << std::endl; out << "reference: " << ref_time.count() << "ms" << std::endl; out << "xtensor : " << xt_time.count() << "ms" << std::endl; out << "=====================" << std::endl; } /********************** * Benchmark functors * **********************/ #define DEFINE_OP_FUNCTOR_2OP(OP, NAME)\ struct NAME##_fn {\ template \ inline auto operator()(const T& lhs, const T& rhs) const { return lhs OP rhs; }\ inline static std::string name() { return #NAME; }\ } #define DEFINE_FUNCTOR_1OP(FN)\ struct FN##_fn {\ template \ inline auto operator()(const T& x) const { using std::FN; using xt::FN; return FN(x); }\ inline static std::string name() { return #FN; }\ } #define DEFINE_FUNCTOR_2OP(FN)\ struct FN##_fn{\ template \ inline auto operator()(const T&lhs, const T& rhs) const { using std::FN; using xt::FN; return FN(lhs, rhs); }\ inline static std::string name() { return #FN; }\ } DEFINE_OP_FUNCTOR_2OP(+, add); DEFINE_OP_FUNCTOR_2OP(-, sub); DEFINE_OP_FUNCTOR_2OP(*, mul); DEFINE_OP_FUNCTOR_2OP(/ , div); DEFINE_FUNCTOR_1OP(exp); DEFINE_FUNCTOR_1OP(exp2); DEFINE_FUNCTOR_1OP(expm1); DEFINE_FUNCTOR_1OP(log); DEFINE_FUNCTOR_1OP(log10); DEFINE_FUNCTOR_1OP(log2); DEFINE_FUNCTOR_1OP(log1p); DEFINE_FUNCTOR_1OP(sin); DEFINE_FUNCTOR_1OP(cos); DEFINE_FUNCTOR_1OP(tan); DEFINE_FUNCTOR_1OP(asin); DEFINE_FUNCTOR_1OP(acos); DEFINE_FUNCTOR_1OP(atan); DEFINE_FUNCTOR_1OP(sinh); DEFINE_FUNCTOR_1OP(cosh); DEFINE_FUNCTOR_1OP(tanh); DEFINE_FUNCTOR_1OP(asinh); DEFINE_FUNCTOR_1OP(acosh); DEFINE_FUNCTOR_1OP(atanh); DEFINE_FUNCTOR_2OP(pow); DEFINE_FUNCTOR_1OP(sqrt); DEFINE_FUNCTOR_1OP(cbrt); DEFINE_FUNCTOR_2OP(hypot); DEFINE_FUNCTOR_1OP(ceil); DEFINE_FUNCTOR_1OP(floor); DEFINE_FUNCTOR_1OP(trunc); DEFINE_FUNCTOR_1OP(round); DEFINE_FUNCTOR_1OP(nearbyint); DEFINE_FUNCTOR_1OP(rint); /******************** * benchmark groups * ********************/ template void benchmark_arithmetic(OS& out, std::size_t size0, std::size_t size1, std::size_t iter) { run_benchmark_2op(add_fn(), out, size0, size1, iter); run_benchmark_2op(sub_fn(), out, size0, size1, iter); run_benchmark_2op(mul_fn(), out, size0, size1, iter); run_benchmark_2op(div_fn(), out, size0, size1, iter); } template void benchmark_exp_log(OS& out, std::size_t size0, std::size_t size1, std::size_t iter) { run_benchmark_1op(exp_fn(), out, size0, size1, iter); run_benchmark_1op(exp2_fn(), out, size0, size1, iter); run_benchmark_1op(expm1_fn(), out, size0, size1, iter); run_benchmark_1op(log_fn(), out, size0, size1, iter); run_benchmark_1op(log2_fn(), out, size0, size1, iter); run_benchmark_1op(log10_fn(), out, size0, size1, iter); run_benchmark_1op(log1p_fn(), out, size0, size1, iter); } template void benchmark_trigo(OS& out, std::size_t size0, std::size_t size1, std::size_t iter) { run_benchmark_1op(sin_fn(), out, size0, size1, iter); run_benchmark_1op(cos_fn(), out, size0, size1, iter); run_benchmark_1op(tan_fn(), out, size0, size1, iter); run_benchmark_1op(asin_fn(), out, size0, size1, iter); run_benchmark_1op(acos_fn(), out, size0, size1, iter); run_benchmark_1op(atan_fn(), out, size0, size1, iter); } template void benchmark_hyperbolic(OS& out, std::size_t size0, std::size_t size1, std::size_t iter) { run_benchmark_1op(sinh_fn(), out, size0, size1, iter); run_benchmark_1op(cosh_fn(), out, size0, size1, iter); run_benchmark_1op(tanh_fn(), out, size0, size1, iter); run_benchmark_1op(asinh_fn(), out, size0, size1, iter); run_benchmark_1op(acosh_fn(), out, size0, size1, iter); run_benchmark_1op(atanh_fn(), out, size0, size1, iter); } template void benchmark_power(OS& out, std::size_t size0, std::size_t size1, std::size_t iter) { run_benchmark_2op(pow_fn(), out, size0, size1, iter); run_benchmark_1op(sqrt_fn(), out, size0, size1, iter); run_benchmark_1op(cbrt_fn(), out, size0, size1, iter); run_benchmark_2op(hypot_fn(), out, size0, size1, iter); } template void benchmark_rounding(OS& out, std::size_t size0, std::size_t size1, std::size_t iter) { run_benchmark_1op(ceil_fn(), out, size0, size1, iter); run_benchmark_1op(floor_fn(), out, size0, size1, iter); run_benchmark_1op(trunc_fn(), out, size0, size1, iter); run_benchmark_1op(round_fn(), out, size0, size1, iter); run_benchmark_1op(nearbyint_fn(), out, size0, size1, iter); run_benchmark_1op(rint_fn(), out, size0, size1, iter); } template using benchmark_function = void(*)(OS&, std::size_t, std::size_t, std::size_t); template using benchmark_map = std::map < std::string, benchmark_function>; template const benchmark_map& get_benchmark_map() { static benchmark_map bm; if (bm.empty()) { bm["op"] = &benchmark_arithmetic; bm["exp"] = &benchmark_exp_log; bm["trigo"] = &benchmark_trigo; bm["hyperbolic"] = &benchmark_hyperbolic; bm["power"] = &benchmark_power; bm["rounding"] = &benchmark_rounding; } return bm; } template void benchmark_math(OS& out, const std::string& meth = "") { std::size_t size0 = 20; std::size_t size1 = 500; std::size_t nb_iter = 1000; const auto& bm = get_benchmark_map(); if (meth != "") { auto iter = bm.find(meth); if (iter != bm.end()) (iter->second)(out, size0, size1, nb_iter); } else { for (auto v : bm) { (v.second)(out, size0, size1, nb_iter); } } } } } #endif xtensor-0.10.11/benchmark/benchmark_views.hpp000066400000000000000000000151111314655136400211750ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef BENCHMARK_VIEWS_HPP #define BENCHMARK_VIEWS_HPP #include "xtensor/xarray.hpp" #include "xtensor/xstridedview.hpp" #include #include #include namespace xt { namespace reducer { template inline auto benchmark_reducer(const E& x, E& res, const X& axes, std::size_t number) { auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < number; ++i) { res = sum(x, axes); } auto end = std::chrono::steady_clock::now(); auto diff = end - start; return diff; } template inline auto benchmark_strided_reducer(const E& x, E& res, const X& axes, std::size_t number) { auto start = std::chrono::steady_clock::now(); using value_type = typename E::value_type; std::size_t stride = x.strides()[axes[0]]; std::size_t offset_end = x.strides()[axes[0]] * x.shape()[axes[0]]; std::size_t offset_iter = 0; if (axes[0] == 1) { offset_iter = x.strides()[0]; } else if (axes[0] == 0) { offset_iter = x.strides()[1]; } for (std::size_t i = 0; i < number; ++i) { for (std::size_t j = 0; j < res.shape()[0]; ++j) { auto begin = x.raw_data() + (offset_iter * j); auto end = begin + offset_end; value_type temp = *begin; begin += stride; for (; begin < end; begin += stride) { temp += *begin; } res(j) = temp; } } auto end = std::chrono::steady_clock::now(); auto diff = end - start; return diff; } template void benchmark(OS& out) { using duration_type = std::chrono::duration; std::size_t number = 100; xarray u = ones({ 10, 100000 }); xarray v = ones({ 100000, 10 }); std::vector axis0 = { 0 }; std::vector axis1 = { 1 }; xarray res0; res0.reshape({ 100000 }); xarray res1; res1.reshape({ 10 }); duration_type du0 = benchmark_reducer(u, res0, axis0, number); duration_type du1 = benchmark_reducer(u, res1, axis1, number); duration_type dv0 = benchmark_reducer(v, res1, axis0, number); duration_type dv1 = benchmark_reducer(v, res0, axis1, number); duration_type dsu0 = benchmark_strided_reducer(u, res0, axis0, number); duration_type dsu1 = benchmark_strided_reducer(u, res1, axis1, number); duration_type dsv0 = benchmark_strided_reducer(v, res1, axis0, number); duration_type dsv1 = benchmark_strided_reducer(v, res0, axis1, number); out << "************************" << std::endl; out << "* REDUCER BENCHMARK : " << " *" << std::endl; out << "************************" << std::endl << std::endl; out << "sum((10, 100000), 0): " << du0.count() << "ms" << std::endl; out << "sum((10, 100000), 1): " << du1.count() << "ms" << std::endl; out << "sum((100000, 10), 0): " << dv0.count() << "ms" << std::endl; out << "sum((100000, 10), 1): " << dv1.count() << "ms" << std::endl; out << "strided sum(10, 100000), 0): " << dsu0.count() << "ms" << std::endl; out << "strided sum(10, 100000), 1): " << dsu1.count() << "ms" << std::endl; out << "strided sum(100000, 10), 0): " << dsv0.count() << "ms" << std::endl; out << "strided sum(100000, 10), 1): " << dsv1.count() << "ms" << std::endl; out << std::endl; } } namespace stridedview { template inline auto benchmark_stridedview(const E1& x, E2& res, std::size_t number) { auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < number; ++i) { res = transpose(x); } auto end = std::chrono::steady_clock::now(); auto diff = end - start; return diff; } template void benchmark(OS& out) { using duration_type = std::chrono::duration; std::size_t number = 100; xarray ar = xt::arange(100000); ar.reshape({ 10, 20, 500 }); xarray ac = xt::arange(100000); ac.reshape({ 10, 20, 500 }); xarray resr; resr.reshape({ 500, 20, 10 }); xarray resc; resc.reshape({ 500, 20, 10 }); duration_type darr = benchmark_stridedview(ar, resr, number); duration_type dacr = benchmark_stridedview(ac, resr, number); duration_type darc = benchmark_stridedview(ar, resc, number); duration_type dacc = benchmark_stridedview(ac, resc, number); out << "*****************************" << std::endl; out << "* STRIDED VIEW BENCHMARK : " << " *" << std::endl; out << "*****************************" << std::endl << std::endl; out << "RM - transpose RM(10, 20, 500): " << darr.count() << "ms" << std::endl; out << "RM - transpose CM(10, 20, 500): " << dacr.count() << "ms" << std::endl; out << "CM - transpose RM(10, 20, 500): " << darc.count() << "ms" << std::endl; out << "CM - transpose CM(10, 20, 500): " << dacc.count() << "ms" << std::endl; out << std::endl; } } } #endif xtensor-0.10.11/benchmark/main.cpp000066400000000000000000000067221314655136400167550ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include "benchmark_assign.hpp" #include "benchmark_container.hpp" #include "benchmark_math.hpp" #include "benchmark_views.hpp" #include template void benchmark_container(OS& out) { xt::axpy_1d::benchmark>(out); xt::axpy_1d::benchmark>(out); xt::func::benchmark>(out); xt::func::benchmark>(out); xt::sum_assign::benchmark>(out); xt::sum_assign::benchmark>(out); } template void benchmark_views(OS& out) { xt::reducer::benchmark(out); xt::stridedview::benchmark(out); } template void benchmark_assign(OS& out) { } int main(int argc, char* argv[]) { std::cout << "Using steady_clock" << std::endl; std::cout << "period num: " << std::chrono::steady_clock::period::num << std::endl; std::cout << "period den: " << std::chrono::steady_clock::period::den << std::endl; std::cout << "steady = " << std::boolalpha << std::chrono::steady_clock::is_steady << std::endl; std::cout << std::endl; if (argc != 1) { if (std::string(argv[1]) == "--help" || std::string(argv[1]) == "-h") { std::cout << "Avalaible options:" << std::endl; std::cout << "assign : run benchmark on tensor assign" << std::endl; std::cout << "container : run benchmark on container basic operations" << std::endl; std::cout << "view : run benchmark on view basic operations" << std::endl; std::cout << "op : run benchmark on arithmetic operations" << std::endl; std::cout << "exp : run benchmark on exponential and logarithm functions" << std::endl; std::cout << "trigo : run benchmark on trigonomeric functions" << std::endl; std::cout << "hyperbolic: run benchmark on hyperbolic functions" << std::endl; std::cout << "power : run benchmark on power functions" << std::endl; std::cout << "rounding : run benchmark on rounding functions" << std::endl; } else { for (int i = 1; i < argc; ++i) { std::string sarg = std::string(argv[i]); if (sarg == "assign") { xt::assign::benchmark(std::cout); } else if (sarg == "container") { benchmark_container(std::cout); } else if (sarg == "view") { benchmark_views(std::cout); } else { xt::math::benchmark_math(std::cout, sarg); } } } } else { xt::assign::benchmark(std::cout); benchmark_container(std::cout); benchmark_views(std::cout); xt::math::benchmark_math(std::cout); } return 0; } xtensor-0.10.11/docs/000077500000000000000000000000001314655136400143145ustar00rootroot00000000000000xtensor-0.10.11/docs/Doxyfile000066400000000000000000000005021314655136400160170ustar00rootroot00000000000000PROJECT_NAME = "xtensor" XML_OUTPUT = xml INPUT = ../include GENERATE_LATEX = NO GENERATE_MAN = NO GENERATE_RTF = NO CASE_SENSE_NAMES = NO GENERATE_HTML = NO GENERATE_XML = YES RECURSIVE = YES QUIET = YES JAVADOC_AUTOBRIEF = YES WARN_IF_UNDOCUMENTED = NO xtensor-0.10.11/docs/Makefile000066400000000000000000000147421314655136400157640ustar00rootroot00000000000000# You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext api default: html help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " applehelp to make an Apple Help Book" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " coverage to run coverage check of the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* rm -rf xml html: doxygen $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: doxygen $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: doxygen $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: doxygen $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: doxygen $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: doxygen $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." epub: doxygen $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: doxygen $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: doxygen $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: doxygen $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: doxygen $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: doxygen $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: doxygen $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: doxygen $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: doxygen $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: doxygen $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: doxygen $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: doxygen $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." coverage: doxygen $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage @echo "Testing of coverage in the sources finished, look at the " \ "results in $(BUILDDIR)/coverage/python.txt." xml: doxygen $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: doxygen $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." xtensor-0.10.11/docs/environment.yml000066400000000000000000000002141314655136400174000ustar00rootroot00000000000000name: xtensor-docs channels: - conda-forge dependencies: - python=3.5 - sphinx_rtd_theme - pip: - breathe - sphinx==1.5.6 xtensor-0.10.11/docs/make.bat000066400000000000000000000161651314655136400157320ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source set I18NSPHINXOPTS=%SPHINXOPTS% source if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled echo. coverage to run coverage check of the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) REM Check if sphinx-build is available and fallback to Python version if any %SPHINXBUILD% 1>NUL 2>NUL if errorlevel 9009 goto sphinx_python goto sphinx_ok :sphinx_python set SPHINXBUILD=python -m sphinx.__init__ %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) :sphinx_ok if "%1" == "html" ( doxygen %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\packagename.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\packagename.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %~dp0 echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %~dp0 echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "coverage" ( %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage if errorlevel 1 exit /b 1 echo. echo.Testing of coverage in the sources finished, look at the ^ results in %BUILDDIR%/coverage/python.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end xtensor-0.10.11/docs/source/000077500000000000000000000000001314655136400156145ustar00rootroot00000000000000xtensor-0.10.11/docs/source/api/000077500000000000000000000000001314655136400163655ustar00rootroot00000000000000xtensor-0.10.11/docs/source/api/basic_functions.rst000066400000000000000000000026001314655136400222660ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Basic functions =============== **xtensor** provides the following basic functions for xexpressions and scalars: Defined in ``xtensor/xmath.hpp`` .. _abs-function-reference: .. doxygenfunction:: abs(E&&) :project: xtensor .. _fabs-function-reference: .. doxygenfunction:: fabs(E&&) :project: xtensor .. _fmod-function-reference: .. doxygenfunction:: fmod(E1&&, E2&&) :project: xtensor .. _remainder-func-ref: .. doxygenfunction:: remainder(E1&&, E2&&) :project: xtensor .. _fma-function-reference: .. doxygenfunction:: fma(E1&&, E2&&, E3&&) :project: xtensor .. _maximum-func-ref: .. doxygenfunction:: maximum(E1&&, E2&&) :project: xtensor .. _minimum-func-ref: .. doxygenfunction:: minimum(E1&&, E2&&) :project: xtensor .. _fmax-function-reference: .. doxygenfunction:: fmax(E1&&, E2&&) :project: xtensor .. _fmin-function-reference: .. doxygenfunction:: fmin(E1&&, E2&&) :project: xtensor .. _fdim-function-reference: .. doxygenfunction:: fdim(E1&&, E2&&) :project: xtensor .. _clip-function-reference: .. doxygenfunction:: clip(E1&&, E2&&, E3&&) :project: xtensor .. _sign-function-reference: .. doxygenfunction:: sign(E&&) :project: xtensor xtensor-0.10.11/docs/source/api/classif_functions.rst000066400000000000000000000014711314655136400226360ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Classification functions ======================== **xtensor** provides the following classification functions for xexpressions and scalars: Defined in ``xtensor/xmath.hpp`` .. _isfinite-func-ref: .. doxygenfunction:: isfinite(E&&) :project: xtensor .. _isinf-func-ref: .. doxygenfunction:: isinf(E&&) :project: xtensor .. _isnan-func-ref: .. doxygenfunction:: isnan(E&&) :project: xtensor .. _isclose-func-ref: .. doxygenfunction:: isclose(E1&&, E2&&, double, double, bool) :project: xtensor .. _allclose-func-ref: .. doxygenfunction:: allclose(E1&&, E2&, double, double) :project: xtensor xtensor-0.10.11/docs/source/api/container_index.rst000066400000000000000000000006271314655136400222750ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Containers and views ==================== .. toctree:: xcontainer xiterable xarray xarray_adaptor xtensor xtensor_adaptor xview xbroadcast xindexview xfunctorview xtensor-0.10.11/docs/source/api/error_functions.rst000066400000000000000000000012651314655136400223440ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Error and gamma functions ========================= **xtensor** provides the following error and gamma functions for xexpressions: Defined in ``xtensor/xmath.hpp`` .. _erf-function-reference: .. doxygenfunction:: erf(E&&) :project: xtensor .. _erfc-function-reference: .. doxygenfunction:: erfc(E&&) :project: xtensor .. _tgamma-func-ref: .. doxygenfunction:: tgamma(E&&) :project: xtensor .. _lgamma-func-ref: .. doxygenfunction:: lgamma(E&&) :project: xtensor xtensor-0.10.11/docs/source/api/exponential_functions.rst000066400000000000000000000016211314655136400235350ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Exponential functions ===================== **xtensor** provides the following exponential functions for xexpressions: Defined in ``xtensor/xmath.hpp`` .. _exp-function-reference: .. doxygenfunction:: exp(E&&) :project: xtensor .. _exp2-function-reference: .. doxygenfunction:: exp2(E&&) :project: xtensor .. _expm1-func-ref: .. doxygenfunction:: expm1(E&&) :project: xtensor .. _log-function-reference: .. doxygenfunction:: log(E&&) :project: xtensor .. _log2-function-reference: .. doxygenfunction:: log2(E&&) :project: xtensor .. _log10-func-ref: .. doxygenfunction:: log10(E&&) :project: xtensor .. _log1p-func-ref: .. doxygenfunction:: log1p(E&&) :project: xtensor xtensor-0.10.11/docs/source/api/expression_index.rst000066400000000000000000000005751314655136400225140ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Expressions and semantic ======================== .. toctree:: xexpression xsemantic_base xcontainer_semantic xadaptor_semantic xview_semantic xeval xtensor-0.10.11/docs/source/api/function_index.rst000066400000000000000000000005231314655136400221330ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Functions and generators ======================== .. toctree:: xfunction xreducer xgenerator xbuilder xrandom xtensor-0.10.11/docs/source/api/hyperbolic_functions.rst000066400000000000000000000015001314655136400233430ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Hyperbolic functions ==================== **xtensor** provides the following hyperbolic functions for xexpressions: Defined in ``xtensor/xmath.hpp`` .. _sinh-function-reference: .. doxygenfunction:: sinh(E&&) :project: xtensor .. _cosh-function-reference: .. doxygenfunction:: cosh(E&&) :project: xtensor .. _tanh-function-reference: .. doxygenfunction:: tanh(E&&) :project: xtensor .. _asinh-func-ref: .. doxygenfunction:: asinh(E&&) :project: xtensor .. _acosh-func-ref: .. doxygenfunction:: acosh(E&&) :project: xtensor .. _atanh-func-ref: .. doxygenfunction:: atanh(E&&) :project: xtensor xtensor-0.10.11/docs/source/api/nearint_operations.rst000066400000000000000000000015511314655136400230240ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Nearest integer floating point operations ========================================= **xtensor** provides the following rounding operations for xexpressions: Defined in ``xtensor/xmath.hpp`` .. _ceil-function-reference: .. doxygenfunction:: ceil(E&&) :project: xtensor .. _floor-func-ref: .. doxygenfunction:: floor(E&&) :project: xtensor .. _trunc-func-ref: .. doxygenfunction:: trunc(E&&) :project: xtensor .. _round-func-ref: .. doxygenfunction:: round(E&&) :project: xtensor .. _nearbyint-func-ref: .. doxygenfunction:: nearbyint(E&&) :project: xtensor .. _rint-function-reference: .. doxygenfunction:: rint(E&&) :project: xtensor xtensor-0.10.11/docs/source/api/operators.rst000066400000000000000000000041521314655136400211370ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Operators and related functions =============================== Defined in ``xtensor/xmath.hpp`` .. _identity-op-ref: .. doxygenfunction:: operator+(E&&) :project: xtensor .. _neg-op-ref: .. doxygenfunction:: operator-(E&&) :project: xtensor .. _plus-op-ref: .. doxygenfunction:: operator+(E1&&, E2&&) :project: xtensor .. _minus-op-ref: .. doxygenfunction:: operator-(E1&&, E2&&) :project: xtensor .. _mul-op-ref: .. doxygenfunction:: operator*(E1&&, E2&&) :project: xtensor .. _div-op-ref: .. doxygenfunction:: operator/(E1&&, E2&&) :project: xtensor .. _or-op-ref: .. doxygenfunction:: operator||(E1&&, E2&&) :project: xtensor .. _and-op-ref: .. doxygenfunction:: operator&&(E1&&, E2&&) :project: xtensor .. _not-op-ref: .. doxygenfunction:: operator!(E&&) :project: xtensor .. _where-op-ref: .. doxygenfunction:: where(E1&&, E2&&, E3&&) :project: xtensor .. _nonzero-op-ref: .. doxygenfunction:: nonzero(const T&) :project: xtensor .. _wherec-op-ref: .. doxygenfunction:: where(const T&) :project: xtensor .. _any-op-ref: .. doxygenfunction:: any(E&&) :project: xtensor .. _all-op-ref: .. doxygenfunction:: all(E&&) :project: xtensor .. _less-op-ref: .. doxygenfunction:: operator<(E1&&, E2&&) :project: xtensor .. _less-eq-op-ref: .. doxygenfunction:: operator<=(E1&&, E2&&) :project: xtensor .. _greater-op-ref: .. doxygenfunction:: operator>(E1&&, E2&&) :project: xtensor .. _greater-eq-op-ref: .. doxygenfunction:: operator>=(E1&&, E2&&) :project: xtensor .. _equal-op-ref: .. doxygenfunction:: operator==(const xexpression&, const xexpression&) :project: xtensor .. _nequal-op-ref: .. doxygenfunction:: operator!=(const xexpression&, const xexpression&) :project: xtensor .. _equal-fn-ref: .. doxygenfunction:: equal(E1&&, E2&&) :project: xtensor .. _nequal-fn-ref: .. doxygenfunction:: not_equal(E1&&, E2&&) :project: xtensor xtensor-0.10.11/docs/source/api/power_functions.rst000066400000000000000000000012661314655136400223500ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Power functions =============== **xtensor** provides the following power functions for xexpressions and scalars: Defined in ``xtensor/xmath.hpp`` .. _pow-function-reference: .. doxygenfunction:: pow(E1&&, E2&&) :project: xtensor .. _sqrt-function-reference: .. doxygenfunction:: sqrt(E&&) :project: xtensor .. _cbrt-function-reference: .. doxygenfunction:: cbrt(E&&) :project: xtensor .. _hypot-func-ref: .. doxygenfunction:: hypot(E1&&, E2&&) :project: xtensor xtensor-0.10.11/docs/source/api/reducing_functions.rst000066400000000000000000000011511314655136400230050ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Reducing functions ================== **xtensor** provides the following reducing functions for xexpressions: Defined in ``xtensor/xmath.hpp`` .. _sum-function-reference: .. doxygenfunction:: sum(E&&, X&&) :project: xtensor .. _prod-function-reference: .. doxygenfunction:: prod(E&&, X&&) :project: xtensor .. _mean-function-reference: .. doxygenfunction:: mean(E&&, X&&) :project: xtensor xtensor-0.10.11/docs/source/api/trigonometric_functions.rst000066400000000000000000000016701314655136400241000ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Trigonometric functions ======================= **xtensor** provides the following trigonometric functions for xexpressions and scalars: Defined in ``xtensor/xmath.hpp`` .. _sin-function-reference: .. doxygenfunction:: sin(E&&) :project: xtensor .. _cos-function-reference: .. doxygenfunction:: cos(E&&) :project: xtensor .. _tan-function-reference: .. doxygenfunction:: tan(E&&) :project: xtensor .. _asin-function-reference: .. doxygenfunction:: asin(E&&) :project: xtensor .. _acos-function-reference: .. doxygenfunction:: acos(E&&) :project: xtensor .. _atan-function-reference: .. doxygenfunction:: atan(E&&) :project: xtensor .. _atan2-func-ref: .. doxygenfunction:: atan2(E1&&, E2&&) :project: xtensor xtensor-0.10.11/docs/source/api/xadaptor_semantic.rst000066400000000000000000000005511314655136400226250ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xadaptor_semantic ================= Defined in ``xtensor/xsemantic.hpp`` .. doxygenclass:: xt::xadaptor_semantic :project: xtensor :members: xtensor-0.10.11/docs/source/api/xarray.rst000066400000000000000000000006041314655136400204250ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xarray ====== Defined in ``xtensor/xarray.hpp`` .. doxygenclass:: xt::xarray_container :project: xtensor :members: .. doxygentypedef:: xt::xarray :project: xtensor xtensor-0.10.11/docs/source/api/xarray_adaptor.rst000066400000000000000000000014751314655136400221460ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xarray_adaptor ============== Defined in ``xtensor/xarray.hpp`` .. doxygenclass:: xt::xarray_adaptor :project: xtensor :members: xadapt (xarray_adaptor) ======================= Defined in ``xtensor/xadapt.hpp`` .. doxygenfunction:: xt::xadapt(C&, const SC&, layout_type) :project: xtensor .. doxygenfunction:: xt::xadapt(C&, const SC&, const SC&) :project: xtensor .. doxygenfunction:: xt::xadapt(P&, typename A::size_type, O, const SC&, layout_type, const A&) :project: xtensor .. doxygenfunction:: xt::xadapt(P&, typename A::size_type, O, const SC&, const SC&, const A&) :project: xtensor xtensor-0.10.11/docs/source/api/xbroadcast.rst000066400000000000000000000006351314655136400212550ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xbroadcast ========== Defined in ``xtensor/xbroadcast.hpp`` .. doxygenclass:: xt::xbroadcast :project: xtensor :members: .. doxygenfunction:: xt::broadcast(E&&, const S&) :project: xtensor xtensor-0.10.11/docs/source/api/xbuilder.rst000066400000000000000000000022211314655136400207320ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xbuilder ======== Defined in ``xtensor/xbuilder.hpp`` .. doxygenfunction:: xt::ones(S) :project: xtensor .. doxygenfunction:: xt::ones(const I (&)[L]) :project: xtensor .. doxygenfunction:: xt::zeros(S) :project: xtensor .. doxygenfunction:: xt::zeros(const I (&)[L]) :project: xtensor .. doxygenfunction:: xt::eye(const std::vector&, int) :project: xtensor .. doxygenfunction:: xt::eye(std::size_t, int) :project: xtensor .. doxygenfunction:: xt::arange(T, T, T) :project: xtensor .. doxygenfunction:: xt::arange(T) :project: xtensor .. doxygenfunction:: xt::linspace :project: xtensor .. doxygenfunction:: xt::logspace :project: xtensor .. doxygenfunction:: xt::diag :project: xtensor .. doxygenfunction:: xt::diagonal :project: xtensor .. doxygenfunction:: xt::tril :project: xtensor .. doxygenfunction:: xt::triu :project: xtensor .. doxygenfunction:: xt::flip :project: xtensor xtensor-0.10.11/docs/source/api/xcontainer.rst000066400000000000000000000012461314655136400212740ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. layout ====== Defined in ``xtensor/xlayout.hpp`` .. doxygenenum:: xt::layout_type :project: xtensor .. doxygenfunction:: xt::compute_layout(Args... args) :project: xtensor xcontainer ========== Defined in ``xtensor/xcontainer.hpp`` .. doxygenclass:: xt::xcontainer :project: xtensor :members: xstrided_container ================== Defined in ``xtensor/xcontainer.hpp`` .. doxygenclass:: xt::xstrided_container :project: xtensor :members: xtensor-0.10.11/docs/source/api/xcontainer_semantic.rst000066400000000000000000000005571314655136400231630ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xcontainer_semantic =================== Defined in ``xtensor/xsemantic.hpp`` .. doxygenclass:: xt::xcontainer_semantic :project: xtensor :members: xtensor-0.10.11/docs/source/api/xeval.rst000066400000000000000000000004751314655136400202440ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xeval ===== Defined in ``xtensor/xeval.hpp`` .. doxygenfunction:: xt::eval(E&& e) :project: xtensor xtensor-0.10.11/docs/source/api/xexpression.rst000066400000000000000000000005311314655136400215050ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xexpression =========== Defined in ``xtensor/xexpression.hpp`` .. doxygenclass:: xt::xexpression :project: xtensor :members: xtensor-0.10.11/docs/source/api/xfunction.rst000066400000000000000000000005221314655136400211330ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xfunction ========= Defined in ``xtensor/xfunction.hpp`` .. doxygenclass:: xt::xfunction :project: xtensor :members: xtensor-0.10.11/docs/source/api/xfunctorview.rst000066400000000000000000000007641314655136400216710ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xfunctorview ============ Defined in ``xtensor/xfunctorview.hpp`` .. doxygenclass:: xt::xfunctorview :project: xtensor :members: Defined in ``xtensor/xcomplex.hpp`` .. doxygenfunction:: xt::real(E&&) :project: xtensor .. doxygenfunction:: xt::imag(E&&) :project: xtensor xtensor-0.10.11/docs/source/api/xgenerator.rst000066400000000000000000000005261314655136400213000ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xgenerator ========== Defined in ``xtensor/xgenerator.hpp`` .. doxygenclass:: xt::xgenerator :project: xtensor :members: xtensor-0.10.11/docs/source/api/xindexview.rst000066400000000000000000000011161314655136400213100ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xindexview ========== Defined in ``xtensor/xindexview.hpp`` .. doxygenclass:: xt::xindexview :project: xtensor :members: .. doxygenclass:: xt::xfiltration :project: xtensor :members: .. doxygenfunction:: xt::index_view(E&&, I&&) :project: xtensor .. doxygenfunction:: xt::filter :project: xtensor .. doxygenfunction:: xt::filtration :project: xtensor xtensor-0.10.11/docs/source/api/xiterable.rst000066400000000000000000000010741314655136400211000ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xiterable ========= Defined in ``xtensor/xiterable.hpp`` .. doxygenclass:: xt::xconst_iterable :project: xtensor :members: .. doxygenclass:: xt::xiterable :project: xtensor :members: .. doxygenclass:: xt::xexpression_const_iterable :project: xtensor :members: .. doxygenclass:: xt::xexpression_iterable :project: xtensor :members: xtensor-0.10.11/docs/source/api/xmath.rst000066400000000000000000000377351314655136400202570ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. .. raw:: html Mathematical functions ====================== .. toctree:: operators +---------------------------------------+----------------------------------------------------+ | :ref:`operator+ ` | identity | +---------------------------------------+----------------------------------------------------+ | :ref:`operator- ` | opposite | +---------------------------------------+----------------------------------------------------+ | :ref:`operator+ ` | addition | +---------------------------------------+----------------------------------------------------+ | :ref:`operator- ` | substraction | +---------------------------------------+----------------------------------------------------+ | :ref:`operator* ` | multiplication | +---------------------------------------+----------------------------------------------------+ | :ref:`operator/ ` | division | +---------------------------------------+----------------------------------------------------+ | :ref:`operator|| ` | logical or | +---------------------------------------+----------------------------------------------------+ | :ref:`operator&& ` | logical and | +---------------------------------------+----------------------------------------------------+ | :ref:`operator! ` | logical not | +---------------------------------------+----------------------------------------------------+ | :ref:`where ` | ternary selection | +---------------------------------------+----------------------------------------------------+ | :ref:`nonzero ` | indices selection | +---------------------------------------+----------------------------------------------------+ | :ref:`where ` | indices selection | +---------------------------------------+----------------------------------------------------+ | :ref:`any ` | return true if any value is truthy | +---------------------------------------+----------------------------------------------------+ | :ref:`all ` | return true if all the values are truthy | +---------------------------------------+----------------------------------------------------+ | :ref:`operator\< ` | element-wise lesser than | +---------------------------------------+----------------------------------------------------+ | :ref:`operator\<= ` | element-wise less or equal | +---------------------------------------+----------------------------------------------------+ | :ref:`operator> ` | element-wise greater than | +---------------------------------------+----------------------------------------------------+ | :ref:`operator>= ` | element-wise greater or equal | +---------------------------------------+----------------------------------------------------+ | :ref:`operator== ` | expression equality | +---------------------------------------+----------------------------------------------------+ | :ref:`operator!= ` | expression inequality | +---------------------------------------+----------------------------------------------------+ | :ref:`equal ` | element-wise equality | +---------------------------------------+----------------------------------------------------+ | :ref:`not_equal ` | element-wise inequality | +---------------------------------------+----------------------------------------------------+ .. toctree:: basic_functions +---------------------------------------+----------------------------------------------------+ | :ref:`abs ` | absolute value | +---------------------------------------+----------------------------------------------------+ | :ref:`fabs ` | absolute value | +---------------------------------------+----------------------------------------------------+ | :ref:`fmod ` | remainder of the floating point division operation | +---------------------------------------+----------------------------------------------------+ | :ref:`remainder ` | signed remainder of the division operation | +---------------------------------------+----------------------------------------------------+ | :ref:`fma ` | fused multiply-add operation | +---------------------------------------+----------------------------------------------------+ | :ref:`minimum ` | element-wise minimum | +---------------------------------------+----------------------------------------------------+ | :ref:`maximum ` | element-wise maximum | +---------------------------------------+----------------------------------------------------+ | :ref:`fmin ` | element-wise minimum for floating point values | +---------------------------------------+----------------------------------------------------+ | :ref:`fmax ` | element-wise maximum for floating point values | +---------------------------------------+----------------------------------------------------+ | :ref:`fdim ` | element-wise positive difference | +---------------------------------------+----------------------------------------------------+ | :ref:`clip ` | element-wise clipping operation | +---------------------------------------+----------------------------------------------------+ | :ref:`sign ` | element-wise indication of the sign | +---------------------------------------+----------------------------------------------------+ .. toctree:: exponential_functions +---------------------------------------+----------------------------------------------------+ | :ref:`exp ` | natural exponential function | +---------------------------------------+----------------------------------------------------+ | :ref:`exp2 ` | base 2 exponential function | +---------------------------------------+----------------------------------------------------+ | :ref:`expm1 ` | natural exponential function, minus one | +---------------------------------------+----------------------------------------------------+ | :ref:`log ` | natural logarithm function | +---------------------------------------+----------------------------------------------------+ | :ref:`log2 ` | base 2 logarithm function | +---------------------------------------+----------------------------------------------------+ | :ref:`log10 ` | base 10 logarithm function | +---------------------------------------+----------------------------------------------------+ | :ref:`log1p ` | natural logarithm of one plus function | +---------------------------------------+----------------------------------------------------+ .. toctree:: power_functions +---------------------------------------+----------------------------------------------------+ | :ref:`pow ` | power function | +---------------------------------------+----------------------------------------------------+ | :ref:`sqrt ` | square root function | +---------------------------------------+----------------------------------------------------+ | :ref:`cbrt ` | cubic root function | +---------------------------------------+----------------------------------------------------+ | :ref:`hypot ` | hypotenuse function | +---------------------------------------+----------------------------------------------------+ .. toctree:: trigonometric_functions +---------------------------------------+----------------------------------------------------+ | :ref:`sin ` | sine function | +---------------------------------------+----------------------------------------------------+ | :ref:`cos ` | cosine function | +---------------------------------------+----------------------------------------------------+ | :ref:`tan ` | tangent function | +---------------------------------------+----------------------------------------------------+ | :ref:`asin ` | arc sine function | +---------------------------------------+----------------------------------------------------+ | :ref:`acos ` | arc cosine function | +---------------------------------------+----------------------------------------------------+ | :ref:`atan ` | arc tangent function | +---------------------------------------+----------------------------------------------------+ | :ref:`atan2 ` | arc tangent function, determining quadrants | +---------------------------------------+----------------------------------------------------+ .. toctree:: hyperbolic_functions +---------------------------------------+----------------------------------------------------+ | :ref:`sinh ` | hyperbolic sine function | +---------------------------------------+----------------------------------------------------+ | :ref:`cosh ` | hyperbolic cosine function | +---------------------------------------+----------------------------------------------------+ | :ref:`tanh ` | hyperbolic tangent function | +---------------------------------------+----------------------------------------------------+ | :ref:`asinh ` | inverse hyperbolic sine function | +---------------------------------------+----------------------------------------------------+ | :ref:`acosh ` | inverse hyperbolic cosine function | +---------------------------------------+----------------------------------------------------+ | :ref:`atanh ` | inverse hyperbolic tangent function | +---------------------------------------+----------------------------------------------------+ .. toctree:: error_functions +---------------------------------------+----------------------------------------------------+ | :ref:`erf ` | error function | +---------------------------------------+----------------------------------------------------+ | :ref:`erfc ` | complementary error function | +---------------------------------------+----------------------------------------------------+ | :ref:`tgamma ` | gamma function | +---------------------------------------+----------------------------------------------------+ | :ref:`lgamma ` | natural logarithm of the gamma function | +---------------------------------------+----------------------------------------------------+ .. toctree:: nearint_operations +---------------------------------------+----------------------------------------------------+ | :ref:`ceil ` | nearest integers not less | +---------------------------------------+----------------------------------------------------+ | :ref:`floor ` | nearest integers not greater | +---------------------------------------+----------------------------------------------------+ | :ref:`trunc ` | nearest integers not greater in magnitude | +---------------------------------------+----------------------------------------------------+ | :ref:`round ` | nearest integers, rounding away from zero | +---------------------------------------+----------------------------------------------------+ | :ref:`nearbyint ` | nearest integers using current rounding mode | +---------------------------------------+----------------------------------------------------+ | :ref:`rint ` | nearest integers using current rounding mode | +---------------------------------------+----------------------------------------------------+ .. toctree:: classif_functions +---------------------------------------+----------------------------------------------------+ | :ref:`isfinite ` | checks for finite values | +---------------------------------------+----------------------------------------------------+ | :ref:`isinf ` | checks for infinite values | +---------------------------------------+----------------------------------------------------+ | :ref:`isnan ` | checks for NaN values | +---------------------------------------+----------------------------------------------------+ | :ref:`isclose ` | element-wise closeness detection | +---------------------------------------+----------------------------------------------------+ | :ref:`allclose ` | closeness reduction | +---------------------------------------+----------------------------------------------------+ .. toctree:: reducing_functions +---------------------------------------+----------------------------------------------------+ | :ref:`sum ` | sum of elements over given axes | +---------------------------------------+----------------------------------------------------+ | :ref:`prod ` | product of elements over given axes | +---------------------------------------+----------------------------------------------------+ | :ref:`mean ` | mean of elements over given axes | +---------------------------------------+----------------------------------------------------+ xtensor-0.10.11/docs/source/api/xrandom.rst000066400000000000000000000012111314655136400205620ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xrandom ======= Defined in ``xtensor/xrandom.hpp`` .. doxygenfunction:: xt::random::get_default_random_engine :project: xtensor .. doxygenfunction:: xt::random::seed :project: xtensor .. doxygenfunction:: xt::random::rand(const S&, T, T, E&) :project: xtensor .. doxygenfunction:: xt::random::randint(const S&, T, T, E&) :project: xtensor .. doxygenfunction:: xt::random::randn(const S&, T, T, E&) :project: xtensor xtensor-0.10.11/docs/source/api/xreducer.rst000066400000000000000000000006221314655136400207400ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xreducer ======== Defined in ``xtensor/xreducer.hpp`` .. doxygenclass:: xt::xreducer :project: xtensor :members: .. doxygenfunction:: xt::reduce(F&&, E&&, X&&) :project: xtensor xtensor-0.10.11/docs/source/api/xsemantic_base.rst000066400000000000000000000005401314655136400221030ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xsemantic_base ============== Defined in ``xtensor/xsemantic.hpp`` .. doxygenclass:: xt::xsemantic_base :project: xtensor :members: xtensor-0.10.11/docs/source/api/xtensor.rst000066400000000000000000000006111314655136400206170ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xtensor ======= Defined in ``xtensor/xtensor.hpp`` .. doxygenclass:: xt::xtensor_container :project: xtensor :members: .. doxygentypedef:: xt::xtensor :project: xtensor xtensor-0.10.11/docs/source/api/xtensor_adaptor.rst000066400000000000000000000020171314655136400223330ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xtensor_adaptor =============== Defined in ``xtensor/xtensor.hpp`` .. doxygenclass:: xt::xtensor_adaptor :project: xtensor :members: xadapt (xtensor_adaptor) ======================== Defined in ``xtensor/xadapt.hpp`` .. doxygenfunction:: xt::xadapt(C&, const std::array&, layout_type) :project: xtensor .. doxygenfunction:: xt::xadapt(C&, const std::array&, const std::array&) :project: xtensor .. doxygenfunction:: xt::xadapt(P&, typename A::size_type, O, const std::array&, layout_type, const A&) :project: xtensor .. doxygenfunction:: xt::xadapt(P&, typename A::size_type, O, const std::array&, const std::array&, const A&) :project: xtensor xtensor-0.10.11/docs/source/api/xview.rst000066400000000000000000000011731314655136400202630ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xview ===== Defined in ``xtensor/xview.hpp`` .. doxygenclass:: xt::xview :project: xtensor :members: .. doxygenfunction:: xt::view :project: xtensor Defined in ``xtensor/xslice.hpp`` .. doxygenfunction:: xt::range(T, T) :project: xtensor .. doxygenfunction:: xt::range(T, T, T) :project: xtensor .. doxygenfunction:: xt::all :project: xtensor .. doxygenfunction:: xt::newaxis :project: xtensor xtensor-0.10.11/docs/source/api/xview_semantic.rst000066400000000000000000000005401314655136400221430ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. xview_semantic ============== Defined in ``xtensor/xsemantic.hpp`` .. doxygenclass:: xt::xview_semantic :project: xtensor :members: xtensor-0.10.11/docs/source/basic_usage.rst000066400000000000000000000027641314655136400206240ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Basic usage =========== **Initialize a 2-D array and compute the sum of one of its rows and a 1-D array.** .. code:: #include #include "xtensor/xarray.hpp" #include "xtensor/xio.hpp" xt::xarray arr1 {{1.0, 2.0, 3.0}, {2.0, 5.0, 7.0}, {2.0, 5.0, 7.0}}; xt::xarray arr2 {5.0, 6.0, 7.0}; xt::xarray res = xt::view(arr1, 1) + arr2; std::cout << res; Outputs: .. code:: {7, 11, 14} **Initialize a 1-D array and reshape it inplace.** .. code:: #include #include "xtensor/xarray.hpp" #include "xtensor/xio.hpp" xt::xarray arr {1, 2, 3, 4, 5, 6, 7, 8, 9}; arr.reshape({3, 3}); std::cout << arr; Outputs: .. code:: {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} **Broadcasting the** ``xt::pow`` **universal functions.** .. code:: #include #include "xtensor/xarray.hpp" #include "xtensor/xmath.hpp" #include "xtensor/xio.hpp" xt::xarray arr1 {1.0, 2.0, 3.0}; xt::xarray arr2 {4, 5, 6, 7}; arr2.reshape({4, 1}); xt::xarray res = xt::pow(arr1, arr2); std::cout << res; Outputs: .. code:: {{1, 16, 81}, {1, 32, 243}, {1, 64, 729}, {1, 128, 2187}} xtensor-0.10.11/docs/source/build-options.rst000066400000000000000000000044561314655136400211470ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Build and configuration ======================= Build ----- ``xtensor`` build supports the following options: - ``BUILD_TESTS``: enables the ``xtest`` and ``xbenchmark`` targets (see below). - ``DOWNLOAD_GTEST``: downloads ``gtest`` and builds it locally instead of using a binary installation. - ``GTEST_SRC_DIR``: indicates where to find the ``gtest`` sources instead of downloading them. - ``XTENSOR_ENABLE_ASSERT``: activates the assertions in ``xtensor``. All these options are disabled by default. Enabling ``DOWNLOAD_GTEST`` or setting ``GTEST_SRC_DIR`` enables ``BUILD_TESTS``. If the ``BUILD_TESTS`` option is enabled, the following targets are available: - xtest: builds an run the test suite. - xbenchmark: builds and runs the benchmarks. For instance, building the test suite of ``xtensor`` with assertions enabled: .. code:: mkdir build cd build cmake -DBUILD_TESTS=ON -DXTENSOR_ENABLE_ASSERT=ON ../ make xtest Building the test suite of ``xtensor`` where the sources of ``gtest`` are located in e.g. ``/usr/share/gtest``: .. code:: mkdir build cd build cmake -DGTEST_SRC_DIR=/usr/share/gtest ../ make xtest Configuration ------------- ``xtensor`` can be configured via macros, which must be defined *before* including any of its header. Here is a list of available macros: - ``XTENSOR_ENABLE_ASSERT``: enables assertions in xtensor, such as bound check. - ``DEFAULT_DATA_CONTAINER(T, A)``: defines the type used as the default data container for tensors and arrays. ``T`` is the ``value_type`` of the container and ``A`` its ``allocator_type``. - ``DEFAULT_SHAPE_CONTAINER(T, EA, SA)``: defines the type used as the default shape container for tensors and arrays. ``T`` is the ``value_type`` of the data container, ``EA`` its ``allocator_type``, and ``SA`` is the ``allocator_type`` of the shape container. - ``DEFAULT_LAYOUT``: defines the default layout (row_major, column_major, dynamic) for tensors and arrays. We *strongly* discourage using this macro, which is provided for testing purpose. Prefer defining alias types on tensor and array containers instead. xtensor-0.10.11/docs/source/builder.rst000066400000000000000000000044721314655136400200030ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Expression builders =================== `xtensor` provides functions to ease the build of common N-dimensional expressions. The expressions returned by these functions implement the lazyness of `xtensor`, that is, they don't hold any value. Values are computed upon request. Ones and zeros -------------- - ``zeros(shape)``: generates an expression containing zeros of the specified shape. - ``ones(shape)``: generates an expression containing ones of the specified shape. - ``eye(shape, k=0)``: generates an expression of the specified shape, with ones on the k-th diagonal. - ``eye(n, k = 0)``: generates a n x n expression with ones on the k-th diagonal. Numerical ranges ---------------- - ``arange(start=0, stop, step=1)``: generates numbers evenly spaced within given half-open interval. - ``linspace(start, stop, num_samples)``: generates num_samples evenly spaced numbers over given interval. - ``logspace(start, stop, num_samples)``: generates num_samples evenly spaced on a log scale over given interval Joining expressions ------------------- - ``concatenate(tuple, axis=0)``: concatenates a list of expressions along the given axis. - ``stack(tuple, axis=0)``: stacks a list of expressions along the given axis. Random distributions -------------------- - ``rand(shape, lower, upper)``: generates an expression of the specified shape, containing uniformly distributed random numbers in the half-open interval [lower, upper). - ``randint(shape, lower, upper)``: generates an expression of the specified shape, containing uniformly distributed random integers in the half-open interval [lower, upper). - ``randn(shape, mean, std_dev)``: generates an expression of the specified shape, containing numbers sampled from the Normal random number distribution. Meshes ------ - ``meshgrid(x1, x2,...)```: generates N-D coordinate expressions given one-dimensional coordinate arrays ``x1``, ``x2``... If specified vectors have lengths ``Ni = len(xi)``, meshgrid returns ``(N1, N2, N3,..., Nn)``-shaped arrays, with the elements of xi repeated to fill the matrix along the first dimension for x1, the second for x2 and so on. xtensor-0.10.11/docs/source/closure-semantics.rst000066400000000000000000000166301314655136400220140ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Closure semantics ================= The ``xtensor`` library is a tensor expression library implementing numpy-style broadcasting and universal functions, but in a lazy fashion. If ``x`` and ``y`` are two tensor expressions with compatible shapes, the result of ``x + y`` is not a tensor but an expression that does not hold any value. Values of ``x + y`` are computed upon access or when the result is assigned to a container such as ``xt::xtensor`` or ``xt::xarray``. The same holds for most functions in xtensor, views, broadcasting views, etc. In order to be able to perform the differed computation of ``x + y``, the returned expression must hold references, const references or copies of the members ``x`` and ``y``, depending on how arguments were passed to ``operator+``. The actual types of held by the expressions are the **closure types**. The concept of closure type is key in the implementation of ``xtensor`` and appears in all the expressions defined in xtensor, and the utility functions and meta functions complements the tools of the standard libary for the move semantics. Basic rules for determinning closure types ------------------------------------------ The two main requirements are the following: - when an argument passed to the function returning an expression (here, ``operator+``) is an *rvalue*, the closure type is always a value and the ``rvalue`` is *moved*. - when an argument passed to the function returning an expression is an *lvalue reference*, the closure type is a reference of the same type. It is important for the closure type not to be a reference when the passed argument is an rvalue, which can result in dangling references. Following the conventions of the C++ standard library for naming type traits, we provide two type traits classes providing an implementation of these rules in the ``xutils.hpp`` header, ``closure``, and ``const_closure``. The latter adds the const qualifier even when the provided argument is not const. .. code:: cpp template struct closure { using underlying_type = std::conditional_t< std::is_const>::value, const std::decay_t, std::decay_t>; using type = typename std::conditional< std::is_lvalue_reference::value, underlying_type&, underlying_type>::type; }; template using closure_t = typename closure::type; The implementation for ``const_closure`` is slightly shorter. .. code:: cpp template struct const_closure { using underlying_type = const std::decay_t; using type = typename std::conditional< std::is_lvalue_reference::value, underlying_type&, underlying_type>::type; }; template using const_closure_t = typename const_closure::type; Using this mechanism, we were able to - avoid dangling references in nested expressions, - hold references whenever possible, - take advantage of the move semantics when holding references is not possible. Closure types and scalar wrappers --------------------------------- A requirement for ``xtensor`` is the ability to mix scalars and tensors in tensor expressions. In order to do so, scalar values are wrapped into the ``xscalar`` wrapper, which is a cheap 0-D tensor expression holding a single scalar value. For the xscalar to be a proper proxy on the scalar value, if actually holds a closure type on the scalar value. The logics for this is encoded into xtensor's ``xclosure`` type trait. .. code:: cpp template struct xclosure { using type = closure_t; }; template struct xclosure>> { using type = xscalar>; }; template using xclosure_t = typename xclosure::type; In doing so, we ensure const-correctness, we avoid dangling reference, and ensure that lvalues remain lvalues. The `const_xclosure` follows the same scheme: .. code:: cpp template struct const_xclosure { using type = const_closure_t; }; template struct const_xclosure>> { using type = xscalar>; }; template using const_xclosure_t = typename const_xclosure::type; Writing functions that return expressions ----------------------------------------- *xtensor closure semantics are not meant to prevent users from doing mistakes, since it would also prevent them from doing something clever*. This section covers cases where understanding C++ move semantics and xtensor closure semantics helps writing better code with xtensor. Returning evaluated or unevaluated expressions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A key feature of xtensor is that a function returning e.g. ``x + y / z`` where ``x``, ``y`` and ``z`` are xtensor expressions does not actually perform any computation. It is only evaluated upon access or assignment. The returned expression holds values or references for ``x``, ``y`` and ``z`` depending on the lvalue-ness of the variables passed to the expression, using the *closure semantics* described earlier. This may result in dangling references when using local variables of a function in an unevaluated expression, unless one properly forwards / move the variables. .. note:: The following rule of thumbs prevents dangling references in the xtensor closure semantics: - If the laziness is not important for your usecase, returning ``xt::eval(x + y / z)`` will return an evaluated container and avoid these complications. - Otherwise, the key is to *move* lvalues that become invalid when leaving the current scope. **Example: moving local variables and forwarding universal references** Let us first consider the following implementation of the ``mean`` function in xtensor: .. raw:: html .. code:: cpp template inline auto mean(E&& e) noexcept { using value_type = typename std::decay_t::value_type; auto size = e.size(); auto s = sum(std::forward(e)); return std::move(s) / value_type(size); } The first thing to take into account is that the result of the final division is an expression, which performs the actual computation upon access or assignent. - In order to perform the division, the expression must hold the values or references on the numerator and denominator. - Since ``s`` is a local variable, it will be destroyed upon leaving the scope of the function, and more importantly it is an *lvalue*. - A consequence of ``s`` being an lvalue and a local variable, is that the ``s / value_type(size)`` would end up holding a dangling const reference on ``s``. - Hence we must call return ``std::move(s) / value_type(size)``. The other place in this example where the C++ move semantics is used is the line ``s = sum(std::forward(e))``. The goal is to have the unevaluated ``s`` expression hold a const reference or a value for ``e`` depending on the lvalue-ness of the parameter passed to the function. xtensor-0.10.11/docs/source/cmake.svg000066400000000000000000000425311314655136400174220ustar00rootroot00000000000000 image/svg+xml xtensor-0.10.11/docs/source/compilers.rst000066400000000000000000000062561314655136400203540ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Compiler workarounds ==================== This page tracks the workarounds for the various compiler issues that we encountered in the development. This is mostly of interest for developers interested in contributing to xtensor. Visual Studio 2015 and ``std::enable_if`` ----------------------------------------- With Visual Studio, ``std::enable_if`` evaluates its second argument, even if the condition is false. This is the reason for the presence of the indirection in the implementation of the ``xfunction_type_t`` meta-function. GCC-4.9 and Clang < 3.8 and constexpr ``std::min`` and ``std::max`` ------------------------------------------------------------------- ``std::min`` and ``std::max`` are not constexpr in these compilers. In ``xio.hpp``, we locally define a ``XTENSOR_MIN`` macro used instead of ``std::min``. The macro is undefined right after it is used. Clang < 3.8 matching ``initializer_list`` with static arrays ------------------------------------------------------------ Old versions of Clang don't handle overload resolution with braced initializer lists correctly: braced initializer lists are not properly matched to static arrays. This prevent compile-time detection of the length of a braced initializer list. A consequence is that we need to use stack-allocated shape types in these cases. Workarounds for this compiler bug arise in various files of the code base. Everywhere, the handling of `Clang < 3.8` is wrapped with checks for the ``X_OLD_CLANG`` macro. GCC < 5.1 and ``std::is_trivially_default_constructible`` --------------------------------------------------------- The version of libstdc++ shipped with GCC older than 5.1 (and also used by Clang on linux) does not implement ``std::is_trivially_default_constructible`` but ``std::has_trivial_default_constructor`` instead. With GCC, this is done with a simple check of the version of GCC. In the case of the clang - linux combination, libstdc++ may be used. Since clang overrides the ``__GNUC__`` macro, the version of libstdc++ used cannot be retrived at runtime and some meta-programming techniques are used to determine which function is available. GCC-6 and the signature of ``std::isnan`` and ``std::isinf`` ------------------------------------------------------------ We are not directly using ``std::isnan`` or ``std::isinf`` for the implementation of ``xt::isnan`` and ``xt::isinf``, as a workaround to the following bug in GCC-6 for the following reason. - C++11 requires that the ```` header declares ``bool std::isnan(double)`` and ``bool std::isinf(double)``. - C99 requires that the ```` header declares ``int ::isnan(double)`` and ``int ::isinf(double)``. These two definitions would clash when importing both headers and using namespace std. As of version 6, GCC detects whether the obsolete functions are present in the C ```` header and uses them if they are, avoiding the clash. However, this means that the function might return int instead of bool as C++11 requires, which is a bug. xtensor-0.10.11/docs/source/conda.svg000066400000000000000000000034151314655136400174240ustar00rootroot00000000000000xtensor-0.10.11/docs/source/conf.py000066400000000000000000000013531314655136400171150ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import subprocess on_rtd = os.environ.get('READTHEDOCS', None) == 'True' if on_rtd: subprocess.call('cd ..; doxygen', shell=True) import sphinx_rtd_theme html_theme = "sphinx_rtd_theme" html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] extensions = ['breathe'] breathe_projects = { 'xtensor': '../xml' } templates_path = ['_templates'] source_suffix = '.rst' master_doc = 'index' project = 'xtensor' copyright = '2016, Johan Mabille and Sylvain Corlay' author = 'Johan Mabille and Sylvain Corlay' html_logo = 'quantstack-white.svg' exclude_patterns = [] highlight_language = 'c++' pygments_style = 'sphinx' todo_include_todos = False htmlhelp_basename = 'xtensordoc' xtensor-0.10.11/docs/source/container.rst000066400000000000000000000166231314655136400203400ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Arrays and tensors ================== Internal memory layout ---------------------- A multi-dimensional array of `xtensor` consists of a contiguous one-dimensional buffer combined with an indexing scheme that maps unsigned integers to the location of an element in the buffer. The range in which the indices can vary is specified by the `shape` of the array. The scheme used to map indices into a location in the buffer is a strided index scheme. In such a scheme, the index ``(i0, ..., in)`` corresponds to the offset ``sum(ik * sk)`` from the beginning of the one-dimensional buffer, where ``(s0, ..., sn)`` are the `strides` of the array. Some particular cases of strided schemes implement well known memory layouts: - the row-major layout (or C layout) is a strided index scheme where the strides grow from right to left - the column-major layout (or Fortran layout) is a strided index scheme where the strides grow from left to right ``xtensor`` provides a ``layout_type`` enum that helps to specify the layout used by multi-dimensional arrays. This enum can be used in two ways: - at compile time, as a template argument. The value ``layout_type::dynamic`` allows to specify any strided index scheme at runtime (including row-major and column-major schemes), whereas ``layout_type::row_major`` and ``layout_type::column_major`` fixes the strided index scheme and disable ``reshape`` and constructor overloads taking a set of strides or a layout value as parameter. The default value of the template parameter is ``DEFAULT_LAYOUT``. - at runtime if the previous template parameter was set to ``layout_type::dynamic``. In that case, ``reshape`` and constructor overloads allow to aspecify a set of strides or a layout value to avoid strides computation. If neither strides nor layout is specified when instantiating or reshaping a multi-dimensional array, strides corresponding to ``DEFAULT_LAYOUT`` are used. The following example shows how to initialize a multi-dimensional array of dynamic layout with specified strides: .. code:: #include #include "xtensor/xarray.hpp" std::vector shape = { 3, 2, 4 }; std::vector strides = { 8, 4, 1 }; xt::xarray a(shape, strides); However, this requires to carefully compute the strides to avoid buffer overflow when accessing elements of the array. We can use the layout shortcut to specify the strides instead of computing them: .. code:: #include #include "xtensor/xarray.hpp" std::vector shape = { 3, 2, 4 }; xt::xarray a(shape, xt::layout::row_major); If the layout of the array can be fixed at compile time, we can even do simpler: .. code:: #include #include "xtensor/xarray.hpp" std::vector shape = { 3, 2, 4 }; xt::xarray a(shape); However, in that latter case, the layout of the array is forced to ``row_major`` at compile time, and therefore cannot be changed at runtime. Runtime vs Compile-time dimensionality -------------------------------------- Two container classes implementing multi-dimensional arrays are provided: ``xarray`` and ``xtensor``. - ``xarray`` can be reshaped dynamically to any number of dimensions. It is the container that is the most similar to numpy arrays. - ``xtensor`` has a dimension set at compilation time, which enables many optimizations. For example, shapes and strides of ``xtensor`` instances are allocated on the stack instead of the heap. ``xarray`` and ``xtensor`` containers are both ``xexpression`` s and can be involved and mixed in mathematical expressions, assigned to each other etc... They provide an augmented interface compared to other ``xexpression`` types: - Each method exposed in ``xexpression`` interface has its non-const counterpart exposed by both ``xarray`` and ``xtensor``. - ``reshape()`` reshapes the container in place, that is, if the global size of the container doesn't change, no memory allocation occurs. - ``transpose()`` transposes the container in place, that is, no memory allocation occurs. - ``strides()`` returns the strides of the container, used to compute the position of an element in the underlying buffer. Performance ----------- The dynamic dimensionality of ``xarray`` comes at a cost. Since the dimension is unknown at build time, the sequences holding shape and strides of ``xarray`` instances are heap-allocated, which makes it significantly more expansive than ``xtensor``. Shape and strides of ``xtensor`` are stack-allocated which makes them more efficient. More generally, the library implements a ``promote_shape`` mechanism at build time to determine the optimal sequence type to hold the shape of an expression. The shape type of a broadcasting expression whose members have a dimensionality determined at compile time will have a stack-allocated shape. If a single member of a broadcasting expression has a dynamic dimension (for example an ``xarray``), it bubbles up to entire broadcasting expression which will have a heap allocated shape. The same hold for views, broadcast expressions, etc... Aliasing and temporaries ------------------------ In some cases, an expression should not be directly assigned to a container. Instead, it has to be assigned to a temporary variable before being copied into the destination container. This occurs when the destination container is involved in the expression and has to be reshaped. This phenomenon is known as *aliasing*. To prevent this, `xtensor` assigns the expression to a temporary variable before copying it. In the case of ``xarray``, this results in an extra dynamic memory allocation and copy. However, if the left-hand side is not involved in the expression being assigned, no temporary variable should be required. `xtensor` cannot detect such cases automatically and applies the "temporary variable rule" by default. A mechanism is provided to forcibly prevent usage of a temporary variable: .. code:: #include "xtensor/xarray.hpp" #include "xtensor/xnoalias.hpp" // a, b, and c are xt::xarrays previously initialized xt::noalias(b) = a + c; // Even if b has to be reshaped, a+c will be assigned directly to it // No temporary variable will be involved Example of aliasing ~~~~~~~~~~~~~~~~~~~ The aliasing phenomenon is illustrated in the following example: .. code:: #include #include "xtensor/xarray.hpp" std::vector a_shape = {3, 2, 4}; xt::xarray a(a_shape); std::vector b_shape = {2, 4}; xt::xarray b(b_shape); b = a + b; // b appears on both left-hand and right-hand sides of the statement In the above example, the shape of ``a + b`` is ``{ 3, 2, 4 }``. Therefore, ``b`` must first be reshaped, which impacts how the right-hand side is computed. If the values of ``b`` were copied into the new buffer directly without an intermediary variable, then we would have ``new_b(0, i, j) == old_b(i, j) for (i,j) in [0,1] x [0, 3]``. After the reshape of ``bb``, ``a(0, i, j) + b(0, i, j)`` is assigned to ``b(0, i, j)``, then, due to broadcasting rules, ``a(1, i, j) + b(0, i, j)`` is assigned to ``b(1, i, j)``. The issue is ``b(0, i, j)`` has been changed by the previous assignment. xtensor-0.10.11/docs/source/debian.svg000066400000000000000000000153171314655136400175660ustar00rootroot00000000000000 ]> xtensor-0.10.11/docs/source/expression.rst000066400000000000000000000174761314655136400205640ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Expressions and lazy evaluation =============================== `xtensor` is more than an N-dimensional array library: it is an expression engine that allows numerical computation on any object implementing the expression interface. These objects can be in-memory containers such as ``xarray`` and ``xtensor``, but can also be backed by a database or a representation on the file system. This also enables creating adaptors as expressions for other data structures. Expressions ----------- Assume ``x``, ``y`` and ``z`` are arrays of *compatible shapes* (we'll come back to that later), the return type of an expression such as ``x + y * sin(z)`` is **not an array**. The result is an ``xexpression`` which offers the same interface as an N-dimensional array but does not hold any value. Such expressions can be plugged into others to build more complex expressions: .. code:: auto f = x + y * sin(z); auto f2 = w + 2 * cos(f); The expression engine avoids the evaluation of intermediate results and their storage in temporary arrays, so you can achieve the same performance as if you had written a simple loop. Assuming ``x``, ``y`` and ``z`` are one-dimensional arrays of length ``n``, .. code:: xt::xarray res = x + y * sin(z) will produce quite the same assembly as the following loop: .. code:: xt::xarray res(n); for(size_t i = 0; i < n; ++i) { res(i) = x(i) + y(i) * sin(z(i)); } Lazy evaluation --------------- An expression such as ``x + y * sin(z)`` does not hold the result. **Values are only computed upon access or when the expression is assigned to a container**. This allows to operate symbolically on very large arrays and only compute the result for the indices of interest: .. code:: // Assume x and y are xarrays each containing 1 000 000 objects auto f = cos(x) + sin(y); double first_res = f(1200); double second_res = f(2500); // Only two values have been computed That means if you use the same expression in two assign statements, the computation of the expression will be done twice. Depending on the complexity of the computation and the size of the data, it might be convenient to store the result of the expression in a temporary variable: .. code:: // Assume x and y are small arrays xt::xarray tmp = cos(x) + sin(y); xt::xarray res1 = tmp + 2 * x; xt::xarray res2 = tmp - 2 * x; Forcing evaluation ------------------ If you have to force the evaluation of an xexpression for some reason (for example, you want to have all results in memory to perform a sort, or use external BLAS functions) then you can use ``xt::eval`` on an xexpression. Evaluating will either return an rvalue to a newly allocated container in the case of a xexpression, or a reference to a container in case you are evaluating a ``xarray`` or ``xtensor``. Note that, in order to avoid copies, you should use an universal reference on the lefthand side (``auto&&``). For example: .. code:: xt::xarray a = {1, 2, 3}; xt::xarray b = {3, 2, 1}; auto calc = a + b; // unevaluated xexpression! auto&& e = xt::eval(calc); // a rvalue container xarray! // this just returns a reference to the existing container auto&& a_ref = xt::eval(a); Broadcasting ------------ The number of dimensions of an ``xexpression`` and the sizes of these dimensions are provided by the ``shape()`` method, which returns a sequence of unsigned integers specifying the size of each dimension. We can operate on expressions of different shapes of dimensions in a elementwise fashion. Broadcasting rules of `xtensor` are similar to those of Numpy_ and libdynd_. In an operation involving two arrays of different dimensions, the array with the lesser dimensions is broadcast across the leading dimensions of the other. For example, if ``A`` has shape ``(2, 3)``, and ``B`` has shape ``(4, 2, 3)``, the result of a broadcasted operation with ``A`` and ``B`` has shape ``(4, 2, 3)``. .. code:: (2, 3) # A (4, 2, 3) # B --------- (4, 2, 3) # Result The same rule holds for scalars, which are handled as 0-D expressions. If `A` is a scalar, the equation becomes: .. code:: () # A (4, 2, 3) # B --------- (4, 2, 3) # Result If matched up dimensions of two input arrays are different, and one of them has size ``1``, it is broadcast to match the size of the other. Let's say B has the shape ``(4, 2, 1)`` in the previous example, so the broadcasting happens as follows: .. code:: (2, 3) # A (4, 2, 1) # B --------- (4, 2, 3) # Result Expression interface -------------------- All ``xexpression`` s in `xtensor` provide at least the following interface: Shape ~~~~~ - ``dimension()`` returns the number of dimension of the expression. - ``shape()`` returns the shape of the expression. .. code:: #include #include "xtensor/xarray.hpp" std::vector shape = {3, 2, 4}; xt::xarray a(shape); size_t d = a.dimension(); const std::vector& s = a.shape(); bool res = (d == shape.size()) && (s == shape); // => res = true Element access ~~~~~~~~~~~~~~ - ``operator()`` is an access operator which can take multiple integral arguments of none. - ``operator[]`` has two overloads: one that takes a single integral argument and is equivalent to the call of ``operator()`` with one argument, and one with a single multi-index argument, which can be of size determined at runtime. This operator also supports braced initializer arguments. - ``element()`` is an access operator which takes a pair of iterators on a container of indices. .. code:: #include #inclde "xtensor/xarray.hpp" // xt::xarray a = ... std::vector index = {1, 1, 1}; double v1 = a(1, 1, 1); double v2 = a[index], double v3 = a.element(index.begin(), index.end()); // => v1 = v2 = v3 Iterators ~~~~~~~~~ - ``xbegin()`` and ``xend()`` return instances of ``xiterator`` which can be used to iterate over all the elements of the expression. The layout of the iteration can be specified through the ``layout_type`` template parameter, accepted values are ``layout_type::row_major`` and ``layout_type::column_major``. If not specified, ``DEFAULT_LAYOUT`` is used. This iterator pair permits to use algorithms of the STL with ``xexpression`` as if they were simple containers. - ``xbegin(shape)`` and ``xend(shape)`` are similar but take a *broadcasting shape* as an argument. Elements are iterated upon in ``DEFAULT_LAYOUT`` if no ``layout_type`` template parameter is specified. Certain dimensions are repeated to match the provided shape as per the rules described above. For an expression ``e``, ``e.xbegin(e.shape())`` and ``e.begin()`` are equivalent. - ``begin()`` and ``end()`` return iterators on the buffer containing the elements of the ``xexpression`` when it is an in-memory container. Otherwise, they are similar to ``xbegin()`` and ``xend()`` with default ``layout_type`` parameter. For in-memory containers, the iteration is done directly on the buffer and may be faster than the one provided by ``xbegin()`` / ``xend()`` . - ``xrbegin()`` and ``xrend()`` return instances of ``xiterator`` which can be used to iterate over all the elements of the reversed expression. As ``xbegin()`` and ``xend()``, the layout of the iteration can be specified through the ``layout_type`` parameter. - ``xrbegin(shape)`` and ``xrend(shape)`` are the reversed counterpart of ``xbegin(shape)`` and ``xend(shape)``. - ``rbegin()`` and ``rend()`` are the reversed counterpart of ``begin()`` and ``end()``. .. _NumPy: http://www.numpy.org .. _libdynd: http://libdynd.org xtensor-0.10.11/docs/source/external-structures.rst000066400000000000000000000353551314655136400224240ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Extending xtensor ================= ``xtensor`` provides means to plug external data structures into its expression engine without copying any data. Adapting one-dimensional containers ----------------------------------- You may want to use your own one-dimensional container as a backend for tensor data containers and even for the shape or the strides. This is the simplest structure to plug into ``xtensor``. In the following example, we define new container and adaptor types for user-specified storage and shape types. .. code:: // Assuming container_type and shape_type are third-party library containers using my_array_type = xt::xarray_container; using my_adaptor_type = xt::xarray_adaptor; // Or, working with a fixed number of dimensions using my_tensor_type = xt::xtensor_container; using my_adaptor_type = xt::xtensor_adaptor; These new types will have all the features of the core ``xt::xtensor`` and ``xt::xarray`` types. ``xt::xarray_container`` and ``xt::xtensor_container`` embed the data container, while ``xt::xarray_adaptor`` and ``xt::xtensor_adaptor`` hold a reference on an already initialized container. A requirement for the user-specified containers is to provide a minimal ``std::vector``-like interface, that is: - usual typedefs for STL sequences - random access methods (``operator[]``, ``front``, ``back`` and ``data``) - iterator methods (``begin``, ``end``, ``cbegin``, ``cend``) - ``size`` and ``resize`` methods ``xtensor`` does not require that the container has a contiguous memory layout, only that it provides the aforementioned interface. In fact, the container could even be backed by a file on the disk, a database or a binary message. Structures that embed shape and strides --------------------------------------- Some structures may gather data container, shape and strides, making them impossible to plug into ``xtensor`` with the method above. This section illustrates how to adapt such structures with the following simple example: .. code:: template struct raw_tensor { using container_type = std::vector; using shape_type = std::vector; container_type m_data; shape_type m_shape; shape_type m_strides; shape_type m_backstrides; }; Define inner types ~~~~~~~~~~~~~~~~~~ The following tells ``xtensor`` which types must be used for getting shape, strides, and data: .. code:: template struct xcontainer_inner_types> { using container_type = typename raw_tensor::container_type; using inner_shape_type = typename raw_tensor::shape_type; using inner_strides_type = inner_shape_type; using inner_backstrides_type = inner_shape_type; using shape_type = inner_shape_type; using strides_type = inner_shape_type; using backstrides_type = inner_shape_type; }; The ``inner_XXX_type`` are the types used to store and read the shape, strides an backstrides, while the other ones are used for reshaping. Most of the time, they will be the same; differences come when inner types cannot be instantiated out of the box (because they are linked to python buffer for instance). Next, bring all the iterable features with this simple definition: .. code:: template struct xiterable_inner_types> : xcontainer_iteratble_types> { }; Inherit ~~~~~~~ Next step is to inherit from the ``xcontainer`` and the ``xcontainer_semantic`` classes: .. code:: template class raw_tensor_adaptor : public xcontainer>, public xcontainer_semantic> { ... }; Thanks to the previous structures definition, inheriting from ``xcontainer`` brings almost all the container API available in the other entities of ``xtensor``, while inheriting from ``xtensor_semantic`` brings the support for mathematical operations. NOTE: if we were to design a class that takes a reference on ``raw_tensor`` instead of embedding an instance, we would inherit from ``xadaptor_semantic`` instead of ``xcontainer_semantic``. Define semantic ~~~~~~~~~~~~~~~ ``xtensor`` classes have full value semantic, so you may define the constructors specific to your structures, and use the default copy and move constructors and assign operators. Note these last ones *must* be declared as they are declared as ``protected`` in the base class. .. code:: template class raw_tensor_adaptor : public xcontainer>, public xcontainer_semantic> { public: using self_type = raw_tensor_adaptor; using base_type = xcontainer; using semantic_base = xcontainer_semantic; // ... specific constructors here raw_tensor_adaptor(const raw_tensor_adaptor&) = default; raw_tensor_adaptor& operator=(const raw_tensor_adaptor&) = default; raw_tensor_adaptor(raw_tensor_adaptor&&) = default; raw_tensor_adaptor& operator=(raw_tensor_adaptor&&) = default; template raw_tensor_type(const xexpression& e) : base_type() { semantic_base::assign(e); } template self_type& operator=(const xexpression& e) { return semantic_base::operator=(e); } }; The last two methods are extended copy constructor and assign operator. They allow to write things like .. code:: using tensor_type = raw_tensor_adaptor; tensor_type a, b, c; // .... init a, b and c tnesor_type d = a + b - c; Implement the reshape methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The next methods to define are the overloads of ``reshape``. ``xtensor`` provides utilities functions to compute strides based on the shape and the layout, so the implementation of the ``reshape`` overloads is straightforward: .. code:: #include "xtensor/xstrides.hpp" // for utitilities functions template void reshape(const shape_type& shape) { if(m_shape != shape) reshape(shape, layout::row_major); } template void reshape(const shape_type& shape, layout l) { m_raw.m_shape = shape; m_raw.m_strides.resize(shape.size()); m_raw.m_backstrides.resize(shape.size()); size_type data_size = compute_strides(m_shape, l, m_strides, m_backstrides); m_raw.m_data.resize(data_size); } template void reshape(const shape_type& shape, const strides_type& strides) { m_raw.m_shape = shape; m_raw.m_strides = strides; m_raw.m_backstrides.resize(shape.size()); adapt_strides(m_raw.m_shape, m_raw.m_strides, m_raw.m_backstrides); m_raw.m_data.resize(compute_size(m_shape)); } Implement private accessors ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``xcontainer`` assume the following methods are implemented in its inheriting class: .. code:: inner_shape_type& shape_impl(); const inner_shape_type& shape_impl() const; inner_strides_type& strides_impl(); const inner_strides_type& strides_impl() const; inner_backstrides_type& backstrides_impl(); const inner_backstrides_type& backstrides_impl() const; However, since ``xcontainer`` provides a public API for getting the shape and the strides, these methods should be declared ``protected`` or ``private`` and ``xcontainer`` should be declared as a friend class so that it can access them. Embedding a full tensor structure --------------------------------- You may need to plug structures that already provide n-dimensional access methods, instead of a one-dimensional container with a strided index scheme. This section illustrates how to adapt such structures with the following (minimal) API: .. code:: template class table { public: using shape_type = std::vector; const shape_type& shape() const; template T& operator()(Args... args); template const T& operator()(Args... args) const; template T& element(It first, It last); template const T& element(It first, It last) const; }; Define inner types ~~~~~~~~~~~~~~~~~~ The following definitions are required: .. code:: template struct xcontainer_inner_type> { using temporary_type = table; }; template struct xiterable_inner_types> { using inner_shape_type = typename table::shape_type; using stepper = xindexed_stepper, false>; using const_stepper = xindexed_stepper, true>; using iterator = xiterator; using const_iterator = xiterator; using broadcast_iterator = iterator; using const_broadcast_iterator = const_iterator; }; Inheritance ~~~~~~~~~~~ Next step is to inherit from the ``xiterable`` and ``xcontainer_semantic`` classes, and to define a bunch of typedefs. .. code:: template class table_adaptor : public xexpression_iterable>, public xcontainer_semantic> { public: using self_type = table; using value_type = T; using reference = T&; using const_reference = const T&; using pointer = T*; using const_pointer = const T*; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using inner_shape_type = typename table::shape_type; using inner_stride_stype = inner_shape_type; using shape_type = inner_shape_type; using strides_type = inner_strides_type; using iterable_base = xexpression_iterable; using stepper = typename iterable_base::stepper; using const_stepper = typename iterable_base::const_stepper; using iterator = typename iterable_base::iterator; using const_iterator = typename iterable_base::const_iterator; using broadcast_iterator = typename iterable_base::iterator; using const_broadcast_iterator = typename iterable_base::const_broadcast_iterator; }; The iterator and stepper used here may not be the most optimal for ``table``, however they are guaranteed to work as long as ``table`` provides an access operator based on indices. NOTE: we inherit from ``xcontainer_semantic`` because we assume the ``table_adaptor`` class embeds an instance of ``table``. If it tooks a reference on it, we would inherit from ``xadaptor_semantic`` instead. Define semantic ~~~~~~~~~~~~~~~ As for one-dimensional containers adaptors, you must define constructors and at least declare default copy and move constuctor and assign operator. You also must define extended copy constructor and assign operator. .. code:: template class table_adaptor : public xexpression_iterable>, public xcontainer_semantic> { public: // .... typedefs // .... specific constructors table_adaptor(const table_adaptor&) = default; table_adaptor& operator=(const table_adaptor&) = default; table_adaptor(table_adaptor&&) = default; table_adaptor& operator=(table_adaptor&&) = default; template table_adaptor(const xexpression& e) : base_type() { semantic_base::assign(e); } template self_type& operator=(const xexpression& e) { return semantic_base::operator=(e); } }; Implement access operators ~~~~~~~~~~~~~~~~~~~~~~~~~~ ``xtensor`` requires that the following access operators are defined .. code:: template reference operator()(Args... args) { // Should forward to table:operator()(args...) } template const_reference operator()(Args... args) const { // Should forward to table::operator()(args...) } reference operator[](const xindex& index) { return element(index.cbegin(), index.cend()); } const_reference operator[](const xindex& index) const { return element(index.cbegin(), index.cend()); } reference operator[](size_type i) { return operator()(i); } const_reference operator[](size_type i) const { return operator()(i); } template reference element(It first, It last) { // Should forward to table::element(first, last) } template const_reference element(It first, It last) { // Should forward to table::element(first, last) } Implement broadcast mechanic ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This part is relatively straightforward: .. code:: size_type dimension() const { return shape().size(); } const shape_type& shape() const { // Should forward to table::shape() } template bool broadcast_shape(const S& s) const { // Available in "xtensor/xtrides.hpp" return xt::broadcast_shape(shape(), s); } template bool is_trivial_broadcast(const S& str) const noexcept { return false; } Implement reshape overloads ~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is very similar to what must be done for one-dimensional containers, except you may ignore the layout and the strides in the implementation. However, these overloads are still required. Provide a stepper API ~~~~~~~~~~~~~~~~~~~~~ The last required step is to provide a stepper API, on which are built iterators. .. code:: template stepper stepper_begin(const ST& s) { size_type offset = s.size() - dimension(); return stepper(this, offset); } template stepper stepper_end(const ST& s) { size_type offset = s.size() - dimension(); return stepper(this, offset, true); } template const_stepper stepper_begin(const ST& s) const { size_type offset = s.size() - dimension(); return const_stepper(this, offset); } template const_stepper stepper_end(const ST& s) const { size_type offset = s.size() - dimension(); return const_stepper(this, offset, true); } xtensor-0.10.11/docs/source/index.rst000066400000000000000000000043201314655136400174540ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. .. image:: xtensor.svg :alt: xtensor Multi-dimensional arrays with broadcasting and lazy computing. Introduction ------------ `xtensor` is a C++ library meant for numerical analysis with multi-dimensional array expressions. `xtensor` provides - an extensible expression system enabling **lazy broadcasting**. - an API following the idioms of the **C++ standard library**. - tools to manipulate array expressions and build upon `xtensor`. Containers of `xtensor` are inspired by `NumPy`_, the Python array programming library. **Adaptors** for existing data structures to be plugged into our expression system can easily be written. In fact, `xtensor` can be used to **process numpy data structures inplace** using Python's `buffer protocol`_. For more details on the numpy bindings, check out the xtensor-python_ project. `xtensor` requires a modern C++ compiler supporting C++14. The following C++ compilers are supported: - On Windows platforms, Visual C++ 2015 Update 2, or more recent - On Unix platforms, gcc 4.9 or a recent version of Clang 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. .. toctree:: :caption: INSTALLATION :maxdepth: 2 installation .. toctree:: :caption: USAGE :maxdepth: 2 basic_usage expression container operator view builder missing .. toctree:: :caption: API REFERENCE :maxdepth: 2 api/expression_index api/container_index api/function_index api/xmath .. toctree:: :caption: DEVELOPER ZONE compilers build-options external-structures releasing .. toctree:: :caption: MISCELLANEOUS numpy numpy-differences closure-semantics related .. _NumPy: http://www.numpy.org .. _Buffer Protocol: https://docs.python.org/3/c-api/buffer.html .. _libdynd: http://libdynd.org .. _xtensor-python: https://github.com/QuantStack/xtensor-python xtensor-0.10.11/docs/source/installation.rst000066400000000000000000000032751314655136400210560ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. .. raw:: html Installation ============ Although ``xtensor`` is a header-only library, we provide standardized means to install it, with package managers or with cmake. Besides the xtendor headers, all these methods place the `cmake` project configuration file in the right location so that third-party projects can use cmake's find_package to locate xtensor headers. .. image:: conda.svg Using the conda package ----------------------- A package for xtensor is available on the conda package manager. .. code:: conda install -c conda-forge xtensor .. image:: debian.svg Using the Debian package ------------------------ A package for xtensor is available on Debian. .. code:: sudo apt-get install xtensor-dev .. image:: cmake.svg From source with cmake ---------------------- You can also install ``xtensor`` from source with cmake. On Unix platforms, from the source directory: .. code:: mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=/path/to/prefix .. make install On Windows platforms, from the source directory: .. code:: mkdir build cd build cmake -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=/path/to/prefix .. nmake nmake install See the section of the documentation on :doc:`build-options`, for more details on how to cmake options. xtensor-0.10.11/docs/source/missing.rst000066400000000000000000000055171314655136400200270ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Missing values ============== ``xtensor`` handles missing values and comprises specialized container types for an optimized support of missing values. Optional expressions -------------------- Support of missing values in xtensor is primarily provided through the ``xoptional`` value type and the ``xtensor_optional`` and ``xarray_optional`` containers. In the following example, we instantiate a 2-D tensor with a missing value: .. code:: cpp xtensor_optional m {{ 1.0 , 2.0 }, { 3.0 , missing() }}; This code is semantically equivalent to .. code:: cpp xtensor, 2> m {{ 1.0 , 2.0 }, { 3.0 , missing() }}; The ``xtensor_optional`` container is optimized to handle missing values. Internally, instead of holding a single container of optional values, it holds an array of ``double`` and a boolean container where each value occupies a single bit instead of ``sizeof(bool)`` bytes. The ``xtensor_optional::reference`` typedef, which is the return type of ``operator()`` is a reference proxy which can be used as an lvalue for assigning new values in the array. It happens to be an instance of ``xoptional`` where ``T`` and ``B`` are actually the reference types of the underlying storage for values and boolean flags. This technique enables performance improvements in mathematical operations over boolean arrays including SIMD optimizations, and reduces the memory footprint of optional arrays. It should be transparent to the user. Operating on missing values --------------------------- Arithmetic operators and mathematical universal functions are overloaded for optional values so that they can be operated upon in the same way as regular scalars. .. code:: cpp xtensor_optional a {{ 1.0 , 2.0 }, { 3.0 , missing() }}; xtensor b { 1.0, 2.0 }; // `b` is broadcasted to match the shape of `a` std::cout << a + b << std::endl; outputs: .. code:: {{ 2, 4}, { 4, N/A}} Handling expressions with missing values ---------------------------------------- Functions ``has_value(E&& e)`` and ``value(E&& e)`` return expressions corresponding to the underlying value and flag of optional elements. When ``e`` is an lvalue, ``value(E&& e)`` and ``has_value(E&& e)`` are lvalues too. .. code:: cpp xtensor_optional a {{ 1.0 , 2.0 }, { 3.0 , missing() }}; xtensor b = has_value(a); std::cout << b << std::endl; outputs: .. code:: {{ true, true}, { true, false}} xtensor-0.10.11/docs/source/numpy-differences.rst000066400000000000000000000052341314655136400217750ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Notable differences with numpy ============================== .. image:: numpy.svg :height: 100px :align: right xtensor and numpy are very different libraries in their internal semantics. While xtensor is a lazy expression system, Numpy manipulates in-memory containers, however, similarities in APIs are obvious. See e.g. the numpy to xtensor cheat sheet. And this page tracks the subtle differences of behavior of numpy and xtensor. Zero-dimensional arrays ----------------------- With numpy, 0-D arrays are nearly indistinguishable from scalars. This led to some issues w.r.t. universal functions returning scalars with 0-D array inputs instead of actual arrays... In xtensor, 0-D expressions are not implicitely convertible to scalar values. Values held by 0-D expressions can be accessed in the same way as values of higher dimensional arrays, that is with ``operator[]``, ``operator()`` and ``element``. Meshgrid -------- Numpy's version of meshgrid supports two modes: the 'xy' indexing and the 'ij' indexing. The following code .. code-block:: python import numpy as np x1, x2, x3, x4 = [1], [10, 20], [100, 200, 300], [1000, 2000, 3000, 4000] ij = np.meshgrid(x1, x2, x3, x4, indexing='ij') xy = np.meshgrid(x1, x2, x3, x4, indexing='xy') print 'ij:', [m.shape for m in ij] print 'xy:', [m.shape for m in xy] would return .. code-block:: python ij: [(1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4)] xy: [(2, 1, 3, 4), (2, 1, 3, 4), (2, 1, 3, 4), (2, 1, 3, 4)] In other words, the 'xy' indexing, which is the default only reverses the first two dimensions compared to the 'ij' indexing. xtensor's version of meshgrid corresponds to the 'ij' indexing. The random module ----------------- Like most functions of xtensor, functions of the random module return expressions that don't hold any value. Every time an element is accessed, a new random value is generated. To fix the values of a generator, it should be assigned to a container such as xarray or xtensor. Missing values -------------- Support of missing values in numpy can be emulated with the masked array module, which provides a means to handle arrays that have missing or invalid data. Support of missing values in xtensor is done through a notion of optional values, implemented in ``xoptional``, which serves both as a value type for container and as a reference proxy for optimized storage types. See the section of the documentation on :doc:`missing`. xtensor-0.10.11/docs/source/numpy.rst000066400000000000000000000727171314655136400175340ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. From numpy to xtensor ===================== .. image:: numpy.svg :height: 100px :align: right .. raw:: html Containers ---------- Two container types are provided. ``xarray`` (dynamic number of dimensions) and ``xtensor`` (static number of dimensions). +------------------------------------------------+------------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +================================================+================================================+ | ``np.array([[3, 4], [5, 6]])`` | | ``xt::xarray({{3, 4}, {5, 6}})`` | | | | ``xt::xtensor({{3, 4}, {5, 6}})`` | +------------------------------------------------+------------------------------------------------+ | ``arr.reshape([3, 4])`` | ``arr.reshape{{3, 4})`` | +------------------------------------------------+------------------------------------------------+ Initializers ------------ Lazy helper functions return tensor expressions. Return types don't hold any value and are evaluated upon access or assignment. They can be assigned to a container or directly used in expressions. +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.linspace(1.0, 10.0, 100)`` | ``xt::linspace(1.0, 10.0, 100)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.logspace(2.0, 3.0, 4)`` | ``xt::logspace(2.0, 3.0, 4)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.arange(3, 7)`` | ``xt::arange(3, 7)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.eye(4)`` | ``xt::eye(4)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.zeros([3, 4])`` | ``xt::zeros({3, 4})`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.ones([3, 4])`` | ``xt::ones({3, 4})`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.meshgrid(x0, x1, x2, indexing='ij')`` | ``xt::meshgrid(x0, x1, x2)`` | +-----------------------------------------------+-----------------------------------------------+ xtensor's ``meshgrid`` implementation corresponds to numpy's ``'ij'`` indexing order. Broadcasting ------------ xtensor offers lazy numpy-style broadcasting, and universal functions. Unlike numpy, no copy or temporary variables are created. +-----------------------------------------------------+-----------------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +=====================================================+=====================================================+ | | ``a[:, np.newaxis]`` | | ``xt::view(a, xt::all(), xt::newaxis())`` | | | ``a[:5, 1:]`` | | ``xt::view(a, xt::range(_, 5), xt::range(1, _))`` | | | ``a[5:1:-1, :]`` | | ``xt::view(a, xt::range(5, 1, -1), xt::all())`` | +-----------------------------------------------------+-----------------------------------------------------+ | ``np.broadcast(a, [4, 5, 7])`` | ``xt::broadcast(a, {4, 5, 7})`` | +-----------------------------------------------------+-----------------------------------------------------+ | ``np.vectorize(f)`` | ``xt::vectorize(f)`` | +-----------------------------------------------------+-----------------------------------------------------+ | ``a[a > 5]`` | ``xt::filter(a, a > 5)`` | +-----------------------------------------------------+-----------------------------------------------------+ | ``a[[0, 1], [0, 0]]`` | ``xt::index_view(a, {{0, 0}, {1, 0}})`` | +-----------------------------------------------------+-----------------------------------------------------+ Random ------ The random module provides simple ways to create random tensor expressions, lazily. +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.random.seed(0)`` | ``xt::random::seed(0)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.random.randn(10, 10)`` | ``xt::random::randn({10, 10})`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.random.randint(10, 10)`` | ``xt::random::randint({10, 10})`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.random.rand(3, 4)`` | ``xt::random::rand({3, 4})`` | +-----------------------------------------------+-----------------------------------------------+ Concatenation ------------- Concatenating expressions does not allocate memory, it returns a tensor expression holding closures on the specified arguments. +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.stack([a, b, c], axis=1)`` | ``xt::stack(xtuple(a, b, c), 1)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.concatenate([a, b, c], axis=1)`` | ``xt::concatenate(xtuple(a, b, c), 1)`` | +-----------------------------------------------+-----------------------------------------------+ Diagonal, triangular and flip ----------------------------- In the same spirit as concatenation, the following operations do not allocate any memory and do not modify the underlying xexpression. +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.diag(a)`` | ``xt::diag(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.diagonal(a)`` | ``xt::diagonal(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.triu(a)`` | ``xt::triu(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.tril(a, k=1)`` | ``xt::tril(a, 1)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.flip(a, axis=3)`` | ``xt::flip(a, 3)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.flipud(a)`` | ``xt::flip(a, 0)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.fliplr(a)`` | ``xt::flip(a, 1)`` | +-----------------------------------------------+-----------------------------------------------+ Iteration --------- xtensor follows the idioms of the C++ STL providing iterator pairs to iterate on arrays in different fashions. +----------------------------------------------------------------+----------------------------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +================================================================+================================================================+ | | ``for x in np.nditer(a):`` | | ``for(auto it=a.xbegin(); it!=a.xend(); ++it)`` | +----------------------------------------------------------------+----------------------------------------------------------------+ | Iterating over ``a`` with a prescribed broadcasting shape | | ``a.xbegin({3, 4})`` | | | | ``a.xend({3, 4})`` | +----------------------------------------------------------------+----------------------------------------------------------------+ | Iterating over ``a`` in a row-major fashion | | ``a.xbegin()`` | | | | ``a.xbegin()`` | +----------------------------------------------------------------+----------------------------------------------------------------+ | Iterating over ``a`` in a column-major fashion | | ``a.begin()`` | | | | ``a.xend()`` | +----------------------------------------------------------------+----------------------------------------------------------------+ Logical ------- Logical universal functions are truly lazy. ``xt::where(condition, a, b)`` does not evaluate ``a`` where ``condition`` is falsy, and it does not evaluate ``b`` where ``condition`` is truthy. +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.where(a > 5, a, b)`` | ``xt::where(a > 5, a, b)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.where(a > 5)`` | ``xt::where(a > 5)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.any(a)`` | ``xt::any(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.all(a)`` | ``xt::all(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.logical_and(a, b)`` | ``a && b`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.logical_or(a, b)`` | ``a || b`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.isclose(a, b)`` | ``xt::isclose(a, b)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.allclose(a, b)`` | ``xt::allclose(a, b)`` | +-----------------------------------------------+-----------------------------------------------+ Comparisons ----------- +--------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +============================================+===============================================+ | ``np.equal(a, b)`` | ``xt::equal(a, b)`` | +--------------------------------------------+-----------------------------------------------+ | ``np.not_equal(a)`` | ``xt::not_equal(a)`` | +--------------------------------------------+-----------------------------------------------+ | ``np.nonzero(a)`` | ``xt::nonzero(a)`` | +--------------------------------------------+-----------------------------------------------+ Complex numbers --------------- Functions ``xt::real`` and ``xt::imag`` respectively return views on the real and imaginary part of a complex expression. The returned value is an expression holding a closure on the passed argument. +--------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +============================================+===============================================+ | ``np.real(a)`` | ``xt::real(a)`` | +--------------------------------------------+-----------------------------------------------+ | ``np.imag(a)`` | ``xt::imag(a)`` | +--------------------------------------------+-----------------------------------------------+ - The constness and value category (rvalue / lvalue) of ``real(a)`` is the same as that of ``a``. Hence, if ``a`` is a non-const lvalue, ``real(a)`` is an non-const lvalue reference, to which one can assign a real expression. - If ``a`` has complex values, the same holds for ``imag(a)``. The constness and value category of ``imag(a)`` is the same as that of ``a``. - If ``a`` has real values, ``imag(a)`` returns ``zeros(a.shape())``. Reducers -------- Reducers accumulate values of tensor expressions along specified axes. When no axis is specified, values are accumulated along all axes. Reducers are lazy, meaning that returned expressons don't hold any values and are computed upon access or assigmnent. +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.sum(a, axis=[0, 1])`` | ``xt::sum(a, {0, 1})`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.sum(a)`` | ``xt::sum(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.prod(a, axis=1)`` | ``xt::prod(a, {1})`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.prod(a)`` | ``xt::prod(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.mean(a, axis=1)`` | ``xt::mean(a, {1})`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.mean(a)`` | ``xt::mean(a)`` | +-----------------------------------------------+-----------------------------------------------+ More generally, one can use the ``xt::reduce(function, input, axes)`` which allows the specification of an arbitrary binary function for the reduction. The binary function must be cummutative and associative up to rounding errors. Mathematical functions ---------------------- xtensor universal functions are provided for a large set number of mathematical functions. **Basic functions:** +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.absolute(a)`` | ``xt::abs(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.sign(a)`` | ``xt::sign(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.remainder(a, b)`` | ``xt::remainder(a, b)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.clip(a, min, max)`` | ``xt::clip(a, min, max)`` | +-----------------------------------------------+-----------------------------------------------+ | | ``xt::fma(a, b, c)`` | +-----------------------------------------------+-----------------------------------------------+ **Exponential functions:** +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.exp(a)`` | ``xt::exp(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.expm1(a)`` | ``xt::expm1(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.log(a)`` | ``xt::log(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.log1p(a)`` | ``xt::log1p(a)`` | +-----------------------------------------------+-----------------------------------------------+ **Power functions:** +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.power(a, p)`` | ``xt::pow(a, b)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.sqrt(a)`` | ``xt::sqrt(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.cbrt(a)`` | ``xt::cbrt(a)`` | +-----------------------------------------------+-----------------------------------------------+ **Trigonometric functions:** +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.sin(a)`` | ``xt::sin(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.cos(a)`` | ``xt::cos(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.tan(a)`` | ``xt::tan(a)`` | +-----------------------------------------------+-----------------------------------------------+ **Hyperbolic functions:** +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.sinh(a)`` | ``xt::sinh(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.cosh(a)`` | ``xt::cosh(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.tang(a)`` | ``xt::tanh(a)`` | +-----------------------------------------------+-----------------------------------------------+ **Error and gamma functions:** +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``scipy.special.erf(a)`` | ``xt::erf(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``scipy.special.gamma(a)`` | ``xt::tgamma(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``scipy.special.gammaln(a)`` | ``xt::lgamma(a)`` | +-----------------------------------------------+-----------------------------------------------+ **Classification functions:** +-----------------------------------------------+-----------------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +===============================================+===============================================+ | ``np.isnan(a)`` | ``xt::isnan(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.isinf(a)`` | ``xt::isinf(a)`` | +-----------------------------------------------+-----------------------------------------------+ | ``np.isfinite(a)`` | ``xt::isfinite(a)`` | +-----------------------------------------------+-----------------------------------------------+ Linear algebra -------------- Many functions found in the ``numpy.linalg`` module are implemented in `xtensor-blas`_, a seperate package offering BLAS and LAPACK bindings, as well as a convenient interface replicating the ``linalg`` module. Please note, however, that while we're trying to be as close to NumPy as possible, some features are not implemented yet. Most prominently that is broadcasting for all functions except for ``dot``. **Matrix and vector products** +--------------------------------------+--------------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +======================================+======================================+ | ``np.dot(a, b)`` | ``xt::linalg::dot(a, b)`` | +--------------------------------------+--------------------------------------+ | ``np.vdot(a, b)`` | ``xt::linalg::vdot(a, b)`` | +--------------------------------------+--------------------------------------+ | ``np.outer(a, b)`` | ``xt::linalg::outer(a, b)`` | +--------------------------------------+--------------------------------------+ | ``np.matrix_power(a, 123)`` | ``xt::linalg::matrix_power(a, 123)`` | +--------------------------------------+--------------------------------------+ | ``np.kron(a, b)`` | ``xt::linalg::kron(a, b)`` | +--------------------------------------+--------------------------------------+ **Decompositions** +-----------------------------+-----------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +=============================+=============================+ | ``np.linalg.cholesky(a)`` | ``xt::linalg::cholesky(a)`` | +-----------------------------+-----------------------------+ | ``np.linalg.qr(a)`` | ``xt::linalg::qr(a)`` | +-----------------------------+-----------------------------+ | ``np.linalg.svd(a)`` | ``xt::linalg::svd(a)`` | +-----------------------------+-----------------------------+ **Matrix eigenvalues** +-----------------------------+-----------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +=============================+=============================+ | ``np.linalg.eig(a)`` | ``xt::linalg::eig(a)`` | +-----------------------------+-----------------------------+ | ``np.linalg.eigvals(a)`` | ``xt::linalg::eigvals(a)`` | +-----------------------------+-----------------------------+ | ``np.linalg.eigh(a)`` | ``xt::linalg::eigh(a)`` | +-----------------------------+-----------------------------+ | ``np.linalg.eigvalsh(a)`` | ``xt::linalg::eigvalsh(a)`` | +-----------------------------+-----------------------------+ **Norms and other numbers** +--------------------------------+--------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +================================+================================+ | ``np.linalg.norm(a, order=2)`` | ``xt::linalg::norm(a, 2)`` | +--------------------------------+--------------------------------+ | ``np.linalg.cond(a)`` | ``xt::linalg::cond(a)`` | +--------------------------------+--------------------------------+ | ``np.linalg.det(a)`` | ``xt::linalg::det(a)`` | +--------------------------------+--------------------------------+ | ``np.linalg.matrix_rank(a)`` | ``xt::linalg::matrix_rank(a)`` | +--------------------------------+--------------------------------+ | ``np.linalg.slogdet(a)`` | ``xt::linalg::slogdet(a)`` | +--------------------------------+--------------------------------+ | ``np.trace(a)`` | ``xt::linalg::trace(a)`` | +--------------------------------+--------------------------------+ **Solving equations and inverting matrices** +--------------------------------+--------------------------------+ | Python 3 - numpy | C++ 14 - xtensor | +================================+================================+ | ``np.linalg.inv(a)`` | ``xt::linalg::inv(a)`` | +--------------------------------+--------------------------------+ | ``np.linalg.pinv(a)`` | ``xt::linalg::pinv(a)`` | +--------------------------------+--------------------------------+ | ``np.linalg.solve(A, b)`` | ``xt::linalg::solve(A, b)`` | +--------------------------------+--------------------------------+ | ``np.linalg.lstsq(A, b)`` | ``xt::linalg::lstsq(A, b)`` | +--------------------------------+--------------------------------+ .. _`xtensor-blas`: https://github.com/QuantStack/xtensor-blas xtensor-0.10.11/docs/source/numpy.svg000066400000000000000000016670011314655136400175200ustar00rootroot00000000000000 image/svg+xmlxtensor-0.10.11/docs/source/operator.rst000066400000000000000000000133441314655136400202060ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Operators and functions ======================= Arithmetic operators -------------------- `xtensor` provides overloads of traditional arithmetic operators for ``xexpression`` objects: - unary ``operator+`` - unary ``operator-`` - ``operator+`` - ``operator-`` - ``operator*`` - ``operator/`` All these operators are element-wise operators and apply the lazy broadcasting rules explained in a previous section. .. code:: #incude "xtensor/xarray.hpp" xt::xarray a = {{1, 2}, {3, 4}}; xt::xarray b = {1, 2}; xt::xarray res = 2 * (a + b); // => res = {{4, 8}, {8, 12}} Logical operators ----------------- `xtensor` also provides overloads of the logical operators: - ``operator!`` - ``operator||`` - ``operator&&`` Like arithmetic operators, these logical operators are element-wise operators and apply the lazy broadcasting rules. In addition to these element-wise logical operators, `xtensor` provides two reducing boolean functions: - ``any(E&& e)`` returns ``true`` if any of ``e`` elements is truthy, ``false`` otherwise. - ``all(E&& e)`` returns ``true`` if all alements of ``e`` are truthy, ``false`` otherwise. and an element-wise ternary function (similar to the ``: ?`` ternary operator): - ``where(E&& b, E1&& e&, E2&& e2)`` returns an ``xexpression`` whose elements are those of ``e1`` when corresponding elements of ``b`` are thruthy, and those of ``e2`` otherwise. .. code:: #include "xtensor/xarray.hpp" xt::xarray b = { false, true, true, false }; xt::xarray a1 = { 1, 2, 3, 4 }; xt::xarray a2 = { 11, 12, 13, 14 }; xt::xarray res = xt::where(b, a1, a2); // => res = { 11, 2, 3, 14 } Unlike in ``numpy.where``, ``xt::where`` takes full advantage of the lazyness of `xtensor`. Comparison operators -------------------- `xtensor` provides overloads of the inequality operators: - ``operator<`` - ``operator<=`` - ``operator>`` - ``operator>=`` These overloads of inequality operators are quite different from the standard C++ inequality operators: they are element-wise operators returning boolean ``xexpression``: .. code:: #include "xtensor/xarray.hpp" xt::xarray a1 = { 1, 12, 3, 14 }; xt::xarray a2 = { 11, 2, 13, 4 }; xt::xarray comp = a1 < a2; // => comp = { true, false, true, false } However, equality operators are similar to the traditional ones in C++: - ``operator==(const E1& e1, const E2& e2)`` returns ``true`` if ``e1`` and ``e2`` hold the same elements. - ``operator!=(const E1& e1, const E2& e2)`` returns ``true`` if ``e1`` and ``e2`` don't hold the same elements. Element-wise equality comparison can be achieved through the ``xt::equal`` function. .. code:: #include "xtensor/xarray.hpp" xt::xarray a1 = { 1, 2, 3, 4}; xt::xarray a2 = { 11, 12, 3, 4}; bool res = (a1 == a2); // => res = false xt::xarray re = xt::equal(a1, a2); // => re = { false, false, true, true } Mathematical functions ---------------------- `xtensor` provides overloads for many of the standard mathematical functions: - basic functions: ``abs``, ``remainder``, ``fma``, ... - exponential functions: ``exp``, ``expm1``, ``log``, ``log1p``, ... - power functions: ``pow``, ``sqrt``, ``cbrt``, ... - trigonometric functions: ``sin``, ``cos``, ``tan``, ... - hyperbolic functions: ``sinh``, ``cosh``, ``tanh``, ... - Error and gamma functions: ``erf``, ``erfc``, ``tgamma``, ``lgamma``, .... - Nearest integer floating point operations: ``ceil``, ``floor``, ``trunc``, ... See the API reference for a comprehensive list of available functions. Like operators, the mathematical functions are element-wise functions and apply the lazy broadcasting rules. Reducers -------- `xtensor` provides reducers, that is, means for accumulating values of tensor expressions over prescribed axes. The return value of a reducer is an ``xexpression`` with the same shape as the input expression, with the specified axes removed. .. code:: #include "xtensor/xarray.hpp" #include "xtensor/xmath.hpp" xt::xarray a = ones({3, 2, 4, 6, 5 }); xt::xarray res = xt::sum(a, {1, 3}); // => res.shape() = { 3, 4, 5 }; // => res(0, 0, 0) = 12 You can also call the ``reduce`` generator with your own reducing function: .. code:: #include "xtensor/xarray.hpp" #include "xtensor/xreducer.hpp" xt::xarray a = some_init_function({3, 2, 4, 6, 5}); xt::xarray res = reduce([](double a, double b) { return a*a + b*b; }, a, {1, 3}); Universal functions and vectorization ------------------------------------- `xtensor` provides utilities to **vectorize any scalar function** (taking multiple scalar arguments) into a function that will perform on ``xexpression`` s, applying the lazy broadcasting rules which we described in a previous section. These functions are called ``xfunction`` s. They are `xtensor`'s counterpart to numpy's universal functions. Actually, all arithmetic and logical operators, inequality operator and mathematical functions we described before are ``xfunction`` s. The following snippet shows how to vectorize a scalar function taking two arguments: .. code:: #include "xtensor/xarray.hpp" #include "xtensor/xvectorize.hpp" int f(int a, int b) { return a + 2 * b; } auto vecf = xt::vectorize(f); xt::xarray a = { 11, 12, 13 }; xt::xarray b = { 1, 2, 3 }; xt::xarray res = vecf(a, b); // => res = { 13, 16, 19 } xtensor-0.10.11/docs/source/quantstack-white.svg000066400000000000000000000116361314655136400216400ustar00rootroot00000000000000 image/svg+xmlxtensor-0.10.11/docs/source/related.rst000066400000000000000000000171611314655136400177740ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. .. raw:: html Related projects ================ xtensor-python -------------- .. image:: xtensor-python.svg :alt: 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** .. code:: #include // 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 &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** .. 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** .. code:: 1.2853996391883833 Example 2: Create a universal function from a C++ scalar function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **C++ code** .. code:: #include "pybind11/pybind11.h" #define FORCE_IMPORT_ARRAY #include "xtensor-python/pyvectorize.hpp" #include #include 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** .. 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** .. code:: [[-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 --------------------------- .. image:: xtensor-cookiecutter.png :alt: 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 ------------- .. image:: xtensor-julia.svg :alt: 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** .. code:: #include // Standard library import for std::accumulate #include // 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 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** .. code:: using xtensor_julia_test arr = [[1.0 2.0] [3.0 4.0]] s = sum_of_sines(arr) s **Outputs** .. code:: 1.2853996391883833 Example 2: Create a numpy-style universal function from a C++ scalar function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **C++ code** .. code:: #include #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** .. 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** .. code:: [[-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 -------------------------- .. image:: xtensor-cookiecutter.png :alt: 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 --------- .. image:: xtensor-r.svg :alt: 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 ------------ .. image:: xtensor-blas.svg :alt: 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. .. _xtensor-python: https://github.com/QuantStack/xtensor-python .. _xtensor-python-cookiecutter: https://github.com/QuantStack/xtensor-python-cookiecutter .. _xtensor-julia: https://github.com/QuantStack/xtensor-julia .. _xtensor-julia-cookiecutter: https://github.com/QuantStack/xtensor-julia-cookiecutter .. _xtensor-r: https://github.com/QuantStack/xtensor-r .. _xtensor-blas: https://github.com/QuantStack/xtensor-blas xtensor-0.10.11/docs/source/releasing.rst000066400000000000000000000024421314655136400203210ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Releasing xtensor ================= Releasing a new version ----------------------- From the master branch of xtensor - Make sure that you are in sync with the master branch of the upstream remote. - In file ``xtensor_config.hpp``, set the macros for ``XTENSOR_VERSION_MAJOR``, ``XTENSOR_VERSION_MINOR`` and ``XTENSOR_VERSION_PATCH`` to the desired values. - Stage the changes (``git add``), commit the changes (``git commit``) and add a tag of the form ``Major.minor.patch``. It is important to not add any other content to the tag name. - Push the new commit and tag to the main repository. (``git push``, and ``git push --tags``) Updating the conda-forge recipe ------------------------------- xtensor has been packaged for the conda package manager. Once the new tag has been pushed on GitHub, edit the conda-forge recipe for xtensor in the following fashion: - Update the version number to the new ``Major.minor.patch``. - Set the build number to ``0``. - Update the hash of the source tarball. - Check for the versions of the dependencies. - Optionally, rerender the conda-forge feedstock. xtensor-0.10.11/docs/source/view.rst000066400000000000000000000135351314655136400173270ustar00rootroot00000000000000.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht Distributed under the terms of the BSD 3-Clause License. The full license is in the file LICENSE, distributed with this software. Views ===== Views are used to adapt the shape of an ``xexpression`` without changing it, nor copying it. `xtensor` provides two kinds of views. Sliced views ------------ Sliced views consist of the combination of the ``xexpression`` to adapt, and a list of ``slice`` s that specify how the shape must be adapted. Sliced views are implemented by the ``xview`` class. Objects of this type should not be instantiated directly, but though the ``view`` helper function. Slices can be specified in the following ways: - selection in a dimension by specifying an index (unsigned integer) - ``range(min, max)``, a slice representing an interval - ``range(min, max, step)``, a slice representing a stepped interval - ``all()``, a slice representing all the elements of a dimension - ``newaxis()``, a slice representing an additional dimension of length one .. code:: #include #include "xtensor/xarray.hpp" #include "xtensor/xview.hpp" std::vector shape = {3, 2, 4}; xt::xarray a(shape); // View with same number of dimensions auto v1 = xt::view(a, xt::range(1, 3), xt::all(), xt::range(1, 3)); // => v1.shape() = { 2, 2, 2 } // => v1(0, 0, 0) = a(1, 0, 1) // => v1(1, 1, 1) = a(2, 1, 2) // View reducing the number of dimensions auto v2 = xt::view(a, 1, xt::all(), xt::range(0, 4, 2)); // => v2.shape() = { 2, 2 } // => v2(0, 0) = a(1, 0, 0) // => v2(1, 1) = a(1, 1, 2) // View increasing the number of dimensions auto v3 = xt::view(a, xt::all(), xt::all(), xt::newaxis(), xt::all()); // => v3.shape() = { 3, 2, 1, 4 } // => v3(0, 0, 0, 0) = a(0, 0, 0) ``xview`` does not perform a copy of the underlying expression. This means if you modify an element of the ``xview``, you are actually also altering the underlying expression. .. code:: #include #include "xtensor/xarray.hpp" #include "xtensor/xview.hpp" std::vector shape = {3, 2, 4}; xt::xarray a(shape, 0); auto v1 = xt::view(a, 1, xt::all(), xt::range(1, 3)); v1(0, 0) = 1; // => a(1, 0, 1) = 1 Index views ----------- Index views are one-dimensional views of an ``xexpression``, containing the elements whose positions are specified by a list of indices. Like for sliced views, the elements of the underlying ``xexpression`` are not copied. Index views should be built with the ``index_view`` helper function. .. code:: #include "xtensor/xarray.hpp" #include "xtensor/xindexview.hpp" xt::xarray a = {{1, 5, 3}, {4, 5, 6}}; auto b = xt::index_view(a, {{0,0}, {1, 0}, {0, 1}}); // => b = { 1, 4, 5 } b += 100; // => a = {{101, 5, 3}, {104, 105, 6}} Filter views ------------ Filters are one-dimensional views holding elements of an ``xexpression`` that verify a given condition. Like for other views, the elements of the underlying ``xexpression`` are not copied. Filters should be built with the ``filter`` helper function. .. code:: #include "xtensor/xarray.hpp" #include "xtensor/xindexview.hpp" xt::xarray a = {{1, 5, 3}, {4, 5, 6}}; auto v = xt::filter(a, a >= 5); // => v = { 5, 5, 6 } v += 100; // => a = {{1, 105, 3}, {4, 105, 106}} Filtration ---------- Sometimes, the only thing you want to do with a filter is to assign it a scalar. Though this can be done as shown in the previous section, this is not the *optimal* way to do it. `xtensor` provides a specially optimized mechanism for that, called filtration. A filtration IS NOT an ``xexpression``, the only methods it provides are scalar and computed scalar assignments. .. code:: #include "xtensor/xarray.hpp" #include "xtensor/xindexview.hpp" xt::xarray a = {{1, 5, 3}, {4, 5, 6}}; filtration(a, a >= 5) += 100; // => a = {{1, 105, 3}, {4, 105, 106}} Broadcasting views ------------------ Another type of view provided by `xtensor` is *broadcasting view*. Such a view broadcast an expression to the specified shape. As long as the view is not assigned to an array, no memory allocation or copy occurs. Broadcasting views should be built with the ``broadcast`` helper function. .. code:: #include #include "xtensor/xarray.hpp" #include "xtensor/xbroadcast.hpp" std::vector s1 = { 2, 3 }; std::vector s2 = { 3, 2, 3 }; xt::xarray a1(s1); auto bv = xt::broadcast(a1, s2); // => bv(0, 0, 0) = bv(1, 0, 0) = bv(2, 0, 0) = a(0, 0) Complex views ------------- In the case of tensor containing complex numbers, `xtensor` provides views returning ``xexpression`` corresponding to the real and imaginary parts of the complex numbers. Like for other views, the elements of the underlying ``xexpression`` are not copied. Functions ``xt::real`` and ``xt::imag`` respectively return views on the real and imaginary part of a complex expression. The returned value is an expression holding a closure on the passed argument. - The constness and value category (rvalue / lvalue) of ``real(a)`` is the same as that of ``a``. Hence, if ``a`` is a non-const lvalue, ``real(a)`` is an non-const lvalue reference, to which one can assign a real expression. - If ``a`` has complex values, the same holds for ``imag(a)``. The constness and value category of ``imag(a)`` is the same as that of ``a``. - If ``a`` has real values, ``imag(a)`` returns ``zeros(a.shape())``. .. code:: #include #include "xtensor/xarray.hpp" #include "xtensor/xcomplex.hpp" using namespace std::complex_literals; xarray> e = {{1.0 , 1.0 + 1.0i}, {1.0 - 1.0i, 1.0 }}; real(e) = zeros({2, 2}); // => e = {{0.0, 0.0 + 1.0i}, {0.0 - 1.0i, 0.0}}; xtensor-0.10.11/docs/source/xtensor-blas.svg000066400000000000000000000272611314655136400207660ustar00rootroot00000000000000 image/svg+xmlxtensor-0.10.11/docs/source/xtensor-cookiecutter.png000066400000000000000000000351611314655136400225300ustar00rootroot00000000000000‰PNG  IHDR"_sÜbKGDÿÿÿ ½§“ pHYsÃÃ(ŒRtIMEà J%0 IDATxÚíyœյǿ§z6ö]Ѐâ3%!î{и¡À” c„)5Æh\ã•5.YÜ—à/fuúi4F F£éZ¤'p1p9зš¸¸¸Ý¬`¾cF£ÑBD£Ñh:·I?®Åß|ÞÑYÜÜiV°^ßAF£Ñh!¢Ñh4O„XÀ À¨NhþÀõÀÝf)}75F£…ˆF£Ñt|r p3þÎÎ?3Ì ÞÖwV£Ñh4Zˆh4MÇ üeMv±K«®Æß?¢gG4F£…ˆF£Ñt Ò˜‰Ÿ ¤«ò,p‚YÁ:}Ç5F£…ˆF£Ñä_„ìÌvë—ûp¬YÁ§úÎk4&Ÿº 4M7!G¯„! X½6nî”—<x)_F£Ñä =#¢Ñhº³ù pi&%L¥àËu°j 45ùëQƒûCß^ ë‰ú0Á¬àÝ4F£…ˆF£ÑäF€÷àçIÏk_ Ÿ ÉdËß¶C OÏNU›€“Í æéV¡Ñh4š\£—fi4šîȽ銦&xÿøteë" ¡>ø–ÉΗª'àz3ÓdF£ÑÄ…žÑh4Ý o&w¤ó[¼»6×…+£WO¹m§[ªõ}³‚Gt Ñh4M®(èªv²5jWƒ‚AíV€¨5Îìš%º)h4ÝB„ Üšîï×o /B6nò7²÷î<Ë´žªu Ñh4"1P¨÷‰ðÝö~§”< £›‚FÓåEÈîÀ#¤¹1 G±¿÷£¡1\YÅEPRÜ©DˆeVP§[‰F£Ñh´‰AFêÛ«Ñh2˜ ô s\aì<Ö¬‡u}A’Lúѳ¾ö¼((ð߯7 èFçØ§EˆF£Ñh´‰“½öÚ«ê†ë-0Æ›I&d×(Ç' ÔÏÿl¡)é”òÅGÂètûA´Ñh4"Ù`—uÛƒ$ôíÕh4ÀíÀ‘±>8þ§£EˆF£ÑhòN— ß›PÆŽúÖj4o&êšøOi¢Ñh4-D²„¨”"àf]ß!åZ„h4¦#Ð%—féêÆ›É$à Žh[2 ÷Ïç^…w–È¡pÐX8ç$?R—!F£ÑB¤³b¨õFu¦[‹pCG´ms=œ~-Ô¼óß¿½õÿyêp®‡!:Ÿ±-³0 hV:®·!_ul[f!0è | ¬r\¯©#¶‡ÀÖmð#ºuh[5ym'½€mñ›•Žë­Ñµ¢é tIo½²¼ì%9 ß*x²Êõt¦k ‘舶ýê0ãÉÖ¿?tOøÝ´Ž-BlËLŽÆ¤G³ŸÕ«€àÙàó†ãz©˜´ÁÀÀQÀ~-¿ù¨g ð1ð<ð7`¾ãz›rìLÜÊÖýÇr@³wñ[?æ¶>ç¸ÞÆÊß8ØèˆŸþøË´×kƒÿ®þè¸Þ‚4Î7œ§ðU}ðÙ|¬¯5¿ÿ¶eVÇÆ­÷_:®÷q 6ŸŒ';KÓ_p\ïþîSàè ´é>Í~Öܧw¶ê_¯8®×ØÎ¹‹ƒ~²CpÞ^@ P "Ô€O€÷€W×K¶sNöö¾´é’ࣂû±åyð ðoÇõÞnvŽ“ƒû’ €_9®÷APöकnv\ï­f׿/p4¸Ÿ:®÷³6îßÀ¤ày”.*èßëƒÏ—@-°Ðq½ÕZˆ”›ŸŠ0L ¦[ŠÀÒà…Ø¡hl‚ýNk?Aâ³÷ÀÐA±ù40).b[æ^À/g:ÊŒúJàWÀïÚs˜Ò°å8àªÀ©Šò.«ÃÏ-sãz‹³,@Ž~Ñnþ \ë¸Þˆ6l|ò¾à¸Þ+­œÏ y=+€c×{38Ç®ÀÛYªöyŽëMlA~Nˆ¤¦!iöÞr}îÑÈ XÒÀ]À¯×[ßÂùw^#\>¥O€²¶f`lËt€Ê¶^ã¸ÞõÁñ»Krü8þ—ãzûÛ–94¸Æ\î™^ê¸ÞnÍêpa ä²ÅÙŽëý¾•6±4æ²>ª*ÇõþÕÞ»ÜÒ¬ öê!R?¬£ÛyÊÄÑ¥FÂ8ÒP²»‚á²eÄCÔF”¬ÞQ°(%êç§nêˆ×2y2FqÃè!1QPßQ"» ôG©^J¨VŠb©R¼,ÈgNÛ£lq1iÒî½ûªÂýÅP+‘ýAm+ŠJˆ¢P„ JÉ—K'“©ùÒÔðüô'–­ÏiýßepQQÉáê…” 쬄¢TO%Ô£d ÞWÂP/‘⹪9µïtô6>å¸=ú'©)©=Ql*°øPÿ ¥sæÖ>sÑ?éˆ"`é‡éei_ü~,B$6b[æ6À¯døÂÜ œk[æ)Žë½Á–C[Îð²JðGóO´-³*pŒÞY€ìØzX†§*·lË|ø¹ãzËBž£0Â;¿¤ï~¡- ÀŸuÙB6¿k[fA³en;fQ„lñ©Þ ÙNzÿü´:o^À4à¶eþÈq½¹Í¾ß5¤ölü™²ÖØ-‚­£rÔZcÛ2áÏNæ:pÓ®¶eîì¸Þ;ÍîM69 ø} /ÏBY#€óómËô€ ×›Ÿ–©´Ìç$äS)5«ªº¦"T§›džÁ½áÊá§UÕÞm[þ=Õ*=FR2ƒÁ¢¢D‹RCõƒÃœWàhÛ2U»åCM•뙽”ŽÓSõJž üP1[ Øê?[¬*Bì*pL¹LõJ­¯,7gŠ¡nuf×dÚ±m™ãïD8ô®fbïÛÙìnÀNdoÆ¥5…¬ËQÀÀÈm Üe[æd¿Ñ~y(ÓÞ=ûåéš÷Å_V—ïvÙ;ËåšÀó¶e>œã¸^]K7â+’ÉäùJ©PÓå"2ùÔ'}Q!êü²ì‹†º»¾f¸2ŽC.d "G |‘á"&dÍ鬴Ê.T=“ï ò›¯DH¸·O~H ¯²ÜüÔãöèŸã…Q´°ìaŠUºÏ â’×¹ç¿"$ÝSÊÞÆ3¶Uv 1.œ:iÝlË|ÞH$^NõEHèz.Fdª‘H¼b[e³§NÚc·¸«tªeNÞåRCxD„£@ ÂÛ){Â]ÅýŒm«ì²ñãw)Êi£¶oùÚJI©ÄCä’ôú¢¼·Dø¿œ1bhûÑ `tf.Iœ"äxàñ˜EÈŽ´-sDšvôÁŸêÿioO/àQÛ2ÿ'Ã:ë Ìʂٚà!Û2¯ DO®¹2Â1_â/;ÚšY¶3«#…h+{/Ä,B¶°ð=:ƒòTn¿<–Ý¿›ÔñN\Û2KÚ"3æ.®¹3ìÙŠ[ÒwÂJ‘P3 )ÅeO<±¬NÈÔI{ì6¢ßÊ ò’¹( ~˜(PµS'•˜}SzM9vôWÎÂéãFW–—ÝPò²@YF§F~Zi•݇•忥"êM`\ŒWoFª¦²Ü¼;ágO3²²Ü|Á€*AbÉu#Â@›/²ËG†­dÛ½öÚëë3ªåe‡iç â"åý™pÙ©mîdèÕ£Cˆu¶ +à‹4켄¿9>û<øµm™¿Xg}ÇòÄ5§Ÿ÷ç²ýÚ–y(ÑÂb_ßÂ>ƒl;cÛtT§Ú¶ÌqÀsÀà,Ú²²“¸JòTn¿<–Ý·› ð0<ئX§¯W¨C:CWZe'¤ó[¹ ¤áó§W{ng!•–Y.†z ‘=³ðºÜV yΞTv|ÖßÌER ðýI»oÛÔ¯÷?Dd"‰x.Cζ­²32{1–Þ(­ٙ “Î3 S +-ó»™´Œä"¯ko¥Ên ãÅ©VÙOrѶE0J·kþ•à.7Ï‘;9Ãe©ÿÄe“7“À!ý¹pìApÑæ£YRy,ü0º”z†˜¢cÙ–ypÙ]Oÿ^{Q«‚Ñþ?ãOïç’smË<=ÂqÄ”KN·-óÜ–÷³Ç,~×Âß³Ófcºx2þµ=0›oFŠ“¹ßžÉ@w+[:Z»ÌAðŽÖ…Èœ9omPJ. ]£Jnœ<¹´°­ß|ßµЉéžS)Rª©é:!¶Uzš(õ¨dñA,#zxªUvdV{KŠÑS¬=ö,”‚‹û¨»RÜ0uü.‘êÉ.7¯ãŠì?1dŠç*-óšð"¤ìÇ(C$«K†D¤Ð@îœZ^v[nZyjû@d}×@ÝåÖ¯M&ߌѠãè$8δà±[àòÓàÄïùÂä‘`Úé`DÛ6ù þLÈæDH`z–EÀœ4~s¹™ i‰ßÚ–i†¨· ð7¿çƒÛƒˆfY~¯™{áj†eZ+QҾȲɟæá^¬j§AÿÊölг¹O_æ©Üuy,{mGj—¹~^µ)D¦W{3ꙞڮE ÆÙmý¤@œn$]=P5oÉèdL-/=Q)ãþ¸f Ú©÷"Qòð”cGoŸ=×8Ç õ"óä@o#…%¡ÅD儲1ˆúyΆ/R¡:óÔIæ¹Ç?67"—ØVéÙ/ˆí-kl?Q̈ÔÖËæÌy+Τwåé9±ã·àÔãຳ}aRºSäSÅ&B~áö}E¡ÀoÛqØÀœ/z3DZ=ý;À­y´µ8°5Û{Å¢ìŸyÉq½G[ùny–ÛØMˆà‡œ>8vÜÕ‰‡ùZˆä3ÒкH6Éù(BíË0„k&±S‹ëÞ&LØ«ðà MªéªÎ&BìIæ^‚Q•KÇS„‰B#{ë„…]é™Ý‹àœöfÔ¾qH÷DÙèÁ[mn•[›öÚq{béa†¨ûòÓ+¦–›ge³„jûÞ©Æë‘PI¶ªOÛþo&Åä'd¾‰U„Ø–y4¹Õ"ð³×‘ýY™ö6·=®Á±›Ov¾Ÿµw›eŽNˆpè¥í´ßlñfØÄjÙvø‚^ÇÖ3?SðÐf¿¹-ìà—ehÇ&`1þ†ÝïÙÞ¡mËÜÇq½ÖF0JfO7ão*nÆ’ÙÌÊXÛ2¿ë¸ÞßãllÁHþ”b MÁé¸^ƒm™GðÍÈl…l‹w6++ÙÊž”°l~â÷5sÛRö$̪–Yƒ?‚¿?ôñ|så\Çõ:•à¸^m¢­{>®…gI[Ô‹Úh›×ej[ædÚž >?I_º,ßmiMıtúRüŒðéð™ãz/Æt»n žñÛáÏžL´0ÜÛ¦%Dœ§nª´Ê.y4}çG†¤z%üæ«xܨ²0£×J¥¦Í›·`sgêH'[£vE…MôG…SH&4mÞôÁ†B£®· (IPª 9Jàœt79 2ÆžXzX2U·rŸxJÁdêåUɆϊ‹{÷è•j,‘³D85ìËY”¤RÂ…éUJ}."7ÑØôdÝFãý =Há0 vH©c”âÕÊuÞZ5×K{ ÁÔ‰£÷ÃÏg¾NQ”dâõÄúuŸÖõ-˜0£±QL‘pË×`?Û*=Õqkìh}¦Q5Æ2#âÍDè8#Ò¹!cž ¸ ‡úßxxÁq=ÕÌ8s§óð—\µåônTD´c~HÛû×[œ¯W Æo&Z>€3ia)…m™ý¢öuüˆQ×÷l kk[f`ü¤¢ûe`ëßcn—Esw;®÷nN¨¢Yô,Û2ÃŽæ7µ”(-ê×{8¦sJôP±ï—sš'(´-s;àŒ -΢â¸Þƒ´Úu«ë|:¤™í¸ÞUi–ý(~ÒÖÖÊ~$¤yÚq½lG²{Üq½|DE{ÑqÿÉÖ¶Ì+?~0pXZB Ê­yÌ.7ÿ†¤¿þZà²ÓǼ÷ùïרD⬴ßnJ½2½º¶ÝŽïT{5ÿ{¥e¾"!à ž¬r½Œ×–’¸:¤“¸.•RLŸSóç–ÔkðyÞ>~Ìí*•š—v´ª„Ø@v…ˆRk•pFUuÍc-Œ2¼¼TY^öFÎ5Œ(Ûy„½z´'B'OÆvM×eR¨M(u S]Ó<‹é‡ÁçàJ»Ü¯àÚ­ëZ)µ ¾H…JÞ%†qMX‡N¡6)¥Îœ^]Û}A)RºI5Ôœ^]si•ëý}Ö“µ«çÏŸŸœþIJõÓ«kOŸSógÇõâ ˽݃¬‰Û2wŠX3×;/õèiŠˆ–,OVsÒ¬üõø$ŸpþÑÁìG¶Ln.BšÙº °ˆ¶áx¤m™CclCè}¿ÈÓFñŽé#ø‘×öpè€Ié„áÕ"D“G1ò%þ€n> %DfÌ[¼L‘º9”ï£dÚ„ {õ蟨?Yôâe+fÌh{c[‡D%ä´0Ñ›RŠ 9Þ‚t?ë‰e«RþT}μ ™b•ŽÉÊuÂHâó/Kçç*Eè)meÐnS%õ‰pvK¨<ÕUsjœÆTS™(N˜>gÑÛaŽ5$uZçý±é®7=ß>ä.z`mk8-bœžýŽÀRí¸µÓ¦?±l}»`w"Ùœ ‰êP¯Îí ¶ü)5ÐÁ¾sñ÷c„ëB´8+ÅÖ‡×{:MÇò<¢%ýÛ?¦{18'ä1ïÒNhænÈX¢ÓøAL{]4šlóNÈ߇"k›zÜ Pï‡xloÛϨ;OPg§éŒÕ%“Ó:cí‹È)!~^›ÎLÈ7ÄKSciÎIJöÉÆu4}Ï™½peðRxgVõmï'oÚg-J%Ó¿?6uRéÄ0f<<ç­Oêš§"ˆµ“Cß[‘_…*£¡înP!GÕÑ“.½^ š”Jf/MG"JÁ†MPWMþ¿;ÏeY„@´å<8®kHÈ`D”Ìäiçðp\ïm`n¦Î½m™­ˆ“ö¸-„­-I\BäÂ'忏^šLû׋Žë½©«NÓIò÷_åJ{Þ¼›§L,ýI"!Õi;®†Üƒ»í¡ÇØÙjþûÖ¨€Ò´/SEË+1cÞÛ_T–›ïаsû¬„l­ù¨×ºP­‘w#¬žn÷¥·`Á‚¦ÑÃË– ŒJ_+n¥UöÛúõ«Y×~–ú±/…’¡R¼ùPõ¢×Ã2ý‰eë+ËËáÇ!ÄraI1ã€ÙY"·UÍ©}2OÝ06!²r |Þ̵.(€~½ýOÏÜæ~˜e°w„cfeÁŽá@aÈc:®·8ä1Ó ŸcÇfÿ ô yŽeŽë½ÁÖÊ mʸ¿Åq½YtJlËüq›OppÒX:¥ý¦ ÷Ó¶Ìm|ÿ¤ãzïåО²¿*´xhníœÊrsžH¤ tm8ç¬XGã±%ª‚CÂìÈP‘GŒEÔg í CFvˆºÙ¼~U²¸wØ‹ì›Þïxšô…H].()”³+ËÍÇP8‹?.~jÁ‚Mq]o*ÉÁFÈ4–A”¬ðe ó¤/Dü‘9$BÄ·Ýãº<6µX„HS¬ZÝòß¿XãúõáC³º +"`H„cdÁŽ(³v/G8&ÊàþÈÖyê‹—v1g¯pO;¿Ù—öÃòŽPökh4­sM;ß×Ú–ùí{ó"c[æDÂÍÁV{õBG&I5É…F:"Τ}"êÊ9ÕomèŒ-A {…qJ Q‹lË̲Q#‚Ðó߯¯,7S¡²Ì§ÒÛ„žLÊ} Î'¬O( |áû£‡×Q:œBÍl(¬y6Ó¨R†ðí‚âŸQÊÚDá‹}h Ù,›•榸%Ïá¶c"+¾„T;-`íz(HÀ¶ƒ³~M¹XŽ•‰ãúq–6#Gq †=Àq½OlËü‚pË äÉÖ5¶e~D¸ð¡ýóÐÿâ¸ÞKt?Kã7Qò,xÚ×Öd@)~DÉO²Yˆm™ÇyØì­’¶Ð‡þºè=$½Ói:GoÔÖ<ЉoöÎÎ"Q};Ž-de£ÝŒ¹Þ"…Ê(S¨ƒ€3 ä©’†²¥¶e^bYcûEnËÒþFûoÓ”z+JY®ûÆZ¥X²´³q/Ö¦þ”çV–±ð®kðEF:lØ”õëy'!›rQy¶e~#íY2'Šs¿"bY«2´-—¶®ÌA=fB#~æõîÈ6Y¸MŽë­Õ¾´&C†fáœGØ–9Ͷ̻mË|?ùh¡ÝˆŸ€”ÈB `͆›” ½C¾ER)uq.óÄÚ¡ã™$%Ý¡‡m ð Ä#˜d'à¶Þ4~l—›¿³'”Ž_ïlöˆO7 Íd g¨>(ŠdaUÑ»ë{Ôç¹)d<#òéÊô7¦FÖ¯ggüM¹"ŠÓš­Ð¬QFŽ×E,+ìqq,ÍŠMn}îi&üËq½wèžô ’fÆÙ®×hZ“#‘–ó𣸞G´±74³é•úÀü÷ë£doÁsšS3¿3ßeQÒ¯£Ù¤D¥ºCsÝ7Öb¨c”ŠotV^ç·*'•]7~ü.E!Ž ]F¡6ÍŸ??ÝÖΉHbò¸Òž]°) ÊäàºØbTß^9¹¦½™\‘+G*Â1Ù’cQΛ«ü E1ØÚ”#[ sܶ-Ó¦û’Œ¹h4™ÓÔÁì©~[ceÔ*¥¢/»Q445¥.ëô·YèÕñL’ÍÝ¥—9³k–¤$õ½P¡¥ÓsÚ{ˆ!?\Tò¢=qÌȬ´ÅÆŒ'*ôèjA£Wl«29øË ``î>æJŒDY’­÷/#õŽ„=®ù(õêÚÚ'C[sÁomËÜ™îÇZÇõêb¾ýlË4šÌø¬Ùò&pdK¡½# e$ï‘LF]M31ž&ì½QjewºÞ‡ÜÚ7“M{+¥ªc?¹°2R/WN*ÝY·¬KäÍx©¬ISΉÀðm ‘ÈéµåBŒ¬ÐËc‡fÉ–(Î}Ô±ÁÚ–K[‡ä 3¥0#Øs¤½Ìv‚ gz5š$D¤³òIDATžu\¯Åwu$!R9©ôh)ÏÈY5)ÈÁѹ~T‡›}‘º[o›1ïí/ªªk¬T*5I)õv¼õÉ0 yÆ>~ÌvC¸Ž gÓÂ.hZŸÚØod!²vCû‘²Ä€C¡w~¶ÝèÍäòlÜq½ágE†Ø–™è|QèÐamËÜ.‚£·:O¶ö'\Ĭ-â2ìü¢›½~ÞÌR»‹F“Á{Ñq½Ž2(ý¬ãz­îÉ -DÆß¥H ùMÆÎÒ«@%îéìwZõЬÅݵçMŸS;wùÚ!¥*%SQ¼ã}©R©[Ú¥ëCž³ç¸qã"¯«°Ë5”JΚ_»© ÞöÈB¤.üϰãvзw^¯ñ¦lŠ¢-‰: ƒ‘}"³_„cÖt"[Wç±­^n[æ]äÙÒü«Ï?;:QÿÒt-ÜVÛ¼¶Ùz•m™­¦„Î#2¨¨ø"ÝcqîDÆO-/=ezuíŒÎÚ|$!2«'Sê°Î¾A¿£lxhʤ=IêL' ôά½rÚ)–yï ×k-ÁØG„ñ”m{¶#u‰bÈåb²Üo²Zˆl¡¾!R\;l Ec±ÉMÞL0+¸9 çþ8|{â üÐq²ão~ m™Ã× ÷ä¶5?ÿg@=Pâ{Ú–9Òq½÷slkT6ׯWà϶eŽq\oU'¶¬u\oÿ˜ÚuXN·-ó—ŽëuÅg¶&s¾ï¸Þ’Nbk/àv`rK_†š™|Ü®Û ruœÖ rç©Ö¨¶)(*üjB§ûOîxh΢×;MÆÐ”JMñ3™«È‘$ ”:¿·oèð•R`Dõ–5¶ŸÃB5UáÝ.z›cOØd0¨?ì4¼Ãˆ­ÅH6fF¢düo[æwâ4Âq½„Oúgg§ûcÛ2w¢,-þw3[€W#œçœ¶kíåÆÖ ˜üO„ã¶þ„&“þµð}]ušÆûø³1aWÔÚLi(!R\XtK¦£ÊßpÄD¶I‘¸-¶ó)nô@e–WA‹Â9ƒ™í­ÑDtpž^¸izuíŒ*·æ8%É(~©¢ÄôŽ<¹å~“аÌPåzzÒxpxÓyC ‘¯Ó¿¿ ý+¡YCÁî#ýì鉎Dó&o&qGüg½±wÛ–YYˆL™´Ç!‚LIËÙVês”J;¶» §O)ßã{1)›ºp¨>™§RÉP#c§LÚãÝ–óGÕì%+œjïj¤i7¥x*dPR7fûVTiè— ÇF¹C1!t[E½¨…È7…È.#`ø0Øa;Ø}2 Ã ­¹9f1òÑ–íí<ŸîÆuÛ2³-³½ÜKQÚiOà Û2·i§ü_ÇG8ÿ‡Žë-ÉÁ,lÝ®[¯¦F8ÿ*Çõb Øá¸Þf¢o@¿Å¶Ì1Ýýã¸Þ»D[.7ø§m™{¤Ù¿lGG]²wTeö%B† D‘¦cðÇ÷pwàâHBdܸq‰„¨»Òv®”:O!„r¬Pÿ7aÂ^=2­¥T¸è/:ö×X¾aØBBæ10DÝÐÚ¨º&–óÿRÚÚ!ÒÒÎbàaÛ2{ ùGÄãF l˼ٶÌÑÍÚŠØ–9Զ̉¶e>ãù¶en³¹Ñ¶Ì‹lËìÙ¬üÝ€§hÆ$N[4C\¯œ‡^m[æð¯¹Té5¼ÿç?#-gO¡Þ[¾n›ÙCz}üRqaÑ)‚¤ðR„l¾˜–YõH¨°…‚|kÊq{ìøÐ_½¥´ùóç'+ËÍÙ"ü(í2…ƒŠÍ«À»^7ç̰'–Ƴ•åeR õMbY¨åV ,h5¢lº¤ÍF5=Zõ÷áKC]D¢à*àÄ´ÛOQÉù" ×ÎyêÏî’/»b0+XéÍä#‡8í Ül`¿%&góöˆÇönn²-óàs ?0¼…÷ÌþÀÿ?hå÷±m™ÇE°c(P…Ÿ\ïm`3°=02úy¸5ˆ†(û8ãï£øM`ëÆ  ï” [3t:m˼øs„ÃGwbOBš ÅvhÂa·Ö¿*"ÚQ\\f[æª`ð¥GÐ^šÛ·ðˆm™5·Åq½µ¶e®&|BÒBü%×Ù–ù&~°Àwü×K$´ÉŒâm³Éq½ldY¿+B¿Þ²qý«¾Ðî¨üäñ» $ÌÈÌóçÏOÎúëÒOÄø„éó—ž:it¦±³C'pI¦ÎͬÈd至Àu•–yMÔO7²¸rRéÅö¤²ã»k/´¬±ýTBDDÎââšJ«ì„ð÷Bú…ù½Õútd2ü‹Z„*'í‘Ö²Ç`öäçaËP"vñæ0§¿âš¹ØÃy¶ÃÏ0’Ö»N·-³­ýQwfhC?üP¹‡Æ B–s³hk_üY¥ïÆ B>fe©M'ú¬ÙY¶e¶øl¶-óZÛ2?µ-sÅ–6üï¹[o[æ'¶ežÃ5 ÄlºŸÚ6–Ü= Äåh00Ø•Ö÷:íü°•ïþša[=?ØÃžˆ€ÿh-‘o„h—«lË<4 5Às¼õÆõv…HqQɯAÒRÏ µf]ªéþ-ÿ®Û°ù¦pY¾¥ e÷e’[%ásG(.ž:©tbÔ"«ª¿¨Tø(%×V–›/ؓ̽Ò=æTkÔ@»Ü¼ Ù¯÷[b·#Ü:yriawì…½UãÝ‚ŒØJPŒäÑÊróE»ÜŸÎC²òøQÃ@¦\#¥>jµ-Ì«Y¨àÉÐc¤î«´ÊÚŒrŠeîOAb®H¸¶JñÎò5ƒëâÍ¡º›¿”nöfòÓ _*k‰6â•imØò àuº½³Qn×{‰ø¢TeÊÿfiäsKâËL¢fþ¡…¥{‚sßÍÚò)yîžÍŽßv®8Çõ¿;­ÌnaxïÊ¡-—Û–Ù’7»´ÓD‹$¦‰>0s^–Îý¿»Ë¶ÌBhgiÖÔ‰e{·¡ª[r¬ÿ0gÎ[_¨ÍzæÝuv¹ù‹0† ²÷ˆþ«~BÄ%’H½Ž )ÒE‚¸¶eÞ¯÷«†:¯¡wQ]áFµ­Q”ØOÇ'%uÇCní«­Û­~27´½ÂÁ¯Ùåæ« õDþUßX¿t³ô]Ý£Çg*ÑаéÔbÈ¡)d¼ÈVi‘ŠÕYø‘Mº ö¤Ò“©l¥N·ËÍê/J©¿«dÂ['E+zôXPÏêz÷èY¼SãIÉ%igˆVŠ/ªæÕ.oGØ^‡pt8Q*=vyY%Š?6É×KÖÔ­hP2 •LŒJœª”ª‘ТS)~äVéÊÌÇÏÞîË-Á2­[38ÇøK¦r±¦ÿ8Û2wv\¯µ°×¿ÆÏ”O¾Hãw¿Ü<Ûº¸/›8®÷˜m™¯áÏà„ePe[æa[ »qµý’½‚ó?™ãû0® ÁñgàgÀ·r`Ç.À±øû²¶æoÀJ`HÛªÛ–¸×d…òtÞ¹ø!}G†?޽Z0Ý­MkÔÝ™½pe © “O'þ6¡.®šW³îÃã@£~×|%F.ÍàøÏÆÚö0[YǾÅiÛœ„¿D*—ÀŽ-´U…?[òqŽëæ?øË5ù¡('Í ”/@¯_½iºdhíY§zq››õR¨ Ã:e¢ÔQœëésk^Ã_3ŸO'ì|ª5ª]5éÌ©yD)~–‡Ö·  èʮ܃¦Žß¥ 7å§tÕ”uN˜#ª^ôlJñã<Ù{k•[s/ݳ‚µÀßõ»æ+n*F×[ƒ'Û£¦)ÚÙ#à¸Þ[øQ€ÞÎQ½= ”GYÃŒôîGîfqfÇfkƒz×ù"ðDÄÃ×çõ›m¹*ýîã4ê/ L${ÎÒm«ßõ –Ç8®·Q?šóãaέvˆˆapÖ7^öq£Êu~¸W‰úU»N™[û¦ù¿pο )((Š´i½¦³”¢.ÎZNbì›Î着½\“‡Vvî”cGoßU{Ñô'–­O*9A©œŽ‚’KÚ VЪÍsjþR\ TÎÖ£Rê·ærº'zyV|bdp8þLS¶x4':Ø»²?10µ Ц9®wJM<ªƒ÷pÙÝ$­€kƒ}ùàJÂ/û|ë¸ÞS[9"Ù$Ëc—§ÙNêñ÷HÝE[^w\oi;"Ù¥û&p”ãzŸ£É+×kÈ¢° Êw!°ŸãzCˆ¨‚‚ÿ)HûTJ½âÌ­}>Ÿ4]Á‰<µr¢6¦8¸K–*âÉ:ü•ýÊH;é]•ë]©ÓQjsNš˜¢¥îH4®êÊ=é¡êEÏ6ÁX¥Ô¹*S)~æT{‘Ã.N¯öî¥NR°>Ë–6—VÍ©ù Ýg_È7ºð%š¸ÄÈ&üœ—kb¶k>pa[VGá' {0âUàÇõb™qu\o~BÆ ˆÄù ü‘åë‚%6yÁq½ÿþrŒ$þr¤C›í¨Í²™‹Z›Ùæƒu˜r\ïüeRÅlÇbàä4lXŒ¿ôüj nG5…Ÿèt_½/$­ºêí2Òûgà Çõ>ôµÁVL-7+D8\í-¯ª®96¥RSêý,*µ¤R“«ª½2~iÏ©™Ýˆ«ÿÌR#XÚ„â¸ÞítcÌ Ö × ·&F"´p\¯Éq½;ð#Ý dº èmü°ðGâ"Œ-Aß ø%™'`\Lt\o_Çõž³Â×K:®w7°3þ~“L™,NöÜjF! õ„ßCÕÞ½>·gkñÛŽëý¼…Ù¯dÁùÝ—|3W…Gö÷ð<¡­<ŒŸƒäZ Ó¥K+€+€}‚™Ätûø/n"ó%muøâ÷t\oZL#ñë³üû|—ýLžÚ¥Šñ™0·ëx8Øq½Ó¶žÉý*á†}䘞ªWrÉÖ âÒð~9nÍ·Ã\ÈäÉÅæñ3ï†ð ¹¥ªÚ‹´Üdjy鉯]Bµ6·â3Ç­‰åC¦N*³ áDvŠ£E)EJ„y*É]Us½Ð ضÌi@(»ö£â „rB*-³NB$§R)~U5ÇK[¬ž>ndqSÿžg¢Œ‹EØ9&’THFÓ´ªÙKâžÚ»ÜœªDýB‘1´ƒ/•âæ/ëîxâ‰e?ìsÕ.²‰7“bà-Ú£Ù¹Ô¬àö ÛÈ@àü5îÇýÛ9d ð<ð,ð¬ãz±m‚ÂQ~7°c|àHµÅfü}DOOË rB\ï­l-MÙ{!°õIÇõÅ`Ãè ¾vÃ(ÕCsOü¨7ëƒÏ:à!Çõæ§qÎmÇ÷ÇÁyšð<ƒÍëÃvŽŸ œIfYº›“nu\ïñÊ;¦ÀÌÂm^ü$ÇÛ¶Ìžø™å'àϪm—F›~!p4ŸÅ_ޕС_•må  ®ÚKåðA üþ <,í$æ¾~9~èø àG^Z ¬Äçj`†ãzÆXv~Xó£¶*w Ð;è+«·*¿¸7ì=°-sgàtü%¨1·ËÕÀ…Žë-o¥^ÏÚ\ïàyÐ( zÖõ»&¨×ÇÛ¹ŽBàVüˆˆ#Qûb Rh©^¾êø•“Ì_Š.FJ¥¦L¯®¶F*ËG,’x!¤ËÕ¤š’ûVÍ[i-ãäq¥½ŠûÊåbÈEÁÃ7¬Ç·\!O¬ÝpÞó߯dƒ/Â& œ¡G…ÍíKWõž f6’ºçawÉt¬.!D¶®Û’†²c•P L †uêWˆ¨ª¸ç·æÝl:%ãÆK|«ßª Ô™Àáˆ$Bûz ùSÃÚÔŸfͯÝã·Ó ‘@ŒØä6Kx·#[µNí0ü$iëñ¦­Vßsåìoɰ½%SwI`ÇÊàóy®7v·akf¶öhfëJÇõ:M8Û2À``M°ÿAO½öߪ ꪭúØêl'´-³oàT>}áºÅ_á¸ÞgúniZh»kÛ[B*Ý­b&O^RRßo¼‚qŒ jJz 4¢Ø€¨u(ya J½Þ(É<â.Y§“&íÞ»/…‡*#µ¿(ì ²m î‹µXƒ’÷A½…ðj2™úÇŒ¹‹kuón› öêÑ_êR‰Ô¡AÝî.ÂP¥è-`€lµF‰|ŒRKAÞP)õ÷ésk‡½öñc†(•üJ¡L¡v%ôT=Â:…¼b‰‚—D¥ž­šSû޾Óm xø¶®ìŠF£Ñh¢"º 4M#G£³­·Å%fwèjÐh4"F¿y?V¾F‹F£Ñt0 ]¦ sÝ7”q:ÜîÍäb] F£ÑBD£ÑhbĬ`!7ßk1¢Ñh4"FW¡3®§#F.ÒÕ Ñh4š\¢÷ˆh4š.7“Þø1îÍÎb³6l‚>=sZìÅfwê£Ñh4-D4&>1²#ð*~Þ‹ÏòÏ`ý&Øm{H$rVl#°«YÁºÅh4&Ûè¥Y¦[`Vðp~æçÍç_šõLªµ9+V§k¢Ñh4-D4&~12¸ #ÛØÐ«¶ÊE¾j 4åF:]lVðn%F£ÑBD£Ñh²#Fîîé¨ö}¾R©ÿþ[¥ü¿e™Ì ~£[‡F£Ñh´Ñh4šìr!ðÛŽf”R°~ã7ÿ¾zÔ7f­Ø;Ì ~¦›„F£ÑhrÞ¬®Ñhº-ÞLÎî ;‚=uõ°ì£–¿ëÛ¶¯î.3+¸M·F£Ñä=#¢Ñhº-fÿ|Ñ! jchhÝhJÆVRP©EˆF£Ñh´Ñh4šü‰‘ùÀ¾@M¾m)H€´!F6lŠ¥˜ÕÀ±zcºF£Ñh´Ñh4šü‹‘w€yù"ýû´þýæúŒ‹xcVð¬¾ëF£ÑBD£Ñh:†Y”7ãïŸÈ C‚´òdVÑ­j~ aV°\ßmF£ÑtôfuF£i†7“½Arx>Ê_½>]õõ0¾ÃÃàþ¡O÷~¢Â7õÕh4"FÓ9É1ÀMÀ˜\—]ß›6ûÿ.)†‘ÛùË·Òäà*àA³‚”¾›F£ÑBD£Ñh:—1€JàÀö¹._)ÿ#ÒöFö­Ø€?›s›YÁ&}5F£…ˆF£ÑtnAR œ\ è€&®~üάà3}Ç4F£…ˆF£Ñt-AÒ˜XÀ8òŸ ñEü,ñš4ê;¤Ñh4-D4¦{ˆ’ãQr Ð;Å*à5à¯Àcf‹ôÐh4"FÓ}EI ð=àx`"°MŒ§ÿx5ë¥WF£ÑBD£Ñh4-‰†ÛÛµñlÖë¶úïûÀ¢-³‚µºV5FÓÕø¥€gç™¶IEND®B`‚xtensor-0.10.11/docs/source/xtensor-julia.svg000066400000000000000000000340101314655136400211370ustar00rootroot00000000000000 image/svg+xmlxtensor-0.10.11/docs/source/xtensor-python.svg000066400000000000000000000375551314655136400213750ustar00rootroot00000000000000 image/svg+xmlxtensor-0.10.11/docs/source/xtensor-r.svg000066400000000000000000000237721314655136400203110ustar00rootroot00000000000000 image/svg+xml xtensor-0.10.11/docs/source/xtensor.svg000066400000000000000000000170111314655136400200370ustar00rootroot00000000000000 image/svg+xmlxtensor-0.10.11/environment.yml000066400000000000000000000001661314655136400164560ustar00rootroot00000000000000name: xtensor channels: - nodefaults - conda-forge - SylvainCorlay dependencies: - cling_ubuntu14 - xtensor xtensor-0.10.11/include/000077500000000000000000000000001314655136400150075ustar00rootroot00000000000000xtensor-0.10.11/include/xtensor/000077500000000000000000000000001314655136400165115ustar00rootroot00000000000000xtensor-0.10.11/include/xtensor/xadapt.hpp000066400000000000000000000243131314655136400205060ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XADAPT_HPP #define XADAPT_HPP #include #include #include #include #include "xarray.hpp" #include "xtensor.hpp" namespace xt { /************************** * xarray_adaptor builder * **************************/ /** * Constructs an xarray_adaptor of the given stl-like container, * with the specified shape and layout. * @param container the container to adapt * @param shape the shape of the xarray_adaptor * @param l the layout_type of the xarray_adaptor */ template std::enable_if_t::value, xarray_adaptor> xadapt(C& container, const SC& shape, layout_type l = L); /** * Constructs an xarray_adaptor of the given stl-like container, * with the specified shape and strides. * @param container the container to adapt * @param shape the shape of the xarray_adaptor * @param strides the strides of the xarray_adaptor */ template std::enable_if_t::value, xarray_adaptor> xadapt(C& container, const SC& shape, const SC& strides); /** * Constructs an xarray_adaptor of the given dynamically allocated C array, * with the specified shape and layout. * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownerhsip()`` or ``accept_ownership()`` * @param shape the shape of the xarray_adaptor * @param l the layout_type of the xarray_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template >> std::enable_if_t::value, xarray_adaptor, O, A>, L, SC>> xadapt(P& pointer, typename A::size_type size, O ownership, const SC& shape, layout_type l = L, const A& alloc = A()); /** * Constructs an xarray_adaptor of the given dynamically allocated C array, * with the specified shape and layout. * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownerhsip()`` or ``accept_ownership()`` * @param shape the shape of the xarray_adaptor * @param strides the strides of the xarray_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template >> std::enable_if_t::value, xarray_adaptor, O, A>, layout_type::dynamic, SC>> xadapt(P& pointer, typename A::size_type size, O ownership, const SC& shape, const SC& strides, const A& alloc = A()); /*************************** * xtensor_adaptor builder * ***************************/ /** * Constructs an xtensor_adaptor of the given stl-like container, * with the specified shape and layout_type. * @param container the container to adapt * @param shape the shape of the xtensor_adaptor * @param l the layout_type of the xtensor_adaptor */ template xtensor_adaptor xadapt(C& container, const std::array& shape, layout_type l = L); /** * Constructs an xtensor_adaptor of the given stl-like container, * with the specified shape and strides. * @param container the container to adapt * @param shape the shape of the xtensor_adaptor * @param strides the strides of the xtensor_adaptor */ template xtensor_adaptor xadapt(C& container, const std::array& shape, const std::array& strides); /** * Constructs an xtensor_adaptor of the given dynamically allocated C array, * with the specified shape and layout. * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownerhsip()`` or ``accept_ownership()`` * @param shape the shape of the xtensor_adaptor * @param l the layout_type of the xtensor_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template >> xtensor_adaptor, O, A>, N, L> xadapt(P& pointer, typename A::size_type size, O ownership, const std::array& shape, layout_type l = L, const A& alloc = A()); /** * Constructs an xtensor_adaptor of the given dynamically allocated C array, * with the specified shape and layout. * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownerhsip()`` or ``accept_ownership()`` * @param shape the shape of the xtensor_adaptor * @param strides the strides of the xtensor_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template >> xtensor_adaptor, O, A>, N, layout_type::dynamic> xadapt(P& pointer, typename A::size_type size, O ownership, const std::array& shape, const std::array& strides, const A& alloc = A()); /***************************************** * xarray_adaptor builder implementation * *****************************************/ template inline std::enable_if_t::value, xarray_adaptor> xadapt(C& container, const SC& shape, layout_type l) { return xarray_adaptor(container, shape, l); } template inline std::enable_if_t::value, xarray_adaptor> xadapt(C& container, const SC& shape, const SC& strides) { return xarray_adaptor(container, shape, strides); } template inline std::enable_if_t::value, xarray_adaptor, O, A>, L, SC>> xadapt(P& pointer, typename A::size_type size, O, const SC& shape, layout_type l, const A& alloc) { using buffer_type = xbuffer_adaptor, O, A>; buffer_type buf(pointer, size, alloc); return xarray_adaptor(std::move(buf), shape, l); } template inline std::enable_if_t::value, xarray_adaptor, O, A>, layout_type::dynamic, SC>> xadapt(P& pointer, typename A::size_type size, O, const SC& shape, const SC& strides, const A& alloc) { using buffer_type = xbuffer_adaptor, O, A>; buffer_type buf(pointer, size, alloc); return xarray_adaptor(std::move(buf), shape, strides); } /****************************************** * xtensor_adaptor builder implementation * ******************************************/ template inline xtensor_adaptor xadapt(C& container, const std::array& shape, layout_type l) { return xtensor_adaptor(container, shape, l); } template inline xtensor_adaptor xadapt(C& container, const std::array& shape, const std::array& strides) { return xtensor_adaptor(container, shape, strides); } template inline xtensor_adaptor, O, A>, N, L> xadapt(P& pointer, typename A::size_type size, O, const std::array& shape, layout_type l, const A& alloc) { using buffer_type = xbuffer_adaptor, O, A>; buffer_type buf(pointer, size, alloc); return xtensor_adaptor(std::move(buf), shape, l); } template inline xtensor_adaptor, O, A>, N, layout_type::dynamic> xadapt(P& pointer, typename A::size_type size, O, const std::array& shape, const std::array& strides, const A& alloc) { using buffer_type = xbuffer_adaptor, O, A>; buffer_type buf(pointer, size, alloc); return xtensor_adaptor(std::move(buf), shape, strides); } } #endif xtensor-0.10.11/include/xtensor/xarray.hpp000066400000000000000000000451271314655136400205410ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XARRAY_HPP #define XARRAY_HPP #include #include #include #include "xbuffer_adaptor.hpp" #include "xcontainer.hpp" #include "xsemantic.hpp" namespace xt { /******************************** * xarray_container declaration * ********************************/ template struct xcontainer_inner_types> { using container_type = EC; using shape_type = SC; using strides_type = shape_type; using backstrides_type = shape_type; using inner_shape_type = shape_type; using inner_strides_type = strides_type; using inner_backstrides_type = backstrides_type; using temporary_type = xarray_container; }; template struct xiterable_inner_types> : xcontainer_iterable_types> { }; /** * @class xarray_container * @brief Dense multidimensional container with tensor semantic. * * The xarray_container class implements a dense multidimensional container * with tensor semantic. * * @tparam EC The type of the container holding the elements. * @tparam L The layout_type of the container. * @tparam SC The type of the containers holding the shape and the strides. * @sa xarray */ template class xarray_container : public xstrided_container, L>, public xcontainer_semantic> { public: using self_type = xarray_container; using base_type = xstrided_container; using semantic_base = xcontainer_semantic; using container_type = typename base_type::container_type; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using const_reference = typename base_type::const_reference; using pointer = typename base_type::pointer; using const_pointer = typename base_type::const_pointer; using shape_type = typename base_type::shape_type; using inner_shape_type = typename base_type::inner_shape_type; using strides_type = typename base_type::strides_type; using backstrides_type = typename base_type::backstrides_type; using inner_strides_type = typename base_type::inner_strides_type; xarray_container(); explicit xarray_container(const shape_type& shape, layout_type l = L); explicit xarray_container(const shape_type& shape, const_reference value, layout_type l = L); explicit xarray_container(const shape_type& shape, const strides_type& strides); explicit xarray_container(const shape_type& shape, const strides_type& strides, const_reference value); explicit xarray_container(container_type&& data, inner_shape_type&& shape, inner_strides_type&& strides); xarray_container(const value_type& t); xarray_container(nested_initializer_list_t t); xarray_container(nested_initializer_list_t t); xarray_container(nested_initializer_list_t t); xarray_container(nested_initializer_list_t t); xarray_container(nested_initializer_list_t t); template static xarray_container from_shape(S&& s); ~xarray_container() = default; xarray_container(const xarray_container&) = default; xarray_container& operator=(const xarray_container&) = default; xarray_container(xarray_container&&) = default; xarray_container& operator=(xarray_container&&) = default; template xarray_container(const xexpression& e); template xarray_container& operator=(const xexpression& e); private: container_type m_data; container_type& data_impl() noexcept; const container_type& data_impl() const noexcept; friend class xcontainer>; }; /****************************** * xarray_adaptor declaration * ******************************/ template > class xarray_adaptor; template struct xcontainer_inner_types> { using container_type = EC; using shape_type = SC; using strides_type = shape_type; using backstrides_type = shape_type; using inner_shape_type = shape_type; using inner_strides_type = strides_type; using inner_backstrides_type = backstrides_type; using temporary_type = xarray_container; }; template struct xiterable_inner_types> : xcontainer_iterable_types> { }; /** * @class xarray_adaptor * @brief Dense multidimensional container adaptor with * tensor semantic. * * The xarray_adaptor class implements a dense multidimensional * container adaptor with tensor semantic. It is used to provide * a multidimensional container semantic and a tensor semantic to * stl-like containers. * * @tparam EC The container type to adapt. * @tparam L The layout_type of the adaptor. * @tparam SC The type of the containers holding the shape and the strides. */ template class xarray_adaptor : public xstrided_container, L>, public xadaptor_semantic> { public: using self_type = xarray_adaptor; using base_type = xstrided_container; using semantic_base = xadaptor_semantic; using container_type = typename base_type::container_type; using shape_type = typename base_type::shape_type; using strides_type = typename base_type::strides_type; using backstrides_type = typename base_type::backstrides_type; using container_closure_type = adaptor_closure_t; xarray_adaptor(container_closure_type data); xarray_adaptor(container_closure_type data, const shape_type& shape, layout_type l = L); xarray_adaptor(container_closure_type data, const shape_type& shape, const strides_type& strides); ~xarray_adaptor() = default; xarray_adaptor(const xarray_adaptor&) = default; xarray_adaptor& operator=(const xarray_adaptor&); xarray_adaptor(xarray_adaptor&&) = default; xarray_adaptor& operator=(xarray_adaptor&&); template xarray_adaptor& operator=(const xexpression& e); private: container_closure_type m_data; container_type& data_impl() noexcept; const container_type& data_impl() const noexcept; using temporary_type = typename xcontainer_inner_types::temporary_type; void assign_temporary_impl(temporary_type&& tmp); friend class xcontainer>; friend class xadaptor_semantic>; }; /*********************************** * xarray_container implementation * ***********************************/ /** * @name Constructors */ //@{ /** * Allocates an uninitialized xarray_container that holds 0 element. */ template inline xarray_container::xarray_container() : base_type(), m_data(1, value_type()) { } /** * Allocates an uninitialized xarray_container with the specified shape and * layout_type. * @param shape the shape of the xarray_container * @param l the layout_type of the xarray_container */ template inline xarray_container::xarray_container(const shape_type& shape, layout_type l) : base_type() { base_type::reshape(shape, l); } /** * Allocates an xarray_container with the specified shape and layout_type. Elements * are initialized to the specified value. * @param shape the shape of the xarray_container * @param value the value of the elements * @param l the layout_type of the xarray_container */ template inline xarray_container::xarray_container(const shape_type& shape, const_reference value, layout_type l) : base_type() { base_type::reshape(shape, l); std::fill(m_data.begin(), m_data.end(), value); } /** * Allocates an uninitialized xarray_container with the specified shape and strides. * @param shape the shape of the xarray_container * @param strides the strides of the xarray_container */ template inline xarray_container::xarray_container(const shape_type& shape, const strides_type& strides) : base_type() { base_type::reshape(shape, strides); } /** * Allocates an uninitialized xarray_container with the specified shape and strides. * Elements are initialized to the specified value. * @param shape the shape of the xarray_container * @param strides the strides of the xarray_container * @param value the value of the elements */ template inline xarray_container::xarray_container(const shape_type& shape, const strides_type& strides, const_reference value) : base_type() { base_type::reshape(shape, strides); std::fill(m_data.begin(), m_data.end(), value); } /** * Allocates an xarray_container that holds a single element initialized to the * specified value. * @param t the value of the element */ template inline xarray_container::xarray_container(const value_type& t) : base_type() { base_type::reshape(xt::shape(t), true); nested_copy(m_data.begin(), t); } /** * Allocates an xarray_container by moving specified data, shape and strides * * @param data the data for the xarray_container * @param shape the shape of the xarray_container * @param strides the strides of the xarray_container */ template inline xarray_container::xarray_container(container_type&& data, inner_shape_type&& shape, inner_strides_type&& strides) : base_type(std::move(shape), std::move(strides)), m_data(std::move(data)) { } //@} /** * @name Constructors from initializer list */ //@{ /** * Allocates a one-dimensional xarray_container. * @param t the elements of the xarray_container */ template inline xarray_container::xarray_container(nested_initializer_list_t t) : base_type() { base_type::reshape(xt::shape(t)); L == layout_type::row_major ? nested_copy(m_data.begin(), t) : nested_copy(this->template xbegin(), t); } /** * Allocates a two-dimensional xarray_container. * @param t the elements of the xarray_container */ template inline xarray_container::xarray_container(nested_initializer_list_t t) : base_type() { base_type::reshape(xt::shape(t)); L == layout_type::row_major ? nested_copy(m_data.begin(), t) : nested_copy(this->template xbegin(), t); } /** * Allocates a three-dimensional xarray_container. * @param t the elements of the xarray_container */ template inline xarray_container::xarray_container(nested_initializer_list_t t) : base_type() { base_type::reshape(xt::shape(t)); L == layout_type::row_major ? nested_copy(m_data.begin(), t) : nested_copy(this->template xbegin(), t); } /** * Allocates a four-dimensional xarray_container. * @param t the elements of the xarray_container */ template inline xarray_container::xarray_container(nested_initializer_list_t t) : base_type() { base_type::reshape(xt::shape(t)); L == layout_type::row_major ? nested_copy(m_data.begin(), t) : nested_copy(this->template xbegin(), t); } /** * Allocates a five-dimensional xarray_container. * @param t the elements of the xarray_container */ template inline xarray_container::xarray_container(nested_initializer_list_t t) : base_type() { base_type::reshape(xt::shape(t)); L == layout_type::row_major ? nested_copy(m_data.begin(), t) : nested_copy(this->template xbegin(), t); } template template inline xarray_container xarray_container::from_shape(S&& s) { shape_type shape = forward_sequence(s); return self_type(shape); } //@} /** * @name Extended copy semantic */ //@{ /** * The extended copy constructor. */ template template inline xarray_container::xarray_container(const xexpression& e) : base_type() { // Avoids unintialized data because of (m_shape == shape) condition // in reshape (called by assign), which is always true when dimension == 0. if (e.derived_cast().dimension() == 0) { m_data.resize(1); } semantic_base::assign(e); } /** * The extended assignment operator. */ template template inline auto xarray_container::operator=(const xexpression& e) -> self_type& { return semantic_base::operator=(e); } //@} template inline auto xarray_container::data_impl() noexcept -> container_type& { return m_data; } template inline auto xarray_container::data_impl() const noexcept -> const container_type& { return m_data; } /****************** * xarray_adaptor * ******************/ /** * @name Constructors */ //@{ /** * Constructs an xarray_adaptor of the given stl-like container. * @param data the container to adapt */ template inline xarray_adaptor::xarray_adaptor(container_closure_type data) : base_type(), m_data(std::forward(data)) { } /** * Constructs an xarray_adaptor of the given stl-like container, * with the specified shape and layout_type. * @param data the container to adapt * @param shape the shape of the xarray_adaptor * @param l the layout_type of the xarray_adaptor */ template inline xarray_adaptor::xarray_adaptor(container_closure_type data, const shape_type& shape, layout_type l) : base_type(), m_data(std::forward(data)) { base_type::reshape(shape, l); } /** * Constructs an xarray_adaptor of the given stl-like container, * with the specified shape and strides. * @param data the container to adapt * @param shape the shape of the xarray_adaptor * @param strides the strides of the xarray_adaptor */ template inline xarray_adaptor::xarray_adaptor(container_closure_type data, const shape_type& shape, const strides_type& strides) : base_type(), m_data(std::forward(data)) { base_type::reshape(shape, strides); } //@} template inline auto xarray_adaptor::operator=(const xarray_adaptor& rhs) -> self_type& { base_type::operator=(rhs); m_data = rhs.m_data; return *this; } template inline auto xarray_adaptor::operator=(xarray_adaptor&& rhs) -> self_type& { base_type::operator=(std::move(rhs)); m_data = rhs.m_data; return *this; } /** * @name Extended copy semantic */ //@{ /** * The extended assignment operator. */ template template inline auto xarray_adaptor::operator=(const xexpression& e) -> self_type& { return semantic_base::operator=(e); } //@} template inline auto xarray_adaptor::data_impl() noexcept -> container_type& { return m_data; } template inline auto xarray_adaptor::data_impl() const noexcept -> const container_type& { return m_data; } template inline void xarray_adaptor::assign_temporary_impl(temporary_type&& tmp) { base_type::shape_impl() = std::move(const_cast(tmp.shape())); base_type::strides_impl() = std::move(const_cast(tmp.strides())); base_type::backstrides_impl() = std::move(const_cast(tmp.backstrides())); m_data = std::move(tmp.data()); } } #endif xtensor-0.10.11/include/xtensor/xassign.hpp000066400000000000000000000176351314655136400207120ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XASSIGN_HPP #define XASSIGN_HPP #include "xiterator.hpp" #include "xtensor_forward.hpp" #include namespace xt { template class xexpression; /******************** * Assign functions * ********************/ template void assign_data(xexpression& e1, const xexpression& e2, bool trivial); template bool reshape(xexpression& e1, const xexpression& e2); template void assign_xexpression(xexpression& e1, const xexpression& e2); template void computed_assign(xexpression& e1, const xexpression& e2); template void scalar_computed_assign(xexpression& e1, const E2& e2, F&& f); template void assert_compatible_shape(const xexpression& e1, const xexpression& e2); /***************** * data_assigner * *****************/ template class data_assigner { public: using lhs_iterator = typename E1::stepper; using rhs_iterator = typename E2::const_stepper; using shape_type = typename E1::shape_type; using index_type = xindex_type_t; using size_type = typename lhs_iterator::size_type; data_assigner(E1& e1, const E2& e2); void run(); void step(size_type i); void reset(size_type i); void to_end(layout_type); private: E1& m_e1; lhs_iterator m_lhs; rhs_iterator m_rhs; rhs_iterator m_rhs_end; index_type m_index; }; /******************** * trivial_assigner * ********************/ template struct trivial_assigner { template static void run(E1& e1, const E2& e2); }; /*********************************** * Assign functions implementation * ***********************************/ namespace detail { template inline bool is_trivial_broadcast(const E1& e1, const E2& e2) { return e2.is_trivial_broadcast(e1.strides()); } template inline bool is_trivial_broadcast(const xview&, const E2&) { return false; } } template inline void assign_data(xexpression& e1, const xexpression& e2, bool trivial) { E1& de1 = e1.derived_cast(); const E2& de2 = e2.derived_cast(); bool trivial_broadcast = trivial && detail::is_trivial_broadcast(de1, de2); if (trivial_broadcast) { constexpr bool contiguous_layout = E1::contiguous_layout && E2::contiguous_layout; trivial_assigner::run(de1, de2); } else { data_assigner assigner(de1, de2); assigner.run(); } } template inline bool reshape(xexpression& e1, const xexpression& e2) { using shape_type = typename E1::shape_type; using size_type = typename E1::size_type; const E2& de2 = e2.derived_cast(); size_type size = de2.dimension(); shape_type shape = make_sequence(size, size_type(1)); bool trivial_broadcast = de2.broadcast_shape(shape); e1.derived_cast().reshape(shape); return trivial_broadcast; } template inline void assign_xexpression(xexpression& e1, const xexpression& e2) { bool trivial_broadcast = reshape(e1, e2); assign_data(e1, e2, trivial_broadcast); } template inline void computed_assign(xexpression& e1, const xexpression& e2) { using shape_type = typename E1::shape_type; using size_type = typename E1::size_type; E1& de1 = e1.derived_cast(); const E2& de2 = e2.derived_cast(); size_type dim = de2.dimension(); shape_type shape = make_sequence(dim, size_type(1)); bool trivial_broadcast = de2.broadcast_shape(shape); if (dim > de1.dimension() || shape > de1.shape()) { typename E1::temporary_type tmp(shape); assign_data(tmp, e2, trivial_broadcast); de1.assign_temporary(std::move(tmp)); } else { assign_data(e1, e2, trivial_broadcast); } } template inline void scalar_computed_assign(xexpression& e1, const E2& e2, F&& f) { E1& d = e1.derived_cast(); std::transform(d.cbegin(), d.cend(), d.begin(), [e2, &f](const auto& v) { return f(v, e2); }); } template inline void assert_compatible_shape(const xexpression& e1, const xexpression& e2) { using shape_type = typename E1::shape_type; using size_type = typename E1::size_type; const E1& de1 = e1.derived_cast(); const E2& de2 = e2.derived_cast(); size_type size = de2.dimension(); shape_type shape = make_sequence(size, size_type(1)); de2.broadcast_shape(shape); if (shape.size() > de1.shape().size() || shape > de1.shape()) { throw broadcast_error(shape, de1.shape()); } } /******************************** * data_assigner implementation * ********************************/ template inline data_assigner::data_assigner(E1& e1, const E2& e2) : m_e1(e1), m_lhs(e1.stepper_begin(e1.shape())), m_rhs(e2.stepper_begin(e1.shape())), m_rhs_end(e2.stepper_end(e1.shape(), L)), m_index(make_sequence(e1.shape().size(), size_type(0))) { } template inline void data_assigner::run() { while (m_rhs != m_rhs_end) { *m_lhs = *m_rhs; stepper_tools::increment_stepper(*this, m_index, m_e1.shape()); } } template inline void data_assigner::step(size_type i) { m_lhs.step(i); m_rhs.step(i); } template inline void data_assigner::reset(size_type i) { m_lhs.reset(i); m_rhs.reset(i); } template inline void data_assigner::to_end(layout_type l) { m_lhs.to_end(l); m_rhs.to_end(l); } /*********************************** * trivial_assigner implementation * ***********************************/ template template inline void trivial_assigner::run(E1& e1, const E2& e2) { using size_type = typename E1::size_type; size_type size = e1.size(); for (size_type i = 0; i < size; ++i) { e1.data_element(i) = e2.data_element(i); } } template <> template inline void trivial_assigner::run(E1& e1, const E2& e2) { std::copy(e2.cbegin(), e2.cend(), e1.begin()); } } #endif xtensor-0.10.11/include/xtensor/xaxis_iterator.hpp000066400000000000000000000125401314655136400222710ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XAXIS_ITERATOR_HPP #define XAXIS_ITERATOR_HPP #include "xview.hpp" namespace xt { /****************** * xaxis_iterator * ******************/ template class xaxis_iterator { public: using self_type = xaxis_iterator; using xexpression_type = std::decay_t; using size_type = typename xexpression_type::size_type; using difference_type = typename xexpression_type::difference_type; using value_type = xview; using reference = std::remove_reference_t>; using pointer = std::nullptr_t; using iterator_category = std::forward_iterator_tag; xaxis_iterator(); template xaxis_iterator(CTA&& e, size_type index); self_type& operator++(); self_type operator++(int); reference operator*() const; pointer operator->() const; bool equal(const self_type& rhs) const; private: using storing_type = ptr_closure_t; mutable storing_type p_expression; size_type m_index; template std::enable_if_t::value, std::add_lvalue_reference_t>> deref(T val) const; template std::enable_if_t::value, T> deref(T& val) const; template std::enable_if_t::value, T> get_storage_init(CTA&& e) const; template std::enable_if_t::value, T> get_storage_init(CTA&& e) const; }; template bool operator==(const xaxis_iterator& lhs, const xaxis_iterator& rhs); template bool operator!=(const xaxis_iterator& lhs, const xaxis_iterator& rhs); template auto axis_begin(E&& e); template auto axis_end(E&& e); /********************************* * xaxis_iterator implementation * *********************************/ template template inline std::enable_if_t::value, std::add_lvalue_reference_t>> xaxis_iterator::deref(T val) const { return *val; } template template inline std::enable_if_t::value, T> xaxis_iterator::deref(T& val) const { return val; } template template inline std::enable_if_t::value, T> xaxis_iterator::get_storage_init(CTA&& e) const { return &e; } template template inline std::enable_if_t::value, T> xaxis_iterator::get_storage_init(CTA&& e) const { return e; } template inline xaxis_iterator::xaxis_iterator() : p_expression(nullptr), m_index(0) { } template template inline xaxis_iterator::xaxis_iterator(CTA&& e, size_type index) : p_expression(get_storage_init(std::forward(e))), m_index(index) { } template inline auto xaxis_iterator::operator++() -> self_type& { ++m_index; return *this; } template inline auto xaxis_iterator::operator++(int) -> self_type { self_type tmp(*this); ++(*this); return tmp; } template inline auto xaxis_iterator::operator*() const -> reference { return view(deref(p_expression), size_type(m_index)); } template inline auto xaxis_iterator::operator->() const -> pointer { return nullptr; } template inline bool xaxis_iterator::equal(const self_type& rhs) const { return p_expression == rhs.p_expression && m_index == rhs.m_index; } template inline bool operator==(const xaxis_iterator& lhs, const xaxis_iterator& rhs) { return lhs.equal(rhs); } template inline bool operator!=(const xaxis_iterator& lhs, const xaxis_iterator& rhs) { return !(lhs == rhs); } template inline auto axis_begin(E&& e) { using return_type = xaxis_iterator>; using size_type = typename std::decay_t::size_type; return return_type(std::forward(e), size_type(0)); } template inline auto axis_end(E&& e) { using return_type = xaxis_iterator>; using size_type = typename std::decay_t::size_type; return return_type(std::forward(e), size_type(e.shape()[0])); } } #endif xtensor-0.10.11/include/xtensor/xbroadcast.hpp000066400000000000000000000257671314655136400213750ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XBROADCAST_HPP #define XBROADCAST_HPP #include #include #include #include #include #include #include #include "xexpression.hpp" #include "xiterable.hpp" #include "xstrides.hpp" #include "xutils.hpp" namespace xt { /************* * broadcast * *************/ template auto broadcast(E&& e, const S& s) noexcept; #ifdef X_OLD_CLANG template auto broadcast(E&& e, std::initializer_list s) noexcept; #else template auto broadcast(E&& e, const I (&s)[L]) noexcept; #endif /************** * xbroadcast * **************/ template class xbroadcast; template struct xiterable_inner_types> { using xexpression_type = std::decay_t; using inner_shape_type = promote_shape_t; using const_stepper = typename xexpression_type::const_stepper; using stepper = const_stepper; using const_iterator = xiterator; using iterator = const_iterator; using const_reverse_iterator = std::reverse_iterator; using reverse_iterator = std::reverse_iterator; }; /** * @class xbroadcast * @brief Broadcasted xexpression to a specified shape. * * The xbroadcast class implements the broadcasting of an \ref xexpression * to a specified shape. xbroadcast is not meant to be used directly, but * only with the \ref broadcast helper functions. * * @tparam CT the closure type of the \ref xexpression to broadcast * @tparam X the type of the specified shape. * * @sa broadcast */ template class xbroadcast : public xexpression>, public xexpression_const_iterable> { public: using self_type = xbroadcast; using xexpression_type = std::decay_t; using value_type = typename xexpression_type::value_type; using reference = typename xexpression_type::reference; using const_reference = typename xexpression_type::const_reference; using pointer = typename xexpression_type::pointer; using const_pointer = typename xexpression_type::const_pointer; using size_type = typename xexpression_type::size_type; using difference_type = typename xexpression_type::difference_type; using iterable_base = xexpression_const_iterable; using inner_shape_type = typename iterable_base::inner_shape_type; using shape_type = inner_shape_type; using stepper = typename iterable_base::stepper; using const_stepper = typename iterable_base::const_stepper; static constexpr layout_type static_layout = xexpression_type::static_layout; //static constexpr bool contiguous_layout = xexpression_type::contiguous_layout; static constexpr bool contiguous_layout = false; template xbroadcast(CTA&& e, S&& s) noexcept; size_type size() const noexcept; size_type dimension() const noexcept; const inner_shape_type& shape() const noexcept; layout_type layout() const noexcept; template const_reference operator()(Args... args) const; const_reference operator[](const xindex& index) const; const_reference operator[](size_type i) const; template const_reference element(It, It last) const; template bool broadcast_shape(S& shape) const; template bool is_trivial_broadcast(const S& strides) const noexcept; template const_stepper stepper_begin(const S& shape) const noexcept; template const_stepper stepper_end(const S& shape, layout_type l) const noexcept; private: CT m_e; inner_shape_type m_shape; }; /**************************** * broadcast implementation * ****************************/ /** * @brief Returns an \ref xexpression broadcasting the given expression to * a specified shape. * * @tparam e the \ref xexpression to broadcast * @tparam s the specified shape to broadcast. * * The returned expression either hold a const reference to \p e or a copy * depending on whether \p e is an lvalue or an rvalue. */ template inline auto broadcast(E&& e, const S& s) noexcept { using broadcast_type = xbroadcast, S>; using shape_type = typename broadcast_type::shape_type; return broadcast_type(std::forward(e), forward_sequence(s)); } #ifdef X_OLD_CLANG template inline auto broadcast(E&& e, std::initializer_list s) noexcept { using broadcast_type = xbroadcast, std::vector>; using shape_type = typename broadcast_type::shape_type; return broadcast_type(std::forward(e), forward_sequence(s)); } #else template inline auto broadcast(E&& e, const I (&s)[L]) noexcept { using broadcast_type = xbroadcast, std::array>; using shape_type = typename broadcast_type::shape_type; return broadcast_type(std::forward(e), forward_sequence(s)); } #endif /***************************** * xbroadcast implementation * *****************************/ /** * @name Constructor */ //@{ /** * Constructs an xbroadcast expression broadcasting the specified * \ref xexpression to the given shape * * @param e the expression to broadcast * @param s the shape to apply */ template template inline xbroadcast::xbroadcast(CTA&& e, S&& s) noexcept : m_e(std::forward(e)), m_shape(std::forward(s)) { xt::broadcast_shape(m_e.shape(), m_shape); } //@} /** * @name Size and shape */ /** * Returns the size of the expression. */ template inline auto xbroadcast::size() const noexcept -> size_type { return compute_size(shape()); } /** * Returns the number of dimensions of the expression. */ template inline auto xbroadcast::dimension() const noexcept -> size_type { return m_shape.size(); } /** * Returns the shape of the expression. */ template inline auto xbroadcast::shape() const noexcept -> const inner_shape_type& { return m_shape; } /** * Returns the layout_type of the expression. */ template inline layout_type xbroadcast::layout() const noexcept { return m_e.layout(); } //@} /** * @name Data */ /** * Returns a constant reference to the element at the specified position in the expression. * @param args a list of indices specifying the position in the function. Indices * must be unsigned integers, the number of indices should be equal or greater than * the number of dimensions of the expression. */ template template inline auto xbroadcast::operator()(Args... args) const -> const_reference { return detail::get_element(m_e, args...); } /** * Returns a constant reference to the element at the specified position in the expression. * @param index a sequence of indices specifying the position in the function. Indices * must be unsigned integers, the number of indices in the sequence should be equal or greater * than the number of dimensions of the container. */ template inline auto xbroadcast::operator[](const xindex& index) const -> const_reference { return element(index.cbegin(), index.cend()); } template inline auto xbroadcast::operator[](size_type i) const -> const_reference { return operator()(i); } /** * Returns a constant reference to the element at the specified position in the expression. * @param first iterator starting the sequence of indices * @param last iterator ending the sequence of indices * The number of indices in the sequence should be equal to or greater * than the number of dimensions of the function. */ template template inline auto xbroadcast::element(It, It last) const -> const_reference { return m_e.element(last - dimension(), last); } //@} /** * @name Broadcasting */ //@{ /** * Broadcast the shape of the function to the specified parameter. * @param shape the result shape * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xbroadcast::broadcast_shape(S& shape) const { return xt::broadcast_shape(m_shape, shape); } /** * Compares the specified strides with those of the container to see whether * the broadcasting is trivial. * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xbroadcast::is_trivial_broadcast(const S& strides) const noexcept { return dimension() == m_e.dimension() && std::equal(m_shape.cbegin(), m_shape.cend(), m_e.shape().cbegin()) && m_e.is_trivial_broadcast(strides); } //@} template template inline auto xbroadcast::stepper_begin(const S& shape) const noexcept -> const_stepper { // Could check if (broadcastable(shape, m_shape) return m_e.stepper_begin(shape); } template template inline auto xbroadcast::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper { // Could check if (broadcastable(shape, m_shape) return m_e.stepper_end(shape, l); } } #endif xtensor-0.10.11/include/xtensor/xbuffer_adaptor.hpp000066400000000000000000000445551314655136400224120ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XBUFFER_ADAPTOR_HPP #define XBUFFER_ADAPTOR_HPP #include #include #include #include #include #include "xstorage.hpp" namespace xt { struct no_ownership { }; struct acquire_ownership { }; namespace detail { template class xbuffer_storage { public: using self_type = xbuffer_storage; using allocator_type = A; using value_type = typename allocator_type::value_type; using reference = typename allocator_type::reference; using const_reference = typename allocator_type::const_reference; using pointer = typename allocator_type::pointer; using const_pointer = typename allocator_type::const_pointer; using size_type = typename allocator_type::size_type; using difference_type = typename allocator_type::difference_type; xbuffer_storage(); xbuffer_storage(T*& data, size_type size, const allocator_type& alloc = allocator_type()); size_type size() const noexcept; void resize(size_type size); pointer data() noexcept; const_pointer data() const noexcept; void swap(self_type& rhs) noexcept; private: pointer p_data; size_type m_size; }; template class xbuffer_owner_storage { public: using self_type = xbuffer_owner_storage; using allocator_type = A; using value_type = typename allocator_type::value_type; using reference = typename allocator_type::reference; using const_reference = typename allocator_type::const_reference; using pointer = typename allocator_type::pointer; using const_pointer = typename allocator_type::const_pointer; using size_type = typename allocator_type::size_type; using difference_type = typename allocator_type::difference_type; xbuffer_owner_storage(); xbuffer_owner_storage(T*& data, size_type size, const allocator_type& alloc = allocator_type()); ~xbuffer_owner_storage(); xbuffer_owner_storage(const self_type&) = delete; self_type& operator=(const self_type&); xbuffer_owner_storage(self_type&&); self_type& operator=(self_type&&); size_type size() const noexcept; void resize(size_type size); pointer data() noexcept; const_pointer data() const noexcept; allocator_type get_allocator() const noexcept; void swap(self_type& rhs) noexcept; private: pointer* p_data; size_type m_size; allocator_type m_allocator; }; template struct get_buffer_storage { using type = xbuffer_storage; }; template struct get_buffer_storage { using type = xbuffer_owner_storage; }; template using buffer_storage_t = typename get_buffer_storage::type; } template > class xbuffer_adaptor : private detail::buffer_storage_t { public: using base_type = detail::buffer_storage_t; using allocator_type = typename base_type::allocator_type; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using const_reference = typename base_type::const_reference; using pointer = typename base_type::pointer; using const_pointer = typename base_type::const_pointer; using size_type = typename base_type::size_type; using difference_type = typename base_type::difference_type; using iterator = pointer; using const_iterator = const_pointer; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; xbuffer_adaptor() = default; template ::value>> xbuffer_adaptor(T*& data, size_type size, const allocator_type& alloc = allocator_type()); template ::value>> xbuffer_adaptor(T* data, size_type size, const allocator_type& alloc = allocator_type()); bool empty() const noexcept; using base_type::size; using base_type::resize; reference operator[](size_type i); const_reference operator[](size_type i) const; reference front(); const_reference front() const; reference back(); const_reference back() const; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; const_iterator cbegin() const; const_iterator cend() const; reverse_iterator rbegin(); reverse_iterator rend(); const_reverse_iterator rbegin() const; const_reverse_iterator rend() const; const_reverse_iterator crbegin() const; const_reverse_iterator crend() const; using base_type::data; using base_type::swap; }; template bool operator==(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs); template bool operator!=(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs); template bool operator<(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs); template bool operator<=(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs); template bool operator>(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs); template bool operator>=(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs); template void swap(xbuffer_adaptor& lhs, xbuffer_adaptor& rhs) noexcept; /******************* * adaptor_closure * *******************/ namespace detail { template struct adaptor_closure_impl { using type = C&; }; template struct adaptor_closure_impl> { using type = xbuffer_adaptor; }; } template using adaptor_closure_t = typename detail::adaptor_closure_impl::type; /********************************** * xbuffer_storage implementation * **********************************/ namespace detail { template inline xbuffer_storage::xbuffer_storage() : p_data(nullptr), m_size(0) { } template inline xbuffer_storage::xbuffer_storage(T*& data, size_type size, const allocator_type&) : p_data(data), m_size(size) { } template inline auto xbuffer_storage::size() const noexcept -> size_type { return m_size; } template inline void xbuffer_storage::resize(size_type size) { if (size != m_size) throw std::runtime_error("xbuffer_storage not resizable"); } template inline auto xbuffer_storage::data() noexcept -> pointer { return p_data; } template inline auto xbuffer_storage::data() const noexcept -> const_pointer { return p_data; } template inline void xbuffer_storage::swap(self_type& rhs) noexcept { using std::swap; swap(p_data, rhs.p_data); swap(m_size, rhs.m_size); } } /**************************************** * xbuffer_owner_storage implementation * ****************************************/ namespace detail { template inline xbuffer_owner_storage::xbuffer_owner_storage() : p_data(nullptr), m_size(0), m_allocator() { } template inline xbuffer_owner_storage::xbuffer_owner_storage(T*& data, size_type size, const allocator_type& alloc) : p_data(&data), m_size(size), m_allocator(alloc) { } template inline xbuffer_owner_storage::~xbuffer_owner_storage() { if (p_data != nullptr) { safe_destroy_deallocate(m_allocator, *p_data, m_size); p_data = nullptr; m_size = 0; } } template inline auto xbuffer_owner_storage::operator=(const self_type& rhs) -> self_type& { using std::swap; if (this != &rhs) { allocator_type al = std::allocator_traits::select_on_container_copy_construction(rhs.get_allocator()); pointer tmp = safe_init_allocate(al, rhs.m_size); if (xtrivially_default_constructible::value) { std::uninitialized_copy(*(rhs.p_data), *(rhs.p_data) + rhs.m_size, tmp); } else { std::copy(*(rhs.p_data), *(rhs.p_data) + rhs.m_size, tmp); } swap(*p_data, tmp); m_size = rhs.m_size; swap(m_allocator, al); safe_destroy_deallocate(al, tmp, m_size); } return *this; } template inline xbuffer_owner_storage::xbuffer_owner_storage(self_type&& rhs) : p_data(rhs.p_data), m_size(rhs.m_size), m_allocator(std::move(rhs.m_allocator)) { rhs.p_data = nullptr; rhs.m_size = 0; } template inline auto xbuffer_owner_storage::operator=(self_type&& rhs) -> self_type& { swap(rhs); return *this; } template inline auto xbuffer_owner_storage::size() const noexcept -> size_type { return m_size; } template void xbuffer_owner_storage::resize(size_type size) { using std::swap; if (size != m_size) { pointer tmp = safe_init_allocate(m_allocator, size); swap(*p_data, tmp); swap(m_size, size); safe_destroy_deallocate(m_allocator, tmp, size); } } template inline auto xbuffer_owner_storage::data() noexcept -> pointer { return *p_data; } template inline auto xbuffer_owner_storage::data() const noexcept -> const_pointer { return *p_data; } template inline auto xbuffer_owner_storage::get_allocator() const noexcept -> allocator_type { return allocator_type(m_allocator); } template inline void xbuffer_owner_storage::swap(self_type& rhs) noexcept { using std::swap; swap(p_data, rhs.p_data); swap(m_size, rhs.m_size); swap(m_allocator, rhs.m_allocator); } } /********************************** * xbuffer_adaptor implementation * **********************************/ template template inline xbuffer_adaptor::xbuffer_adaptor(T*& data, size_type size, const allocator_type& alloc) : base_type(data, size, alloc) { } template template inline xbuffer_adaptor::xbuffer_adaptor(T* data, size_type size, const allocator_type& alloc) : base_type(data, size, alloc) { } template bool xbuffer_adaptor::empty() const noexcept { return size() == 0; } template inline auto xbuffer_adaptor::operator[](size_type i) -> reference { return data()[i]; } template inline auto xbuffer_adaptor::operator[](size_type i) const -> const_reference { return data()[i]; } template inline auto xbuffer_adaptor::front() -> reference { return data()[0]; } template inline auto xbuffer_adaptor::front() const -> const_reference { return data()[0]; } template inline auto xbuffer_adaptor::back() -> reference { return data()[size() - 1]; } template inline auto xbuffer_adaptor::back() const -> const_reference { return data()[size() - 1]; } template inline auto xbuffer_adaptor::begin() -> iterator { return data(); } template inline auto xbuffer_adaptor::end() -> iterator { return data() + size(); } template inline auto xbuffer_adaptor::begin() const -> const_iterator { return data(); } template inline auto xbuffer_adaptor::end() const -> const_iterator { return data() + size(); } template inline auto xbuffer_adaptor::cbegin() const -> const_iterator { return begin(); } template inline auto xbuffer_adaptor::cend() const -> const_iterator { return end(); } template inline auto xbuffer_adaptor::rbegin() -> reverse_iterator { return reverse_iterator(end()); } template inline auto xbuffer_adaptor::rend() -> reverse_iterator { return reverse_iterator(begin()); } template inline auto xbuffer_adaptor::rbegin() const -> const_reverse_iterator { return const_reverse_iterator(end()); } template inline auto xbuffer_adaptor::rend() const -> const_reverse_iterator { return const_reverse_iterator(begin()); } template inline auto xbuffer_adaptor::crbegin() const -> const_reverse_iterator { return rbegin(); } template inline auto xbuffer_adaptor::crend() const -> const_reverse_iterator { return rend(); } template inline bool operator==(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs) { return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); } template inline bool operator!=(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs) { return !(lhs == rhs); } template inline bool operator<(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs) { return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), std::less()); } template inline bool operator<=(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs) { return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), std::less_equal()); } template inline bool operator>(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs) { return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), std::greater()); } template inline bool operator>=(const xbuffer_adaptor& lhs, const xbuffer_adaptor& rhs) { return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), std::greater_equal()); } template inline void swap(xbuffer_adaptor& lhs, xbuffer_adaptor& rhs) noexcept { lhs.swap(rhs); } } #endif xtensor-0.10.11/include/xtensor/xbuilder.hpp000066400000000000000000000674001314655136400210470ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ /** * @brief standard mathematical functions for xexpressions */ #ifndef XBUILDER_HPP #define XBUILDER_HPP #include #include #include #include #include #include #include "xbroadcast.hpp" #include "xfunction.hpp" #include "xgenerator.hpp" #ifdef X_OLD_CLANG #include #endif namespace xt { /******** * ones * ********/ /** * Returns an \ref xexpression containing ones of the specified shape. * @tparam shape the shape of the returned expression. */ template inline auto ones(S shape) noexcept { return broadcast(T(1), std::forward(shape)); } #ifdef X_OLD_CLANG template inline auto ones(std::initializer_list shape) noexcept { return broadcast(T(1), shape); } #else template inline auto ones(const I (&shape)[L]) noexcept { return broadcast(T(1), shape); } #endif /********* * zeros * *********/ /** * Returns an \ref xexpression containing zeros of the specified shape. * @tparam shape the shape of the returned expression. */ template inline auto zeros(S shape) noexcept { return broadcast(T(0), std::forward(shape)); } #ifdef X_OLD_CLANG template inline auto zeros(std::initializer_list shape) noexcept { return broadcast(T(0), shape); } #else template inline auto zeros(const I (&shape)[L]) noexcept { return broadcast(T(0), shape); } #endif namespace detail { template class arange_impl { public: using value_type = T; arange_impl(T start, T stop, T step) : m_start(start), m_stop(stop), m_step(step) { } template inline T operator()(Args... args) const { return access_impl(args...); } template inline T element(It first, It) const { return m_start + m_step * T(*first); } private: value_type m_start; value_type m_stop; value_type m_step; template inline T access_impl(T1 t, Args...) const { return m_start + m_step * T(t); } inline T access_impl() const { return m_start; } }; template class fn_impl { public: using value_type = typename F::value_type; using size_type = std::size_t; fn_impl(F&& f) : m_ft(f) { } inline value_type operator()() const { size_type idx[1] = {0ul}; return access_impl(std::begin(idx), std::end(idx)); } template inline value_type operator()(Args... args) const { size_type idx[sizeof...(Args)] = {static_cast(args)...}; return access_impl(std::begin(idx), std::end(idx)); } template inline value_type element(It first, It last) const { return access_impl(first, last); } private: F m_ft; template inline value_type access_impl(const It& begin, const It& end) const { return m_ft(begin, end); } }; template class eye_fn { public: using value_type = T; eye_fn(int k) : m_k(k) { } template inline T operator()(const It& /*begin*/, const It& end) const { return *(end - 1) == *(end - 2) + m_k ? T(1) : T(0); } private: int m_k; }; } /** * Generates an array with ones on the diagonal. * @param shape shape of the resulting expression * @param k index of the diagonal. 0 (default) refers to the main diagonal, * a positive value refers to an upper diagonal, and a negative * value to a lower diagonal. * @tparam T value_type of xexpression * @return xgenerator that generates the values on access */ template inline auto eye(const std::vector& shape, int k = 0) { return detail::make_xgenerator(detail::fn_impl>(detail::eye_fn(k)), shape); } /** * Generates a (n x n) array with ones on the diagonal. * @param n length of the diagonal. * @param k index of the diagonal. 0 (default) refers to the main diagonal, * a positive value refers to an upper diagonal, and a negative * value to a lower diagonal. * @tparam T value_type of xexpression * @return xgenerator that generates the values on access */ template inline auto eye(std::size_t n, int k = 0) { return eye({n, n}, k); } /** * Generates numbers evenly spaced within given half-open interval [start, stop). * @param start start of the interval * @param stop stop of the interval * @param step stepsize * @tparam T value_type of xexpression * @return xgenerator that generates the values on access */ template inline auto arange(T start, T stop, T step = 1) noexcept { std::size_t shape = static_cast(std::ceil((stop - start) / step)); return detail::make_xgenerator(detail::arange_impl(start, stop, step), {shape}); } /** * Generate numbers evenly spaced within given half-open interval [0, stop) * with a step size of 1. * @param stop stop of the interval * @tparam T value_type of xexpression * @return xgenerator that generates the values on access */ template inline auto arange(T stop) noexcept { return arange(T(0), stop, T(1)); } /** * Generates @a num_samples evenly spaced numbers over given interval * @param start start of interval * @param stop stop of interval * @param num_samples number of samples (defaults to 50) * @param endpoint if true, include endpoint (defaults to true) * @tparam T value_type of xexpression * @return xgenerator that generates the values on access */ template inline auto linspace(T start, T stop, std::size_t num_samples = 50, bool endpoint = true) noexcept { T step = (stop - start) / T(num_samples - (endpoint ? 1 : 0)); return detail::make_xgenerator(detail::arange_impl(start, stop, step), {num_samples}); } /** * Generates @a num_samples numbers evenly spaced on a log scale over given interval * @param start start of interval (pow(base, start) is the first value). * @param stop stop of interval (pow(base, stop) is the final value, except if endpoint = false) * @param num_samples number of samples (defaults to 50) * @param base the base of the log space. * @param endpoint if true, include endpoint (defaults to true) * @tparam T value_type of xexpression * @return xgenerator that generates the values on access */ template inline auto logspace(T start, T stop, std::size_t num_samples, T base = 10, bool endpoint = true) noexcept { return pow(std::forward(base), linspace(start, stop, num_samples, endpoint)); } namespace detail { template class concatenate_impl { public: using size_type = std::size_t; using value_type = std::common_type_t::value_type...>; inline concatenate_impl(std::tuple&& t, size_type axis) : m_t(t), m_axis(axis) { } template inline value_type operator()(Args... args) const { // TODO: avoid memory allocation return access_impl(xindex({{static_cast(args)...}})); } template inline value_type element(It first, It last) const { // TODO: avoid memory allocation return access_impl(xindex(first, last)); } private: inline value_type access_impl(xindex idx) const { auto match = [this, &idx](auto& arr) { if (idx[this->m_axis] >= arr.shape()[this->m_axis]) { idx[this->m_axis] -= arr.shape()[this->m_axis]; return false; } return true; }; auto get = [&idx](auto& arr) { return arr[idx]; }; size_type i = 0; for (; i < sizeof...(CT); ++i) { if (apply(i, match, m_t)) { break; } } return apply(i, get, m_t); } std::tuple m_t; size_type m_axis; }; template class stack_impl { public: using size_type = std::size_t; using value_type = std::common_type_t::value_type...>; inline stack_impl(std::tuple&& t, size_type axis) : m_t(t), m_axis(axis) { } template inline value_type operator()(Args... args) const { // TODO: avoid memory allocation return access_impl(xindex({{static_cast(args)...}})); } template inline value_type element(It first, It last) const { // TODO: avoid memory allocation return access_impl(xindex(first, last)); } private: inline value_type access_impl(xindex idx) const { auto get_item = [&idx](auto& arr) { return arr[idx]; }; size_type i = idx[m_axis]; idx.erase(idx.begin() + m_axis); return apply(i, get_item, m_t); } const std::tuple m_t; const size_type m_axis; }; template class repeat_impl { public: using xexpression_type = std::decay_t; using size_type = typename xexpression_type::size_type; using value_type = typename xexpression_type::value_type; template repeat_impl(CTA&& source, size_type axis) : m_source(std::forward(source)), m_axis(axis) { } template value_type operator()(Args... args) const { std::array args_arr = {static_cast(args)...}; return m_source(args_arr[m_axis]); } template inline value_type element(It first, It) const { return m_source(*(first + m_axis)); } private: CT m_source; size_type m_axis; }; } /** * @brief Creates tuples from arguments for \ref concatenate and \ref stack. * Very similar to std::make_tuple. */ template inline auto xtuple(Types&&... args) { return std::tuple...>(std::forward(args)...); } /** * @brief Concatenates xexpressions along \em axis. * * @param t \ref xtuple of xexpressions to concatenate * @param axis axis along which elements are concatenated * @returns xgenerator evaluating to concatenated elements * * \code{.cpp} * xt::xarray a = {{1, 2, 3}}; * xt::xarray b = {{2, 3, 4}}; * xt::xarray c = xt::concatenate(xt::xtuple(a, b)); // => {{1, 2, 3}, * {2, 3, 4}} * xt::xarray d = xt::concatenate(xt::xtuple(a, b), 1); // => {{1, 2, 3, 2, 3, 4}} * \endcode */ template inline auto concatenate(std::tuple&& t, std::size_t axis = 0) { using shape_type = promote_shape_t::shape_type...>; shape_type new_shape = forward_sequence(std::get<0>(t).shape()); auto shape_at_axis = [&axis](std::size_t prev, auto& arr) -> std::size_t { return prev + arr.shape()[axis]; }; new_shape[axis] += accumulate(shape_at_axis, std::size_t(0), t) - new_shape[axis]; return detail::make_xgenerator(detail::concatenate_impl(std::forward>(t), axis), new_shape); } namespace detail { template inline std::array add_axis(std::array arr, std::size_t axis, std::size_t value) { std::array temp; std::copy(arr.begin(), arr.begin() + axis, temp.begin()); temp[axis] = value; std::copy(arr.begin() + axis, arr.end(), temp.begin() + axis + 1); return temp; } template inline T add_axis(T arr, std::size_t axis, std::size_t value) { T temp(arr); temp.insert(temp.begin() + axis, value); return temp; } } /** * @brief Stack xexpressions along \em axis. * Stacking always creates a new dimension along which elements are stacked. * * @param t \ref xtuple of xexpressions to concatenate * @param axis axis along which elements are stacked * @returns xgenerator evaluating to stacked elements * * \code{.cpp} * xt::xarray a = {1, 2, 3}; * xt::xarray b = {5, 6, 7}; * xt::xarray s = xt::stack(xt::xtuple(a, b)); // => {{1, 2, 3}, * {5, 6, 7}} * xt::xarray t = xt::stack(xt::xtuple(a, b), 1); // => {{1, 5}, * {2, 6}, * {3, 7}} * \endcode */ template inline auto stack(std::tuple&& t, std::size_t axis = 0) { using shape_type = promote_shape_t::shape_type...>; auto new_shape = detail::add_axis(forward_sequence(std::get<0>(t).shape()), axis, sizeof...(CT)); return detail::make_xgenerator(detail::stack_impl(std::forward>(t), axis), new_shape); } namespace detail { template inline auto meshgrid_impl(std::index_sequence, E&&... e) noexcept { #if defined X_OLD_CLANG || defined _MSC_VER const std::array shape { e.shape()[0]... }; return std::make_tuple( detail::make_xgenerator( detail::repeat_impl>(std::forward(e), I), shape )... ); #else return std::make_tuple( detail::make_xgenerator( detail::repeat_impl>(std::forward(e), I), { e.shape()[0]... } )... ); #endif } } /** * @brief Return coordinate tensors from coordinate vectors. * Make N-D coordinate tensor expressions for vectorized evaluations of N-D scalar/vector * fields over N-D grids, given one-dimensional coordinate arrays x1, x2,..., xn. * * @param e xexpressions to concatenate * @returns tuple of xgenerator expressions. */ template inline auto meshgrid(E&&... e) noexcept { return detail::meshgrid_impl(std::make_index_sequence(), std::forward(e)...); } namespace detail { template class diagonal_fn { public: using xexpression_type = std::decay_t; using value_type = typename xexpression_type::value_type; template diagonal_fn(CTA&& source, int offset, std::size_t axis_1, std::size_t axis_2) : m_source(std::forward(source)), m_offset(offset), m_axis_1(axis_1), m_axis_2(axis_2) { } template inline value_type operator()(It begin, It) const { xindex idx(m_source.shape().size()); for (std::size_t i = 0; i < idx.size(); i++) { if (i != m_axis_1 && i != m_axis_2) { idx[i] = *begin++; } } if (m_offset >= 0) { idx[m_axis_1] = *(begin); idx[m_axis_2] = *(begin) + m_offset; } else { idx[m_axis_1] = *(begin) - m_offset; idx[m_axis_2] = *(begin); } return m_source[idx]; } private: CT m_source; const int m_offset; const std::size_t m_axis_1; const std::size_t m_axis_2; }; template class diag_fn { public: using xexpression_type = std::decay_t; using value_type = typename xexpression_type::value_type; template diag_fn(CTA&& source, int k) : m_source(std::forward(source)), m_k(k) { } template inline value_type operator()(It begin, It) const { if (m_k > 0) { return *begin + m_k == *(begin + 1) ? m_source(*begin) : value_type(0); } else { return *begin + m_k == *(begin + 1) ? m_source(*begin + m_k) : value_type(0); } } private: CT m_source; const int m_k; }; template class flip_impl { public: using xexpression_type = std::decay_t; using value_type = typename xexpression_type::value_type; using size_type = typename xexpression_type::size_type; template flip_impl(CTA&& source, std::size_t axis) : m_source(std::forward(source)), m_axis(axis), m_shape_at_axis(m_source.shape()[m_axis] - 1) { } template inline value_type operator()(Args... args) const { std::array idx({static_cast(args)...}); return access_impl(idx.begin(), idx.end()); } template inline value_type element(It first, It last) const { // TODO: avoid memory allocation xindex idx(first, last); return access_impl(idx.begin(), idx.end()); } private: template inline value_type access_impl(It begin, It end) const { auto it = begin + m_axis; *it = m_shape_at_axis - *it; return m_source.element(begin, end); } CT m_source; const size_type m_axis; const size_type m_shape_at_axis; }; template class trilu_fn { public: using xexpression_type = std::decay_t; using value_type = typename xexpression_type::value_type; using signed_idx_type = long int; template trilu_fn(CTA&& source, int k, Comp comp) : m_source(std::forward(source)), m_k(k), m_comp(comp) { } template inline value_type operator()(It begin, It end) const { // have to cast to signed int otherwise -1 can lead to overflow return m_comp(signed_idx_type(*begin) + m_k, signed_idx_type(*(begin + 1))) ? m_source.element(begin, end) : value_type(0); } private: CT m_source; const signed_idx_type m_k; const Comp m_comp; }; } namespace detail { // meta-function returning the shape type for a diagonal template struct diagonal_shape_type { using type = ST; }; template struct diagonal_shape_type> { using type = std::array; }; } /** * @brief Returns the elements on the diagonal of arr * If arr has more than two dimensions, then the axes specified by * axis_1 and axis_2 are used to determine the 2-D sub-array whose * diagonal is returned. The shape of the resulting array can be * determined by removing axis1 and axis2 and appending an index * to the right equal to the size of the resulting diagonals. * * @param arr the input array * @param offset offset of the diagonal from the main diagonal. Can * be positive or negative. * @param axis_1 Axis to be used as the first axis of the 2-D sub-arrays * from which the diagonals should be taken. * @param axis_2 Axis to be used as the second axis of the 2-D sub-arrays * from which the diagonals should be taken. * @returns xexpression with values of the diagonal * * \code{.cpp} * xt::xarray a = {{1, 2, 3}, * {4, 5, 6} * {7, 8, 9}}; * auto b = xt::diagonal(a); // => {1, 5, 9} * \endcode */ template inline auto diagonal(E&& arr, int offset = 0, std::size_t axis_1 = 0, std::size_t axis_2 = 1) { using CT = xclosure_t; using shape_type = typename detail::diagonal_shape_type::shape_type>::type; auto shape = arr.shape(); auto dimension = arr.dimension(); // The following shape calculation code is an almost verbatim adaptation of numpy: // https://github.com/numpy/numpy/blob/2aabeafb97bea4e1bfa29d946fbf31e1104e7ae0/numpy/core/src/multiarray/item_selection.c#L1799 auto ret_shape = make_sequence(dimension - 1, 0); std::size_t dim_1 = shape[axis_1]; std::size_t dim_2 = shape[axis_2]; offset >= 0 ? dim_2 -= offset : dim_1 += offset; auto diag_size = dim_2 < dim_1 ? dim_2 : dim_1; std::size_t i = 0; for (std::size_t idim = 0; idim < dimension; ++idim) { if (idim != axis_1 && idim != axis_2) { ret_shape[i++] = shape[idim]; } } ret_shape.back() = diag_size; return detail::make_xgenerator(detail::fn_impl>(detail::diagonal_fn(std::forward(arr), offset, axis_1, axis_2)), ret_shape); } /** * @brief xexpression with values of arr on the diagonal, zeroes otherwise * * @param arr the 1D input array of length n * @param k the offset of the considered diagonal * @returns xexpression function with shape n x n and arr on the diagonal * * \code{.cpp} * xt::xarray a = {1, 5, 9}; * auto b = xt::diag(a); // => {{1, 0, 0}, * // {0, 5, 0}, * // {0, 0, 9}} * \endcode */ template inline auto diag(E&& arr, int k = 0) { using CT = xclosure_t; std::size_t s = arr.shape()[0] + std::abs(k); return detail::make_xgenerator(detail::fn_impl>(detail::diag_fn(std::forward(arr), k)), {s, s}); } /** * @brief Reverse the order of elements in an xexpression along the given axis. * Note: A NumPy/Matlab style `flipud(arr)` is equivalent to `xt::flip(arr, 0)`, * `fliplr(arr)` to `xt::flip(arr, 1)`. * * @param arr the input xexpression * @param axis the axis along which elements should be reversed * * @return xexpression evaluating to reversed array */ template inline auto flip(E&& arr, std::size_t axis) { using CT = xclosure_t; auto shape = arr.shape(); return detail::make_xgenerator(detail::flip_impl(std::forward(arr), axis), shape); } /** * @brief Extract lower triangular matrix from xexpression. The parameter k selects the * offset of the diagonal. * * @param arr the input array * @param k the diagonal above which to zero elements. 0 (default) selects the main diagonal, * k < 0 is below the main diagonal, k > 0 above. * @returns xexpression containing lower triangle from arr, 0 otherwise */ template inline auto tril(E&& arr, int k = 0) { using CT = xclosure_t; auto shape = arr.shape(); return detail::make_xgenerator(detail::fn_impl>>( detail::trilu_fn>(std::forward(arr), k, std::greater_equal())), shape); } /** * @brief Extract upper triangular matrix from xexpression. The parameter k selects the * offset of the diagonal. * * @param arr the input array * @param k the diagonal below which to zero elements. 0 (default) selects the main diagonal, * k < 0 is below the main diagonal, k > 0 above. * @returns xexpression containing lower triangle from arr, 0 otherwise */ template inline auto triu(E&& arr, int k = 0) { using CT = xclosure_t; auto shape = arr.shape(); return detail::make_xgenerator(detail::fn_impl>>( detail::trilu_fn>(std::forward(arr), k, std::less_equal())), shape); } } #endif xtensor-0.10.11/include/xtensor/xcomplex.hpp000066400000000000000000000200631314655136400210620ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XCOMPLEX_HPP #define XCOMPLEX_HPP #include #include #include "xtensor/xbuilder.hpp" #include "xtensor/xexpression.hpp" #include "xtensor/xoffsetview.hpp" namespace xt { /****************************** * real and imag declarations * ******************************/ template decltype(auto) real(E&& e) noexcept; template decltype(auto) imag(E&& e) noexcept; /******************************** * real and imag implementation * ********************************/ namespace detail { template struct complex_helper { template static inline auto real(E&& e) noexcept { using real_type = typename std::decay_t::value_type::value_type; return xoffsetview, real_type, 0>(std::forward(e)); } template static inline auto imag(E&& e) noexcept { using real_type = typename std::decay_t::value_type::value_type; return xoffsetview, real_type, sizeof(real_type)>(std::forward(e)); } }; template <> struct complex_helper { template static inline decltype(auto) real(E&& e) noexcept { return e; } template static inline auto imag(E&& e) noexcept { return zeros::value_type>(e.shape()); } }; template struct complex_expression_helper { template static inline auto real(E&& e) noexcept { return detail::complex_helper::value_type>::value>::real(e); } template static inline auto imag(E&& e) noexcept { return detail::complex_helper::value_type>::value>::imag(e); } }; template <> struct complex_expression_helper { template static inline decltype(auto) real(E&& e) noexcept { return forward_real(std::forward(e)); } template static inline decltype(auto) imag(E&& e) noexcept { return forward_imag(std::forward(e)); } }; } /** * @brief Returns an \ref xexpression representing the real part of the given expression. * * @tparam e the \ref xexpression * * The returned expression either hold a const reference to \p e or a copy * depending on whether \p e is an lvalue or an rvalue. */ template inline decltype(auto) real(E&& e) noexcept { return detail::complex_expression_helper>::value>::real(std::forward(e)); } /** * @brief Returns an \ref xexpression representing the imaginary part of the given expression. * * @tparam e the \ref xexpression * * The returned expression either hold a const reference to \p e or a copy * depending on whether \p e is an lvalue or an rvalue. */ template inline decltype(auto) imag(E&& e) noexcept { return detail::complex_expression_helper>::value>::imag(std::forward(e)); } #define UNARY_COMPLEX_FUNCTOR(NAME) \ template \ struct NAME##_fun \ { \ using argument_type = T; \ using result_type = decltype(std::NAME(std::declval())); \ constexpr result_type operator()(const T& t) const \ { \ using std::NAME; \ return NAME(t); \ } \ } namespace math { UNARY_COMPLEX_FUNCTOR(norm); UNARY_COMPLEX_FUNCTOR(arg); namespace detail { // libc++ (OSX) conj is unfortunately broken and returns // std::complex instead of T. template constexpr T conj(const T& c) { return c; } template constexpr std::complex conj(const std::complex& c) { return std::complex(c.real(), -c.imag()); } } template struct conj_fun { using argument_type = T; using result_type = decltype(detail::conj(std::declval())); constexpr result_type operator()(const T& t) const { return detail::conj(t); } }; } #undef UNARY_COMPLEX_FUNCTOR /** * @brief Returns an \ref xfunction evaluating to the complex conjugate of the given expression. * * @param e the \ref xexpression */ template inline auto conj(E&& e) noexcept { using value_type = typename std::decay_t::value_type; using functor = math::conj_fun; using result_type = typename functor::result_type; using type = xfunction>; return type(functor(), std::forward(e)); } /** * @brief Calculates the phase angle (in radians) elementwise for the complex numbers in e. * @param e the \ref xexpression */ template inline auto arg(E&& e) noexcept { using value_type = typename std::decay_t::value_type; using functor = math::arg_fun; using result_type = typename functor::result_type; using type = xfunction>; return type(functor(), std::forward(e)); } /** * @brief Calculates the phase angle elementwise for the complex numbers in e. * Note that this function might be slightly less perfomant than \ref arg. * @param e the \ref xexpression * @param deg calculate angle in degrees instead of radians */ template inline auto angle(E&& e, bool deg = false) noexcept { using value_type = complex_value_type_t::value_type>; value_type multiplier = 1.0; if (deg) { multiplier = value_type(180) / numeric_constants::PI; } return arg(std::forward(e)) * std::move(multiplier); } /** * Calculates the squared magnitude elementwise for the complex numbers in e. * Equivalent to pow(real(e), 2) + pow(imag(e), 2). * @param e the \ref xexpression */ template inline auto norm(E&& e) noexcept { using value_type = typename std::decay_t::value_type; using functor = math::norm_fun; using result_type = typename functor::result_type; using type = xfunction>; return type(functor(), std::forward(e)); } } #endif xtensor-0.10.11/include/xtensor/xcontainer.hpp000066400000000000000000000671431314655136400214070ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XCONTAINER_HPP #define XCONTAINER_HPP #include #include #include #include #include "xiterable.hpp" #include "xiterator.hpp" #include "xmath.hpp" #include "xoperation.hpp" #include "xstrides.hpp" #include "xtensor_forward.hpp" namespace xt { template struct xcontainer_iterable_types { using inner_shape_type = typename xcontainer_inner_types::inner_shape_type; using container_type = typename xcontainer_inner_types::container_type; using iterator = typename container_type::iterator; using const_iterator = typename container_type::const_iterator; using reverse_iterator = typename container_type::reverse_iterator; using const_reverse_iterator = typename container_type::const_reverse_iterator; using stepper = xstepper; using const_stepper = xstepper; }; /** * @class xcontainer * @brief Base class for dense multidimensional containers. * * The xcontainer class defines the interface for dense multidimensional * container classes. It does not embed any data container, this responsibility * is delegated to the inheriting classes. * * @tparam D The derived type, i.e. the inheriting class for which xcontainer * provides the interface. */ template class xcontainer : public xiterable { public: using derived_type = D; using inner_types = xcontainer_inner_types; using container_type = typename inner_types::container_type; using value_type = typename container_type::value_type; using reference = typename container_type::reference; using const_reference = typename container_type::const_reference; using pointer = typename container_type::pointer; using const_pointer = typename container_type::const_pointer; using size_type = typename container_type::size_type; using difference_type = typename container_type::difference_type; using shape_type = typename inner_types::shape_type; using strides_type = typename inner_types::strides_type; using backstrides_type = typename inner_types::backstrides_type; using inner_shape_type = typename inner_types::inner_shape_type; using inner_strides_type = typename inner_types::inner_strides_type; using inner_backstrides_type = typename inner_types::inner_backstrides_type; using iterable_base = xiterable; using iterator = typename iterable_base::iterator; using const_iterator = typename iterable_base::const_iterator; using stepper = typename iterable_base::stepper; using const_stepper = typename iterable_base::const_stepper; using reverse_iterator = typename iterable_base::reverse_iterator; using const_reverse_iterator = typename iterable_base::const_reverse_iterator; size_type size() const noexcept; constexpr size_type dimension() const noexcept; const inner_shape_type& shape() const noexcept; const inner_strides_type& strides() const noexcept; const inner_backstrides_type& backstrides() const noexcept; template reference operator()(Args... args); template const_reference operator()(Args... args) const; reference operator[](const xindex& index); reference operator[](size_type i); const_reference operator[](const xindex& index) const; const_reference operator[](size_type i) const; template reference element(It first, It last); template const_reference element(It first, It last) const; container_type& data() noexcept; const container_type& data() const noexcept; value_type* raw_data() noexcept; const value_type* raw_data() const noexcept; const size_type raw_data_offset() const noexcept; template bool broadcast_shape(S& shape) const; template bool is_trivial_broadcast(const S& strides) const noexcept; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; reverse_iterator rbegin() noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rbegin() const noexcept; const_reverse_iterator rend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; template stepper stepper_begin(const S& shape) noexcept; template stepper stepper_end(const S& shape, layout_type l) noexcept; template const_stepper stepper_begin(const S& shape) const noexcept; template const_stepper stepper_end(const S& shape, layout_type l) const noexcept; using container_iterator = typename container_type::iterator; using const_container_iterator = typename container_type::const_iterator; reference data_element(size_type i); const_reference data_element(size_type i) const; protected: xcontainer() = default; ~xcontainer() = default; xcontainer(const xcontainer&) = default; xcontainer& operator=(const xcontainer&) = default; xcontainer(xcontainer&&) = default; xcontainer& operator=(xcontainer&&) = default; container_iterator data_xbegin() noexcept; const_container_iterator data_xbegin() const noexcept; container_iterator data_xend(layout_type l) noexcept; const_container_iterator data_xend(layout_type l) const noexcept; private: template friend class xstepper; template It data_xend_impl(It end, layout_type l) const noexcept; inner_shape_type& mutable_shape(); inner_strides_type& mutable_strides(); inner_backstrides_type& mutable_backstrides(); derived_type& derived_cast(); const derived_type& derived_cast() const; }; /** * @class xstrided_container * @brief Partial implementation of xcontainer that embeds the strides and the shape * * The xstrided_container class is a partial implementation of the xcontainer interface * that embed the strides and the shape of the multidimensional container. It does * not embed the data container, this responsibility is delegated to the inheriting * classes. * * @tparam D The derived type, i.e. the inheriting class for which xstrided_container * provides the partial imlpementation of xcontainer. * @tparam L The layout_type of the xstrided_container. */ template class xstrided_container : public xcontainer { public: using base_type = xcontainer; using container_type = typename base_type::container_type; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using const_reference = typename base_type::const_reference; using pointer = typename base_type::pointer; using const_pointer = typename base_type::const_pointer; using size_type = typename base_type::size_type; using shape_type = typename base_type::shape_type; using strides_type = typename base_type::strides_type; using inner_shape_type = typename base_type::inner_shape_type; using inner_strides_type = typename base_type::inner_strides_type; using inner_backstrides_type = typename base_type::inner_backstrides_type; static constexpr layout_type static_layout = L; static constexpr bool contiguous_layout = static_layout != layout_type::dynamic; template void reshape(const S& shape, bool force = false); template void reshape(const S& shape, layout_type l); template void reshape(const S& shape, const strides_type& strides); layout_type layout() const noexcept; protected: xstrided_container() noexcept; ~xstrided_container() = default; xstrided_container(const xstrided_container&) = default; xstrided_container& operator=(const xstrided_container&) = default; xstrided_container(xstrided_container&&) = default; xstrided_container& operator=(xstrided_container&&) = default; explicit xstrided_container(inner_shape_type&&, inner_strides_type&&) noexcept; inner_shape_type& shape_impl() noexcept; const inner_shape_type& shape_impl() const noexcept; inner_strides_type& strides_impl() noexcept; const inner_strides_type& strides_impl() const noexcept; inner_backstrides_type& backstrides_impl() noexcept; const inner_backstrides_type& backstrides_impl() const noexcept; private: inner_shape_type m_shape; inner_strides_type m_strides; inner_backstrides_type m_backstrides; layout_type m_layout = L; }; /****************************** * xcontainer implementation * ******************************/ template template inline It xcontainer::data_xend_impl(It end, layout_type l) const noexcept { return strided_data_end(*this, end, l); } template inline auto xcontainer::mutable_shape() -> inner_shape_type& { return derived_cast().shape_impl(); } template inline auto xcontainer::mutable_strides() -> inner_strides_type& { return derived_cast().strides_impl(); } template inline auto xcontainer::mutable_backstrides() -> inner_backstrides_type& { return derived_cast().backstrides_impl(); } template inline auto xcontainer::derived_cast() -> derived_type& { return *static_cast(this); } template inline auto xcontainer::derived_cast() const -> const derived_type& { return *static_cast(this); } /** * @name Size and shape */ //@{ /** * Returns the number of element in the container. */ template inline auto xcontainer::size() const noexcept -> size_type { return data().size(); } /** * Returns the number of dimensions of the container. */ template inline constexpr auto xcontainer::dimension() const noexcept -> size_type { return shape().size(); } /** * Returns the shape of the container. */ template inline auto xcontainer::shape() const noexcept -> const inner_shape_type& { return derived_cast().shape_impl(); } /** * Returns the strides of the container. */ template inline auto xcontainer::strides() const noexcept -> const inner_strides_type& { return derived_cast().strides_impl(); } /** * Returns the backstrides of the container. */ template inline auto xcontainer::backstrides() const noexcept -> const inner_backstrides_type& { return derived_cast().backstrides_impl(); } //@} /** * @name Data */ //@{ /** * Returns a reference to the element at the specified position in the container. * @param args a list of indices specifying the position in the container. Indices * must be unsigned integers, the number of indices should be equal or greater than * the number of dimensions of the container. */ template template inline auto xcontainer::operator()(Args... args) -> reference { XTENSOR_ASSERT(check_index(shape(), args...)); size_type index = data_offset(strides(), static_cast(args)...); return data()[index]; } /** * Returns a constant reference to the element at the specified position in the container. * @param args a list of indices specifying the position in the container. Indices * must be unsigned integers, the number of indices should be equal or greater than * the number of dimensions of the container. */ template template inline auto xcontainer::operator()(Args... args) const -> const_reference { XTENSOR_ASSERT(check_index(shape(), args...)); size_type index = data_offset(strides(), static_cast(args)...); return data()[index]; } /** * Returns a reference to the element at the specified position in the container. * @param index a sequence of indices specifying the position in the container. Indices * must be unsigned integers, the number of indices in the list should be equal or greater * than the number of dimensions of the container. */ template inline auto xcontainer::operator[](const xindex& index) -> reference { return element(index.cbegin(), index.cend()); } template inline auto xcontainer::operator[](size_type i) -> reference { return operator()(i); } /** * Returns a constant reference to the element at the specified position in the container. * @param index a sequence of indices specifying the position in the container. Indices * must be unsigned integers, the number of indices in the list should be equal or greater * than the number of dimensions of the container. */ template inline auto xcontainer::operator[](const xindex& index) const -> const_reference { return element(index.cbegin(), index.cend()); } template inline auto xcontainer::operator[](size_type i) const -> const_reference { return operator()(i); } /** * Returns a reference to the element at the specified position in the container. * @param first iterator starting the sequence of indices * @param last iterator ending the sequence of indices * The number of indices in the sequence should be equal to or greater * than the number of dimensions of the container. */ template template inline auto xcontainer::element(It first, It last) -> reference { XTENSOR_ASSERT(check_element_index(shape(), first, last)); return data()[element_offset(strides(), first, last)]; } /** * Returns a reference to the element at the specified position in the container. * @param first iterator starting the sequence of indices * @param last iterator ending the sequence of indices * The number of indices in the sequence should be equal to or greater * than the number of dimensions of the container. */ template template inline auto xcontainer::element(It first, It last) const -> const_reference { XTENSOR_ASSERT(check_element_index(shape(), first, last)); return data()[element_offset(strides(), first, last)]; } /** * Returns a reference to the buffer containing the elements of the container. */ template inline auto xcontainer::data() noexcept -> container_type& { return derived_cast().data_impl(); } /** * Returns a constant reference to the buffer containing the elements of the * container. */ template inline auto xcontainer::data() const noexcept -> const container_type& { return derived_cast().data_impl(); } /** * Returns the offset to the first element in the container. */ template inline auto xcontainer::raw_data() noexcept -> value_type* { return data().data(); } template inline auto xcontainer::raw_data() const noexcept -> const value_type* { return data().data(); } /** * Returns the offset to the first element in the container. */ template inline auto xcontainer::raw_data_offset() const noexcept -> const size_type { return size_type(0); } //@} /** * @name Broadcasting */ //@{ /** * Broadcast the shape of the container to the specified parameter. * @param shape the result shape * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xcontainer::broadcast_shape(S& shape) const { return xt::broadcast_shape(this->shape(), shape); } /** * Compares the specified strides with those of the container to see whether * the broadcasting is trivial. * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xcontainer::is_trivial_broadcast(const S& str) const noexcept { return str.size() == strides().size() && std::equal(str.cbegin(), str.cend(), strides().begin()); } //@} /**************** * iterator api * ****************/ /** * @name Iterators */ //@{ /** * Returns an iterator to the first element of the buffer containing * the elements of the container. */ template inline auto xcontainer::begin() noexcept -> iterator { return data().begin(); } /** * Returns an iterator to the element following the last element of * the buffer containing the elements of the container. */ template inline auto xcontainer::end() noexcept -> iterator { return data().end(); } /** * Returns a constant iterator to the first element of the buffer * containing the elements of the container. */ template inline auto xcontainer::begin() const noexcept -> const_iterator { return cbegin(); } /** * Returns a constant iterator to the element following the last * element of the buffer containing the elements of the container. */ template inline auto xcontainer::end() const noexcept -> const_iterator { return cend(); } /** * Returns a constant iterator to the first element of the buffer * containing the elements of the container. */ template inline auto xcontainer::cbegin() const noexcept -> const_iterator { return data().cbegin(); } /** * Returns a constant iterator to the element following the last * element of the buffer containing the elements of the container. */ template inline auto xcontainer::cend() const noexcept -> const_iterator { return data().cend(); } //@} /** * @name Reverse iterators */ //@{ /** * Returns an iterator to the first element of the reversed buffer containing * the elements of the container. */ template inline auto xcontainer::rbegin() noexcept -> reverse_iterator { return data().rbegin(); } /** * Returns an iterator to the element following the last element of * the reversed buffer containing the elements of the container. */ template inline auto xcontainer::rend() noexcept -> reverse_iterator { return data().rend(); } /** * Returns a constant iterator to the first element of the reversed * buffer containing the elements of the container. */ template inline auto xcontainer::rbegin() const noexcept -> const_reverse_iterator { return data().rbegin(); } /** * Returns a constant iterator to the element following the last * element of the reversed buffer containing the elements of the container. */ template inline auto xcontainer::rend() const noexcept -> const_reverse_iterator { return data().rend(); } /** * Returns a constant iterator to the first element of the reversed * buffer containing the elements of the container. */ template inline auto xcontainer::crbegin() const noexcept -> const_reverse_iterator { return data().crbegin(); } /** * Returns a constant iterator to the element following the last * element of the reversed buffer containing the elements of the container. */ template inline auto xcontainer::crend() const noexcept -> const_reverse_iterator { return data().crend(); } //@} /*************** * stepper api * ***************/ template template inline auto xcontainer::stepper_begin(const S& shape) noexcept -> stepper { size_type offset = shape.size() - dimension(); return stepper(static_cast(this), data_xbegin(), offset); } template template inline auto xcontainer::stepper_end(const S& shape, layout_type l) noexcept -> stepper { size_type offset = shape.size() - dimension(); return stepper(static_cast(this), data_xend(l), offset); } template template inline auto xcontainer::stepper_begin(const S& shape) const noexcept -> const_stepper { size_type offset = shape.size() - dimension(); return const_stepper(static_cast(this), data_xbegin(), offset); } template template inline auto xcontainer::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper { size_type offset = shape.size() - dimension(); return const_stepper(static_cast(this), data_xend(l), offset); } template inline auto xcontainer::data_xbegin() noexcept -> container_iterator { return data().begin(); } template inline auto xcontainer::data_xbegin() const noexcept -> const_container_iterator { return data().begin(); } template inline auto xcontainer::data_xend(layout_type l) noexcept -> container_iterator { return data_xend_impl(data().end(), l); } template inline auto xcontainer::data_xend(layout_type l) const noexcept -> const_container_iterator { return data_xend_impl(data().end(), l); } template inline auto xcontainer::data_element(size_type i) -> reference { return data()[i]; } template inline auto xcontainer::data_element(size_type i) const -> const_reference { return data()[i]; } /************************************* * xstrided_container implementation * *************************************/ template inline xstrided_container::xstrided_container() noexcept : base_type() { m_shape = make_sequence(base_type::dimension(), 1); } template inline xstrided_container::xstrided_container(inner_shape_type&& shape, inner_strides_type&& strides) noexcept : base_type(), m_shape(std::move(shape)), m_strides(std::move(strides)) { m_backstrides = make_sequence(m_shape.size(), 0); adapt_strides(m_shape, m_strides, m_backstrides); } template inline auto xstrided_container::shape_impl() noexcept -> inner_shape_type& { return m_shape; } template inline auto xstrided_container::shape_impl() const noexcept -> const inner_shape_type& { return m_shape; } template inline auto xstrided_container::strides_impl() noexcept -> inner_strides_type& { return m_strides; } template inline auto xstrided_container::strides_impl() const noexcept -> const inner_strides_type& { return m_strides; } template inline auto xstrided_container::backstrides_impl() noexcept -> inner_backstrides_type& { return m_backstrides; } template inline auto xstrided_container::backstrides_impl() const noexcept -> const inner_backstrides_type& { return m_backstrides; } /** * Return the layout_type of the container * @return layout_type of the container */ template layout_type xstrided_container::layout() const noexcept { return m_layout; } /** * Reshapes the container. * @param shape the new shape * @param force force reshaping, even if the shape stays the same (default: false) */ template template inline void xstrided_container::reshape(const S& shape, bool force) { if (m_shape.size() != shape.size() || !std::equal(std::begin(shape), std::end(shape), std::begin(m_shape)) || force) { if (m_layout == layout_type::dynamic || m_layout == layout_type::any) { m_layout = layout_type::row_major; // fall back to row major } m_shape = forward_sequence(shape); resize_container(m_strides, m_shape.size()); resize_container(m_backstrides, m_shape.size()); size_type data_size = compute_strides(m_shape, m_layout, m_strides, m_backstrides); this->data().resize(data_size); } } /** * Reshapes the container. * @param shape the new shape * @param l the new layout_type */ template template inline void xstrided_container::reshape(const S& shape, layout_type l) { if (L != layout_type::dynamic && l != L) { throw std::runtime_error("Cannot change layout_type if template parameter not layout_type::dynamic."); } m_layout = l; reshape(shape, true); } /** * Reshapes the container. * @param shape the new shape * @param strides the new strides */ template template inline void xstrided_container::reshape(const S& shape, const strides_type& strides) { if (L != layout_type::dynamic) { throw std::runtime_error("Cannot reshape with custom strides when layout() is != layout_type::dynamic."); } m_shape = forward_sequence(shape); m_strides = strides; resize_container(m_backstrides, m_strides.size()); adapt_strides(m_shape, m_strides, m_backstrides); m_layout = layout_type::dynamic; this->data().resize(compute_size(m_shape)); } } #endif xtensor-0.10.11/include/xtensor/xcsv.hpp000066400000000000000000000131251314655136400202070ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XCSV_HPP #define XCSV_HPP #include #include #include #include #include #include #include "xtensor.hpp" namespace xt { /************************************** * load_csv and dump_csv declarations * **************************************/ template > xtensor_container, 2> load_csv(std::istream& stream); template void dump_csv(std::ostream& stream, const xexpression& e); /***************************************** * load_csv and dump_csv implementations * *****************************************/ namespace detail { template inline T lexical_cast(const std::string& cell) { T res; std::istringstream iss(cell); iss >> res; return res; } template <> inline float lexical_cast(const std::string& cell) { return std::stof(cell); } template <> inline double lexical_cast(const std::string& cell) { return std::stod(cell); } template <> inline long double lexical_cast(const std::string& cell) { return std::stold(cell); } template <> inline int lexical_cast(const std::string& cell) { return std::stoi(cell); } template <> inline long lexical_cast(const std::string& cell) { return std::stol(cell); } template <> inline long long lexical_cast(const std::string& cell) { return std::stoll(cell); } template <> inline unsigned int lexical_cast(const std::string& cell) { return static_cast(std::stoul(cell)); } template <> inline unsigned long lexical_cast(const std::string& cell) { return std::stoul(cell); } template <> inline unsigned long long lexical_cast(const std::string& cell) { return std::stoull(cell); } template ST load_csv_row(std::istream& row_stream, OI output, std::string cell) { ST length = 0; while (std::getline(row_stream, cell, ',')) { *output++ = lexical_cast(cell); ++length; } return length; } } /** * @brief Load tensor from CSV. * * Returns an \ref xexpression for the parsed CSV * @param stream the input stream containing the CSV encoded values */ template xtensor_container, 2> load_csv(std::istream& stream) { using container_type = typename std::vector; using tensor_type = xtensor_container; using size_type = typename tensor_type::size_type; using inner_shape_type = typename tensor_type::inner_shape_type; using inner_strides_type = typename tensor_type::inner_strides_type; using output_iterator = std::back_insert_iterator; container_type data; size_type nbrow = 0, nbcol = 0; { output_iterator output(data); std::string row, cell; while (std::getline(stream, row)) { std::stringstream row_stream(row); nbcol = detail::load_csv_row(row_stream, output, cell); ++nbrow; } } inner_shape_type shape = {nbrow, nbcol}; inner_strides_type strides; // no need for initializer list for stack-allocated strides_type size_type data_size = compute_strides(shape, layout_type::row_major, strides); // Sanity check for data size. if (data.size() != data_size) { throw std::runtime_error("Inconsistent row lengths in CSV"); } return tensor_type(std::move(data), std::move(shape), std::move(strides)); } /** * @brief Dump tensor to CSV. * * @param stream the output stream to write the CSV encoded values * @param e the tensor expression to serialize */ template void dump_csv(std::ostream& stream, const xexpression& e) { using size_type = typename E::size_type; const E& ex = e.derived_cast(); if (ex.dimension() != 2) { throw std::runtime_error("Only 2-D expressions can be serialized to CSV"); } size_type nbrows = ex.shape()[0], nbcols = ex.shape()[1]; auto st = ex.stepper_begin(ex.shape()); for (size_type r = 0; r != nbrows; ++r) { for (size_type c = 0; c != nbcols; ++c) { stream << *st; if (c != nbcols - 1) { st.step(1); stream << ','; } else { st.reset(1); st.step(0); stream << std::endl; } } } } } #endif xtensor-0.10.11/include/xtensor/xeval.hpp000066400000000000000000000040251314655136400203420ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEVAL_HPP #define XEVAL_HPP #include "xarray.hpp" #include "xtensor.hpp" namespace xt { namespace detail { template using is_container = std::is_base_of>, T>; } /** * Force evaluation of xexpression. * @return xarray or xtensor depending on shape type * * \code{.cpp} * xarray a = {1,2,3,4}; * auto&& b = xt::eval(a); // b is a reference to a, no copy! * auto&& c = xt::eval(a + b); // c is xarray, not an xexpression * \endcode */ template inline auto eval(T&& t) -> std::enable_if_t>::value, T&&> { return std::forward(t); } /// @cond DOXYGEN_INCLUDE_SFINAE template > inline auto eval(T&& t) -> std::enable_if_t::value && detail::is_array::value, xtensor::value>> { return xtensor::value>(std::forward(t)); } template > inline auto eval(T&& t) -> std::enable_if_t::value && !detail::is_array::value, xt::xarray> { return xarray(std::forward(t)); } /// @endcond } #endifxtensor-0.10.11/include/xtensor/xexception.hpp000066400000000000000000000132461314655136400214160ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEXCEPTION_HPP #define XEXCEPTION_HPP #include #include #include #include namespace xt { /******************* * broadcast_error * *******************/ class broadcast_error : public std::exception { public: template broadcast_error(const S1& lhs, const S2& rhs); virtual const char* what() const noexcept; private: std::string m_message; }; /********************************** * broadcast_error implementation * **********************************/ template inline broadcast_error::broadcast_error(const S1& lhs, const S2& rhs) { std::ostringstream buf("Incompatible dimension of arrays:", std::ios_base::ate); buf << "\n LHS shape = ("; using size_type1 = typename S1::value_type; std::ostream_iterator iter1(buf, ", "); std::copy(lhs.cbegin(), lhs.cend(), iter1); buf << ")\n RHS shape = ("; using size_type2 = typename S2::value_type; std::ostream_iterator iter2(buf, ", "); std::copy(rhs.cbegin(), rhs.cend(), iter2); buf << ")"; m_message = buf.str(); } inline const char* broadcast_error::what() const noexcept { return m_message.c_str(); } /******************* * transpose_error * *******************/ class transpose_error : public std::exception { public: transpose_error(const std::string& msg); virtual const char* what() const noexcept; private: std::string m_message; }; /********************************** * transpose_error implementation * **********************************/ inline transpose_error::transpose_error(const std::string& msg) : m_message(msg) {} inline const char* transpose_error::what() const noexcept { return m_message.c_str(); } /*************** * check_index * ***************/ template void check_index(const S& shape, Args... args); template void check_element_index(const S& shape, It first, It last); namespace detail { template inline void check_index_impl(const S&) { } template inline void check_index_impl(const S& shape, std::size_t arg, Args... args) { if (sizeof...(Args) + 1 > shape.size()) { check_index_impl(shape, args...); } else { if (arg >= shape[dim] && shape[dim] != 1) { throw std::out_of_range("index " + std::to_string(arg) + " is out of bounds for axis " + std::to_string(dim) + " with size " + std::to_string(shape[dim])); } check_index_impl(shape, args...); } } } template inline void check_index(const S& shape, Args... args) { detail::check_index_impl(shape, args...); } template inline void check_element_index(const S& shape, It first, It last) { auto dst = static_cast(last - first); It efirst = last - std::min(shape.size(), dst); std::size_t axis = 0; while (efirst != last) { if (*efirst >= shape[axis] && shape[axis] != 1) { throw std::out_of_range("index " + std::to_string(*efirst) + " is out of bounds for axis " + std::to_string(axis) + " with size " + std::to_string(shape[axis])); } ++efirst, ++axis; } } #ifdef XTENSOR_ENABLE_ASSERT #define XTENSOR_ASSERT(expr) XTENSOR_ASSERT_IMPL(expr, __FILE__, __LINE__) #define XTENSOR_ASSERT_IMPL(expr, file, line) \ try \ { \ expr; \ } \ catch (std::exception & e) \ { \ throw std::runtime_error(std::string(file) + ':' + std::to_string(line) \ + ": check failed\n\t" + std::string(e.what())); \ } #else #define XTENSOR_ASSERT(expr) #endif } #endif xtensor-0.10.11/include/xtensor/xexpression.hpp000066400000000000000000000130421314655136400216110ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XEXPRESSION_HPP #define XEXPRESSION_HPP #include #include #include #include "xutils.hpp" namespace xt { using xindex = std::vector; /*************************** * xexpression declaration * ***************************/ /** * @class xexpression * @brief Base class for xexpressions * * The xexpression class is the base class for all classes representing an expression * that can be evaluated to a multidimensional container with tensor semantic. * Functions that can apply to any xexpression regardless of its specific type should take a * xexpression argument. * * \tparam E The derived type. * */ template class xexpression { public: using derived_type = D; derived_type& derived_cast() & noexcept; const derived_type& derived_cast() const& noexcept; derived_type derived_cast() && noexcept; protected: xexpression() = default; ~xexpression() = default; xexpression(const xexpression&) = default; xexpression& operator=(const xexpression&) = default; xexpression(xexpression&&) = default; xexpression& operator=(xexpression&&) = default; }; /****************************** * xexpression implementation * ******************************/ /** * @name Downcast functions */ //@{ /** * Returns a reference to the actual derived type of the xexpression. */ template inline auto xexpression::derived_cast() & noexcept -> derived_type& { return *static_cast(this); } /** * Returns a constant reference to the actual derived type of the xexpression. */ template inline auto xexpression::derived_cast() const & noexcept -> const derived_type& { return *static_cast(this); } /** * Returns a constant reference to the actual derived type of the xexpression. */ template inline auto xexpression::derived_cast() && noexcept -> derived_type { return *static_cast(this); } //@} namespace detail { template struct is_xexpression_impl : std::is_base_of, E> { }; template struct is_xexpression_impl> : std::true_type { }; } template using is_xexpression = detail::is_xexpression_impl; template using disable_xexpression = typename std::enable_if::value, R>::type; template using has_xexpression = or_...>; /************ * xclosure * ************/ template class xscalar; template struct xclosure { using type = closure_t; }; template struct xclosure>> { using type = xscalar>; }; template using xclosure_t = typename xclosure::type; template struct const_xclosure { using type = const_closure_t; }; template struct const_xclosure>> { using type = xscalar>; }; template using const_xclosure_t = typename const_xclosure::type; /*************** * xvalue_type * ***************/ namespace detail { template struct xvalue_type_impl { using type = E; }; template struct xvalue_type_impl::value>> { using type = typename E::value_type; }; } template using xvalue_type = detail::xvalue_type_impl; template using xvalue_type_t = typename xvalue_type::type; /*************** * get_element * ***************/ namespace detail { template inline typename E::reference get_element(E& e) { return e(); } template inline typename E::reference get_element(E& e, S i, Args... args) { if (sizeof...(Args) >= e.dimension()) return get_element(e, args...); return e(i, args...); } template inline typename E::const_reference get_element(const E& e) { return e(); } template inline typename E::const_reference get_element(const E& e, S i, Args... args) { if (sizeof...(Args) >= e.dimension()) return get_element(e, args...); return e(i, args...); } } } #endif xtensor-0.10.11/include/xtensor/xfunction.hpp000066400000000000000000000652661314655136400212560ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XFUNCTION_HPP #define XFUNCTION_HPP #include #include #include #include #include #include #include #include "xexpression.hpp" #include "xiterable.hpp" #include "xlayout.hpp" #include "xscalar.hpp" #include "xutils.hpp" namespace xt { namespace detail { /******************** * common_size_type * ********************/ template struct common_size_type { using type = std::common_type_t; }; template <> struct common_size_type<> { using type = std::size_t; }; template using common_size_type_t = typename common_size_type::type; /************************** * common_difference type * **************************/ template struct common_difference_type { using type = std::common_type_t; }; template <> struct common_difference_type<> { using type = std::size_t; }; template using common_difference_type_t = typename common_difference_type::type; /********************* * common_value_type * *********************/ template struct common_value_type { using type = std::common_type_t...>; }; template using common_value_type_t = typename common_value_type::type; } template class xfunction_iterator; template class xfunction_stepper; template class xfunction; template struct xiterable_inner_types> { using inner_shape_type = promote_shape_t::shape_type...>; using const_iterator = xfunction_iterator; using iterator = const_iterator; using const_stepper = xfunction_stepper; using stepper = const_stepper; using const_reverse_iterator = std::reverse_iterator; using reverse_iterator = std::reverse_iterator; }; /************* * xfunction * *************/ /** * @class xfunction * @brief Multidimensional function operating on xexpression. * * Th xfunction class implements a multidimensional function * operating on xexpression. * * @tparam F the function type * @tparam R the return type of the function * @tparam CT the closure types for arguments of the function */ template class xfunction : public xexpression>, public xconst_iterable> { public: using self_type = xfunction; using functor_type = typename std::remove_reference::type; using value_type = R; using reference = value_type; using const_reference = value_type; using pointer = value_type*; using const_pointer = const value_type*; using size_type = detail::common_size_type_t...>; using difference_type = detail::common_difference_type_t...>; using iterable_base = xconst_iterable>; using inner_shape_type = typename iterable_base::inner_shape_type; using shape_type = inner_shape_type; using iterator = typename iterable_base::iterator; using const_iterator = typename iterable_base::const_iterator; using stepper = typename iterable_base::stepper; using const_stepper = typename iterable_base::const_stepper; using reverse_iterator = typename iterable_base::reverse_iterator; using const_reverse_iterator = typename iterable_base::const_reverse_iterator; static constexpr layout_type static_layout = compute_layout(std::decay_t::static_layout...); static constexpr bool contiguous_layout = and_c::contiguous_layout...>::value; template xfunction(Func&& f, CT... e) noexcept; size_type size() const noexcept; size_type dimension() const noexcept; const shape_type& shape() const; layout_type layout() const noexcept; template const_reference operator()(Args... args) const; const_reference operator[](const xindex& index) const; const_reference operator[](size_type i) const; template const_reference element(It first, It last) const; template bool broadcast_shape(S& shape) const; template bool is_trivial_broadcast(const S& strides) const noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator rbegin() const noexcept; const_reverse_iterator rend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; template const_stepper stepper_begin(const S& shape) const noexcept; template const_stepper stepper_end(const S& shape, layout_type l) const noexcept; const_reference data_element(size_type i) const; private: template layout_type layout_impl(std::index_sequence) const noexcept; template const_reference access_impl(std::index_sequence, Args... args) const; template const_reference element_access_impl(std::index_sequence, It first, It last) const; template const_reference data_element_impl(std::index_sequence, size_type i) const; template const_stepper build_stepper(Func&& f, std::index_sequence) const noexcept; template const_iterator build_iterator(Func&& f, std::index_sequence) const noexcept; size_type compute_dimension() const noexcept; std::tuple m_e; functor_type m_f; mutable shape_type m_shape; mutable bool m_shape_computed; friend class xfunction_iterator; friend class xfunction_stepper; }; /********************** * xfunction_iterator * **********************/ template class xscalar; namespace detail { template struct get_iterator_impl { using type = typename C::iterator; }; template struct get_iterator_impl { using type = typename C::const_iterator; }; template struct get_iterator_impl> { using type = typename xscalar::dummy_iterator; }; template struct get_iterator_impl> { using type = typename xscalar::const_dummy_iterator; }; } template using get_iterator = typename detail::get_iterator_impl::type; template class xfunction_iterator { public: using self_type = xfunction_iterator; using functor_type = typename std::remove_reference::type; using xfunction_type = xfunction; using value_type = typename xfunction_type::value_type; using reference = typename xfunction_type::value_type; using pointer = typename xfunction_type::const_pointer; using difference_type = typename xfunction_type::difference_type; using iterator_category = std::forward_iterator_tag; template xfunction_iterator(const xfunction_type* func, It&&... it) noexcept; self_type& operator++(); self_type operator++(int); self_type& operator--(); self_type operator--(int); reference operator*() const; bool equal(const self_type& rhs) const; private: template reference deref_impl(std::index_sequence) const; const xfunction_type* p_f; std::tuple>...> m_it; }; template bool operator==(const xfunction_iterator& it1, const xfunction_iterator& it2); template bool operator!=(const xfunction_iterator& it1, const xfunction_iterator& it2); /********************* * xfunction_stepper * *********************/ template class xfunction_stepper { public: using self_type = xfunction_stepper; using functor_type = typename std::remove_reference::type; using xfunction_type = xfunction; using value_type = typename xfunction_type::value_type; using reference = typename xfunction_type::value_type; using pointer = typename xfunction_type::const_pointer; using size_type = typename xfunction_type::size_type; using difference_type = typename xfunction_type::difference_type; using shape_type = typename xfunction_type::shape_type; template xfunction_stepper(const xfunction_type* func, It&&... it) noexcept; void step(size_type dim, size_type n = 1); void step_back(size_type dim, size_type n = 1); void reset(size_type dim); void reset_back(size_type dim); void to_begin(); void to_end(layout_type l); reference operator*() const; bool equal(const self_type& rhs) const; private: template reference deref_impl(std::index_sequence) const; const xfunction_type* p_f; std::tuple::const_stepper...> m_it; }; template bool operator==(const xfunction_stepper& it1, const xfunction_stepper& it2); template bool operator!=(const xfunction_stepper& it1, const xfunction_stepper& it2); /**************************** * xfunction implementation * ****************************/ /** * @name Constructor */ //@{ /** * Constructs an xfunction applying the specified function to the given * arguments. * @param f the function to apply * @param e the \ref xexpression arguments */ template template inline xfunction::xfunction(Func&& f, CT... e) noexcept : m_e(e...), m_f(std::forward(f)), m_shape(make_sequence(0, size_type(1))), m_shape_computed(false) { } //@} /** * @name Size and shape */ //@{ /** * Returns the size of the expression. */ template inline auto xfunction::size() const noexcept -> size_type { return compute_size(shape()); } /** * Returns the number of dimensions of the function. */ template inline auto xfunction::dimension() const noexcept -> size_type { size_type dimension = m_shape_computed ? m_shape.size() : compute_dimension(); return dimension; } /** * Returns the shape of the xfunction. */ template inline auto xfunction::shape() const -> const shape_type& { if (!m_shape_computed) { m_shape = make_sequence(compute_dimension(), size_type(1)); broadcast_shape(m_shape); m_shape_computed = true; } return m_shape; } /** * Returns the layout_type of the xfunction. */ template inline layout_type xfunction::layout() const noexcept { return layout_impl(std::make_index_sequence()); } //@} /** * @name Data */ /** * Returns a constant reference to the element at the specified position in the function. * @param args a list of indices specifying the position in the function. Indices * must be unsigned integers, the number of indices should be equal or greater than * the number of dimensions of the function. */ template template inline auto xfunction::operator()(Args... args) const -> const_reference { return access_impl(std::make_index_sequence(), args...); } template inline auto xfunction::operator[](const xindex& index) const -> const_reference { return element(index.cbegin(), index.cend()); } template inline auto xfunction::operator[](size_type i) const -> const_reference { return operator()(i); } /** * Returns a constant reference to the element at the specified position in the function. * @param first iterator starting the sequence of indices * @param last iterator ending the sequence of indices * The number of indices in the sequence should be equal to or greater * than the number of dimensions of the container. */ template template inline auto xfunction::element(It first, It last) const -> const_reference { return element_access_impl(std::make_index_sequence(), first, last); } //@} /** * @name Broadcasting */ //@{ /** * Broadcast the shape of the function to the specified parameter. * @param shape the result shape * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xfunction::broadcast_shape(S& shape) const { // e.broadcast_shape must be evaluated even if b is false auto func = [&shape](bool b, auto&& e) { return e.broadcast_shape(shape) && b; }; return accumulate(func, true, m_e); } /** * Compares the specified strides with those of the container to see whether * the broadcasting is trivial. * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xfunction::is_trivial_broadcast(const S& strides) const noexcept { auto func = [&strides](bool b, auto&& e) { return b && e.is_trivial_broadcast(strides); }; return accumulate(func, true, m_e); } //@} /** * @name Iterators */ /** * Returns an iterator to the first element of the buffer * containing the elements of the function. */ template inline auto xfunction::begin() const noexcept -> const_iterator { auto f = [](const auto& e) noexcept { return detail::trivial_begin(e); }; return build_iterator(f, std::make_index_sequence()); } /** * Returns a constant iterator to the element following the last * element of the buffer containing the elements of the function. */ template inline auto xfunction::end() const noexcept -> const_iterator { auto f = [](const auto& e) noexcept { return detail::trivial_end(e); }; return build_iterator(f, std::make_index_sequence()); } /** * Returns a constant iterator to the first element of the buffer * containing the elements of the function. */ template inline auto xfunction::cbegin() const noexcept -> const_iterator { return begin(); } /** * Returns a constant iterator to the element following the last * element of the buffer containing the elements of the function. */ template inline auto xfunction::cend() const noexcept -> const_iterator { return end(); } //@} /** * @name Reverse iterators */ //@{ /** * Returns an iterator to the first element of the reversed buffer * containing the elements of the function. */ template inline auto xfunction::rbegin() const noexcept -> const_reverse_iterator { return crbegin(); } /** * Returns a constant iterator to the element following the last * element of the reversed buffer containing the elements of the function. */ template inline auto xfunction::rend() const noexcept -> const_reverse_iterator { return crend(); } /** * Returns an iterator to the first element of the reversed buffer * containing the elements of the function. */ template inline auto xfunction::crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(cend()); } /** * Returns a constant iterator to the element following the last * element of the reversed buffer containing the elements of the function. */ template inline auto xfunction::crend() const noexcept -> const_reverse_iterator { return const_reverse_iterator(cbegin()); } //@} template template inline auto xfunction::stepper_begin(const S& shape) const noexcept -> const_stepper { auto f = [&shape](const auto& e) noexcept { return e.stepper_begin(shape); }; return build_stepper(f, std::make_index_sequence()); } template template inline auto xfunction::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper { auto f = [&shape, l](const auto& e) noexcept { return e.stepper_end(shape, l); }; return build_stepper(f, std::make_index_sequence()); } template inline auto xfunction::data_element(size_type i) const -> const_reference { return data_element_impl(std::make_index_sequence(), i); } template template inline layout_type xfunction::layout_impl(std::index_sequence) const noexcept { return compute_layout(std::get(m_e).layout()...); } template template inline auto xfunction::access_impl(std::index_sequence, Args... args) const -> const_reference { return m_f(detail::get_element(std::get(m_e), args...)...); } template template inline auto xfunction::element_access_impl(std::index_sequence, It first, It last) const -> const_reference { return m_f((std::get(m_e).element(first, last))...); } template template inline auto xfunction::data_element_impl(std::index_sequence, size_type i) const ->const_reference { return m_f((std::get(m_e).data_element(i))...); } template template inline auto xfunction::build_stepper(Func&& f, std::index_sequence) const noexcept -> const_stepper { return const_stepper(this, f(std::get(m_e))...); } template template inline auto xfunction::build_iterator(Func&& f, std::index_sequence) const noexcept -> const_iterator { return const_iterator(this, f(std::get(m_e))...); } template inline auto xfunction::compute_dimension() const noexcept -> size_type { auto func = [](size_type d, auto&& e) noexcept { return std::max(d, e.dimension()); }; return accumulate(func, size_type(0), m_e); } /************************************* * xfunction_iterator implementation * *************************************/ template template inline xfunction_iterator::xfunction_iterator(const xfunction_type* func, It&&... it) noexcept : p_f(func), m_it(std::forward(it)...) { } template inline auto xfunction_iterator::operator++() -> self_type& { auto f = [](auto& it) { ++it; }; for_each(f, m_it); return *this; } template inline auto xfunction_iterator::operator++(int) -> self_type { self_type tmp(*this); ++(*this); return tmp; } template inline auto xfunction_iterator::operator--() -> self_type& { auto f = [](auto& it) { return --it; }; for_each(f, m_it); return *this; } template inline auto xfunction_iterator::operator--(int) -> self_type { self_type tmp(*this); --(*this); return tmp; } template inline auto xfunction_iterator::operator*() const -> reference { return deref_impl(std::make_index_sequence()); } template inline bool xfunction_iterator::equal(const self_type& rhs) const { return p_f == rhs.p_f && m_it == rhs.m_it; } template template inline auto xfunction_iterator::deref_impl(std::index_sequence) const -> reference { return (p_f->m_f)(*std::get(m_it)...); } template inline bool operator==(const xfunction_iterator& it1, const xfunction_iterator& it2) { return it1.equal(it2); } template inline bool operator!=(const xfunction_iterator& it1, const xfunction_iterator& it2) { return !(it1.equal(it2)); } /************************************ * xfunction_stepper implementation * ************************************/ template template inline xfunction_stepper::xfunction_stepper(const xfunction_type* func, It&&... it) noexcept : p_f(func), m_it(std::forward(it)...) { } template inline void xfunction_stepper::step(size_type dim, size_type n) { auto f = [dim, n](auto& it) { it.step(dim, n); }; for_each(f, m_it); } template inline void xfunction_stepper::step_back(size_type dim, size_type n) { auto f = [dim, n](auto& it) { it.step_back(dim, n); }; for_each(f, m_it); } template inline void xfunction_stepper::reset(size_type dim) { auto f = [dim](auto& it) { it.reset(dim); }; for_each(f, m_it); } template inline void xfunction_stepper::reset_back(size_type dim) { auto f = [dim](auto& it) { it.reset_back(dim); }; for_each(f, m_it); } template inline void xfunction_stepper::to_begin() { auto f = [](auto& it) { it.to_begin(); }; for_each(f, m_it); } template inline void xfunction_stepper::to_end(layout_type l) { auto f = [l](auto& it) { it.to_end(l); }; for_each(f, m_it); } template inline auto xfunction_stepper::operator*() const -> reference { return deref_impl(std::make_index_sequence()); } template inline bool xfunction_stepper::equal(const self_type& rhs) const { return p_f == rhs.p_f && m_it == rhs.m_it; } template template inline auto xfunction_stepper::deref_impl(std::index_sequence) const -> reference { return (p_f->m_f)(*std::get(m_it)...); } template inline bool operator==(const xfunction_stepper& it1, const xfunction_stepper& it2) { return it1.equal(it2); } template inline bool operator!=(const xfunction_stepper& it1, const xfunction_stepper& it2) { return !(it1.equal(it2)); } } #endif xtensor-0.10.11/include/xtensor/xfunctorview.hpp000066400000000000000000001224411314655136400217710ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XFUNCTORVIEW_HPP #define XFUNCTORVIEW_HPP #include #include #include #include #include #include "xtensor/xexpression.hpp" #include "xtensor/xiterator.hpp" #include "xtensor/xsemantic.hpp" #include "xtensor/xutils.hpp" #include "xtensor/xarray.hpp" #include "xtensor/xtensor.hpp" namespace xt { /**************************** * xfunctorview declaration * ****************************/ template class xfunctor_iterator; template class xfunctor_stepper; template class xfunctorview; /******************************* * xfunctorview_temporary_type * *******************************/ namespace detail { template struct functorview_temporary_type_impl { using type = xarray; }; template struct functorview_temporary_type_impl, L> { using type = xtensor; }; } template struct xfunctorview_temporary_type { using type = typename detail::functorview_temporary_type_impl::type; }; template struct xcontainer_inner_types> { using xexpression_type = std::decay_t; using temporary_type = typename xfunctorview_temporary_type::type; }; #define DL DEFAULT_LAYOUT /** * @class xfunctorview * @brief View of an xexpression . * * The xfunctorview class is an expression addressing its elements by applying a functor to the * corresponding element of an underlying expression. Unlike e.g. xgenerator, an xfunctorview is * an lvalue. It is used e.g. to access real and imaginary parts of complex expressions. * expressions. * xfunctorview is not meant to be used directly, but through helper functions such * as \ref real or \ref imag. * * @tparam F the functor type to be applied to the elements of specified expression. * @tparam CT the closure type of the \ref xexpression type underlying this view * * @sa real, imag */ template class xfunctorview : public xview_semantic> { public: using self_type = xfunctorview; using xexpression_type = std::decay_t; using semantic_base = xview_semantic; using functor_type = typename std::decay_t; using value_type = typename functor_type::value_type; using reference = typename functor_type::reference; using const_reference = typename functor_type::const_reference; using pointer = typename functor_type::pointer; using const_pointer = typename functor_type::const_pointer; using size_type = typename xexpression_type::size_type; using difference_type = typename xexpression_type::difference_type; using shape_type = typename xexpression_type::shape_type; using stepper = xfunctor_stepper; using const_stepper = xfunctor_stepper; using iterator = xfunctor_iterator; using const_iterator = xfunctor_iterator; template using broadcast_iterator = xfunctor_iterator>; template using const_broadcast_iterator = xfunctor_iterator>; template using shaped_xiterator = xfunctor_iterator>; template using const_shaped_xiterator = xfunctor_iterator>; using reverse_iterator = xfunctor_iterator; using const_reverse_iterator = xfunctor_iterator; template using reverse_broadcast_iterator = xfunctor_iterator>; template using const_reverse_broadcast_iterator = xfunctor_iterator>; template using reverse_shaped_xiterator = xfunctor_iterator>; template using const_reverse_shaped_xiterator = xfunctor_iterator>; static constexpr layout_type static_layout = xexpression_type::static_layout; static constexpr bool contiguous_layout = false; xfunctorview(CT) noexcept; template xfunctorview(Func&&, E&&) noexcept; template self_type& operator=(const xexpression& e); template disable_xexpression& operator=(const E& e); size_type size() const noexcept; size_type dimension() const noexcept; const shape_type& shape() const noexcept; layout_type layout() const noexcept; template reference operator()(Args... args); reference operator[](const xindex& index); reference operator[](size_type i); template reference element(IT first, IT last); template const_reference operator()(Args... args) const; const_reference operator[](const xindex& index) const; const_reference operator[](size_type i) const; template const_reference element(IT first, IT last) const; template bool broadcast_shape(S& shape) const; template bool is_trivial_broadcast(const S& strides) const; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; template broadcast_iterator xbegin() noexcept; template broadcast_iterator xend() noexcept; template const_broadcast_iterator xbegin() const noexcept; template const_broadcast_iterator xend() const noexcept; template const_broadcast_iterator cxbegin() const noexcept; template const_broadcast_iterator cxend() const noexcept; template shaped_xiterator xbegin(const S& shape) noexcept; template shaped_xiterator xend(const S& shape) noexcept; template const_shaped_xiterator xbegin(const S& shape) const noexcept; template const_shaped_xiterator xend(const S& shape) const noexcept; template const_shaped_xiterator cxbegin(const S& shape) const noexcept; template const_shaped_xiterator cxend(const S& shape) const noexcept; reverse_iterator rbegin() noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rbegin() const noexcept; const_reverse_iterator rend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; template reverse_broadcast_iterator xrbegin() noexcept; template reverse_broadcast_iterator xrend() noexcept; template const_reverse_broadcast_iterator xrbegin() const noexcept; template const_reverse_broadcast_iterator xrend() const noexcept; template const_reverse_broadcast_iterator cxrbegin() const noexcept; template const_reverse_broadcast_iterator cxrend() const noexcept; template reverse_shaped_xiterator xrbegin(const S& shape) noexcept; template reverse_shaped_xiterator xrend(const S& shape) noexcept; template const_reverse_shaped_xiterator xrbegin(const S& shape) const noexcept; template const_reverse_shaped_xiterator xrend(const S& shape) const noexcept; template const_reverse_shaped_xiterator cxrbegin(const S& shape) const noexcept; template const_reverse_shaped_xiterator cxrend(const S& shape) const noexcept; template stepper stepper_begin(const S& shape) noexcept; template stepper stepper_end(const S& shape, layout_type l) noexcept; template const_stepper stepper_begin(const S& shape) const noexcept; template const_stepper stepper_end(const S& shape, layout_type l) const noexcept; private: CT m_e; functor_type m_functor; using temporary_type = typename xcontainer_inner_types::temporary_type; void assign_temporary_impl(temporary_type&& tmp); friend class xview_semantic>; }; #undef DL /********************************* * xfunctor_iterator declaration * *********************************/ template class xfunctor_iterator { public: using functor_type = std::decay_t; using value_type = typename functor_type::value_type; using subiterator_traits = std::iterator_traits; using reference = apply_cv_t; using pointer = std::remove_reference_t*; using difference_type = typename subiterator_traits::difference_type; using iterator_category = typename subiterator_traits::iterator_category; using self_type = xfunctor_iterator; xfunctor_iterator(const IT&, const functor_type*); self_type& operator++(); self_type operator++(int); reference operator*() const; pointer operator->() const; bool equal(const xfunctor_iterator& rhs) const; private: IT m_it; const functor_type* p_functor; template friend xfunctor_iterator operator+(xfunctor_iterator, xfunctor_iterator); template friend typename xfunctor_iterator::difference_type operator-(xfunctor_iterator, xfunctor_iterator); }; template bool operator==(const xfunctor_iterator& lhs, const xfunctor_iterator& rhs); template bool operator!=(const xfunctor_iterator& lhs, const xfunctor_iterator& rhs); template xfunctor_iterator operator+(xfunctor_iterator it1, xfunctor_iterator it2) { return xfunctor_iterator(it1.m_it + it2.m_it); } template typename xfunctor_iterator::difference_type operator-(xfunctor_iterator it1, xfunctor_iterator it2) { return it1.m_it - it2.m_it; } /******************************** * xfunctor_stepper declaration * ********************************/ template class xfunctor_stepper { public: using functor_type = std::decay_t; using value_type = typename functor_type::value_type; using reference = apply_cv_t; using pointer = std::remove_reference_t*; using size_type = typename ST::size_type; using difference_type = typename ST::difference_type; xfunctor_stepper() = default; xfunctor_stepper(const ST&, const functor_type*); reference operator*() const; void step(size_type dim, size_type n = 1); void step_back(size_type dim, size_type n = 1); void reset(size_type dim); void reset_back(size_type dim); void to_begin(); void to_end(layout_type); bool equal(const xfunctor_stepper& rhs) const; private: ST m_stepper; const functor_type* p_functor; }; template bool operator==(const xfunctor_stepper& lhs, const xfunctor_stepper& rhs); template bool operator!=(const xfunctor_stepper& lhs, const xfunctor_stepper& rhs); /******************************* * xfunctorview implementation * *******************************/ /** * @name Constructors */ //@{ /** * Constructs an xfunctorview expression wrappering the specified \ref xexpression. * * @param e the underlying expression */ template inline xfunctorview::xfunctorview(CT e) noexcept : m_e(e), m_functor(functor_type()) { } /** * Constructs an xfunctorview expression wrappering the specified \ref xexpression. * * @param func the functor to be applied to the elements of the underlying expression. * @param e the underlying expression */ template template inline xfunctorview::xfunctorview(Func&& func, E&& e) noexcept : m_e(std::forward(e)), m_functor(std::forward(func)) { } //@} /** * @name Extended copy semantic */ //@{ /** * The extended assignment operator. */ template template inline auto xfunctorview::operator=(const xexpression& e) -> self_type& { bool cond = (e.derived_cast().shape().size() == dimension()) && std::equal(shape().begin(), shape().end(), e.derived_cast().shape().begin()); if (!cond) { semantic_base::operator=(broadcast(e.derived_cast(), shape())); } else { semantic_base::operator=(e); } return *this; } //@} template template inline auto xfunctorview::operator=(const E& e) -> disable_xexpression& { std::fill(begin(), end(), e); return *this; } template inline void xfunctorview::assign_temporary_impl(temporary_type&& tmp) { std::copy(tmp.cbegin(), tmp.cend(), xbegin()); } /** * @name Size and shape */ /** * Returns the size of the expression. */ template inline auto xfunctorview::size() const noexcept -> size_type { return m_e.size(); } /** * Returns the number of dimensions of the expression. */ template inline auto xfunctorview::dimension() const noexcept -> size_type { return m_e.dimension(); } /** * Returns the shape of the expression. */ template inline auto xfunctorview::shape() const noexcept -> const shape_type& { return m_e.shape(); } /** * Returns the layout_type of the expression. */ template inline layout_type xfunctorview::layout() const noexcept { return m_e.layout(); } //@} /** * @name Data */ /** * Returns a reference to the element at the specified position in the expression. * @param args a list of indices specifying the position in the function. Indices * must be unsigned integers, the number of indices should be equal or greater than * the number of dimensions of the expression. */ template template inline auto xfunctorview::operator()(Args... args) -> reference { return m_functor(m_e(args...)); } /** * Returns a reference to the element at the specified position in the expression. * @param index a sequence of indices specifying the position in the function. Indices * must be unsigned integers, the number of indices in the sequence should be equal or greater * than the number of dimensions of the container. */ template inline auto xfunctorview::operator[](const xindex& index) -> reference { return m_functor(m_e[index]); } template inline auto xfunctorview::operator[](size_type i) -> reference { return operator()(i); } /** * Returns a reference to the element at the specified position in the expression. * @param first iterator starting the sequence of indices * @param last iterator ending the sequence of indices * The number of indices in the sequence should be equal to or greater * than the number of dimensions of the function. */ template template inline auto xfunctorview::element(IT first, IT last) -> reference { return m_functor(m_e.element(first, last)); } /** * Returns a constant reference to the element at the specified position in the expression. * @param args a list of indices specifying the position in the function. Indices * must be unsigned integers, the number of indices should be equal or greater than * the number of dimensions of the expression. */ template template inline auto xfunctorview::operator()(Args... args) const -> const_reference { return m_functor(m_e(args...)); } /** * Returns a constant reference to the element at the specified position in the expression. * @param index a sequence of indices specifying the position in the function. Indices * must be unsigned integers, the number of indices in the sequence should be equal or greater * than the number of dimensions of the container. */ template inline auto xfunctorview::operator[](const xindex& index) const -> const_reference { return m_functor(m_e[index]); } template inline auto xfunctorview::operator[](size_type i) const -> const_reference { return operator()(i); } /** * Returns a constant reference to the element at the specified position in the expression. * @param first iterator starting the sequence of indices * @param last iterator ending the sequence of indices * The number of indices in the sequence should be equal to or greater * than the number of dimensions of the function. */ template template inline auto xfunctorview::element(IT first, IT last) const -> const_reference { return m_functor(m_e.element(first, last)); } //@} /** * @name Broadcasting */ //@{ /** * Broadcast the shape of the function to the specified parameter. * @param shape the result shape * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xfunctorview::broadcast_shape(S& shape) const { return m_e.broadcast_shape(shape); } /** * Compares the specified strides with those of the container to see whether * the broadcasting is trivial. * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xfunctorview::is_trivial_broadcast(const S& strides) const { return m_e.is_trivial_broadcast(strides); } //@} /** * @name Iterators */ //@{ /** * Returns an iterator to the first element of the expression. */ template inline auto xfunctorview::begin() noexcept -> iterator { return iterator(m_e.begin(), &m_functor); } /** * Returns an iterator to the element following the last element * of the expression. */ template inline auto xfunctorview::end() noexcept -> iterator { return iterator(m_e.end(), &m_functor); } /** * Returns a constant iterator to the first element of the expression. */ template inline auto xfunctorview::begin() const noexcept -> const_iterator { return const_iterator(m_e.cbegin(), &m_functor); } /** * Returns a constant iterator to the element following the last element * of the expression. */ template inline auto xfunctorview::end() const noexcept -> const_iterator { return const_iterator(m_e.cend(), &m_functor); } /** * Returns a constant iterator to the first element of the expression. */ template inline auto xfunctorview::cbegin() const noexcept -> const_iterator { return const_iterator(m_e.cbegin(), &m_functor); } /** * Returns a constant iterator to the element following the last element * of the expression. */ template inline auto xfunctorview::cend() const noexcept -> const_iterator { return const_iterator(m_e.cend(), &m_functor); } //@} /** * @name Broadcast iterators */ //@{ /** * Returns an iterator to the first element of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xbegin() noexcept -> broadcast_iterator { return broadcast_iterator(m_e.template xbegin(), &m_functor); } /** * Returns an iterator to the element following the last element * of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xend() noexcept -> broadcast_iterator { return broadcast_iterator(m_e.template xend(), &m_functor); } /** * Returns a constant iterator to the first element of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xbegin() const noexcept -> const_broadcast_iterator { return cxbegin(); } /** * Returns a constant iterator to the element following the last element * of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xend() const noexcept -> const_broadcast_iterator { return cxend(); } /** * Returns a constant iterator to the first element of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::cxbegin() const noexcept -> const_broadcast_iterator { return const_broadcast_iterator(m_e.template cxbegin(), &m_functor); } /** * Returns a constant iterator to the element following the last element * of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::cxend() const noexcept -> const_broadcast_iterator { return const_broadcast_iterator(m_e.template cxend(), &m_functor); } /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xbegin(const S& shape) noexcept -> shaped_xiterator { return shaped_xiterator(m_e.template xbegin(shape), &m_functor); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xend(const S& shape) noexcept -> shaped_xiterator { return shaped_xiterator(m_e.template xend(shape), &m_functor); } /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xbegin(const S& shape) const noexcept -> const_shaped_xiterator { return cxbegin(shape); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xend(const S& shape) const noexcept -> const_shaped_xiterator { return cxend(shape); } /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::cxbegin(const S& shape) const noexcept -> const_shaped_xiterator { return const_shaped_xiterator(m_e.template cxbegin(shape), &m_functor); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::cxend(const S& shape) const noexcept -> const_shaped_xiterator { return const_shaped_xiterator(m_e.template cxend(shape), &m_functor); } //@} /** * @name Reverse iterators */ //@{ /** * Returns an iterator to the first element of the reversed expression. */ template inline auto xfunctorview::rbegin() noexcept -> reverse_iterator { return reverse_iterator(m_e.rbegin(), &m_functor); } /** * Returns an iterator to the element following the last element * of the reversed expression. */ template inline auto xfunctorview::rend() noexcept -> reverse_iterator { return reverse_iterator(m_e.rend(), &m_functor); } /** * Returns a constant iterator to the first element of the reversed expression. */ template inline auto xfunctorview::rbegin() const noexcept -> const_reverse_iterator { return crbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. */ template inline auto xfunctorview::rend() const noexcept -> const_reverse_iterator { return crend(); } /** * Returns a constant iterator to the first element of the reversed expression. */ template inline auto xfunctorview::crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(m_e.crbegin(), &m_functor); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. */ template inline auto xfunctorview::crend() const noexcept -> const_reverse_iterator { return const_reverse_iterator(m_e.crend(), &m_functor); } //@} /** * @name Reverse broadcast iterators */ //@{ /** * Returns an iterator to the first element of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xrbegin() noexcept -> reverse_broadcast_iterator { return reverse_broadcast_iterator(m_e.template xrbegin(), &m_functor); } /** * Returns an iterator to the element following the last element * of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xrend() noexcept -> reverse_broadcast_iterator { return reverse_broadcast_iterator(m_e.template xrend(), &m_functor); } /** * Returns a constant iterator to the first element of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xrbegin() const noexcept -> const_reverse_broadcast_iterator { return cxrbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xrend() const noexcept -> const_reverse_broadcast_iterator { return cxrend(); } /** * Returns a constant iterator to the first element of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::cxrbegin() const noexcept -> const_reverse_broadcast_iterator { return const_reverse_broadcast_iterator(m_e.template cxrbegin(), &m_functor); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::cxrend() const noexcept -> const_reverse_broadcast_iterator { return const_reverse_broadcast_iterator(m_e.template cxrend(), &m_functor); } /** * Returns an iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xrbegin(const S& shape) noexcept -> reverse_shaped_xiterator { return reverse_shaped_xiterator(m_e.template xrbegin(shape), &m_functor); } /** * Returns an iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xrend(const S& shape) noexcept -> reverse_shaped_xiterator { return reverse_shaped_xiterator(m_e.template xrend(shape), &m_functor); } /** * Returns a constant iterator to the first element of the reversed expression. * The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xrbegin(const S& shape) const noexcept -> const_reverse_shaped_xiterator { return cxrbegin(shape); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::xrend(const S& shape) const noexcept -> const_reverse_shaped_xiterator { return cxrend(); } /** * Returns a constant iterator to the first element of the reversed expression. * The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::cxrbegin(const S& shape) const noexcept -> const_reverse_shaped_xiterator { return const_reverse_shaped_xiterator(m_e.template cxrbegin(), &m_functor); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xfunctorview::cxrend(const S& shape) const noexcept -> const_reverse_shaped_xiterator { return const_reverse_shaped_xiterator(m_e.template cxrend(shape), &m_functor); } //@} /*************** * stepper api * ***************/ template template inline auto xfunctorview::stepper_begin(const S& shape) noexcept -> stepper { return stepper(m_e.stepper_begin(shape), &m_functor); } template template inline auto xfunctorview::stepper_end(const S& shape, layout_type l) noexcept -> stepper { return stepper(m_e.stepper_end(shape, l), &m_functor); } template template inline auto xfunctorview::stepper_begin(const S& shape) const noexcept -> const_stepper { const xexpression_type& const_m_e = m_e; return const_stepper(const_m_e.stepper_begin(shape), &m_functor); } template template inline auto xfunctorview::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper { const xexpression_type& const_m_e = m_e; return const_stepper(const_m_e.stepper_end(shape, l), &m_functor); } /************************************ * xfunctor_iterator implementation * ************************************/ template xfunctor_iterator::xfunctor_iterator(const IT& it, const functor_type* pf) : m_it(it), p_functor(pf) { } template auto xfunctor_iterator::operator++() -> self_type& { ++m_it; return *this; } template auto xfunctor_iterator::operator++(int) -> self_type { self_type tmp(*this); ++m_it; return tmp; } template auto xfunctor_iterator::operator*() const -> reference { return (*p_functor)(*m_it); } template auto xfunctor_iterator::operator->() const -> pointer { return &((*p_functor)(*m_it)); } template auto xfunctor_iterator::equal(const xfunctor_iterator& rhs) const -> bool { return m_it == rhs.m_it; } template bool operator==(const xfunctor_iterator& lhs, const xfunctor_iterator& rhs) { return lhs.equal(rhs); } template bool operator!=(const xfunctor_iterator& lhs, const xfunctor_iterator& rhs) { return !lhs.equal(rhs); } /*********************************** * xfunctor_stepper implementation * ***********************************/ template xfunctor_stepper::xfunctor_stepper(const ST& stepper, const functor_type* pf) : m_stepper(stepper), p_functor(pf) { } template auto xfunctor_stepper::operator*() const -> reference { return (*p_functor)(*m_stepper); } template void xfunctor_stepper::step(size_type dim, size_type n) { m_stepper.step(dim, n); } template void xfunctor_stepper::step_back(size_type dim, size_type n) { m_stepper.step_back(dim, n); } template void xfunctor_stepper::reset(size_type dim) { m_stepper.reset(dim); } template void xfunctor_stepper::reset_back(size_type dim) { m_stepper.reset_back(dim); } template void xfunctor_stepper::to_begin() { m_stepper.to_begin(); } template void xfunctor_stepper::to_end(layout_type l) { m_stepper.to_end(l); } template auto xfunctor_stepper::equal(const xfunctor_stepper& rhs) const -> bool { return m_stepper == rhs.m_stepper; } template bool operator==(const xfunctor_stepper& lhs, const xfunctor_stepper& rhs) { return lhs.equal(rhs); } template bool operator!=(const xfunctor_stepper& lhs, const xfunctor_stepper& rhs) { return !lhs.equal(rhs); } } #endif xtensor-0.10.11/include/xtensor/xgenerator.hpp000066400000000000000000000226311314655136400214040ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XGENERATOR_HPP #define XGENERATOR_HPP #include #include #include #include #include #include #include "xexpression.hpp" #include "xiterable.hpp" #include "xstrides.hpp" #include "xutils.hpp" namespace xt { /************** * xgenerator * **************/ template class xgenerator; template struct xiterable_inner_types> { using inner_shape_type = S; using const_stepper = xindexed_stepper>; using stepper = const_stepper; using const_iterator = xiterator; using iterator = const_iterator; using const_reverse_iterator = std::reverse_iterator; using reverse_iterator = std::reverse_iterator; }; /** * @class xgenerator * @brief Multidimensional function operating on indices. * * The xgenerator class implements a multidimensional function, * generating a value from the supplied indices. * * @tparam F the function type * @tparam R the return type of the function * @tparam S the shape type of the generator */ template class xgenerator : public xexpression>, public xexpression_const_iterable> { public: using self_type = xgenerator; using functor_type = typename std::remove_reference::type; using value_type = R; using reference = value_type; using const_reference = value_type; using pointer = value_type*; using const_pointer = const value_type*; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using iterable_base = xexpression_const_iterable; using inner_shape_type = typename iterable_base::inner_shape_type; using shape_type = inner_shape_type; using strides_type = S; using stepper = typename iterable_base::stepper; using const_stepper = typename iterable_base::const_stepper; static constexpr layout_type static_layout = layout_type::any; static constexpr bool contiguous_layout = false; template xgenerator(Func&& f, const S& shape) noexcept; size_type size() const noexcept; size_type dimension() const noexcept; const inner_shape_type& shape() const noexcept; layout_type layout() const noexcept; template const_reference operator()(Args... args) const; const_reference operator[](const xindex& index) const; const_reference operator[](size_type i) const; template const_reference element(It first, It last) const; template bool broadcast_shape(O& shape) const; template bool is_trivial_broadcast(const O& /*strides*/) const noexcept; template const_stepper stepper_begin(const O& shape) const noexcept; template const_stepper stepper_end(const O& shape, layout_type) const noexcept; private: functor_type m_f; inner_shape_type m_shape; }; /***************************** * xgenerator implementation * *****************************/ /** * @name Constructor */ //@{ /** * Constructs an xgenerator applying the specified function over the * given shape. * @param f the function to apply * @param shape the shape of the xgenerator */ template template inline xgenerator::xgenerator(Func&& f, const S& shape) noexcept : m_f(std::forward(f)), m_shape(shape) { } //@} /** * @name Size and shape */ //@{ /** * Returns the size of the expression. */ template inline auto xgenerator::size() const noexcept -> size_type { return compute_size(shape()); } /** * Returns the number of dimensions of the function. */ template inline auto xgenerator::dimension() const noexcept -> size_type { return m_shape.size(); } /** * Returns the shape of the xgenerator. */ template inline auto xgenerator::shape() const noexcept -> const inner_shape_type& { return m_shape; } template inline layout_type xgenerator::layout() const noexcept { return static_layout; } //@} /** * @name Data */ /** * Returns the evaluated element at the specified position in the function. * @param args a list of indices specifying the position in the function. Indices * must be unsigned integers, the number of indices should be equal or greater than * the number of dimensions of the function. */ template template inline auto xgenerator::operator()(Args... args) const -> const_reference { XTENSOR_ASSERT(check_index(shape(), args...)); return m_f(args...); } template inline auto xgenerator::operator[](const xindex& index) const -> const_reference { return element(index.begin(), index.end()); } template inline auto xgenerator::operator[](size_type i) const -> const_reference { return operator()(i); } /** * Returns a constant reference to the element at the specified position in the function. * @param first iterator starting the sequence of indices * @param last iterator ending the sequence of indices * The number of indices in the sequence should be equal to or greater * than the number of dimensions of the container. */ template template inline auto xgenerator::element(It first, It last) const -> const_reference { XTENSOR_ASSERT(check_element_index(shape(), first, last)); return m_f.element(first, last); } //@} /** * @name Broadcasting */ //@{ /** * Broadcast the shape of the function to the specified parameter. * @param shape the result shape * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xgenerator::broadcast_shape(O& shape) const { return xt::broadcast_shape(m_shape, shape); } /** * Compares the specified strides with those of the container to see whether * the broadcasting is trivial. * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xgenerator::is_trivial_broadcast(const O& /*strides*/) const noexcept { return false; } //@} template template inline auto xgenerator::stepper_begin(const O& shape) const noexcept -> const_stepper { size_type offset = shape.size() - dimension(); return const_stepper(this, offset); } template template inline auto xgenerator::stepper_end(const O& shape, layout_type) const noexcept -> const_stepper { size_type offset = shape.size() - dimension(); return const_stepper(this, offset, true); } namespace detail { #ifdef X_OLD_CLANG template inline auto make_xgenerator(Functor&& f, std::initializer_list shape) noexcept { using shape_type = std::vector; using type = xgenerator; return type(std::forward(f), forward_sequence(shape)); } #else template inline auto make_xgenerator(Functor&& f, const I (&shape)[L]) noexcept { using shape_type = std::array; using type = xgenerator; return type(std::forward(f), forward_sequence(shape)); } #endif template inline auto make_xgenerator(Functor&& f, S&& shape) noexcept { using type = xgenerator>; return type(std::forward(f), std::forward(shape)); } } } #endif xtensor-0.10.11/include/xtensor/xindexview.hpp000066400000000000000000000476551314655136400214350ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XINDEXVIEW_HPP #define XINDEXVIEW_HPP #include #include #include #include #include #include "xexpression.hpp" #include "xiterable.hpp" #include "xstrides.hpp" #include "xutils.hpp" namespace xt { template class xindexview; template struct xcontainer_inner_types> { using xexpression_type = std::decay_t; using temporary_type = xarray; }; template struct xiterable_inner_types> { using inner_shape_type = std::array; using const_stepper = xindexed_stepper>; using stepper = xindexed_stepper, false>; using const_iterator = xiterator; using iterator = xiterator; using const_reverse_iterator = std::reverse_iterator; using reverse_iterator = std::reverse_iterator; }; /************** * xindexview * **************/ /** * @class xindexview * @brief View of an xexpression from vector of indices. * * The xindexview class implements a flat (1D) view into a multidimensional * xexpression yielding the values at the indices of the index array. * xindexview is not meant to be used directly, but only with the \ref index_view * and \ref filter helper functions. * * @tparam CT the closure type of the \ref xexpression type underlying this view * @tparam I the index array type of the view * * @sa index_view, filter */ template class xindexview : public xview_semantic>, public xexpression_iterable> { public: using self_type = xindexview; using xexpression_type = std::decay_t; using semantic_base = xview_semantic; using value_type = typename xexpression_type::value_type; using reference = typename xexpression_type::reference; using const_reference = typename xexpression_type::const_reference; using pointer = typename xexpression_type::pointer; using const_pointer = typename xexpression_type::const_pointer; using size_type = typename xexpression_type::size_type; using difference_type = typename xexpression_type::difference_type; using iterable_base = xexpression_iterable; using inner_shape_type = typename iterable_base::inner_shape_type; using shape_type = inner_shape_type; using strides_type = shape_type; using indices_type = I; using stepper = typename iterable_base::stepper; using const_stepper = typename iterable_base::const_stepper; using temporary_type = typename xcontainer_inner_types::temporary_type; using base_index_type = xindex_type_t; static constexpr layout_type static_layout = layout_type::dynamic; static constexpr bool contiguous_layout = false; template xindexview(CT e, I2&& indices) noexcept; template self_type& operator=(const xexpression& e); template disable_xexpression& operator=(const E& e); size_type size() const noexcept; size_type dimension() const noexcept; const inner_shape_type& shape() const noexcept; layout_type layout() const noexcept; reference operator()(); template reference operator()(std::size_t idx, Args... /*args*/); reference operator[](const xindex& index); reference operator[](size_type i); template reference element(It first, It last); const_reference operator()() const; template const_reference operator()(std::size_t idx, Args... /*args*/) const; const_reference operator[](const xindex& index) const; const_reference operator[](size_type i) const; template const_reference element(It first, It last) const; template bool broadcast_shape(O& shape) const; template bool is_trivial_broadcast(const O& /*strides*/) const noexcept; template stepper stepper_begin(const ST& shape); template stepper stepper_end(const ST& shape, layout_type); template const_stepper stepper_begin(const ST& shape) const; template const_stepper stepper_end(const ST& shape, layout_type) const; private: CT m_e; const indices_type m_indices; const inner_shape_type m_shape; void assign_temporary_impl(temporary_type&& tmp); friend class xview_semantic>; }; /*************** * xfiltration * ***************/ /** * @class xfiltration * @brief Filter of a xexpression for fast scalar assign. * * The xfiltration class implements a lazy filtration of a multidimentional * \ref xexpression, optimized for scalar and computed scalar assignments. * Actually, the \ref xfiltration class IS NOT an \ref xexpression and the * scalar and computed scalar assignments are the only method it provides. * The filtering condition is not evaluated until the filtration is assigned. * * xfiltration is not meant to be used directly, but only with the \ref filtration * helper function. * * @tparam ECT the closure type of the \ref xexpression type underlying this filtration * @tparam CCR the closure type of the filtering \ref xexpression type * * @sa filtration */ template class xfiltration { public: using self_type = xfiltration; using xexpression_type = std::decay_t; using const_reference = typename xexpression_type::const_reference; xfiltration(ECT e, CCT condition); template disable_xexpression operator=(const E&); template disable_xexpression operator+=(const E&); template disable_xexpression operator-=(const E&); template disable_xexpression operator*=(const E&); template disable_xexpression operator/=(const E&); private: template self_type& apply(F&& func); ECT m_e; CCT m_condition; }; /***************************** * xindexview implementation * *****************************/ /** * @name Constructor */ //@{ /** * Constructs an xindexview, selecting the indices specified by \a indices. * The resulting xexpression has a 1D shape with a length of n for n indices. * * @param e the underlying xexpression for this view * @param indices the indices to select */ template template inline xindexview::xindexview(CT e, I2&& indices) noexcept : m_e(e), m_indices(std::forward(indices)), m_shape({m_indices.size()}) { } //@} /** * @name Extended copy semantic */ //@{ /** * The extended assignment operator. */ template template inline auto xindexview::operator=(const xexpression& e) -> self_type& { return semantic_base::operator=(e); } //@} template template inline auto xindexview::operator=(const E& e) -> disable_xexpression& { std::fill(this->begin(), this->end(), e); return *this; } template inline void xindexview::assign_temporary_impl(temporary_type&& tmp) { std::copy(tmp.cbegin(), tmp.cend(), this->xbegin()); } /** * @name Size and shape */ //@{ /** * Returns the size of the xindexview. */ template inline auto xindexview::size() const noexcept -> size_type { return compute_size(shape()); } /** * Returns the number of dimensions of the xindexview. */ template inline auto xindexview::dimension() const noexcept -> size_type { return 1; } /** * Returns the shape of the xindexview. */ template inline auto xindexview::shape() const noexcept -> const inner_shape_type& { return m_shape; } template inline layout_type xindexview::layout() const noexcept { return static_layout; } //@} /** * @name Data */ template inline auto xindexview::operator()() -> reference { return m_e(); } template inline auto xindexview::operator()() const -> const_reference { return m_e(); } template template inline auto xindexview::operator()(std::size_t idx, Args... /*args*/) -> reference { return m_e[m_indices[idx]]; } /** * Returns the element at the specified position in the xindexview. * * @param idx the position in the view */ template template inline auto xindexview::operator()(std::size_t idx, Args... /*args*/) const -> const_reference { return m_e[m_indices[idx]]; } template inline auto xindexview::operator[](const xindex& index) -> reference { return m_e[m_indices[index[0]]]; } template inline auto xindexview::operator[](size_type i) -> reference { return operator()(i); } template inline auto xindexview::operator[](const xindex& index) const -> const_reference { return m_e[m_indices[index[0]]]; } template inline auto xindexview::operator[](size_type i) const -> const_reference { return operator()(i); } /** * Returns a reference to the element at the specified position in the xindexview. * @param first iterator starting the sequence of indices * The number of indices in the sequence should be equal to or greater 1. */ template template inline auto xindexview::element(It first, It /*last*/) -> reference { return m_e[m_indices[(*first)]]; } template template inline auto xindexview::element(It first, It /*last*/) const -> const_reference { return m_e[m_indices[(*first)]]; } //@} /** * @name Broadcasting */ //@{ /** * Broadcast the shape of the xindexview to the specified parameter. * @param shape the result shape * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xindexview::broadcast_shape(O& shape) const { return xt::broadcast_shape(m_shape, shape); } /** * Compares the specified strides with those of the container to see whether * the broadcasting is trivial. * @return a boolean indicating whether the broadcasting is trivial */ template template inline bool xindexview::is_trivial_broadcast(const O& /*strides*/) const noexcept { return false; } //@} /*************** * stepper api * ***************/ template template inline auto xindexview::stepper_begin(const ST& shape) -> stepper { size_type offset = shape.size() - dimension(); return stepper(this, offset); } template template inline auto xindexview::stepper_end(const ST& shape, layout_type) -> stepper { size_type offset = shape.size() - dimension(); return stepper(this, offset, true); } template template inline auto xindexview::stepper_begin(const ST& shape) const -> const_stepper { size_type offset = shape.size() - dimension(); return const_stepper(this, offset); } template template inline auto xindexview::stepper_end(const ST& shape, layout_type) const -> const_stepper { size_type offset = shape.size() - dimension(); return const_stepper(this, offset, true); } /****************************** * xfiltration implementation * ******************************/ /** * @name Constructor */ //@{ /** * Constructs a xfiltration on the given expression \c e, selecting * the elements matching the specified \c condition. * * @param e the \ref xexpression to filter. * @param condition the filtering \ref xexpression to apply. */ template inline xfiltration::xfiltration(ECT e, CCT condition) : m_e(e), m_condition(condition) { } //@} /** * @name Extended copy semantic */ //@{ /** * Assigns the scalar \c e to \c *this. * @param e the scalar to assign. * @return a reference to \ *this. */ template template inline auto xfiltration::operator=(const E& e) -> disable_xexpression { return apply([this, &e](const_reference v, bool cond) { return cond ? e : v; }); } //@} /** * @name Computed assignement */ //@{ /** * Adds the scalar \c e to \c *this. * @param e the scalar to add. * @return a reference to \c *this. */ template template inline auto xfiltration::operator+=(const E& e) -> disable_xexpression { return apply([this, &e](const_reference v, bool cond) { return cond ? v + e : v; }); } /** * Subtracts the scalar \c e from \c *this. * @param e the scalar to subtract. * @return a reference to \c *this. */ template template inline auto xfiltration::operator-=(const E& e) -> disable_xexpression { return apply([this, &e](const_reference v, bool cond) { return cond ? v - e : v; }); } /** * Multiplies \c *this with the scalar \c e. * @param e the scalar involved in the operation. * @return a reference to \c *this. */ template template inline auto xfiltration::operator*=(const E& e) -> disable_xexpression { return apply([this, &e](const_reference v, bool cond) { return cond ? v * e : v; }); } /** * Divides \c *this by the scalar \c e. * @param e the scalar involved in the operation. * @return a reference to \c *this. */ template template inline auto xfiltration::operator/=(const E& e) -> disable_xexpression { return apply([this, &e](const_reference v, bool cond) { return cond ? v / e : v; }); } template template inline auto xfiltration::apply(F&& func) -> self_type& { std::transform(m_e.cbegin(), m_e.cend(), m_condition.cbegin(), m_e.begin(), func); return *this; } /** * @brief creates an indexview from a container of indices. * * Returns a 1D view with the elements at \a indices selected. * * @param e the underlying xexpression * @param indices the indices to select * * \code{.cpp} * xarray a = {{1,5,3}, {4,5,6}}; * b = index_view(a, {{0, 0}, {1, 0}, {1, 1}}); * std::cout << b << std::endl; // {1, 4, 5} * b += 100; * std::cout << a << std::endl; // {{101, 5, 3}, {104, 105, 6}} * \endcode */ template inline auto index_view(E&& e, I&& indices) noexcept { using view_type = xindexview, std::decay_t>; return view_type(std::forward(e), std::forward(indices)); } #ifdef X_OLD_CLANG template inline auto index_view(E&& e, std::initializer_list> indices) noexcept { std::vector idx; for (auto it = indices.begin(); it != indices.end(); ++it) { idx.emplace_back(xindex(it->begin(), it->end())); } using view_type = xindexview, std::vector>; return view_type(std::forward(e), std::move(idx)); } #else template inline auto index_view(E&& e, const xindex (&indices)[L]) noexcept { using view_type = xindexview, std::array>; return view_type(std::forward(e), to_array(indices)); } #endif /** * @brief creates a view into \a e filtered by \a condition. * * Returns a 1D view with the elements selected where \a condition evaluates to \em true. * This is equivalent to \verbatim{index_view(e, where(condition));}\endverbatim * The returned view is not optimal if you just want to assign a scalar to the filtered * elements. In that case, you should consider using the \ref filtration function * instead. * * @param e the underlying xexpression * @param condition xexpression with shape of \a e which selects indices * * \code{.cpp} * xarray a = {{1,5,3}, {4,5,6}}; * b = filter(a, a >= 5); * std::cout << b << std::endl; // {5, 5, 6} * \endcode * * \sa filtration */ template inline auto filter(E&& e, O&& condition) noexcept { auto indices = where(std::forward(condition)); using view_type = xindexview, decltype(indices)>; return view_type(std::forward(e), std::move(indices)); } /** * @brief creates a filtration of \c e filtered by \a condition. * * Returns a lazy filtration optimized for scalar assignment. * Actually, scalar assignment and computed scalar assignments * are the only available methods of the filtration, the filtration * IS NOT an \ref xexpression. * * @param e the \ref xexpression to filter * @param condition the filtering \ref xexpression * * \code{.cpp} * xarray a = {{1,5,3}, {4,5,6}}; * filtration(a, a >= 5) += 2; * std::cout << a << std::endl; // {{1, 7, 3}, {4, 7, 8}} * \endcode */ template inline auto filtration(E&& e, C&& condition) noexcept { using filtration_type = xfiltration, xclosure_t>; return filtration_type(std::forward(e), std::forward(condition)); } } #endif xtensor-0.10.11/include/xtensor/xinfo.hpp000066400000000000000000000062361314655136400203540ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #include namespace xt { // see http://stackoverflow.com/a/20170989 struct static_string { template constexpr static_string(const char (&a)[N]) noexcept : data(a), size(N - 1) { } constexpr static_string(const char* a, const std::size_t sz) noexcept : data(a), size(sz) { } const char* const data; const std::size_t size; }; template constexpr static_string type_name() { #ifdef __clang__ static_string p = __PRETTY_FUNCTION__; return static_string(p.data + 31, p.size - 31 - 1); #elif defined(__GNUC__) static_string p = __PRETTY_FUNCTION__; #if __cplusplus < 201402 return static_string(p.data + 36, p.size - 36 - 1); #else return static_string(p.data + 46, p.size - 46 - 1); #endif #elif defined(_MSC_VER) static_string p = __FUNCSIG__; return static_string(p.data + 38, p.size - 38 - 7); #endif } template constexpr std::string type_to_string() { static_string static_name = type_name(); return std::string(static_name.data, static_name.size); } template std::string info(const T& t) { std::string s; using shape_type = typename T::shape_type; if (detail::is_array::value) { s += "Type: xtensor, fixed dimension " + std::to_string(t.dimension()); } else { s += "Type: xarray, dimension " + std::to_string(t.dimension()); } s += "\nValue type: " + type_to_string(); s += "\nLayout: "; if (t.layout() == layout_type::row_major) { s += "row_major"; } else if (t.layout() == layout_type::column_major) { s += "column_major"; } else if (t.layout() == layout_type::dynamic) { s += "dynamic"; } else { s += "any"; } s += "\nShape: ("; bool first = true; for (const auto& el : t.shape()) { if (!first) { s += ", "; } first = false; s += std::to_string(el); } s += ")\nStrides: ("; first = true; for (const auto& el : t.strides()) { if (!first) { s += ", "; } first = false; s += std::to_string(el); } s += ")\nSize: " + std::to_string(t.size()) + "\n"; return s; } }xtensor-0.10.11/include/xtensor/xio.hpp000066400000000000000000000511001314655136400200160ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XIO_HPP #define XIO_HPP #include #include #include #include #include #include #include #include "xexpression.hpp" #include "xmath.hpp" #include "xview.hpp" #if _WIN32 using precision_type = typename std::streamsize; #else using precision_type = int; #endif namespace xt { template inline std::ostream& operator<<(std::ostream& out, const xexpression& e); namespace print_options { struct print_options_impl { std::size_t edge_items = 3; std::size_t line_width = 75; std::size_t threshold = 1000; precision_type precision = -1; // default precision }; inline print_options_impl& print_options() { static print_options_impl po; return po; } /** * @brief Sets the line width. After \a line_width chars, * a new line is added. * * @param line_width The line width */ inline void set_line_width(std::size_t line_width) { print_options().line_width = line_width; } /** * @brief Sets the threshold after which summarization is triggered (default: 1000). * * @param threshold The number of elements in the xexpression that triggers * summarization in the output */ inline void set_threshold(std::size_t threshold) { print_options().threshold = threshold; } /** * @brief Sets the number of edge items. If the summarization is * triggered, this value defines how many items of each dimension * are printed. * * @param edge_items The number of edge items */ inline void set_edge_items(std::size_t edge_items) { print_options().edge_items = edge_items; } /** * @brief Sets the precision for printing floating point values. * * @param precision The number of digits for floating point output */ inline void set_precision(precision_type precision) { print_options().precision = precision; } } /************************************** * xexpression ostream implementation * **************************************/ namespace detail { template struct xout { template static std::ostream& output(std::ostream& out, const E& e, F& printer, std::size_t blanks, precision_type element_width, std::size_t edge_items, std::size_t line_width) { using size_type = typename E::size_type; if (e.dimension() == 0) { printer.print_next(out); } else { std::string indents(blanks, ' '); size_type i = 0; size_type elems_on_line = 0; size_type line_lim = (size_type)std::floor(line_width / (element_width + 2)); out << '{'; for (; i != e.shape()[0] - 1; ++i) { if (edge_items && e.shape()[0] > (edge_items * 2) && i == edge_items) { out << "..., "; if (e.dimension() > 1) { elems_on_line = 0; out << std::endl << indents; } i = e.shape()[0] - edge_items; } if (e.dimension() == 1 && line_lim != 0 && elems_on_line >= line_lim) { out << std::endl << indents; elems_on_line = 0; } xout::output(out, view(e, i), printer, blanks + 1, element_width, edge_items, line_width) << ','; elems_on_line++; if (I == 1 || e.dimension() == 1) { out << ' '; } else { out << std::endl << indents; } } if (e.dimension() == 1 && line_lim != 0 && elems_on_line >= line_lim) { out << std::endl << indents; } xout::output(out, view(e, i), printer, blanks + 1, element_width, edge_items, line_width) << '}'; } return out; } }; template <> struct xout<0> { template static std::ostream& output(std::ostream& out, const E& e, F& printer, std::size_t, precision_type, std::size_t, std::size_t) { if (e.dimension() == 0) { return printer.print_next(out); } else { return out << "{...}"; } } }; template struct recurser { template static void run(F& fn, const E& e, std::size_t lim = 0) { using size_type = typename E::size_type; if (e.dimension() == 0) { fn.update(e()); } else { size_type i = 0; for (; i != e.shape()[0] - 1; ++i) { if (lim && e.shape()[0] > (lim * 2) && i == lim) { i = e.shape()[0] - lim; } recurser::run(fn, view(e, i), lim); } recurser::run(fn, view(e, i), lim); } } }; template <> struct recurser<0> { template static void run(F& fn, const E& e, std::size_t) { if (e.dimension() == 0) { fn.update(e()); } } }; template struct printer; template struct printer::value>> { using value_type = typename T::value_type; using cache_type = std::vector; using cache_iterator = typename cache_type::const_iterator; printer(precision_type precision) : m_precision(precision) { } void init() { m_precision = m_required_precision < m_precision ? m_required_precision : m_precision; m_it = m_cache.cbegin(); if (m_scientific) { // 3 = sign, number and dot and 4 = "e+00" m_width = m_precision + 7; if (m_large_exponent) { // = e+000 (additional number) m_width += 1; } } else { precision_type decimals = 1; // print a leading 0 if (std::floor(m_max) != 0) { decimals += (precision_type)std::log10(std::floor(m_max)); } // 2 => sign and dot m_width = 2 + decimals + m_precision; } if (!m_required_precision) { --m_width; } } std::ostream& print_next(std::ostream& out) { if (!m_scientific) { std::stringstream buf; buf << std::setw(m_width) << std::fixed << std::setprecision(m_precision) << (*m_it); if (!m_required_precision) { buf << '.'; } std::string res = buf.str(); auto sit = res.rbegin(); while (*sit == '0') { *sit = ' '; ++sit; } out << res; } else { if (!m_large_exponent) { out << std::scientific << std::setw(m_width) << (*m_it); } else { std::stringstream buf; buf << std::setw(m_width) << std::scientific << std::setprecision(m_precision) << (*m_it); std::string res = buf.str(); if (res[res.size() - 4] == 'e') { res.erase(0, 1); res.insert(res.size() - 2, "0"); } out << res; } } ++m_it; return out; } void update(const value_type& val) { if (val != 0 && !std::isinf(val) && !std::isnan(val)) { if (!m_scientific || !m_large_exponent) { int exponent = 1 + (int)std::log10(std::abs(val)); if (exponent <= -5 || exponent > 7) { m_scientific = true; m_required_precision = m_precision; if (exponent <= -100 || exponent >= 100) { m_large_exponent = true; } } } if (std::abs(val) > m_max) { m_max = std::abs(val); } if (m_required_precision < m_precision) { while (std::floor(val * std::pow(10, m_required_precision)) != val * std::pow(10, m_required_precision)) { m_required_precision++; } } } m_cache.push_back(val); } precision_type width() { return m_width; } private: bool m_large_exponent = false; bool m_scientific = false; precision_type m_width = 9; precision_type m_precision; precision_type m_required_precision = 0; value_type m_max = 0; cache_type m_cache; cache_iterator m_it; }; template struct printer::value && !std::is_same::value>> { using value_type = typename T::value_type; using cache_type = std::vector; using cache_iterator = typename cache_type::const_iterator; printer(precision_type) { } void init() { m_it = m_cache.cbegin(); m_width = 1 + (precision_type)std::log10(m_max) + m_sign; } std::ostream& print_next(std::ostream& out) { // + enables printing of chars etc. as numbers // TODO should chars be printed as numbers? out << std::setw(m_width) << +(*m_it); ++m_it; return out; } void update(const value_type& val) { if (std::abs(val) > m_max) { m_max = std::abs(val); } if (std::is_signed::value && val < 0) { m_sign = true; } m_cache.push_back(val); } precision_type width() { return m_width; } private: precision_type m_width; bool m_sign = false; value_type m_max = 0; cache_type m_cache; cache_iterator m_it; }; template struct printer::value>> { using value_type = bool; using cache_type = std::vector; using cache_iterator = typename cache_type::const_iterator; printer(precision_type) { } void init() { m_it = m_cache.cbegin(); } std::ostream& print_next(std::ostream& out) { if (*m_it) { out << " true"; } else { out << "false"; } // the following std::setw(5) isn't working correctly on OSX. // out << std::boolalpha << std::setw(m_width) << (*m_it); ++m_it; return out; } void update(const value_type& val) { m_cache.push_back(val); } precision_type width() { return m_width; } private: precision_type m_width = 5; cache_type m_cache; cache_iterator m_it; }; template struct printer::value>> { using value_type = typename T::value_type; using cache_type = std::vector; using cache_iterator = typename cache_type::const_iterator; printer(precision_type precision) : real_printer(precision), imag_printer(precision) { } void init() { real_printer.init(); imag_printer.init(); m_it = m_signs.cbegin(); } std::ostream& print_next(std::ostream& out) { real_printer.print_next(out); if (*m_it) { out << "-"; } else { out << "+"; } std::stringstream buf; imag_printer.print_next(buf); std::string s = buf.str(); if (s[0] == ' ') { s.erase(0, 1); // erase space for +/- } // insert j at end of number std::size_t idx = s.find_last_not_of(" "); s.insert(idx + 1, "i"); out << s; ++m_it; return out; } void update(const value_type& val) { real_printer.update(val.real()); imag_printer.update(std::abs(val.imag())); m_signs.push_back(std::signbit(val.imag())); } precision_type width() { return real_printer.width() + imag_printer.width() + 2; } private: printer real_printer, imag_printer; cache_type m_signs; cache_iterator m_it; }; template struct printer::value && !is_complex::value>> { using value_type = typename T::value_type; using cache_type = std::vector; using cache_iterator = typename cache_type::const_iterator; printer(precision_type) { } void init() { m_it = m_cache.cbegin(); if (m_width > 20) { m_width = 0; } } std::ostream& print_next(std::ostream& out) { out << std::setw(m_width) << *m_it; ++m_it; return out; } void update(const value_type& val) { std::stringstream buf; buf << val; std::string s = buf.str(); if (int(s.size()) > m_width) { m_width = int(s.size()); } m_cache.push_back(s); } precision_type width() { return m_width; } private: precision_type m_width = 0; cache_type m_cache; cache_iterator m_it; }; template struct custom_formatter { using value_type = typename E::value_type; template custom_formatter(F&& func) : m_func(func) { } std::string operator()(const value_type& val) const { return m_func(val); } private: std::function m_func; }; template struct recursion_depth { static constexpr std::size_t value = 5; }; // Note: std::min is not constexpr on old versions of gcc (4.x) and clang. #define XTENSOR_MIN(x, y) (x > y ? y : x) template struct recursion_depth> { static constexpr std::size_t value = XTENSOR_MIN(5, N); }; #undef XTENSOR_MIN } template std::ostream& pretty_print(const xexpression& e, F&& func, std::ostream& out = std::cout) { xfunction, std::string, const_xclosure_t> print_fun(detail::custom_formatter(std::forward(func)), e); return pretty_print(print_fun, out); } template std::ostream& pretty_print(const xexpression& e, std::ostream& out = std::cout) { const E& d = e.derived_cast(); size_t lim = 0; std::size_t sz = compute_size(d.shape()); if (sz > print_options::print_options().threshold) { lim = print_options::print_options().edge_items; } if (sz == 0) { out << "{}"; return out; } precision_type temp_precision = (precision_type)out.precision(); precision_type precision = temp_precision; if (print_options::print_options().precision != -1) { out << std::setprecision(print_options::print_options().precision); precision = print_options::print_options().precision; } detail::printer p(precision); constexpr std::size_t depth = detail::recursion_depth::value; detail::recurser::run(p, d, lim); p.init(); detail::xout::output(out, d, p, 1, p.width(), lim, print_options::print_options().line_width); out << std::setprecision(temp_precision); // restore precision return out; } template inline std::ostream& operator<<(std::ostream& out, const xexpression& e) { return pretty_print(e, out); } } #endif xtensor-0.10.11/include/xtensor/xiterable.hpp000066400000000000000000001071611314655136400212070ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XITERABLE_HPP #define XITERABLE_HPP #include "xiterator.hpp" namespace xt { /******************* * xconst_iterable * *******************/ template struct xiterable_inner_types; #define DL DEFAULT_LAYOUT /** * @class xconst_iterable * @brief Base class for multidimensional iterable constant expressions * * The xconst_iterable class defines the interface for multidimensional * constant expressions that can be iterated. * * @tparam D The derived type, i.e. the inheriting class for which xconst_iterable * provides the interface. */ template class xconst_iterable { public: using derived_type = D; using iterable_types = xiterable_inner_types; using inner_shape_type = typename iterable_types::inner_shape_type; using stepper = typename iterable_types::stepper; using const_stepper = typename iterable_types::const_stepper; using iterator = typename iterable_types::iterator; using const_iterator = typename iterable_types::const_iterator; template using broadcast_iterator = xiterator; template using const_broadcast_iterator = xiterator; template using shaped_xiterator = xiterator; template using const_shaped_xiterator = xiterator; using reverse_iterator = typename iterable_types::reverse_iterator; using const_reverse_iterator = typename iterable_types::const_reverse_iterator; template using reverse_broadcast_iterator = std::reverse_iterator>; template using const_reverse_broadcast_iterator = std::reverse_iterator>; template using reverse_shaped_xiterator = std::reverse_iterator>; template using const_reverse_shaped_xiterator = std::reverse_iterator>; template const_broadcast_iterator xbegin() const noexcept; template const_broadcast_iterator xend() const noexcept; template const_broadcast_iterator cxbegin() const noexcept; template const_broadcast_iterator cxend() const noexcept; template const_shaped_xiterator xbegin(const S& shape) const noexcept; template const_shaped_xiterator xend(const S& shape) const noexcept; template const_shaped_xiterator cxbegin(const S& shape) const noexcept; template const_shaped_xiterator cxend(const S& shape) const noexcept; template const_reverse_broadcast_iterator xrbegin() const noexcept; template const_reverse_broadcast_iterator xrend() const noexcept; template const_reverse_broadcast_iterator cxrbegin() const noexcept; template const_reverse_broadcast_iterator cxrend() const noexcept; template const_reverse_shaped_xiterator xrbegin(const S& shape) const noexcept; template const_reverse_shaped_xiterator xrend(const S& shape) const noexcept; template const_reverse_shaped_xiterator cxrbegin(const S& shape) const noexcept; template const_reverse_shaped_xiterator cxrend(const S& shape) const noexcept; protected: const inner_shape_type& get_shape() const; private: template const_broadcast_iterator get_cxbegin(bool reverse) const noexcept; template const_broadcast_iterator get_cxend(bool reverse) const noexcept; template const_shaped_xiterator get_cxbegin(const S& shape, bool reverse) const noexcept; template const_shaped_xiterator get_cxend(const S& shape, bool reverse) const noexcept; template const_stepper get_stepper_begin(const S& shape) const noexcept; template const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept; const derived_type& derived_cast() const; }; /************* * xiterable * *************/ /** * @class xiterable * @brief Base class for multidimensional iterable expressions * * The xiterable class defines the interface for multidimensional * expressions that can be iterated. * * @tparam D The derived type, i.e. the inheriting class for which xiterable * provides the interface. */ template class xiterable : public xconst_iterable { public: using derived_type = D; using base_type = xconst_iterable; using inner_shape_type = typename base_type::inner_shape_type; using stepper = typename base_type::stepper; using const_stepper = typename base_type::const_stepper; using iterator = typename base_type::iterator; using const_iterator = typename base_type::const_iterator; template using broadcast_iterator = typename base_type::template broadcast_iterator; template using const_broadcast_iterator = typename base_type::template const_broadcast_iterator; template using shaped_xiterator = typename base_type::template shaped_xiterator; template using const_shaped_xiterator = typename base_type::template const_shaped_xiterator; using reverse_iterator = typename base_type::reverse_iterator; using const_reverse_iterator = typename base_type::const_reverse_iterator; template using reverse_broadcast_iterator = typename base_type::template reverse_broadcast_iterator; template using const_reverse_broadcast_iterator = typename base_type::template const_reverse_broadcast_iterator; template using reverse_shaped_xiterator = typename base_type::template reverse_shaped_xiterator; template using const_reverse_shaped_xiterator = typename base_type::template const_reverse_shaped_xiterator; template broadcast_iterator xbegin() noexcept; template broadcast_iterator xend() noexcept; using base_type::xbegin; using base_type::xend; template shaped_xiterator xbegin(const S& shape) noexcept; template shaped_xiterator xend(const S& shape) noexcept; template reverse_broadcast_iterator xrbegin() noexcept; template reverse_broadcast_iterator xrend() noexcept; using base_type::xrbegin; using base_type::xrend; template reverse_shaped_xiterator xrbegin(const S& shape) noexcept; template reverse_shaped_xiterator xrend(const S& shape) noexcept; private: template broadcast_iterator get_xbegin(bool reverse) noexcept; template broadcast_iterator get_xend(bool reverse) noexcept; template shaped_xiterator get_xbegin(const S& shape, bool reverse) noexcept; template shaped_xiterator get_xend(const S& shape, bool reverse) noexcept; template stepper get_stepper_begin(const S& shape) noexcept; template stepper get_stepper_end(const S& shape, layout_type l) noexcept; derived_type& derived_cast(); }; #undef DL /****************************** * xexpression_const_iterable * ******************************/ /** * @class xexpression_const_iterable * @brief Base class for multidimensional iterable constant expressions * that don't store any data * * The xexpression_const_iterable class defines the interface for multidimensional * constant expressions that don't store any data and that can be iterated. * * @tparam D The derived type, i.e. the inheriting class for which xexpression_const_iterable * provides the interface. */ template class xexpression_const_iterable : public xconst_iterable { public: using base_type = xconst_iterable; using inner_shape_type = typename base_type::inner_shape_type; using stepper = typename base_type::stepper; using const_stepper = typename base_type::const_stepper; using iterator = typename base_type::iterator; using const_iterator = typename base_type::const_iterator; template using broadcast_iterator = typename base_type::template broadcast_iterator; template using const_broadcast_iterator = typename base_type::template const_broadcast_iterator; template using shaped_xiterator = typename base_type::template shaped_xiterator; template using const_shaped_xiterator = typename base_type::template const_shaped_xiterator; using reverse_iterator = typename base_type::reverse_iterator; using const_reverse_iterator = typename base_type::const_reverse_iterator; template using reverse_broadcast_iterator = typename base_type::template reverse_broadcast_iterator; template using const_reverse_broadcast_iterator = typename base_type::template const_reverse_broadcast_iterator; template using reverse_shaped_xiterator = typename base_type::template reverse_shaped_xiterator; template using const_reverse_shaped_xiterator = typename base_type::template const_reverse_shaped_xiterator; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator rbegin() const noexcept; const_reverse_iterator rend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; }; /************************ * xexpression_iterable * ************************/ /** * @class xexpression_iterable * @brief Base class for multidimensional iterable expressions * that don't store any data * * The xexpression_iterable class defines the interface for multidimensional * expressions that don't store any data and that can be iterated. * * @tparam D The derived type, i.e.the inheriting class for which xexpression_iterable * provides the interface. */ template class xexpression_iterable : public xiterable { public: using base_type = xiterable; using inner_shape_type = typename base_type::inner_shape_type; using stepper = typename base_type::stepper; using const_stepper = typename base_type::const_stepper; using iterator = typename base_type::iterator; using const_iterator = typename base_type::const_iterator; template using broadcast_iterator = typename base_type::template broadcast_iterator; template using const_broadcast_iterator = typename base_type::template const_broadcast_iterator; template using shaped_xiterator = typename base_type::template shaped_xiterator; template using const_shaped_xiterator = typename base_type::template const_shaped_xiterator; using reverse_iterator = typename base_type::reverse_iterator; using const_reverse_iterator = typename base_type::const_reverse_iterator; template using reverse_broadcast_iterator = typename base_type::template reverse_broadcast_iterator; template using const_reverse_broadcast_iterator = typename base_type::template const_reverse_broadcast_iterator; template using reverse_shaped_xiterator = typename base_type::template reverse_shaped_xiterator; template using const_reverse_shaped_xiterator = typename base_type::template const_reverse_shaped_xiterator; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; reverse_iterator rbegin() noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rbegin() const noexcept; const_reverse_iterator rend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; }; /********************************** * xconst_iterable implementation * **********************************/ /** * @name Constant broadcast iterators */ //@{ /** * Returns a constant iterator to the first element of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::xbegin() const noexcept -> const_broadcast_iterator { return cxbegin(); } /** * Returns a constant iterator to the element following the last element * of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::xend() const noexcept -> const_broadcast_iterator { return cxend(); } /** * Returns a constant iterator to the first element of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::cxbegin() const noexcept -> const_broadcast_iterator { return get_cxbegin(false); } /** * Returns a constant iterator to the element following the last element * of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::cxend() const noexcept -> const_broadcast_iterator { return get_cxend(false); } /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::xbegin(const S& shape) const noexcept -> const_shaped_xiterator { return cxbegin(shape); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::xend(const S& shape) const noexcept -> const_shaped_xiterator { return cxend(shape); } /** * Returns a constant iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::cxbegin(const S& shape) const noexcept -> const_shaped_xiterator { return get_cxbegin(shape, false); } /** * Returns a constant iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::cxend(const S& shape) const noexcept -> const_shaped_xiterator { return get_cxend(shape, false); } //@} /** * @name Constant reverse broadcast iterators */ //@{ /** * Returns a constant iterator to the first element of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::xrbegin() const noexcept -> const_reverse_broadcast_iterator { return cxrbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::xrend() const noexcept -> const_reverse_broadcast_iterator { return cxrend(); } /** * Returns a constant iterator to the first element of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::cxrbegin() const noexcept -> const_reverse_broadcast_iterator { return const_reverse_broadcast_iterator(get_cxend(true)); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::cxrend() const noexcept -> const_reverse_broadcast_iterator { return const_reverse_broadcast_iterator(get_cxbegin(true)); } /** * Returns a constant iterator to the first element of the reversed expression. * The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::xrbegin(const S& shape) const noexcept -> const_reverse_shaped_xiterator { return cxrbegin(shape); } /** * Returns a constant iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::xrend(const S& shape) const noexcept -> const_reverse_shaped_xiterator { return cxrend(shape); } /** * Returns a constant iterator to the first element of the reversed expression. * The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::cxrbegin(const S& shape) const noexcept -> const_reverse_shaped_xiterator { return const_reverse_shaped_xiterator(get_cxend(shape, true)); } /** * Returns a constant iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xconst_iterable::cxrend(const S& shape) const noexcept -> const_reverse_shaped_xiterator { return const_reverse_shaped_xiterator(get_cxbegin(shape, true)); } //@} template template inline auto xconst_iterable::get_cxbegin(bool reverse) const noexcept -> const_broadcast_iterator { return const_broadcast_iterator(get_stepper_begin(get_shape()), &get_shape(), reverse); } template template inline auto xconst_iterable::get_cxend(bool reverse) const noexcept -> const_broadcast_iterator { return const_broadcast_iterator(get_stepper_end(get_shape(), L), &get_shape(), reverse); } template template inline auto xconst_iterable::get_cxbegin(const S& shape, bool reverse) const noexcept -> const_shaped_xiterator { return const_shaped_xiterator(get_stepper_begin(shape), shape, reverse); } template template inline auto xconst_iterable::get_cxend(const S& shape, bool reverse) const noexcept -> const_shaped_xiterator { return const_shaped_xiterator(get_stepper_end(shape, L), shape, reverse); } template template inline auto xconst_iterable::get_stepper_begin(const S& shape) const noexcept -> const_stepper { return derived_cast().stepper_begin(shape); } template template inline auto xconst_iterable::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper { return derived_cast().stepper_end(shape, l); } template inline auto xconst_iterable::get_shape() const -> const inner_shape_type& { return derived_cast().shape(); } template inline auto xconst_iterable::derived_cast() const -> const derived_type& { return *static_cast(this); } /**************************** * xiterable implementation * ****************************/ /** * @name Broadcast iterators */ //@{ /** * Returns an iterator to the first element of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xiterable::xbegin() noexcept -> broadcast_iterator { return get_xbegin(false); } /** * Returns an iterator to the element following the last element * of the expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xiterable::xend() noexcept -> broadcast_iterator { return get_xend(false); } /** * Returns an iterator to the first element of the expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xiterable::xbegin(const S& shape) noexcept -> shaped_xiterator { return get_xbegin(shape, false); } /** * Returns an iterator to the element following the last element of the * expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xiterable::xend(const S& shape) noexcept -> shaped_xiterator { return get_xend(shape, false); } //@} /** * @name Reverse broadcast iterators */ //@{ /** * Returns an iterator to the first element of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xiterable::xrbegin() noexcept -> reverse_broadcast_iterator { return reverse_broadcast_iterator(get_xend(true)); } /** * Returns an iterator to the element following the last element * of the reversed expression. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xiterable::xrend() noexcept -> reverse_broadcast_iterator { return reverse_broadcast_iterator(get_xbegin(true)); } /** * Returns an iterator to the first element of the reversed expression. The * iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xiterable::xrbegin(const S& shape) noexcept -> reverse_shaped_xiterator { return reverse_shaped_xiterator(get_xend(shape, true)); } /** * Returns an iterator to the element following the last element of the * reversed expression. The iteration is broadcasted to the specified shape. * @param shape the shape used for broadcasting * @tparam S type of the \c shape parameter. * @tparam L layout used for the traversal. Default value is \c DEFAULT_LAYOUT. */ template template inline auto xiterable::xrend(const S& shape) noexcept -> reverse_shaped_xiterator { return reverse_shaped_xiterator(get_xbegin(shape, true)); } //@} template template inline auto xiterable::get_xbegin(bool reverse) noexcept -> broadcast_iterator { return broadcast_iterator(get_stepper_begin(this->get_shape()), &(this->get_shape()), reverse); } template template inline auto xiterable::get_xend(bool reverse) noexcept -> broadcast_iterator { return broadcast_iterator(get_stepper_end(this->get_shape(), L), &(this->get_shape()), reverse); } template template inline auto xiterable::get_xbegin(const S& shape, bool reverse) noexcept -> shaped_xiterator { return shaped_xiterator(get_stepper_begin(shape), shape, reverse); } template template inline auto xiterable::get_xend(const S& shape, bool reverse) noexcept -> shaped_xiterator { return shaped_xiterator(get_stepper_end(shape, L), shape, reverse); } template template inline auto xiterable::get_stepper_begin(const S& shape) noexcept -> stepper { return derived_cast().stepper_begin(shape); } template template inline auto xiterable::get_stepper_end(const S& shape, layout_type l) noexcept -> stepper { return derived_cast().stepper_end(shape, l); } template inline auto xiterable::derived_cast() -> derived_type& { return *static_cast(this); } /********************************************* * xexpression_const_iterable implementation * *********************************************/ /** * @name Constant Iterators */ //@{ /** * Returns a constant iterator to the first element of the expression. */ template inline auto xexpression_const_iterable::begin() const noexcept -> const_iterator { return this->cxbegin(); } /** * Returns a constant iterator to the element following the last element * of the expression. */ template inline auto xexpression_const_iterable::end() const noexcept -> const_iterator { return this->cxend(); } /** * Returns a constant iterator to the first element of the expression. */ template inline auto xexpression_const_iterable::cbegin() const noexcept -> const_iterator { return this->cxbegin(); } /** * Returns a constant iterator to the element following the last element * of the expression. */ template inline auto xexpression_const_iterable::cend() const noexcept -> const_iterator { return this->cxend(); } //@} /** * @name Constant Reverse Iterators */ //@{ /** * Returns a constant iterator to the first element of the reversed expression. */ template inline auto xexpression_const_iterable::rbegin() const noexcept -> const_reverse_iterator { return this->cxrbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. */ template inline auto xexpression_const_iterable::rend() const noexcept -> const_reverse_iterator { return this->cxrend(); } /** * Returns a constant iterator to the first element of the reversed expression. */ template inline auto xexpression_const_iterable::crbegin() const noexcept -> const_reverse_iterator { return this->cxrbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. */ template inline auto xexpression_const_iterable::crend() const noexcept -> const_reverse_iterator { return this->cxrend(); } //@} /*************************************** * xexpression_iterable implementation * ***************************************/ /** * @name Iterators */ //@{ /** * Returns an iterator to the first element of the expression. */ template inline auto xexpression_iterable::begin() noexcept -> iterator { return this->xbegin(); } /** * Returns an iterator to the element following the last element of * the expression. */ template inline auto xexpression_iterable::end() noexcept -> iterator { return this->xend(); } //@} /** * @name Constant Iterators */ /** * Returns a constant iterator to the first element of the expression. */ template inline auto xexpression_iterable::begin() const noexcept -> const_iterator { return this->cxbegin(); } /** * Returns a constant iterator to the element following the last element * of the expression. */ template inline auto xexpression_iterable::end() const noexcept -> const_iterator { return this->cxend(); } /** * Returns a constant iterator to the first element of the expression. */ template inline auto xexpression_iterable::cbegin() const noexcept -> const_iterator { return this->cxbegin(); } /** * Returns a constant iterator to the element following the last element * of the expression. */ template inline auto xexpression_iterable::cend() const noexcept -> const_iterator { return this->cxend(); } //@} /** * @name Reverse Iterators */ //@{ /** * Returns an iterator to the first element of the reversed expression. */ template inline auto xexpression_iterable::rbegin() noexcept -> reverse_iterator { return this->xrbegin(); } /** * Returns an iterator to the element following the last element * of the reversed expression. */ template inline auto xexpression_iterable::rend() noexcept -> reverse_iterator { return this->xrend(); } //@} /** * @name Constant Reverse Iterators */ //@{ /** * Returns a constant iterator to the first element of the reversed expression. */ template inline auto xexpression_iterable::rbegin() const noexcept -> const_reverse_iterator { return this->cxrbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. */ template inline auto xexpression_iterable::rend() const noexcept -> const_reverse_iterator { return this->cxrend(); } /** * Returns a constant iterator to the first element of the reversed expression. */ template inline auto xexpression_iterable::crbegin() const noexcept -> const_reverse_iterator { return this->cxrbegin(); } /** * Returns a constant iterator to the element following the last element * of the reversed expression. */ template inline auto xexpression_iterable::crend() const noexcept -> const_reverse_iterator { return this->cxrend(); } //@} } #endif xtensor-0.10.11/include/xtensor/xiterator.hpp000066400000000000000000000502171314655136400212500ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XITERATOR_HPP #define XITERATOR_HPP #include #include #include #include #include #include "xexception.hpp" #include "xlayout.hpp" #include "xutils.hpp" namespace xt { /*********************** * iterator meta utils * ***********************/ template class xscalar; namespace detail { template struct get_stepper_iterator_impl { using type = typename C::container_iterator; }; template struct get_stepper_iterator_impl { using type = typename C::const_container_iterator; }; template struct get_stepper_iterator_impl> { using type = typename xscalar::dummy_iterator; }; template struct get_stepper_iterator_impl> { using type = typename xscalar::const_dummy_iterator; }; } template using get_stepper_iterator = typename detail::get_stepper_iterator_impl::type; namespace detail { template struct index_type_impl { using type = std::vector; }; template struct index_type_impl> { using type = std::array; }; } template using xindex_type_t = typename detail::index_type_impl::type; /************ * xstepper * ************/ template class xstepper { public: using container_type = C; using subiterator_type = get_stepper_iterator; using subiterator_traits = std::iterator_traits; using value_type = typename subiterator_traits::value_type; using reference = typename subiterator_traits::reference; using pointer = typename subiterator_traits::pointer; using difference_type = typename subiterator_traits::difference_type; using size_type = typename container_type::size_type; using shape_type = typename container_type::shape_type; xstepper() = default; xstepper(container_type* c, subiterator_type it, size_type offset) noexcept; reference operator*() const; void step(size_type dim, size_type n = 1); void step_back(size_type dim, size_type n = 1); void reset(size_type dim); void reset_back(size_type dim); void to_begin(); void to_end(layout_type l); bool equal(const xstepper& rhs) const; private: container_type* p_c; subiterator_type m_it; size_type m_offset; }; template bool operator==(const xstepper& lhs, const xstepper& rhs); template bool operator!=(const xstepper& lhs, const xstepper& rhs); template struct stepper_tools { template static void increment_stepper(S& stepper, IT& index, const ST& shape); template static void decrement_stepper(S& stepper, IT& index, const ST& shape); }; /******************** * xindexed_stepper * ********************/ template class xindexed_stepper { public: using self_type = xindexed_stepper; using xexpression_type = std::conditional_t; using value_type = typename xexpression_type::value_type; using reference = std::conditional_t; using pointer = std::conditional_t; using size_type = typename xexpression_type::size_type; using difference_type = typename xexpression_type::difference_type; using shape_type = typename xexpression_type::shape_type; using index_type = xindex_type_t; xindexed_stepper() = default; xindexed_stepper(xexpression_type* e, size_type offset, bool end = false) noexcept; reference operator*() const; void step(size_type dim, size_type n = 1); void step_back(size_type dim, size_type n = 1); void reset(size_type dim); void reset_back(size_type dim); void to_begin(); void to_end(layout_type l); bool equal(const self_type& rhs) const; private: xexpression_type* p_e; index_type m_index; size_type m_offset; }; template bool operator==(const xindexed_stepper& lhs, const xindexed_stepper& rhs); template bool operator!=(const xindexed_stepper& lhs, const xindexed_stepper& rhs); /************* * xiterator * *************/ namespace detail { template class shape_storage { public: using shape_type = S; using param_type = const S&; shape_storage() = default; shape_storage(param_type shape); const S& shape() const; private: S m_shape; }; template class shape_storage { public: using shape_type = S; using param_type = const S*; shape_storage(param_type shape = 0); const S& shape() const; private: const S* p_shape; }; template struct LAYOUT_FORBIDEN_FOR_XITERATOR; } template class xiterator : detail::shape_storage { public: using self_type = xiterator; using subiterator_type = It; using value_type = typename subiterator_type::value_type; using reference = typename subiterator_type::reference; using pointer = typename subiterator_type::pointer; using difference_type = typename subiterator_type::difference_type; using size_type = typename subiterator_type::size_type; using iterator_category = std::bidirectional_iterator_tag; using private_base = detail::shape_storage; using shape_type = typename private_base::shape_type; using shape_param_type = typename private_base::param_type; using index_type = xindex_type_t; xiterator() = default; xiterator(It it, shape_param_type shape, bool reverse); self_type& operator++(); self_type operator++(int); self_type& operator--(); self_type operator--(int); reference operator*() const; pointer operator->() const; bool equal(const xiterator& rhs) const; private: subiterator_type m_it; index_type m_index; using checking_type = typename detail::LAYOUT_FORBIDEN_FOR_XITERATOR::type; }; template bool operator==(const xiterator& lhs, const xiterator& rhs); template bool operator!=(const xiterator& lhs, const xiterator& rhs); /******************************* * trivial_begin / trivial_end * *******************************/ namespace detail { template constexpr auto trivial_begin(C& c) -> decltype(c.begin()) { return c.begin(); } template constexpr auto trivial_end(C& c) -> decltype(c.end()) { return c.end(); } template constexpr auto trivial_begin(const C& c) -> decltype(c.begin()) { return c.begin(); } template constexpr auto trivial_end(const C& c) -> decltype(c.end()) { return c.end(); } } /*************************** * xstepper implementation * ***************************/ template inline xstepper::xstepper(container_type* c, subiterator_type it, size_type offset) noexcept : p_c(c), m_it(it), m_offset(offset) { } template inline auto xstepper::operator*() const -> reference { return *m_it; } template inline void xstepper::step(size_type dim, size_type n) { if (dim >= m_offset) m_it += n * p_c->strides()[dim - m_offset]; } template inline void xstepper::step_back(size_type dim, size_type n) { if (dim >= m_offset) m_it -= n * p_c->strides()[dim - m_offset]; } template inline void xstepper::reset(size_type dim) { if (dim >= m_offset) m_it -= p_c->backstrides()[dim - m_offset]; } template inline void xstepper::reset_back(size_type dim) { if (dim >= m_offset) m_it += p_c->backstrides()[dim - m_offset]; } template inline void xstepper::to_begin() { m_it = p_c->data_xbegin(); } template inline void xstepper::to_end(layout_type l) { m_it = p_c->data_xend(l); } template inline bool xstepper::equal(const xstepper& rhs) const { return p_c == rhs.p_c && m_it == rhs.m_it && m_offset == rhs.m_offset; } template inline bool operator==(const xstepper& lhs, const xstepper& rhs) { return lhs.equal(rhs); } template inline bool operator!=(const xstepper& lhs, const xstepper& rhs) { return !(lhs.equal(rhs)); } template <> template void stepper_tools::increment_stepper(S& stepper, IT& index, const ST& shape) { using size_type = typename S::size_type; size_type i = index.size(); while (i != 0) { --i; if (index[i] != shape[i] - 1) { ++index[i]; stepper.step(i); return; } else { index[i] = 0; if (i != 0) { stepper.reset(i); } } } if (i == 0) { stepper.to_end(layout_type::row_major); } } template <> template void stepper_tools::decrement_stepper(S& stepper, IT& index, const ST& shape) { using size_type = typename S::size_type; size_type i = index.size(); while (i != 0) { --i; if (index[i] != 0) { --index[i]; stepper.step_back(i); return; } else { index[i] = shape[i] - 1; if (i != 0) { stepper.reset_back(i); } } } if (i == 0) { stepper.to_begin(); } } template <> template void stepper_tools::increment_stepper(S& stepper, IT& index, const ST& shape) { using size_type = typename S::size_type; size_type size = index.size(); size_type i = 0; while (i != size) { if (index[i] != shape[i] - 1) { ++index[i]; stepper.step(i); return; } else { index[i] = 0; if (i != size - 1) { stepper.reset(i); } } ++i; } if (i == size) { stepper.to_end(layout_type::column_major); } } template <> template void stepper_tools::decrement_stepper(S& stepper, IT& index, const ST& shape) { using size_type = typename S::size_type; size_type size = index.size(); size_type i = 0; while (i != size) { if (index[i] != 0) { --index[i]; stepper.step_back(i); return; } else { index[i] = shape[i] - 1; if (i != size - 1) { stepper.reset_back(i); } } ++i; } if (i == size) { stepper.to_begin(); } } /*********************************** * xindexed_stepper implementation * ***********************************/ template inline xindexed_stepper::xindexed_stepper(xexpression_type* e, size_type offset, bool end) noexcept : p_e(e), m_index(make_sequence(e->shape().size(), size_type(0))), m_offset(offset) { if (end) to_end(layout_type::row_major); } template inline auto xindexed_stepper::operator*() const -> reference { return p_e->element(m_index.cbegin(), m_index.cend()); } template inline void xindexed_stepper::step(size_type dim, size_type n) { if (dim >= m_offset) m_index[dim - m_offset] += n; } template inline void xindexed_stepper::step_back(size_type dim, size_type n) { if (dim >= m_offset) m_index[dim - m_offset] -= n; } template inline void xindexed_stepper::reset(size_type dim) { if (dim >= m_offset) m_index[dim - m_offset] = 0; } template inline void xindexed_stepper::reset_back(size_type dim) { if (dim >= m_offset) m_index[dim - m_offset] = p_e->shape()[dim - m_offset] - 1; } template inline void xindexed_stepper::to_begin() { std::fill(m_index.begin(), m_index.end(), size_type(0)); } template inline void xindexed_stepper::to_end(layout_type) { m_index = p_e->shape(); } template inline bool xindexed_stepper::equal(const self_type& rhs) const { return p_e == rhs.p_e && m_index == rhs.m_index && m_offset == rhs.m_offset; } template inline bool operator==(const xindexed_stepper& lhs, const xindexed_stepper& rhs) { return lhs.equal(rhs); } template inline bool operator!=(const xindexed_stepper& lhs, const xindexed_stepper& rhs) { return !lhs.equal(rhs); } /**************************** * xiterator implementation * ****************************/ namespace detail { template inline shape_storage::shape_storage(param_type shape) : m_shape(shape) { } template inline const S& shape_storage::shape() const { return m_shape; } template inline shape_storage::shape_storage(param_type shape) : p_shape(shape) { } template inline const S& shape_storage::shape() const { return *p_shape; } template <> struct LAYOUT_FORBIDEN_FOR_XITERATOR { using type = int; }; template <> struct LAYOUT_FORBIDEN_FOR_XITERATOR { using type = int; }; } template inline xiterator::xiterator(It it, shape_param_type shape, bool reverse) : private_base(shape), m_it(it), m_index(reverse ? forward_sequence(this->shape()) : make_sequence(this->shape().size(), size_type(0))) { if (reverse) { auto iter_begin = (L == layout_type::row_major) ? m_index.begin() : m_index.begin() + 1; auto iter_end = (L == layout_type::row_major) ? m_index.end() - 1 : m_index.end(); std::transform(iter_begin, iter_end, iter_begin, [](const auto& v) { return v - 1; }); } } template inline auto xiterator::operator++() -> self_type& { stepper_tools::increment_stepper(m_it, m_index, this->shape()); return *this; } template inline auto xiterator::operator++(int) -> self_type { self_type tmp(*this); ++(*this); return tmp; } template inline auto xiterator::operator--() -> self_type& { stepper_tools::decrement_stepper(m_it, m_index, this->shape()); return *this; } template inline auto xiterator::operator--(int) -> self_type { self_type tmp(*this); --(*this); return tmp; } template inline auto xiterator::operator*() const -> reference { return *m_it; } template inline auto xiterator::operator->() const -> pointer { return &(*m_it); } template inline bool xiterator::equal(const xiterator& rhs) const { return m_it == rhs.m_it && this->shape() == rhs.shape(); } template inline bool operator==(const xiterator& lhs, const xiterator& rhs) { return lhs.equal(rhs); } template inline bool operator!=(const xiterator& lhs, const xiterator& rhs) { return !(lhs.equal(rhs)); } } #endif xtensor-0.10.11/include/xtensor/xlayout.hpp000066400000000000000000000055471314655136400207420ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XLAYOUT_HPP #define XLAYOUT_HPP namespace xt { /*! layout_type enum for xcontainer based xexpressions */ enum class layout_type { /*! dynamic layout_type: you can reshape to row major, column major, or use custom strides */ dynamic = 0x00, /*! layout_type compatible with all others */ any = 0xFF, /*! row major layout_type */ row_major = 0x01, /*! column major layout_type */ column_major = 0x02 }; /** * Implementation of the following logical table: * * @verbatim | d | a | r | c | --+---+---+---+---+ d | d | d | d | d | a | d | a | r | c | r | d | r | r | d | c | d | c | d | c | d = dynamic, a = any, r = row_major, c = column_major. @endverbatim * Using bitmasks to avoid nested if-else statements. * * @param args the input layouts. * @return the output layout, computed with the previous logical table. */ template constexpr layout_type compute_layout(Args... args) noexcept; constexpr layout_type default_assignable_layout(layout_type l) noexcept; /****************** * Implementation * ******************/ namespace detail { constexpr layout_type compute_layout_impl() noexcept { return layout_type::any; } constexpr layout_type compute_layout_impl(layout_type l) noexcept { return l; } constexpr layout_type compute_layout_impl(layout_type lhs, layout_type rhs) noexcept { using type = std::underlying_type_t; return layout_type(static_cast(lhs) & static_cast(rhs)); } template constexpr layout_type compute_layout_impl(layout_type lhs, Args... args) noexcept { return compute_layout_impl(lhs, compute_layout_impl(args...)); } } template constexpr layout_type compute_layout(Args... args) noexcept { return detail::compute_layout_impl(args...); } constexpr layout_type default_assignable_layout(layout_type l) noexcept { return (l == layout_type::row_major || l == layout_type::column_major) ? l : layout_type::row_major; } } #endif xtensor-0.10.11/include/xtensor/xmath.hpp000066400000000000000000001333661314655136400203570ustar00rootroot00000000000000/*************************************************************************** * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ /** * @brief standard mathematical functions for xexpressions */ #ifndef XMATH_HPP #define XMATH_HPP #include #include #include #include "xoperation.hpp" #include "xreducer.hpp" namespace xt { template struct numeric_constants { static constexpr T PI = 3.141592653589793238463; static constexpr T PI_2 = 1.57079632679489661923; static constexpr T PI_4 = 0.785398163397448309616; static constexpr T D_1_PI = 0.318309886183790671538; static constexpr T D_2_PI = 0.636619772367581343076; static constexpr T D_2_SQRTPI = 1.12837916709551257390; static constexpr T SQRT2 = 1.41421356237309504880; static constexpr T SQRT1_2 = 0.707106781186547524401; static constexpr T E = 2.71828182845904523536; static constexpr T LOG2E = 1.44269504088896340736; static constexpr T LOG10E = 0.434294481903251827651; static constexpr T LN2 = 0.693147180559945309417; }; /*********** * Helpers * ***********/ namespace detail { template struct bool_functor_return_type { using type = bool; }; } #define UNARY_MATH_FUNCTOR(NAME) \ template \ struct NAME##_fun \ { \ using argument_type = T; \ using result_type = T; \ constexpr T operator()(const T& arg) const \ { \ using std::NAME; \ return NAME(arg); \ } \ } #define UNARY_MATH_FUNCTOR_COMPLEX_REDUCING(NAME) \ template \ struct NAME##_fun \ { \ using argument_type = T; \ using result_type = complex_value_type_t; \ constexpr result_type operator()(const T& arg) const \ { \ using std::NAME; \ return NAME(arg); \ } \ } #define BINARY_MATH_FUNCTOR(NAME) \ template \ struct NAME##_fun \ { \ using first_argument_type = T; \ using second_argument_type = T; \ using result_type = T; \ constexpr T operator()(const T& arg1, const T& arg2) const \ { \ using std::NAME; \ return NAME(arg1, arg2); \ } \ } #define TERNARY_MATH_FUNCTOR(NAME) \ template \ struct NAME##_fun \ { \ using first_argument_type = T; \ using second_argument_type = T; \ using third_argument_type = T; \ using result_type = T; \ constexpr T operator()(const T& arg1, const T& arg2, const T& arg3) const \ { \ using std::NAME; \ return NAME(arg1, arg2, arg3); \ } \ } #define UNARY_BOOL_FUNCTOR(NAME) \ template \ struct NAME##_fun \ { \ using argument_type = T; \ using result_type = typename xt::detail::bool_functor_return_type::type; \ constexpr result_type operator()(const T& arg) const \ { \ using std::NAME; \ return NAME(arg); \ } \ } namespace math { UNARY_MATH_FUNCTOR_COMPLEX_REDUCING(abs); UNARY_MATH_FUNCTOR(fabs); BINARY_MATH_FUNCTOR(fmod); BINARY_MATH_FUNCTOR(remainder); TERNARY_MATH_FUNCTOR(fma); BINARY_MATH_FUNCTOR(fmax); BINARY_MATH_FUNCTOR(fmin); BINARY_MATH_FUNCTOR(fdim); UNARY_MATH_FUNCTOR(exp); UNARY_MATH_FUNCTOR(exp2); UNARY_MATH_FUNCTOR(expm1); UNARY_MATH_FUNCTOR(log); UNARY_MATH_FUNCTOR(log10); UNARY_MATH_FUNCTOR(log2); UNARY_MATH_FUNCTOR(log1p); BINARY_MATH_FUNCTOR(pow); UNARY_MATH_FUNCTOR(sqrt); UNARY_MATH_FUNCTOR(cbrt); BINARY_MATH_FUNCTOR(hypot); UNARY_MATH_FUNCTOR(sin); UNARY_MATH_FUNCTOR(cos); UNARY_MATH_FUNCTOR(tan); UNARY_MATH_FUNCTOR(asin); UNARY_MATH_FUNCTOR(acos); UNARY_MATH_FUNCTOR(atan); BINARY_MATH_FUNCTOR(atan2); UNARY_MATH_FUNCTOR(sinh); UNARY_MATH_FUNCTOR(cosh); UNARY_MATH_FUNCTOR(tanh); UNARY_MATH_FUNCTOR(asinh); UNARY_MATH_FUNCTOR(acosh); UNARY_MATH_FUNCTOR(atanh); UNARY_MATH_FUNCTOR(erf); UNARY_MATH_FUNCTOR(erfc); UNARY_MATH_FUNCTOR(tgamma); UNARY_MATH_FUNCTOR(lgamma); UNARY_MATH_FUNCTOR(ceil); UNARY_MATH_FUNCTOR(floor); UNARY_MATH_FUNCTOR(trunc); UNARY_MATH_FUNCTOR(round); UNARY_MATH_FUNCTOR(nearbyint); UNARY_MATH_FUNCTOR(rint); UNARY_BOOL_FUNCTOR(isfinite); UNARY_BOOL_FUNCTOR(isinf); UNARY_BOOL_FUNCTOR(isnan); } #undef UNARY_BOOL_FUNCTOR #undef TERNARY_MATH_FUNCTOR #undef BINARY_MATH_FUNCTOR #undef UNARY_MATH_FUNCTOR #undef UNARY_MATH_FUNCTOR_COMPLEX_REDUCING /******************* * basic functions * *******************/ /** * @defgroup basic_functions Basic functions */ /** * @ingroup basic_functions * @brief Absolute value function. * * Returns an \ref xfunction for the element-wise absolute value * of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto abs(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup basic_functions * @brief Absolute value function. * * Returns an \ref xfunction for the element-wise absolute value * of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto fabs(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup basic_functions * @brief Remainder of the floating point division operation. * * Returns an \ref xfunction for the element-wise remainder of * the floating point division operation e1 / e2. * @param e1 an \ref xexpression or a scalar * @param e2 an \ref xexpression or a scalar * @return an \ref xfunction * @note e1 and e2 can't be both scalars. */ template inline auto fmod(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /** * @ingroup basic_functions * @brief Signed remainder of the division operation. * * Returns an \ref xfunction for the element-wise signed remainder * of the floating point division operation e1 / e2. * @param e1 an \ref xexpression or a scalar * @param e2 an \ref xexpression or a scalar * @return an \ref xfunction * @note e1 and e2 can't be both scalars. */ template inline auto remainder(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /** * @ingroup basic_functions * @brief Fused multiply-add operation. * * Returns an \ref xfunction for e1 * e2 + e3 as if * to infinite precision and rounded only once to fit the result type. * @param e1 an \ref xfunction or a scalar * @param e2 an \ref xfunction or a scalar * @param e3 an \ref xfunction or a scalar * @return an \ref xfunction * @note e1, e2 and e3 can't be scalars every three. */ template inline auto fma(E1&& e1, E2&& e2, E3&& e3) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2), std::forward(e3)); } /** * @ingroup basic_functions * @brief Maximum function. * * Returns an \ref xfunction for the element-wise maximum * of \a e1 and \a e2. * @param e1 an \ref xexpression or a scalar * @param e2 an \ref xexpression or a scalar * @return an \ref xfunction * @note e1 and e2 can't be both scalars. */ template inline auto fmax(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /** * @ingroup basic_functions * @brief Minimum function. * * Returns an \ref xfunction for the element-wise minimum * of \a e1 and \a e2. * @param e1 an \ref xexpression or a scalar * @param e2 an \ref xexpression or a scalar * @return an \ref xfunction * @note e1 and e2 can't be both scalars. */ template inline auto fmin(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /** * @ingroup basic_functions * @brief Positive difference function. * * Returns an \ref xfunction for the element-wise positive * difference of \a e1 and \a e2. * @param e1 an \ref xexpression or a scalar * @param e2 an \ref xexpression or a scalar * @return an \ref xfunction * @note e1 and e2 can't be both scalars. */ template inline auto fdim(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } namespace math { template struct minimum { using result_type = T; constexpr result_type operator()(const T& t1, const T& t2) const noexcept { return (t1 < t2) ? t1 : t2; } }; template struct maximum { using result_type = T; constexpr result_type operator()(const T& t1, const T& t2) const noexcept { return (t1 > t2) ? t1 : t2; } }; template struct clamp_fun { using first_argument_type = T; using second_argument_type = T; using third_argument_type = T; using result_type = T; constexpr T operator()(const T& v, const T& lo, const T& hi) const { return v < lo ? lo : hi < v ? hi : v; } }; } /** * @ingroup basic_functions * @brief Elementwise maximum * * Returns an \ref xfunction for the element-wise * maximum between e1 and e2. * @param e1 an \ref xexpression * @param e2 an \ref xexpression * @return an \ref xfunction */ template inline auto maximum(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /** * @ingroup basic_functions * @brief Elementwise minimum * * Returns an \ref xfunction for the element-wise * minimum between e1 and e2. * @param e1 an \ref xexpression * @param e2 an \ref xexpression * @return an \ref xfunction */ template inline auto minimum(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /** * @ingroup basic_functions * @brief Maximum element along given axis. * * Returns an \ref xreducer for the maximum of elements over given * \em axes. * @param e an \ref xexpression * @param axes the axes along which the maximum is found (optional) * @return an \ref xreducer */ template inline auto amax(E&& e, X&& axes) noexcept { using functor_type = math::maximum::value_type>; return reduce(functor_type(), std::forward(e), std::forward(axes)); } template inline auto amax(E&& e) noexcept { using functor_type = math::maximum::value_type>; return reduce(functor_type(), std::forward(e)); } #ifdef X_OLD_CLANG template inline auto amax(E&& e, std::initializer_list axes) noexcept { using functor_type = math::maximum::value_type>; return reduce(functor_type(), std::forward(e), axes); } #else template inline auto amax(E&& e, const I(&axes)[N]) noexcept { using functor_type = math::maximum::value_type>; return reduce(functor_type(), std::forward(e), axes); } #endif /** * @ingroup basic_functions * @brief Minimum element along given axis. * * Returns an \ref xreducer for the minimum of elements over given * \em axes. * @param e an \ref xexpression * @param axes the axes along which the minimum is found (optional) * @return an \ref xreducer */ template inline auto amin(E&& e, X&& axes) noexcept { using functor_type = math::minimum::value_type>; return reduce(functor_type(), std::forward(e), std::forward(axes)); } template inline auto amin(E&& e) noexcept { using functor_type = math::minimum::value_type>; return reduce(functor_type(), std::forward(e)); } #ifdef X_OLD_CLANG template inline auto amin(E&& e, std::initializer_list axes) noexcept { using functor_type = math::minimum::value_type>; return reduce(functor_type(), std::forward(e), axes); } #else template inline auto amin(E&& e, const I(&axes)[N]) noexcept { using functor_type = math::minimum::value_type>; return reduce(functor_type(), std::forward(e), axes); } #endif /** * @ingroup basic_functions * @brief Clip values between hi and lo * * Returns an \ref xfunction for the element-wise clipped * values between lo and hi * @param e1 an \ref xexpression or a scalar * @param lo a scalar * @param hi a scalar * * @return a \ref xfunction */ template inline auto clip(E1&& e1, E2&& lo, E3&& hi) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(lo), std::forward(hi)); } namespace math { namespace detail { template constexpr std::enable_if_t::value, T> sign_impl(T x) { return std::isnan(x) ? std::numeric_limits::quiet_NaN() : x == 0 ? (T)copysign(T(0), x) : (T)copysign(T(1), x); } template inline std::enable_if_t::value, T> sign_impl(T x) { typename T::value_type e = x.real() ? x.real() : x.imag(); return T(sign_impl(e), 0); } template constexpr std::enable_if_t::value, T> sign_impl(T x) { return T(x > T(0)); } } template struct sign_fun { using argument_type = T; using result_type = T; constexpr T operator()(const T& x) const { return detail::sign_impl(x); } }; } /** * @ingroup basic_functions * @brief Returns an element-wise indication of the sign of a number * * If the number is positive, returns +1. If negative, -1. If the number * is zero, returns 0. * * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto sign(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /************************* * exponential functions * *************************/ /** * @defgroup exp_functions Exponential functions */ /** * @ingroup exp_functions * @brief Natural exponential function. * * Returns an \ref xfunction for the element-wise natural * exponential of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto exp(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup exp_functions * @brief Base 2 exponential function. * * Returns an \ref xfunction for the element-wise base 2 * exponential of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto exp2(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup exp_functions * @brief Natural exponential minus one function. * * Returns an \ref xfunction for the element-wise natural * exponential of \em e, minus 1. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto expm1(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup exp_functions * @brief Natural logarithm function. * * Returns an \ref xfunction for the element-wise natural * logarithm of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto log(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup exp_functions * @brief Base 10 logarithm function. * * Returns an \ref xfunction for the element-wise base 10 * logarithm of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto log10(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup exp_functions * @brief Base 2 logarithm function. * * Returns an \ref xfunction for the element-wise base 2 * logarithm of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto log2(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup exp_functions * @brief Natural logarithm of one plus function. * * Returns an \ref xfunction for the element-wise natural * logarithm of \em e, plus 1. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto log1p(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /******************* * power functions * *******************/ /** * @defgroup pow_functions Power functions */ /** * @ingroup pow_functions * @brief Power function. * * Returns an \ref xfunction for the element-wise value of * of \em e1 raised to the power \em e2. * @param e1 an \ref xexpression or a scalar * @param e2 an \ref xexpression or a scalar * @return an \ref xfunction * @note e1 and e2 can't be both scalars. */ template inline auto pow(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /** * @ingroup pow_functions * @brief Square root function. * * Returns an \ref xfunction for the element-wise square * root of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto sqrt(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup pow_functions * @brief Cubic root function. * * Returns an \ref xfunction for the element-wise cubic * root of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto cbrt(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup pow_functions * @brief Hypotenuse function. * * Returns an \ref xfunction for the element-wise square * root of the sum of the square of \em e1 and \em e2, avoiding * overflow and underflow at intermediate stages of computation. * @param e1 an \ref xexpression or a scalar * @param e2 an \ref xexpression or a scalar * @return an \ref xfunction * @note e1 and e2 can't be both scalars. */ template inline auto hypot(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /*************************** * trigonometric functions * ***************************/ /** * @defgroup trigo_functions Trigonometric function */ /** * @ingroup trigo_functions * @brief Sine function. * * Returns an \ref xfunction for the element-wise sine * of \em e (measured in radians). * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto sin(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup trigo_functions * @brief Cosine function. * * Returns an \ref xfunction for the element-wise cosine * of \em e (measured in radians). * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto cos(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup trigo_functions * @brief Tangent function. * * Returns an \ref xfunction for the element-wise tangent * of \em e (measured in radians). * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto tan(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup trigo_functions * @brief Arcsine function. * * Returns an \ref xfunction for the element-wise arcsine * of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto asin(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup trigo_functions * @brief Arccosine function. * * Returns an \ref xfunction for the element-wise arccosine * of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto acos(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup trigo_functions * @brief Arctangent function. * * Returns an \ref xfunction for the element-wise arctangent * of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto atan(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup trigo_functions * @brief Artangent function, using signs to determine quadrants. * * Returns an \ref xfunction for the element-wise arctangent * of e1 / e2, using the signs of arguments to determine the * correct quadrant. * @param e1 an \ref xexpression or a scalar * @param e2 an \ref xexpression or a scalar * @return an \ref xfunction * @note e1 and e2 can't be both scalars. */ template inline auto atan2(E1&& e1, E2&& e2) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e1), std::forward(e2)); } /************************ * hyperbolic functions * ************************/ /** * @defgroup hyper_functions Hyperbolic functions */ /** * @ingroup hyper_functions * @brief Hyperbolic sine function. * * Returns an \ref xfunction for the element-wise hyperbolic * sine of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto sinh(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup hyper_functions * @brief Hyperbolic cosine function. * * Returns an \ref xfunction for the element-wise hyperbolic * cosine of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto cosh(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup hyper_functions * @brief Hyperbolic tangent function. * * Returns an \ref xfunction for the element-wise hyperbolic * tangent of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto tanh(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup hyper_functions * @brief Inverse hyperbolic sine function. * * Returns an \ref xfunction for the element-wise inverse hyperbolic * sine of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto asinh(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup hyper_functions * @brief Inverse hyperbolic cosine function. * * Returns an \ref xfunction for the element-wise inverse hyperbolic * cosine of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto acosh(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup hyper_functions * @brief Inverse hyperbolic tangent function. * * Returns an \ref xfunction for the element-wise inverse hyperbolic * tangent of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto atanh(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /***************************** * error and gamma functions * *****************************/ /** * @defgroup err_functions Error and gamma functions */ /** * @ingroup err_functions * @brief Error function. * * Returns an \ref xfunction for the element-wise error function * of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto erf(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup err_functions * @brief Complementary error function. * * Returns an \ref xfunction for the element-wise complementary * error function of \em e, whithout loss of precision for large argument. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto erfc(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup err_functions * @brief Gamma function. * * Returns an \ref xfunction for the element-wise gamma function * of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto tgamma(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup err_functions * @brief Natural logarithm of the gamma function. * * Returns an \ref xfunction for the element-wise logarithm of * the asbolute value fo the gamma function of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto lgamma(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /********************************************* * nearest integer floating point operations * *********************************************/ /** * @defgroup nearint_functions Nearest integer floating point operations */ /** * @ingroup nearint_functions * @brief ceil function. * * Returns an \ref xfunction for the element-wise smallest integer value * not less than \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto ceil(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup nearint_functions * @brief floor function. * * Returns an \ref xfunction for the element-wise smallest integer value * not greater than \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto floor(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup nearint_functions * @brief trunc function. * * Returns an \ref xfunction for the element-wise nearest integer not greater * in magnitude than \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto trunc(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup nearint_functions * @brief round function. * * Returns an \ref xfunction for the element-wise nearest integer value * to \em e, rounding halfway cases away from zero, regardless of the * current rounding mode. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto round(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup nearint_functions * @brief nearbyint function. * * Returns an \ref xfunction for the element-wise rounding of \em e to integer * values in floating point format, using the current rounding mode. nearbyint * never raises FE_INEXACT error. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto nearbyint(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup nearint_functions * @brief rint function. * * Returns an \ref xfunction for the element-wise rounding of \em e to integer * values in floating point format, using the current rounding mode. Contrary * to nearbyint, rint may raise FE_INEXACT error. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto rint(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /**************************** * classification functions * ****************************/ /** * @defgroup classif_functions Classification functions */ /** * @ingroup classif_functions * @brief finite value check * * Returns an \ref xfunction for the element-wise finite value check * tangent of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto isfinite(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup classif_functions * @brief infinity check * * Returns an \ref xfunction for the element-wise infinity check * tangent of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto isinf(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } /** * @ingroup classif_functions * @brief NaN check * * Returns an \ref xfunction for the element-wise NaN check * tangent of \em e. * @param e an \ref xexpression * @return an \ref xfunction */ template inline auto isnan(E&& e) noexcept -> detail::xfunction_type_t { return detail::make_xfunction(std::forward(e)); } namespace detail { template inline auto get_functor(T&& args, std::index_sequence) { return FUNCTOR(std::get(args)...); } template