diff --git a/docs/source/adaptor.rst b/docs/source/adaptor.rst index b66d53635..6f679ddce 100644 --- a/docs/source/adaptor.rst +++ b/docs/source/adaptor.rst @@ -76,7 +76,7 @@ ownership of the array: // prints 0 2 (data is still available here) } -However if you replace ``xt::no_ownership`` with ``xt::acquire_ownership``, the adaptor will take +However if you replace :cpp:enumerator:`xt::no_ownership` with :cpp:enumerator:`xt::acquire_ownership`, the adaptor will take the ownership of the array, meaning it will be deleted when the adaptor is destroyed: .. code:: @@ -179,8 +179,8 @@ Adapting C++ smart pointers --------------------------- If you want to manage your data with shared or unique pointers, you can use the -``adapt_smart_ptr`` function of xtensor. It will automatically increment the -reference count of shared pointers upon creation, and decrement upon deletion. +:cpp:func:`xt::adapt_smart_ptr` function of xtensor. +It will automatically increment the reference count of shared pointers upon creation, and decrement upon deletion. .. code:: diff --git a/docs/source/api/container_index.rst b/docs/source/api/container_index.rst index 29424161c..985e5d217 100644 --- a/docs/source/api/container_index.rst +++ b/docs/source/api/container_index.rst @@ -8,7 +8,7 @@ Containers and views ==================== Containers are in-memory expressions that share a common implementation of most of the methods of the xexpression API. -The final container classes (``xarray``, ``xtensor``) mainly implement constructors and value semantic, most of the +The final container classes (:cpp:type:`xt::xarray`, :cpp:type:`xt::xtensor`) mainly implement constructors and value semantic, most of the xexpression API is actually implemented in ``xstrided_container`` and ``xcontainer``. .. toctree:: diff --git a/docs/source/api/expression_index.rst b/docs/source/api/expression_index.rst index 6fef3019f..c257117db 100644 --- a/docs/source/api/expression_index.rst +++ b/docs/source/api/expression_index.rst @@ -7,7 +7,7 @@ Expressions and semantic ======================== -``xexpression`` and the semantic classes contain all the methods required to perform evaluation and +:cpp:type:`xt::xexpression` and the semantic classes contain all the methods required to perform evaluation and assignment of expressions. They define the computed assignment operators, the assignment methods for ``noalias`` and the downcast methods. diff --git a/docs/source/api/xrandom.rst b/docs/source/api/xrandom.rst index 146c22fc5..84e665562 100644 --- a/docs/source/api/xrandom.rst +++ b/docs/source/api/xrandom.rst @@ -11,84 +11,67 @@ Defined in ``xtensor/xrandom.hpp`` .. warning:: xtensor uses a lazy generator for random numbers. You need to assign them or use ``eval`` to keep the generated values consistent. -.. _random-get_default_random_engine-function-reference: .. doxygenfunction:: xt::random::get_default_random_engine :project: xtensor -.. _random-seed-function-reference: .. doxygenfunction:: xt::random::seed :project: xtensor -.. _random-rand-function-reference: .. doxygenfunction:: xt::random::rand(const S&, T, T, E&) :project: xtensor -.. _random-randint-function-reference: .. doxygenfunction:: xt::random::randint(const S&, T, T, E&) :project: xtensor -.. _random-randn-function-reference: .. doxygenfunction:: xt::random::randn(const S&, T, T, E&) :project: xtensor -.. _random-binomial-function-reference: .. doxygenfunction:: xt::random::binomial(const S&, T, D, E&) :project: xtensor -.. _random-geometric-function-reference: .. doxygenfunction:: xt::random::geometric(const S&, D, E&) :project: xtensor -.. _random-negative_binomial-function-reference: .. doxygenfunction:: xt::random::negative_binomial(const S&, T, D, E&) :project: xtensor -.. _random-poisson-function-reference: .. doxygenfunction:: xt::random::poisson(const S&, D, E&) :project: xtensor -.. _random-exponential-function-reference: .. doxygenfunction:: xt::random::exponential(const S&, T, E&) :project: xtensor -.. _random-gamma-function-reference: .. doxygenfunction:: xt::random::gamma(const S&, T, T, E&) :project: xtensor -.. _random-weibull-function-reference: .. doxygenfunction:: xt::random::weibull(const S&, T, T, E&) :project: xtensor -.. _random-extreme_value-function-reference: .. doxygenfunction:: xt::random::extreme_value(const S&, T, T, E&) :project: xtensor -.. _random-lognormal-function-reference: .. doxygenfunction:: xt::random::lognormal(const S&, T, T, E&) :project: xtensor -.. _random-cauchy-function-reference: +.. doxygenfunction:: xt::random::chi_squared(const S&, T, E&) + :project: xtensor + .. doxygenfunction:: xt::random::cauchy(const S&, T, T, E&) :project: xtensor -.. _random-fisher_f-function-reference: .. doxygenfunction:: xt::random::fisher_f(const S&, T, T, E&) :project: xtensor -.. _random-student_t-function-reference: .. doxygenfunction:: xt::random::student_t(const S&, T, E&) :project: xtensor -.. _random-choice-function-reference: .. doxygenfunction:: xt::random::choice(const xexpression&, std::size_t, bool, E&) :project: xtensor .. doxygenfunction:: xt::random::choice(const xexpression&, std::size_t, const xexpression&, bool, E&) :project: xtensor -.. _random-shuffle-function-reference: .. doxygenfunction:: xt::random::shuffle :project: xtensor -.. _random-permutation-function-reference: .. doxygenfunction:: xt::random::permutation(T, E&) :project: xtensor diff --git a/docs/source/build-options.rst b/docs/source/build-options.rst index a3c352680..44b4022e0 100644 --- a/docs/source/build-options.rst +++ b/docs/source/build-options.rst @@ -12,15 +12,15 @@ Build and configuration Configuration ------------- -``xtensor`` can be configured via macros which must be defined *before* including +`xtensor` can be configured via macros which must be defined *before* including any of its headers. This can be achieved the following ways: - either define them in the CMakeLists of your project, with ``target_compile_definitions`` cmake command. - or create a header where you define all the macros you want and then include the headers you - need. Then include this header whenever you need ``xtensor`` in your project. + need. Then include this header whenever you need `xtensor` in your project. -The following macros are already defined in ``xtensor`` but can be overwritten: +The following macros are already defined in `xtensor` but can be overwritten: - ``XTENSOR_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``. @@ -35,8 +35,8 @@ The following macros are already defined in ``xtensor`` but can be overwritten: The following macros are helpers for debugging, they are not defined by default: -- ``XTENSOR_ENABLE_ASSERT``: enables assertions in xtensor, such as bound check. -- ``XTENSOR_ENABLE_CHECK_DIMENSION``: enables the dimensions check in ``xtensor``. Note that this option should not be turned +- ``XTENSOR_ENABLE_ASSERT``: enables assertions in `xtensor`, such as bound check. +- ``XTENSOR_ENABLE_CHECK_DIMENSION``: enables the dimensions check in `xtensor`. Note that this option should not be turned on if you expect ``operator()`` to perform broadcasting. .. _external-dependencies: @@ -47,14 +47,14 @@ External dependencies The last group of macros is for using external libraries to achieve maximum performance (see next section for additional requirements): -- ``XTENSOR_USE_XSIMD``: enables SIMD acceleration in ``xtensor``. This requires that you have xsimd_ installed +- ``XTENSOR_USE_XSIMD``: enables SIMD acceleration in `xtensor`. This requires that you have xsimd_ installed on your system. - ``XTENSOR_USE_TBB``: enables parallel assignment loop. This requires that you have tbb_ installed on your system. - ``XTENSOR_DISABLE_EXCEPTIONS``: disables c++ exceptions. - ``XTENSOR_USE_OPENMP``: enables parallel assignment loop using OpenMP. This requires that OpenMP is available on your system. -Defining these macros in the CMakeLists of your project before searching for ``xtensor`` will trigger automatic finding +Defining these macros in the CMakeLists of your project before searching for `xtensor` will trigger automatic finding of dependencies, so you don't have to include the ``find_package(xsimd)`` and ``find_package(TBB)`` commands in your CMakeLists: diff --git a/docs/source/builder.rst b/docs/source/builder.rst index 418f85087..dd071e9fa 100644 --- a/docs/source/builder.rst +++ b/docs/source/builder.rst @@ -14,68 +14,70 @@ 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 an expression of shape ``(n, n)`` with ones on the k-th diagonal. +- :cpp:func:`xt::zeros(shape) `: generates an expression containing zeros of the specified shape. +- :cpp:func:`xt::ones(shape) `: generates an expression containing ones of the specified shape. +- :cpp:func:`xt::eye(shape, k=0) `: generates an expression of the specified shape, with ones on the k-th diagonal. +- :cpp:func:`xt::eye(n, k = 0) `: generates an expression of shape ``(n, n)`` 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 +- :cpp:func:`xt::arange(start=0, stop, step=1) `: generates numbers evenly spaced within given half-open interval. +- :cpp:func:`xt::linspace(start, stop, num_samples) `: generates num_samples evenly spaced numbers over given interval. +- :cpp:func:`xt::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. -- ``hstack(tuple)``: stacks expressions in sequence horizontally (i.e. column-wise). -- ``vstack(tuple)``: stacks expressions in sequence vertically (i.e. row wise). +- :cpp:func:`xt::concatenate(tuple, axis=0) `: concatenates a list of expressions along the given axis. +- :cpp:func:`xt::stack(tuple, axis=0) `: stacks a list of expressions along the given axis. +- :cpp:func:`xt::hstack(tuple) `: stacks expressions in sequence horizontally (i.e. column-wise). +- :cpp:func:`xt::vstack(tuple) `: stacks expressions in sequence vertically (i.e. row wise). Random distributions -------------------- -.. warning:: xtensor uses a lazy generator for random numbers. You need to assign them or use ``eval`` to keep the generated values consistent. - -- ``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. -- ``binomial(shape, trials, prob)``: generates an expression of the specified shape, containing numbers - sampled from the binomial random number distribution. -- ``geometric(shape, prob)``: generates an expression of the specified shape, containing numbers - sampled from the geometric random number distribution. -- ``negative_binomial(shape, k, prob)``: generates an expression of the specified shape, containing numbers - sampled from the negative binomial random number distribution. -- ``poisson(shape, rate)``: generates an expression of the specified shape, containing numbers - sampled from the Poisson random number distribution. -- ``exponential(shape, rate)``: generates an expression of the specified shape, containing numbers - sampled from the exponential random number distribution. -- ``gamma(shape, alpha, beta)``: generates an expression of the specified shape, containing numbers - sampled from the gamma random number distribution. -- ``weibull(shape, a, b)``: generates an expression of the specified shape, containing numbers - sampled from the Weibull random number distribution. -- ``extreme_value(shape, a, b)``: generates an expression of the specified shape, containing numbers - sampled from the extreme value random number distribution. -- ``lognormal(shape, a, b)``: generates an expression of the specified shape, containing numbers - sampled from the Log-Normal random number distribution. -- ``chi_squared(shape, a, b)``: generates an expression of the specified shape, containing numbers - sampled from the chi-squared random number distribution. -- ``cauchy(shape, a, b)``: generates an expression of the specified shape, containing numbers - sampled from the Cauchy random number distribution. -- ``fisher_f(shape, m, n)``: generates an expression of the specified shape, containing numbers - sampled from the Fisher-f random number distribution. -- ``student_t(shape, n)``: generates an expression of the specified shape, containing numbers - sampled from the Student-t random number distribution. +.. warning:: xtensor uses a lazy generator for random numbers. + You need to assign them or use :cpp:func:`xt::eval` to keep the generated values consistent. + +- :cpp:func:`xt::random::rand(shape, lower, upper) `: generates an expression of the specified + shape, containing uniformly distributed random numbers in the half-open interval [lower, upper). +- :cpp:func:`xt::random::randint(shape, lower, upper) `: generates an expression of the specified + shape, containing uniformly distributed random integers in the half-open interval [lower, upper). +- :cpp:func:`xt::random::randn(shape, mean, std_dev) `: generates an expression of the specified + shape, containing numbers sampled from the Normal random number distribution. +- :cpp:func:`xt::random::binomial(shape, trials, prob) `: generates an expression of the specified + shape, containing numbers sampled from the binomial random number distribution. +- :cpp:func:`xt::random::geometric(shape, prob) `: generates an expression of the specified shape, + containing numbers sampled from the geometric random number distribution. +- :cpp:func:`xt::random::negative_binomial(shape, k, prob) `: generates an expression + of the specified shape, containing numbers sampled from the negative binomial random number distribution. +- :cpp:func:`xt::random::poisson(shape, rate) `: generates an expression of the specified shape, + containing numbers sampled from the Poisson random number distribution. +- :cpp:func:`xt::random::exponential(shape, rate) `: generates an expression of the specified + shape, containing numbers sampled from the exponential random number distribution. +- :cpp:func:`xt::random::gamma(shape, alpha, beta) `: generates an expression of the specified shape, + containing numbers sampled from the gamma random number distribution. +- :cpp:func:`xt::random::weibull(shape, a, b) `: generates an expression of the specified shape, + containing numbers sampled from the Weibull random number distribution. +- :cpp:func:`xt::random::extreme_value(shape, a, b) `: generates an expression of the + specified shape, containing numbers sampled from the extreme value random number distribution. +- :cpp:func:`xt::random::lognormal(shape, a, b) `: generates an expression of the specified + shape, containing numbers sampled from the Log-Normal random number distribution. +- :cpp:func:`xt::random::chi_squared(shape, a, b) `: generates an expression of the specified + shape, containing numbers sampled from the chi-squared random number distribution. +- :cpp:func:`xt::random::cauchy(shape, a, b) `: generates an expression of the specified shape, + containing numbers sampled from the Cauchy random number distribution. +- :cpp:func:`xt::random::fisher_f(shape, m, n) `: generates an expression of the specified shape, + containing numbers sampled from the Fisher-f random number distribution. +- :cpp:func:`xt::random::student_t(shape, n) `: generates an expression of the specified shape, + containing numbers sampled from the Student-t random number distribution. Meshes ------ -- ``meshgrid(x1, x2,...)```: generates N-D coordinate expressions given one-dimensional coordinate arrays ``x1``, ``x2``... +- :cpp:func:`xt::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. diff --git a/docs/source/closure-semantics.rst b/docs/source/closure-semantics.rst index af0de8d34..aa6f2ddda 100644 --- a/docs/source/closure-semantics.rst +++ b/docs/source/closure-semantics.rst @@ -12,8 +12,8 @@ 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. +not hold any value. Values of ``x + y`` are computed upon access or when the result is assigned to a container such as :cpp:type:`xt::xtensor` or +:cpp:type:`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 held by the expressions diff --git a/docs/source/conf.py b/docs/source/conf.py index 87f96b9fa..bb451fa68 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -46,4 +46,5 @@ def setup(app): "numpy": ("https://numpy.org/doc/stable/", None), "scipy": ("https://docs.scipy.org/doc/scipy/reference", None), "xtensor-blas": ("https://xtensor-blas.readthedocs.io/en/stable", None), + "xtl": ("https://xtl.readthedocs.io/en/stable", None), } diff --git a/docs/source/container.rst b/docs/source/container.rst index 5a2f740eb..7b12d0005 100644 --- a/docs/source/container.rst +++ b/docs/source/container.rst @@ -14,15 +14,27 @@ A multi-dimensional array of `xtensor` consists of a contiguous one-dimensional 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 indexing 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 scheme used to map indices into a location in the buffer is a strided indexing 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 multidimensional arrays. This enum can be used in two ways: - -- at compile time, as a template argument. The value ``layout_type::dynamic`` allows specifying any strided index scheme at runtime (including row-major and column-major schemes), while ``layout_type::row_major`` and ``layout_type::column_major`` fixes the strided index scheme and disable ``resize`` and constructor overloads taking a set of strides or a layout value as parameter. The default value of the template parameter is ``XTENSOR_DEFAULT_LAYOUT``. -- at runtime if the previous template parameter was set to ``layout_type::dynamic``. In that case, ``resize`` and constructor overloads allow specifying a set of strides or a layout value to avoid strides computation. If neither strides nor layout is specified when instantiating or resizing a multi-dimensional array, strides corresponding to ``XTENSOR_DEFAULT_LAYOUT`` are used. +`xtensor` provides a :cpp:enum:`xt::layout_type` enum that helps to specify the layout used by multidimensional arrays. +This enum can be used in two ways: + +- at compile time, as a template argument. The value :cpp:enumerator:`xt::layout_type::dynamic` allows specifying any + strided index scheme at runtime (including row-major and column-major schemes), while :cpp:enumerator:`xt::layout_type::row_major` + and :cpp:enumerator:`xt::layout_type::column_major` fixes the strided index scheme and disable + :cpp:func:`resize() ` and constructor overloads taking a set of strides or a layout + value as parameter. + The default value of the template parameter is :c:macro:`XTENSOR_DEFAULT_LAYOUT`. +- at runtime if the previous template parameter was set to :cpp:enumerator:`xt::layout_type::dynamic`. + In that case, :cpp:func:`resize() ` and constructor overloads allow specifying a set of + strides or a layout value to avoid strides computation. + If neither strides nor layout is specified when instantiating or resizing a multi-dimensional array, strides + corresponding to :c:macro:`XTENSOR_DEFAULT_LAYOUT` are used. The following example shows how to initialize a multi-dimensional array of dynamic layout with specified strides: @@ -35,7 +47,8 @@ The following example shows how to initialize a multi-dimensional array of dynam 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 following shortcut to specify the strides instead of computing them: +However, this requires to carefully compute the strides to avoid buffer overflow when accessing elements of the array. +We can use the following shortcut to specify the strides instead of computing them: .. code:: @@ -57,20 +70,23 @@ If the layout of the array can be fixed at compile time, we can make it even sim // this shortcut is equivalent: // xt::xarray a(shape); -However, in the latter case, the layout of the array is forced to ``row_major`` at compile time, and therefore cannot be changed at runtime. +However, in the latter case, the layout of the array is forced to :cpp:enumerator:`xt::layout_type::row_major` at +compile time, and therefore cannot be changed at runtime. Runtime vs Compile-time dimensionality -------------------------------------- -Three container classes implementing multidimensional arrays are provided: ``xarray`` and ``xtensor`` and ``xtensor_fixed``. +Three container classes implementing multidimensional arrays are provided: :cpp:type:`xt::xarray` and +:cpp:type:`xt::xtensor` and :cpp:type:`xt::xtensor_fixed`. -- ``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. -- ``xtensor_fixed`` has a shape fixed at compile time. This allows even more optimizations, such as allocating the storage for the container +- :cpp:type:`xt::xarray` can be reshaped dynamically to any number of dimensions. It is the container that is the most similar to numpy arrays. +- :cpp:type:`xt::xtensor` has a dimension set at compilation time, which enables many optimizations. + For example, shapes and strides of :cpp:type:`xt::xtensor` instances are allocated on the stack instead of the heap. +- :cpp:type:`xt::xtensor_fixed` has a shape fixed at compile time. + This allows even more optimizations, such as allocating the storage for the container on the stack, as well as computing strides and backstrides at compile time, making the allocation of this container extremely cheap. -Let's use ``xtensor`` instead of ``xarray`` in the previous example: +Let's use :cpp:type:`xt::xtensor` instead of :cpp:type:`xt::xarray` in the previous example: .. code:: @@ -82,7 +98,7 @@ Let's use ``xtensor`` instead of ``xarray`` in the previous example: // this is equivalent to // xt::xtensor a(shape); -Or when using ``xtensor_fixed``: +Or when using :cpp:type:`xt::xtensor_fixed`: .. code:: @@ -91,19 +107,24 @@ Or when using ``xtensor_fixed``: xt::xtensor_fixed> a(); // or xt::xtensor_fixed, xt::layout_type::row_major>() -``xarray``, ``xtensor`` and ``xtensor_fixed`` containers are all ``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: +:cpp:type:`xt::xarray`, :cpp:type:`xt::xtensor` and :cpp:type:`xt::xtensor_fixed` containers are all +:cpp:type:`xt::xexpression` s and can be involved and mixed in mathematical expressions, assigned to each +other etc... +They provide an augmented interface compared to other :cpp:type:`xt::xexpression` types: -- Each method exposed in ``xexpression`` interface has its non-const counterpart exposed by ``xarray``, ``xtensor`` and ``xtensor_fixed``. -- ``reshape()`` reshapes the container in place, and the global size of the container has to stay the same. -- ``resize()`` resizes the container in place, that is, if the global size of the container doesn't change, no memory allocation occurs. -- ``strides()`` returns the strides of the container, used to compute the position of an element in the underlying buffer. +- Each method exposed in :cpp:type:`xt::xexpression` interface has its non-const counterpart exposed by + :cpp:type:`xt::xarray`, :cpp:type:`xt::xtensor` and :cpp:type:`xt::xtensor_fixed`. +- :cpp:func:`reshape() ` reshapes the container in place, and the global size of the container has to stay the same. +- :cpp:func:`resize() ` resizes the container in place, that is, if the global size of the container doesn't change, no memory allocation occurs. +- :cpp:func:`strides() ` returns the strides of the container, used to compute the position of an element in the underlying buffer. Reshape ------- -The ``reshape`` method accepts any kind of 1D-container, you don't have to pass an instance of ``shape_type``. It only requires the new shape to be -compatible with the old one, that is, the number of elements in the container must remain the same: +The :cpp:func:`reshape() ` method accepts any kind of 1D-container, you don't have to +pass an instance of ``shape_type``. +It only requires the new shape to be compatible with the old one, that is, the number of elements in the container must +remain the same: .. code:: @@ -119,8 +140,8 @@ compatible with the old one, that is, the number of elements in the container mu // ... which are equivalent to the following a.reshape({2, 4}); -One of the values in the ``shape`` argument can be -1. In this case, the value is inferred from the number of elements in the container and the remaining -values in the ``shape``: +One of the values in the ``shape`` argument can be -1. +In this case, the value is inferred from the number of elements in the container and the remaining values in the ``shape``: .. code:: @@ -132,22 +153,33 @@ values in the ``shape``: 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 expensive than ``xtensor``. Shape and strides of ``xtensor`` are stack-allocated which makes them more efficient. +The dynamic dimensionality of :cpp:type:`xt::xarray` comes at a cost. +Since the dimension is unknown at build time, the sequences holding shape and strides of :cpp:type:`xt::xarray` +instances are heap-allocated, which makes it significantly more expensive than :cpp:type:`xt::xtensor`. +Shape and strides of :cpp:type:`xt::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 the entire broadcasting expression which will have a heap-allocated shape. The same hold for views, broadcast expressions, etc... +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 :cpp:type:`xt::xarray`), +it bubbles up to the 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. A typical case where this happens is when the destination container is involved in the expression and has to be resized. +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. +A typical case where this happens is when the destination container is involved in the expression and has to be resized. 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. +To prevent this, `xtensor` assigns the expression to a temporary variable before copying it. +In the case of :cpp:type:`xt::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: +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:: @@ -178,8 +210,11 @@ The aliasing phenomenon is illustrated in the following example: 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 resized, which impacts how the right-hand side is computed. +In the above example, the shape of ``a + b`` is ``{ 3, 2, 4 }``. +Therefore, ``b`` must first be resized, 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 resize 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. +``new_b(0, i, j) == old_b(i, j) for (i,j) in [0,1] x [0, 3]``. +After the resize 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. diff --git a/docs/source/developer/assignment.rst b/docs/source/developer/assignment.rst index 3b17aead6..0da6eaf79 100644 --- a/docs/source/developer/assignment.rst +++ b/docs/source/developer/assignment.rst @@ -9,14 +9,14 @@ Assignment ========== -In this section, we consider the class ``xarray`` and its semantic bases (``xcontainer_semantic`` and +In this section, we consider the class :cpp:type:`xt::xarray` and its semantic bases (``xcontainer_semantic`` and ``xsemantic_base``) to illustrate how the assignment works. `xtensor` provides different mechanics of assignment depending on the type of expression. Extended copy semantic ~~~~~~~~~~~~~~~~~~~~~~ -``xarray`` provides an extended copy constructor and an extended assignment operator: +:cpp:type:`xt::xarray` provides an extended copy constructor and an extended assignment operator: .. code:: @@ -37,8 +37,8 @@ The assignment operator forwards to ``xsemantic_base::operator=`` whose implemen return this->derived_cast().assign_temporary(std::move(tmp)); } -Here ``temporary_type`` is ``xarray``, the assignment operator computes the result of the expression in -a temporary variable and then assigns it to the ``xarray`` instance. This temporary variable avoids aliasing +Here ``temporary_type`` is :cpp:type:`xt::xarray`, the assignment operator computes the result of the expression in +a temporary variable and then assigns it to the :cpp:type:`xt::xarray` instance. This temporary variable avoids aliasing when the array is involved in the rhs expression where broadcasting happens: .. code:: diff --git a/docs/source/developer/concepts.rst b/docs/source/developer/concepts.rst index 6e55c66cb..dc20401c7 100644 --- a/docs/source/developer/concepts.rst +++ b/docs/source/developer/concepts.rst @@ -19,10 +19,10 @@ dispatching. xexpression ~~~~~~~~~~~ -``xexpression`` is the base class for all expression classes. It is a CRTP base whose template +:cpp:type:`xt::xexpression` is the base class for all expression classes. It is a CRTP base whose template parameter must be the most derived class in the hierarchy. For instance, if ``A`` inherits -from ``B`` which in turn inherits from ``xexpression``, then ``B`` should be a template -class whose template parameter is ``A`` and should forward this parameter to ``xexpression``: +from ``B`` which in turn inherits from :cpp:type:`xt::xexpression`, then ``B`` should be a template +class whose template parameter is ``A`` and should forward this parameter to :cpp:type:`xt::xexpression`: .. code:: @@ -39,7 +39,7 @@ class whose template parameter is ``A`` and should forward this parameter to ``x // ... }; -``xexpression`` only provides three overloads of a same function, that cast an ``xexpression`` +:cpp:type:`xt::xexpression` only provides three overloads of a same function, that cast an :cpp:type:`xt::xexpression` object to the most inheriting type, depending on the nature of the object (*lvalue*, *const lvalue* or *rvalue*): @@ -99,7 +99,7 @@ where ``a`` and ``b`` can be arbitrary types (from `xtensor`, the STL or any ext supporting standard iteration. ``xiterable`` inherits from ``xconst_iterable`` and provides non-const counterpart of methods -defined in ``xconst_iterable``. Like ``xexpression``, both are CRTP classes whose template +defined in ``xconst_iterable``. Like :cpp:type:`xt::xexpression`, both are CRTP classes whose template parameter must be the most derived type. Besides traditional methods for iterating, ``xconst_iterable`` and ``xiterable`` provide overloads @@ -160,7 +160,7 @@ The first overload is meant for computed assignment involving a scalar; it allow We rely on SFINAE to remove this overload from the overload resolution set when the parameter that we want to assign is not a scalar, avoiding ambiguity. -Operator-based methods taking a general ``xexpression`` parameter don't perform a direct assignment. Instead, +Operator-based methods taking a general :cpp:type:`xt::xexpression` parameter don't perform a direct assignment. Instead, the result is assigned to a temporary variable first, in order to prevent issues with aliasing. Thus, if ``a`` and ``b`` are expressions, the following @@ -191,9 +191,9 @@ Temporaries can be avoided with the assign-based methods: derived_type& modulus_assign(const xexpression&); ``xsemantic_base`` is a CRTP class whose parameter must be the most derived type in the hierarchy. It inherits -from ``xexpression`` and forwards its template parameter to this latter one. +from :cpp:type:`xt::xexpression` and forwards its template parameter to this latter one. -``xsemantic_base`` also provides a assignment operator that takes an ``xexpression`` in its protected section: +``xsemantic_base`` also provides a assignment operator that takes an :cpp:type:`xt::xexpression` in its protected section: .. code:: diff --git a/docs/source/developer/implementation_classes.rst b/docs/source/developer/implementation_classes.rst index 803d13390..8fc03d227 100644 --- a/docs/source/developer/implementation_classes.rst +++ b/docs/source/developer/implementation_classes.rst @@ -12,7 +12,7 @@ Requirements An implementation class in `xtensor` is a final class that models a specific kind of expression. It must inherit (either directly or indirectly) from -``xexpression`` and define (or inherit from classes that define) the following +:cpp:type:`xt::xexpression` and define (or inherit from classes that define) the following types: **container types** @@ -129,8 +129,8 @@ inheriting classes only provide constructors and assignment operators for the va The container classes are generally used through type aliases which set many of the template arguments: -- ``xarray`` -- ``xtensor`` +- :cpp:type:`xt::xarray` +- :cpp:type:`xt::xtensor` - ``xfixed_tensor`` The classes for adaptors can be instantiated through the many overloads of ``xt::adapt`` function, @@ -149,7 +149,7 @@ Most of the mehtods of these classes are defined in their base class ``xoptional **Views** -- ``xview``: N-dimensional view with static number of slices, supporting all kind of slices +- :cpp:type:`xt::xview`: N-dimensional view with static number of slices, supporting all kind of slices - ``xstrided_view``: N-dimensional view with dynamic number of slices, supporting strided slices only (see below) - ``xdynamic_view``: N-dimensional view with dynamic number of slices, supporting all kind of slices - ``xfunctor_view``: N-dimensional view applying a functor to its underlying elements (e.g. ``imag``, ``real``) @@ -181,16 +181,16 @@ Contrary to containers and views, the functional expressions are immutable. xarray and xtensor ~~~~~~~~~~~~~~~~~~ -Although they represent different concepts, ``xarray`` and ``xtensor`` have really similar -implementations so only ``xarray`` will be covered. +Although they represent different concepts, :cpp:type:`xt::xarray` and :cpp:type:`xt::xtensor` have really similar +implementations so only :cpp:type:`xt::xarray` will be covered. -``xarray`` is a strided array expression that can be assigned to. Everything ``xarray`` needs -is already defined in classes modeling :ref:`concepts-label`, so ``xarray`` only has to inherit +:cpp:type:`xt::xarray` is a strided array expression that can be assigned to. Everything :cpp:type:`xt::xarray` needs +is already defined in classes modeling :ref:`concepts-label`, so :cpp:type:`xt::xarray` only has to inherit from these classes and define constructors and assignment operators: .. image:: xarray_uml.svg -Besides implementing the methods that define value semantic, ``xarray`` and ``xtensor`` hold +Besides implementing the methods that define value semantic, :cpp:type:`xt::xarray` and :cpp:type:`xt::xtensor` hold the data container. Since the ``xcontainer`` base class implements all the logic for accessing the data, it must me able to access the data container. This is achieved by requiring that every class inheriting from ``xcontainer`` provides the following methods: @@ -201,7 +201,7 @@ every class inheriting from ``xcontainer`` provides the following methods: const storage_type& storage_impl() const noexcept; These are the implementation methods of the ``storage()`` interface methods defined in ``xcontainer``, -and thus are defined in the private section of ``xarray`` and ``xtensor``. In order to grant access +and thus are defined in the private section of :cpp:type:`xt::xarray` and :cpp:type:`xt::xtensor`. In order to grant access to ``xcontainer``, this last one is declared as ``friend``: .. code:: @@ -233,8 +233,8 @@ Although the base classes use the types defined in the Requirement section, they define them; first because different base classes may need the same types and we want to avoid duplication of type definitions. The second reason is that most of the types may rely on other types specific to the implementation classes. For instance, -``value_type``, ``reference``, etc, of ``xarray`` are simply the types defined in the -container type hold by ``xarray``: +``value_type``, ``reference``, etc, of :cpp:type:`xt::xarray` are simply the types defined in the +container type hold by :cpp:type:`xt::xarray`: .. code:: diff --git a/docs/source/expression.rst b/docs/source/expression.rst index 2a08eea24..27692a0c4 100644 --- a/docs/source/expression.rst +++ b/docs/source/expression.rst @@ -11,15 +11,15 @@ 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. +These objects can be in-memory containers such as :cpp:type:`xt::xarray\` and :cpp:type:`xt::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: +The result is an :cpp:type:`xt::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:: @@ -71,8 +71,10 @@ and the size of the data, it might be convenient to store the result of the expr 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 a *rvalue* to a newly allocated container in the case of an 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 a universal reference on the lefthand side (``auto&&``). For example: +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 :cpp:func:`xt::eval` on an xexpression. +Evaluating will either return a *rvalue* to a newly allocated container in the case of an xexpression, or a reference to a container in case you are evaluating a :cpp:type:`xt::xarray` or :cpp:type:`xt::xtensor`. +Note that, in order to avoid copies, you should use a universal reference on the lefthand side (``auto&&``). +For example: .. code:: @@ -86,14 +88,14 @@ Evaluating will either return a *rvalue* to a newly allocated container in the c 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 an elementwise fashion. Broadcasting rules of `xtensor` are -similar to those of Numpy_ and libdynd_. +The number of dimensions of an :cpp:type:`xt::xexpression` and the sizes of these dimensions are provided by the :cpp:func:`~xt::xexpression::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 an 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 broadcast operation with ``A`` and ``B`` has shape ``(4, 2, 3)``. -.. code:: +.. code:: none (2, 3) # A (4, 2, 3) # B @@ -102,7 +104,7 @@ For example, if ``A`` has shape ``(2, 3)``, and ``B`` has shape ``(4, 2, 3)``, t The same rule holds for scalars, which are handled as 0-D expressions. If `A` is a scalar, the equation becomes: -.. code:: +.. code:: none () # A (4, 2, 3) # B @@ -112,7 +114,7 @@ The same rule holds for scalars, which are handled as 0-D expressions. If `A` is 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:: +.. code:: none (2, 3) # A (4, 2, 1) # B @@ -122,7 +124,7 @@ in the previous example, so the broadcasting happens as follows: Accessing elements ------------------ -You can access the elements of any ``xexpression`` with ``operator()``: +You can access the elements of any :cpp:type:`xt::xexpression` with :cpp:func:`~xt::xexpression::operator()()`: .. code:: @@ -134,11 +136,11 @@ You can access the elements of any ``xexpression`` with ``operator()``: double d1 = a(0, 2); double d2 = f(1, 2); -It is possible to call ``operator()`` with fewer or more arguments than the number of dimensions +It is possible to call :cpp:func:`~xt::xexpression::operator()()` with fewer or more arguments than the number of dimensions of the expression: -- if ``operator()`` is called with too many arguments, we drop the most left ones -- if ``operator()`` is called with too few arguments, we prepend them with ``0`` values until +- if :cpp:func:`~xt::xexpression::operator()()` is called with too many arguments, we drop the most left ones +- if :cpp:func:`~xt::xexpression::operator()()` is called with too few arguments, we prepend them with ``0`` values until we match the number of dimensions .. code:: @@ -156,13 +158,13 @@ i.e. commutativity of element access and broadcasting. Expression interface -------------------- -All ``xexpression`` s in `xtensor` provide at least the following interface: +All :cpp:type:`xt::xexpression` s in :cpp:type:`xt::xtensor` provide at least the following interface: Shape ~~~~~ -- ``dimension()`` returns the number of dimensions of the expression. -- ``shape()`` returns the shape of the expression. +- :cpp:func:`~xt::xexpression::dimension`: returns the number of dimensions of the expression. +- :cpp:func:`~xt::xexpression::shape`: returns the shape of the expression. .. code:: @@ -181,12 +183,18 @@ Shape Element access ~~~~~~~~~~~~~~ -- ``operator()`` is an access operator that can take multiple integral arguments or none. -- ``at()`` is similar to ``operator()`` but checks that its number of arguments does not exceed the number of dimensions, and performs bounds checking. This should not be used where you expect ``operator()`` to perform broadcasting. -- ``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 a 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. -- ``periodic()`` is the equivalent of ``operator()`` that can deal with periodic indices (for example ``-1`` for the last item along an axis). -- ``in_bounds()`` returns a ``bool`` that is ``true`` only if indices are valid for the array. +- :cpp:func:`~xt::xexpression::operator()()` is an access operator that can take multiple integral arguments or none. +- :cpp:func:`~xt::xexpression::at` is similar to :cpp:func:`~xt::xexpression::operator()()` but checks that its number + of arguments does not exceed the number of dimensions, and performs bounds checking. + This should not be used where you expect :cpp:func:`~xt::xexpression::operator()()` to perform broadcasting. +- :cpp:func:`~xt::xexpression::operator[]` has two overloads: one that takes a single integral argument and is + equivalent to the call of :cpp:func:`~xt::xexpression::operator()()` with one argument, and one with a single + multi-index argument, which can be of a size determined at runtime. + This operator also supports braced initializer arguments. +- :cpp:func:`~xt::xexpression::element` is an access operator which takes a pair of iterators on a container of indices. +- :cpp:func:`~xt::xexpression::periodic` is the equivalent of :cpp:func:`~xt::xexpression::operator()()` that can deal + with periodic indices (for example ``-1`` for the last item along an axis). +- :cpp:func:`~xt::xexpression::in_bounds` returns a ``bool`` that is ``true`` only if indices are valid for the array. .. code:: @@ -203,12 +211,26 @@ Element access Iterators ~~~~~~~~~ -- ``begin()`` and ``end()`` 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, ``XTENSOR_DEFAULT_TRAVERSAL`` is used. - This iterator pair permits to use algorithms of the STL with ``xexpression`` as if they were simple containers. -- ``begin(shape)`` and ``end(shape)`` are similar but take a *broadcasting shape* as an argument. Elements are iterated upon in ``XTENSOR_DEFAULT_TRAVERSAL`` if no ``layout_type`` template parameter is specified. Certain dimensions are repeated to match the provided shape as per the rules described above. -- ``rbegin()`` and ``rend()`` return instances of ``xiterator`` which can be used to iterate over all the elements of the reversed expression. As ``begin()`` and ``end()``, the layout of the iteration can be specified through the ``layout_type`` parameter. -- ``rbegin(shape)`` and ``rend(shape)`` are the reversed counterpart of ``begin(shape)`` and ``end(shape)``. +- :cpp:func:`~xt::xexpression::begin` and :cpp:func:`~xt::xexpression::end` return instances of :cpp:type:`xt::xiterator` + which can be used to iterate over all the elements of the expression. + The layout of the iteration can be specified through the :cpp:enum:`xt::layout_type` template parameter, accepted values + are :cpp:enumerator:`xt::layout_type::row_major` and :cpp:enumerator:`xt::layout_type::column_major`. + If not specified, :c:macro:`XTENSOR_DEFAULT_TRAVERSAL` is used. + This iterator pair permits to use algorithms of the STL with :cpp:type:`xt::xexpression` as if they were simple containers. +- :cpp:func:`begin(shape) ` and + :cpp:func:`end(shape) ` are similar but take a *broadcasting shape* + as an argument. + Elements are iterated upon in :c:macro:`XTENSOR_DEFAULT_TRAVERSAL` if no :cpp:enum:`xt::layout_type` template parameter + is specified. + Certain dimensions are repeated to match the provided shape as per the rules described above. +- :cpp:func:`~xt::xexpression::rbegin` and :cpp:func:`~xt::xexpression::rend` return instances of :cpp:type:`xt::xiterator` + which can be used to iterate over all the elements of the reversed expression. + As :cpp:func:`~xt::xexpression::begin` and :cpp:func:`~xt::xexpression::end`, the layout of the iteration can be + specified through the :cpp:enum:`xt::layout_type` parameter. +- :cpp:func:`rbegin(shape) ` and + :cpp:func:`rend(shape) ` are the reversed counterpart of + :cpp:func:`begin(shape) ` and + :cpp:func:`end(shape) `. .. _NumPy: http://www.numpy.org .. _libdynd: http://libdynd.org diff --git a/docs/source/external-structures.rst b/docs/source/external-structures.rst index f3f4c52df..23f2a0b49 100644 --- a/docs/source/external-structures.rst +++ b/docs/source/external-structures.rst @@ -27,7 +27,7 @@ In the following example, we define new container and adaptor types for user-spe 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. +These new types will have all the features of the core :cpp:type:`xt::xtensor` and :cpp:type:`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. diff --git a/docs/source/file_loading.rst b/docs/source/file_loading.rst index fab07ebc7..9b413806a 100644 --- a/docs/source/file_loading.rst +++ b/docs/source/file_loading.rst @@ -7,19 +7,19 @@ File input and output ===================== -``xtensor`` has some built-in mechanisms to make loading and saving data easy. -The base xtensor package allows to save and load data in the ``.csv``, ``.json`` and ``.npy`` +`xtensor` has some built-in mechanisms to make loading and saving data easy. +The base `xtensor` package allows to save and load data in the ``.csv``, ``.json`` and ``.npy`` format. Please note that many more input and output formats are available in the `xtensor-io `_ package. -``xtensor-io`` offers functions to load and store from image files (``jpg``, ``gif``, ``png``...), +`xtensor-io` offers functions to load and store from image files (``jpg``, ``gif``, ``png``...), sound files (``wav``, ``ogg``...), HDF5 files (``h5``, ``hdf5``, ...), and compressed numpy format (``npz``). Loading CSV data into xtensor ----------------------------- -The following example code demonstrates how to use ``load_csv`` and ``dump_csv`` to load and +The following example code demonstrates how to use :cpp:func:`xt::load_csv` and :cpp:func:`xt::dump_csv` to load and save data in the Comma-separated value format. The reference documentation is :doc:`api/xcsv`. .. code:: @@ -33,11 +33,11 @@ save data in the Comma-separated value format. The reference documentation is :d int main() { - ifstream in_file; + std::ifstream in_file; in_file.open("in.csv"); auto data = xt::load_csv(in_file); - ofstream out_file; + std::ofstream out_file; out_file("out.csv"); xt::xarray a = {{1,2,3,4}, {5,6,7,8}}; @@ -50,7 +50,7 @@ Loading NPY data into xtensor ----------------------------- The following example demonstrates how to load and store xtensor data in the ``npy`` "NumPy" format, -using the ``load_npy`` and ``dump_npy`` functions. +using the :cpp:func:`xt::load_npy` and :cpp:func:`xt::dump_npy` functions. Reference documentation for the functions used is found here :doc:`api/xnpy`. .. code:: @@ -78,7 +78,7 @@ Loading JSON data into xtensor ------------------------------ It's possible to load and dump data to json, using the json library written by -``nlohmann`` (https://nlohmann.github.io/json/) which offers a convenient way +`nlohmann` (https://nlohmann.github.io/json/) which offers a convenient way to handle json data in C++. Note that the library needs to be separately installed. The reference documentation is found :doc:`api/xjson`. @@ -102,5 +102,5 @@ The reference documentation is found :doc:`api/xjson`. xt::xarray res; auto j = "[[10.0,10.0],[10.0,10.0]]"_json; - from_json(j, res); + xt::from_json(j, res); } diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 4ced4b104..4bccfffb8 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -214,7 +214,7 @@ Outputs: Fourth example: broadcasting ---------------------------- -This last example shows how to broadcast the ``xt::pow`` universal function: +This last example shows how to broadcast the :cpp:func:`xt::pow` universal function: .. code:: diff --git a/docs/source/histogram.rst b/docs/source/histogram.rst index e2f983ebc..f7796ce04 100644 --- a/docs/source/histogram.rst +++ b/docs/source/histogram.rst @@ -12,23 +12,21 @@ Histogram Basic usage ----------- -.. note:: - - .. code-block:: cpp - - xt::histogram(a, bins[, weights][, density]) - xt::histogram_bin_edges(a[, weights][, left, right][, bins][, mode]) +* :cpp:func:`xt::histogram(a, bins[, weights][, density]) ` +* :cpp:func:`xt::histogram_bin_edges(a[, weights][, left, right][, bins][, mode]) ` +.. note:: Any of the options ``[...]`` can be omitted (though the order must be preserved). The defaults are: - * ``weights = xt::ones(data.shape())`` - * ``density = false`` - * ``left = xt::amin(data)(0)`` - * ``right = xt::amax(data)(0)`` - * ``bins = 10`` - * ``mode = xt::histogram::automatic`` + * ``weights`` = :cpp:func:`xt::ones(data.shape()) ` + * ``density`` = ``false`` + * ``left`` = :cpp:func:`xt::amin(data)(0) ` + * ``right`` = :cpp:func:`Xt::amax(data)(0) ` + * ``bins`` = ``10`` + * ``mode`` = :cpp:enumerator:`xt::histogram::automatic` -The behavior, in-, and output of ``histogram`` is similar to that of :any:`numpy.histogram` with that difference that the bin-edges are obtained by a separate function call: +The behavior, in-, and output of :cpp:func:`xt::histogram` is similar to that of :any:`numpy.histogram` +with that difference that the bin-edges are obtained by a separate function call: .. code-block:: cpp @@ -50,7 +48,8 @@ The behavior, in-, and output of ``histogram`` is similar to that of :any:`numpy Bin-edges algorithm ------------------- -To customize the algorithm to be used to construct the histogram, one needs to make use of the latter ``histogram_bin_edges``. For example: +To customize the algorithm to be used to construct the histogram, one needs to make use of the latter +:cpp:func:`xt::histogram_bin_edges`. For example: .. code-block:: cpp @@ -72,12 +71,10 @@ To customize the algorithm to be used to construct the histogram, one needs to m return 0; } -The following algorithms are available: - -* ``automatic``: equivalent to ``linspace``. - -* ``linspace``: linearly spaced bin-edges. - -* ``logspace``: bins that logarithmically increase in size. +The following :cpp:enum:`xt::histogram_algorithm` are available: -* ``uniform``: bin-edges such that the number of data points is the same in all bins (as much as possible). +* :cpp:enumerator:`~xt::histogram_algorithm::automatic`: equivalent to :cpp:enumerator:`~xt::histogram_algorithm::linspace`. +* :cpp:enumerator:`~xt::histogram_algorithm::linspace`: linearly spaced bin-edges. +* :cpp:enumerator:`~xt::histogram_algorithm::logspace`: bins that logarithmically increase in size. +* :cpp:enumerator:`~xt::histogram_algorithm::uniform`: bin-edges such that the number of data points is + the same in all bins (as much as possible). diff --git a/docs/source/indices.rst b/docs/source/indices.rst index 3273954c2..c9e9908ff 100644 --- a/docs/source/indices.rst +++ b/docs/source/indices.rst @@ -43,8 +43,8 @@ Operators: array index An *array index* can be specified to an operators by a sequence of numbers. To this end the following operators are at your disposal: -``operator()(args...)`` -^^^^^^^^^^^^^^^^^^^^^^^ +:cpp:func:`operator()(args...) ` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Example: ``a(1, 2) == 6``. * See also: :cpp:func:`xt::xcontainer::operator()`. @@ -62,27 +62,27 @@ specified by an *array index* given by a number of unsigned integers. * To post-pad an arbitrary number of zeros use ``xt::missing`` (example ``a(2, xt::missing) == a(2, 0) == 8``. -``at(args...)`` -^^^^^^^^^^^^^^^ +:cpp:func:`at(args...) ` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Example: ``a.at(1, 2) == 6``. * See also: :cpp:func:`xt::xcontainer::at`. -Same as ``operator()``: +Same as :cpp:func:`~xt::xcontainer::operator()`: Returns a (constant) reference to the element, specified by an *array index* given by a number of unsigned integers. -``unchecked(args...)`` -^^^^^^^^^^^^^^^^^^^^^^ +:cpp:func:`unchecked(args...) ` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Example: ``a.unchecked(1, 2) == 6``. * See also: :cpp:func:`xt::xcontainer::unchecked`. Returns a (constant) reference to the element, specified by an *array index* given by a number of unsigned integers. -Different than ``operator()`` there are no bounds checks (even when assertions) are turned on, -and the number of indices is assumed to match the dimension of the array. -``unchecked`` is thus aimed at performance. +Different than :cpp:func:`~xt::xcontainer::operator()` there are no bounds checks (even when assertions) +are turned on, and the number of indices is assumed to match the dimension of the array. +:cpp:func:`~xt::xcontainer::unchecked` is thus aimed at performance. .. note:: @@ -90,8 +90,8 @@ and the number of indices is assumed to match the dimension of the array. post-pad zeros if you specify less indices than the rank of the array. Example: ``a.unchecked(1) == a(1, 0)``. -``periodic(args...)`` -^^^^^^^^^^^^^^^^^^^^^ +:cpp:func:`periodic(args...) ` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Example: ``a.periodic(-1, -2) == 7``. * See also: :cpp:func:`xt::xcontainer::periodic`. @@ -103,16 +103,16 @@ For example, for the first axis: ``-1 -> a.shape(0) - 1 = 2``, likewise for example ``3 -> 3 - a.shape(0) = 0``. Of course this comes as the cost of some extra complexity. -``in_bounds(args...)`` -^^^^^^^^^^^^^^^^^^^^^^ +:cpp:func:`in_bounds(args...) ` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Example: ``a.in_bounds(1, 2) == true``. * See also: :cpp:func:`xt::xcontainer::in_bounds`. Check if the *array index* is 'in bounds', return ``false`` otherwise. -``operator[]({...})`` -^^^^^^^^^^^^^^^^^^^^^^ +:cpp:func:`operator[]({...}) ` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Example: ``a[{1, 2}] == 6``. * See also: :cpp:func:`xt::xcontainer::operator[]`. @@ -123,8 +123,8 @@ specified by an *array index* given by a list of unsigned integers. Operators: flat index --------------------- -``flat(i)`` -^^^^^^^^^^^ +:cpp:func:`flat(i) ` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Example: ``a.flat(6) == 6``. * See also: :cpp:func:`xt::xcontainer::flat`. @@ -144,7 +144,8 @@ given an unsigned integer. Array indices ------------- -Functions like ``xt::argwhere(a < 5)`` return a ``std::vector`` of *array indices*. Using the same matrix as above, we can do +Functions like :cpp:func:`xt::argwhere(a \< 5) ` return a ``std::vector`` of *array indices*. +Using the same matrix as above, we can do .. code-block:: cpp @@ -170,12 +171,15 @@ which prints {2, 2}, {2, 3}} -To print the ``std::vector``, it is converted to a ``xt::xtensor`` array, which is done using ``xt::from_indices``. +To print the ``std::vector``, it is converted to a :cpp:type:`xt::xtensor\ ` +array, which is done using :cpp:func:`xt::from_indices`. From array indices to flat indices ---------------------------------- -To convert the array indices to a ``xt::xtensor`` of flat indices, ``xt::ravel_indices`` can be used. For the same example: +To convert the array indices to a :cpp:type:`xt::xtensor\ ` of flat indices, +:cpp:func:`xt::ravel_indices` can be used. +For the same example: .. code-block:: cpp @@ -211,7 +215,10 @@ which prints 1-D arrays: array indices == flat indices ----------------------------------------- -For 1-D arrays the array indices and flat indices coincide. One can use the generic functions ``xt::flatten_indices`` to get a ``xt::xtensor`` of (array/flat) indices. For example: +For 1-D arrays the array indices and flat indices coincide. +One can use the generic functions :cpp:func:`xt::flatten_indices` to get a +:cpp:type:`xt::xtensor\ ` of (array/flat) indices. +For example: .. code-block:: cpp @@ -240,7 +247,8 @@ which prints the indices and the selection (which are in this case identical): From flat indices to array indices ---------------------------------- -To convert *flat indices* to *array_indices* the function ``xt::unravel_indices`` can be used. For example +To convert *flat indices* to *array_indices* the function :cpp:func:`xt::unravel_indices` can be used. +For example .. code-block:: cpp @@ -277,4 +285,5 @@ which prints {2, 2}, {2, 3}} -Notice that once again the function ``xt::from_indices`` has been used to convert a ``std::vector`` of indices to a ``xt::xtensor`` array for printing. +Notice that once again the function :cpp:func:`xt::from_indices` has been used to convert a +``std::vector`` of indices to a :cpp:type:`xt::xtensor` array for printing. diff --git a/docs/source/missing.rst b/docs/source/missing.rst index 4d9f0677e..892a36bc6 100644 --- a/docs/source/missing.rst +++ b/docs/source/missing.rst @@ -7,17 +7,18 @@ Missing values ============== -``xtensor`` handles missing values and provides specialized container types for an optimized support of missing values. +`xtensor` handles missing values and provides 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: +Support of missing values in xtensor is primarily provided through the :cpp:type:`xtl::xoptional` +value type and the :cpp:type:`xt::xtensor_optional` and :cpp:type:`xt::xarray_optional` containers. +In the following example, we instantiate a 2-D tensor with a missing value: .. code:: cpp - xtensor_optional m + xt::xtensor_optional m {{ 1.0 , 2.0 }, { 3.0 , missing() }}; @@ -25,16 +26,19 @@ This code is semantically equivalent to .. code:: cpp - xtensor, 2> m + xt::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 :cpp:type:`xt::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. +The :cpp:type:`xt::xtensor_optional::reference` typedef, which is the return type of +:cpp:func:`~xt::xexpression::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 :cpp:type:`xtl::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. @@ -47,11 +51,11 @@ same way as regular scalars. .. code:: cpp - xtensor_optional a + xt::xtensor_optional a {{ 1.0 , 2.0 }, { 3.0 , missing() }}; - xtensor b + xt::xtensor b { 1.0, 2.0 }; // `b` is broadcasted to match the shape of `a` @@ -67,23 +71,25 @@ outputs: Optional assemblies ------------------- -The classes ``xoptional_assembly`` and ``xoptional_assembly_adaptor`` provide containers and adaptors holding missing values that are optimized -for element-wise operations. -Contrary to ``xtensor_optional`` and ``xarray_optional``, the optional assemblies hold two expressions, one holding the values, the other holding -the mask for the missing values. The difference between ``xoptional_assembly`` and ``xoptional_assembly_adaptor`` is that the first one is the owner -of the two expressions while the last one holds a reference on at least one of the two expressions. +The classes :cpp:type:`xt::xoptional_assembly` and :cpp:type:`xt::xoptional_assembly_adaptor` provide +containers and adaptors holding missing values that are optimized for element-wise operations. +Contrary to :cpp:type:`xt::xtensor_optional` and :cpp:type:`xt::xarray_optional`, the optional +assemblies hold two expressions, one holding the values, the other holding the mask for the missing values. +The difference between :cpp:type:`xt::xoptional_assembly` and :cpp:type:`xt::xoptional_assembly_adaptor` +is that the first one is the owner of the two expressions while the last one holds a reference on at least +one of the two expressions. .. code:: cpp - xarray v + xt::xarray v {{ 1.0, 2.0 }, { 3.0, 4.0 }}; - xarray hv + xt::xarray hv {{ true, true }, { true, false }}; - xoptional_assembly, xarray> assembly(v, hv); + xt::xoptional_assembly, xt::xarray> assembly(v, hv); std::cout << assembly << std::endl; outputs: @@ -96,16 +102,19 @@ outputs: 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. +Functions :cpp:func:`xt::has_value(E&& e) ` and :cpp:func:`xt::value(E&& e) ` +return expressions corresponding to the underlying value and flag of optional elements. +When ``e`` is an lvalue, :cpp:func:`xt::has_value(E&& e) ` and +:cpp:func:`xt::value(E&& e) ` are lvalues too. .. code:: cpp - xtensor_optional a + xt::xtensor_optional a {{ 1.0 , 2.0 }, { 3.0 , missing() }}; - xtensor b = has_value(a); + xt::xtensor b = xt::has_value(a); std::cout << b << std::endl; diff --git a/docs/source/operator.rst b/docs/source/operator.rst index b6c2566e6..695ba26d2 100644 --- a/docs/source/operator.rst +++ b/docs/source/operator.rst @@ -11,15 +11,15 @@ Arithmetic operators -------------------- `xtensor` provides overloads of traditional arithmetic operators for -``xexpression`` objects: +:cpp:type:`xt::xexpression` objects: -- unary ``operator+`` -- unary ``operator-`` -- ``operator+`` -- ``operator-`` -- ``operator*`` -- ``operator/`` -- ``operator%`` +- unary :cpp:func:`~xt::xexpression::operator+` +- unary :cpp:func:`~xt::xexpression::operator-` +- :cpp:func:`~xt::xexpression::operator+` +- :cpp:func:`~xt::xexpression::operator-` +- :cpp:func:`~xt::xexpression::operator*` +- :cpp:func:`~xt::xexpression::operator/` +- :cpp:func:`~xt::xexpression::operator%` All these operators are element-wise operators and apply the lazy broadcasting rules explained in a previous section. @@ -39,20 +39,20 @@ Logical operators `xtensor` also provides overloads of the logical operators: -- ``operator!`` -- ``operator||`` -- ``operator&&`` +- :cpp:func:`~xt::xexpression::operator!` +- :cpp:func:`~xt::xexpression::operator||` +- :cpp:func:`~xt::xexpression::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 elements of ``e`` are truthy, ``false`` otherwise. +- :cpp:func:`xt::any(E&& e) ` returns ``true`` if any of ``e`` elements is truthy, ``false`` otherwise. +- :cpp:func:`xt::all(E&& e) ` returns ``true`` if all elements of ``e`` are truthy, ``false`` otherwise. and an element-wise ternary function (similar to the ``: ?`` ternary operator): -- ``where(E&& b, E1&& e1, E2&& e2)`` returns an ``xexpression`` whose elements +- :cpp:func:`xt::where(E&& b, E1&& e1, E2&& e2) ` returns an :cpp:type:`xt::xexpression` whose elements are those of ``e1`` when corresponding elements of ``b`` are truthy, and those of ``e2`` otherwise. @@ -67,7 +67,7 @@ and an element-wise ternary function (similar to the ``: ?`` ternary operator): xt::xarray res = xt::where(b, a1, a2); // => res = { 11, 2, 3, 14 } -Unlike in :any:`numpy.where`, ``xt::where`` takes full advantage of the lazyness +Unlike in :any:`numpy.where`, :cpp:func:`xt::where` takes full advantage of the lazyness of `xtensor`. Comparison operators @@ -75,14 +75,14 @@ Comparison operators `xtensor` provides overloads of the inequality operators: -- ``operator<`` -- ``operator<=`` -- ``operator>`` -- ``operator>=`` +- :cpp:func:`~xt::xexpression::operator\<` +- :cpp:func:`~xt::xexpression::operator\<=` +- :cpp:func:`~xt::xexpression::operator\>` +- :cpp:func:`~xt::xexpression::operator\>=` These overloads of inequality operators are quite different from the standard C++ inequality operators: they are element-wise operators returning boolean -``xexpression``: +:cpp:type:`xexpression`: .. code:: @@ -95,10 +95,12 @@ C++ inequality operators: they are element-wise operators returning boolean 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. +- :cpp:func:`operator==(const E1& e1, const E2& e2) ` returns ``true`` if ``e1`` + and ``e2`` hold the same elements. +- :cpp:func:`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`` +Element-wise equality comparison can be achieved through the :cpp:func:`xt::equal` function. .. code:: @@ -119,24 +121,24 @@ Bitwise operators `xtensor` also contains the following bitwise operators: -- Bitwise and: ``operator&`` -- Bitwise or: ``operator|`` -- Bitwise xor: ``operator^`` -- Bitwise not: ``operator~`` -- Bitwise left/right shift: ``left_shift``, ``right_shift`` +- Bitwise and: :cpp:func:`~xt::xexpression::operator&` +- Bitwise or: :cpp:func:`~xt::xexpression::operator|` +- Bitwise xor: :cpp:func:`~xt::xexpression::operator^` +- Bitwise not: :cpp:func:`~xt::xexpression::operator~` +- Bitwise left/right shift: :cpp:func:`~xt::xexpression::left_shift`, :cpp:func:`~xt::xexpression::right_shift` 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``, ... +- basic functions: :cpp:func:`xt::abs`, :cpp:func:`xt::remainder`, :cpp:func:`xt::fma`, ... +- exponential functions: :cpp:func:`xt::exp`, :cpp:func:`xt::expm1`, :cpp:func:`xt::log`, :cpp:func:`xt::log1p`, ... +- power functions: :cpp:func:`xt::pow`, :cpp:func:`xt::sqrt`, :cpp:func:`xt::cbrt`, ... +- trigonometric functions: :cpp:func:`xt::sin`, :cpp:func:`xt::cos`, :cpp:func:`xt::tan`, ... +- hyperbolic functions: :cpp:func:`xt::sinh`, :cpp:func:`xt::cosh`, :cpp:func:`xt::tanh`, ... +- Error and gamma functions: :cpp:func:`xt::erf`, :cpp:func:`xt::erfc`, :cpp:func:`xt::tgamma`, :cpp:func:`xt::lgamma`, .... +- Nearest integer floating point operations: :cpp:func:`xt::ceil`, :cpp:func:`xt::floor`, :cpp:func:`xt::trunc`, ... See the API reference for a comprehensive list of available functions. Like operators, the mathematical functions are element-wise functions and apply the @@ -147,7 +149,7 @@ Casting `xtensor` will implicitly promote and/or cast tensor expression elements as needed, which suffices for most use-cases. But explicit casting can be -performed via ``cast``, which performs an element-wise ``static_cast``. +performed via :cpp:func:`xt::cast`, which performs an element-wise ``static_cast``. .. code:: @@ -166,7 +168,7 @@ 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 +:cpp:type:`xt::xexpression` with the same shape as the input expression, with the specified axes removed. .. code:: @@ -179,7 +181,7 @@ axes removed. // => res.shape() = { 3, 4, 5 }; // => res(0, 0, 0) = 12 -You can also call the ``reduce`` generator with your own reducing function: +You can also call the :cpp:func:`xt::reduce` generator with your own reducing function: .. code:: @@ -191,9 +193,9 @@ You can also call the ``reduce`` generator with your own reducing function: arr, {1, 3}); -The reduce generator also accepts a ``xreducer_functors`` object, a tuple of three functions -(one for reducing, one for initialization and one for merging). A generator is provided to -build the ``xreducer_functors`` object, the last function can be omitted: +The reduce generator also accepts a :cpp:type:`xt::xreducer_functors` object, a tuple of three functions +(one for reducing, one for initialization and one for merging). +A generator is provided to build the :cpp:type:`xt::xreducer_functors` object, the last function can be omitted: .. code:: @@ -218,8 +220,8 @@ the evaluation and get the result: xt::xarray arr = some_init_function({3, 2, 4, 6, 5}); double res = xt::reduce([](double a, double b) { return a*a + b*b; }, arr)(); -The ``value_type`` of a reducer is the traditional result type of the reducing operation. For instance, -the ``value_type`` of the reducer for the sum is: +The ``value_type`` of a reducer is the traditional result type of the reducing operation. +For instance, the ``value_type`` of the reducer for the sum is: - ``int`` if the underlying expression holds ``int`` values - ``int`` if the underlying expression holds ``short`` values, because ``short + short`` = ``int`` @@ -237,14 +239,14 @@ computation: auto s1 = xt::sum(arr); // No effect, short + int = int auto s2 = xt::sum(arr); // The value_type of s2 is long int -When you write generic code and you want to limit overflows, you can use ``xt::big_promote_value_type_t`` +When you write generic code and you want to limit overflows, you can use :cpp:any:`xt::big_promote_value_type_t` as shown below: .. code:: #include #include - + template void my_computation(E&& e) { @@ -255,10 +257,10 @@ Accumulators ------------ Similar to reducers, `xtensor` provides accumulators which are used to -implement cumulative functions such as ``cumsum`` or ``cumprod``. Accumulators +implement cumulative functions such as :cpp:func:`xt::cumsum` or :cpp:func:`xt::cumprod`. Accumulators can currently only work on a single axis. Additionally, the accumulators are -not lazy and do not return an xexpression, but rather an evaluated ``xarray`` -or ``xtensor``. +not lazy and do not return an xexpression, but rather an evaluated :cpp:type:`xt::xarray` +or :cpp:type:`xt::xtensor`. .. code:: @@ -271,7 +273,7 @@ or ``xtensor``. // => res(0, 0, 0) = 1 // => res(0, 7, 0) = 8 -You can also call the ``accumumulate`` generator with your own accumulating +You can also call the :cpp:func:`xt::accumulate` generator with your own accumulating function. For example, the implementation of cumsum is as follows: .. code:: @@ -310,9 +312,10 @@ lot of CPU cycles. Additionally, *greedy* execution can benefit from SIMD acceleration over reduction axes and is faster when the entire result needs to be computed. -Therefore, xtensor allows to select an ``evaluation_strategy``. Currently, two -evaluation strategies are implemented: ``evaluation_strategy::immediate`` and -``evaluation_strategy::lazy``. When ``immediate`` evaluation is selected, the +Therefore, xtensor allows to select an :cpp:enum:`xt::evaluation_strategy`. Currently, two +evaluation strategies are implemented: :cpp:enumerator:`xt::evaluation_strategy::immediate` and +:cpp:enumerator:`xt::evaluation_strategy::lazy`. +When :cpp:enumerator:`~xt::evaluation_strategy::immediate` evaluation is selected, the return value is not an xexpression, but an in-memory datastructure such as a xarray or xtensor (depending on the input values). @@ -328,20 +331,20 @@ Choosing an evaluation_strategy is straightforward. For reducers: // or select the default: // auto res = xt::sum(a, {1, 3}, xt::evaluation_strategy::lazy); -Note: for accumulators, only the ``immediate`` evaluation strategy is currently -implemented. +Note: for accumulators, only the :cpp:enumerator:`~xt::evaluation_strategy::immediate` evaluation +strategy is currently implemented. 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. +:cpp:type:`xt::xexpression` s, applying the lazy broadcasting rules which we described in a +previous section. These functions are called :cpp:type:`xt::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. +mathematical functions we described before are :cpp:type:`xt::xfunction` s. The following snippet shows how to vectorize a scalar function taking two arguments: diff --git a/docs/source/pitfall.rst b/docs/source/pitfall.rst index 6e40218f0..860773765 100644 --- a/docs/source/pitfall.rst +++ b/docs/source/pitfall.rst @@ -22,13 +22,13 @@ It is strictly equivalent to xt::xarray a = {1, 3, 4, 2}; -To initialize a 4D-array with the given shape, use the ``from_shape`` static method: +To initialize a 4D-array with the given shape, use the :cpp:func:`xt::xarray::from_shape` static method: .. code:: auto a = xt::xarray::from_shape({1, 3, 4, 2}); -The confusion often comes from the way ``xtensor`` can be initialized: +The confusion often comes from the way :cpp:type:`xt::xtensor` can be initialized: .. code:: @@ -61,7 +61,7 @@ be tempted to simplify it a bit: return (1 - tmp) / (1 + tmp); } -Unfortunately, you introduced a bug; indeed, expressions in ``xtensor`` are not evaluated +Unfortunately, you introduced a bug; indeed, expressions in `xtensor` are not evaluated immediately, they capture their arguments by reference or copy depending on their nature, for future evaluation. Since ``tmp`` is an lvalue, it is captured by reference in the last statement; when the function returns, ``tmp`` is destroyed, leading to a dangling reference @@ -85,20 +85,19 @@ generator does not give the same random number if called twice. // a0 != a1 !!! -You need to explicitly assign or eval a random number generator, -like so: +You need to explicitly assign or eval a random number generator, like so: .. code:: xt::xarray xr = xt::random::rand({10, 10}); - auto xr2 = eval(xt::random::rand({10, 10})); + auto xr2 = xt::eval(xt::random::rand({10, 10})); // now xr(0, 0) == xr(0, 0) is true. variance arguments ------------------ -When ``variance`` is passed an expression and an integer parameter, this latter +When :cpp:func:`xt::variance` is passed an expression and an integer parameter, this latter is not the axis along which the variance must be computed, but the degree of freedom: .. code:: @@ -118,7 +117,7 @@ If you want to specify an axis, you need to pass an initializer list: fixed_shape on Windows ---------------------- -Builder functions such as ``empty`` or ``ones`` accept an initializer list +Builder functions such as :cpp:func:`xt::empty` or :cpp:func:`xt::ones` accept an initializer list as argument. If the elements of this list do not have the same type, a curious compilation error may occur on Windows: @@ -140,7 +139,7 @@ Alignment of fixed-size members If you are using ``C++ >= 17`` you should not have to worry about this. -When building with ``xsimd`` (see :ref:`external-dependencies`), if you define a structure +When building with `xsimd` (see :ref:`external-dependencies`), if you define a structure having members of fixed-size xtensor types, you must ensure that the buffers properly aligned. For this you can use the macro ``XTENSOR_FIXED_ALIGN`` available in ``xtensor/xtensor_config.hpp``. diff --git a/docs/source/quickref/basic.rst b/docs/source/quickref/basic.rst index a70b5f784..1d8cb83f8 100644 --- a/docs/source/quickref/basic.rst +++ b/docs/source/quickref/basic.rst @@ -18,7 +18,7 @@ Tensor types .. note:: Except if mentioned otherwise, the methods described below are available for the - three kinds of containers, even if the examples show ``xarray`` usage only. + three kinds of containers, even if the examples show :cpp:type:`xt::xarray` usage only. Initialization -------------- @@ -107,7 +107,7 @@ Print the shape Reshape ------- -The number of elements of an ``xarray`` must remain the same: +The number of elements of an :cpp:type:`xt::xarray` must remain the same: .. code:: @@ -116,7 +116,7 @@ The number of elements of an ``xarray`` must remain the same: std::cout << a0 << std::endl; // outputs {{1., 2., 3.}, {4., 5., 6. }} -For ``xtensor`` the number of elements and the number of dimensions +For :cpp:type:`xt::xtensor` the number of elements and the number of dimensions must remain the same: .. code:: @@ -151,7 +151,7 @@ Resize xt::xarray a0 = {1., 2., 3, 4.}; a0.resize({2, 3}); -When resizing an ``xtensor`` object, the number of dimensions must remain +When resizing an :cpp:type:`xt::xtensor` object, the number of dimensions must remain the same: .. code:: diff --git a/docs/source/quickref/chunked_arrays.rst b/docs/source/quickref/chunked_arrays.rst index 119086638..c7e0e9ebb 100644 --- a/docs/source/quickref/chunked_arrays.rst +++ b/docs/source/quickref/chunked_arrays.rst @@ -11,7 +11,7 @@ Motivation ---------- Arrays can be very large and may not fit in memory. In this case, you may not be -able to use an in-memory array such as an ``xarray``. A solution to this problem +able to use an in-memory array such as an :cpp:type:`xt::xarray`. A solution to this problem is to cut up the large array into many small arrays, called chunks. Not only do the chunks fit comfortably in memory, but this also allows to process them in parallel, including in a distributed environment (although this is not supported @@ -55,7 +55,7 @@ use the `chunked_array` factory function: a(3, 9, 2) = 1.; // this will address the chunk of index (1, 3, 0) // and in this chunk, the element of index (1, 0, 2) -Chunked arrays implement the full semantic of ``xarray``, including lazy +Chunked arrays implement the full semantic of :cpp:type:`xt::xarray`, including lazy evaluation. Stored chunked arrays diff --git a/docs/source/quickref/math.rst b/docs/source/quickref/math.rst index d3be052e0..5087761a4 100644 --- a/docs/source/quickref/math.rst +++ b/docs/source/quickref/math.rst @@ -9,7 +9,7 @@ Mathematical functions Operations and functions of ``xtensor`` are not evaluated until they are assigned. In the following, ``e1``, ``e2`` and ``e3`` can be arbitrary tensor expressions. -The results of operations and functions are assigned to ``xt::xarray`` in the examples, +The results of operations and functions are assigned to :cpp:type:`xt::xarray` in the examples, but that could be any other container (or even views). To keep an unevaluated operator / function, assign to an ``auto`` variable: diff --git a/docs/source/quickref/operator.rst b/docs/source/quickref/operator.rst index adecd9799..04c58e8a9 100644 --- a/docs/source/quickref/operator.rst +++ b/docs/source/quickref/operator.rst @@ -9,7 +9,7 @@ Operators Operations and functions of ``xtensor`` are not evaluated until they are assigned. In the following, ``e1``, ``e2`` and ``e3`` can be arbitrary tensor expressions. -The results of operations and functions are assigned to ``xt::xarray`` in the examples, +The results of operations and functions are assigned to :cpp:type:`xt::xarray` in the examples, but that could be any other container (or even views). To keep an unevaluated operator / function, assign to an ``auto`` variable: diff --git a/docs/source/random.rst b/docs/source/random.rst index ab8dfad04..69e51384a 100644 --- a/docs/source/random.rst +++ b/docs/source/random.rst @@ -10,10 +10,8 @@ Random ****** -xt::random::seed -================ - -:ref:`xt::random::seed ` +:cpp:func:`xt::random::seed` +============================ Set seed for random number generator. A common practice to get a 'real' random number is to use: @@ -25,50 +23,32 @@ Set seed for random number generator. A common practice to get a 'real' random n xt::random::seed(time(NULL)); -xt::random::rand -================ - -:ref:`xt::random::rand ` - -xt::random::randint -=================== - -:ref:`xt::random::randint ` - -xt::random::randn -================= +:cpp:func:`xt::random::rand` +============================ -:ref:`xt::random::randn ` +:cpp:func:`xt::random::randint` +=============================== -xt::random::binomial -==================== - -:ref:`xt::random::binomial ` - -xt::random::geometric -===================== - -:ref:`xt::random::geometric ` - -xt::random::negative_binomial +:cpp:func:`xt::random::randn` ============================= -:ref:`xt::random::negative_binomial ` - -xt::random::poisson -=================== +:cpp:func:`xt::random::binomial` +================================ -:ref:`xt::random::poisson ` +:cpp:func:`xt::random::geometric` +================================= -xt::random::exponential -======================= +:cpp:func:`xt::random::negative_binomial` +========================================= -:ref:`xt::random::exponential ` +:cpp:func:`xt::random::poisson` +=============================== -xt::random::gamma -================= +:cpp:func:`xt::random::exponential` +=================================== -:ref:`xt::random::gamma ` +:cpp:func:`xt::random::gamma` +============================= Produces (an array of) random positive floating-point values, distributed according to the probability density: @@ -77,7 +57,8 @@ distributed according to the probability density: P(x) = x^{\alpha-1} \frac{e^{-x / \beta}}{\beta^\alpha \; \Gamma(\alpha)} -where :math:`\alpha` is the shape (also known as :math:`k`) and :math:`\beta` the scale (also known as :math:`\theta`), and :math:`\Gamma` is the Gamma function. +where :math:`\alpha` is the shape (also known as :math:`k`) and :math:`\beta` the scale +(also known as :math:`\theta`), and :math:`\Gamma` is the Gamma function. .. note:: @@ -90,10 +71,8 @@ where :math:`\alpha` is the shape (also known as :math:`k`) and :math:`\beta` th * `Weisstein, Eric W. "Gamma Distribution." From MathWorld – A Wolfram Web Resource. `_ * `Wikipedia, "Gamma distribution". `_ -xt::random::weibull -=================== - -:ref:`xt::random::weibull ` +:cpp:func:`xt::random::weibull` +=============================== Produces (an array of) random positive floating-point values, distributed according to the probability density: @@ -124,42 +103,26 @@ Note that you can specify only :math:`a` while choosing the default for :math:`b * `std::weibull_distribution `_ * `Wikipedia, "Weibull distribution". `_ -xt::random::extreme_value -========================= - -:ref:`xt::random::extreme_value ` - -xt::random::lognormal -===================== - -:ref:`xt::random::lognormal ` - -xt::random::cauchy -================== - -:ref:`xt::random::cauchy ` - -xt::random::fisher_f -==================== - -:ref:`xt::random::fisher_f ` - -xt::random::student_t -===================== +:cpp:func:`xt::random::extreme_value` +===================================== -:ref:`xt::random::student_t ` +:cpp:func:`xt::random::lognormal` +================================= -xt::random::choice -================== +:cpp:func:`xt::random::cauchy` +============================== -:ref:`xt::random::choice ` +:cpp:func:`xt::random::fisher_f` +================================ -xt::random::shuffle -=================== +:cpp:func:`xt::random::student_t` +================================= -:ref:`xt::random::shuffle ` +:cpp:func:`xt::random::choice` +============================== -xt::random::permutation -======================= +:cpp:func:`xt::random::shuffle` +=============================== -:ref:`xt::random::permutation ` +:cpp:func:`xt::random::permutation` +=================================== diff --git a/docs/source/rank.rst b/docs/source/rank.rst index b9496eead..330ac8c50 100644 --- a/docs/source/rank.rst +++ b/docs/source/rank.rst @@ -81,7 +81,8 @@ Consider the following example: Rank as member -------------- -If you want to use the rank as a member of your own class you can use ``xt::get_rank``. +If you want to use the rank as a member of your own class you can use +:cpp:type:`xt::get_rank\ `. Consider the following example: .. code-block:: cpp diff --git a/docs/source/scalar.rst b/docs/source/scalar.rst index 6c0dab9b0..562ffc876 100644 --- a/docs/source/scalar.rst +++ b/docs/source/scalar.rst @@ -10,9 +10,9 @@ Scalars and 0-D expressions Assignment ---------- -In ``xtensor``, scalars are handled as if they were 0-dimensional expressions. This means that when assigning -a scalar value to an ``xarray``, the array is **not filled** with that value, but resized to become a 0-D -array containing the scalar value: +In `xtensor`, scalars are handled as if they were 0-dimensional expressions. +This means that when assigning a scalar value to an :cpp:type:`xt::xarray`, the array is **not filled** with that value, +but resized to become a 0-D array containing the scalar value: .. code:: @@ -94,9 +94,10 @@ Then, somewhere in your program: eval_mean(a, b); // Now b is a 0-D container holding 3.5. -After that, ``b`` is a 0-dimensional array containing the mean of the elements of ``a``. Indeed, ``sum(a) / e1.size()`` is a -0-D expression, thus when assigned to ``b``, this latter is resized. Later, you realize that you also need the sum of the elements -of ``a``. Since the ``eval_mean`` function already computes it, you decide to return it from that function: +After that, ``b`` is a 0-dimensional array containing the mean of the elements of ``a``. +Indeed, ``sum(a) / e1.size()`` is a 0-D expression, thus when assigned to ``b``, this latter is resized. +Later, you realize that you also need the sum of the elements of ``a``. +Since the ``eval_mean()`` function already computes it, you decide to return it from that function: .. code:: @@ -120,8 +121,9 @@ And then you change the client code: double s = eval_mean(a, b); // Now b is a 2-D container! -After that, ``b`` has become a 2-dimensional array! Indeed, since assigning a scalar to an expression does not resize it, the change in -``eval_mean`` implementation now assigns the mean of ``a`` to each elements of ``b``. +After that, ``b`` has become a 2-dimensional array! +Indeed, since assigning a scalar to an expression does not resize it, the change in ``eval_mean()`` +implementation now assigns the mean of ``a`` to each elements of ``b``. This simple example shows that without consistency between scalars and 0-D expressions, refactoring the code to cache the result of some 0-D computation actually *silently* changes the shape of the expressions that this result is assigned to. diff --git a/docs/source/view.rst b/docs/source/view.rst index b30e404c5..a3f4efe22 100644 --- a/docs/source/view.rst +++ b/docs/source/view.rst @@ -9,26 +9,26 @@ Views ===== -Views are used to adapt the shape of an ``xexpression`` without changing it, nor copying it. Views are +Views are used to adapt the shape of an :cpp:type:`xt::xexpression` without changing it, nor copying it. Views are convenient tools for assigning parts of an expression: since they do not copy the underlying expression, assigning to the view actually assigns to the underlying expression. `xtensor` provides many kinds of views. Sliced views ------------ -Sliced views consist of the combination of the ``xexpression`` to adapt, and a list of ``slice`` 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. +Sliced views consist of the combination of the :cpp:type:`xt::xexpression` to adapt, and a list of ``slice`` that specify how +the shape must be adapted. Sliced views are implemented by the :cpp:type:`xt::xview` class. Objects of this type should not be +instantiated directly, but though the :cpp:func:`xt::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 the interval [min, max) -- ``range(min, max, step)``, a slice representing the stepped interval [min, max) -- ``all()``, a slice representing all the elements of a dimension -- ``newaxis()``, a slice representing an additional dimension of length one -- ``keep(i0, i1, i2, ...)`` a slice selecting non-contiguous indices to keep on the underlying expression -- ``drop(i0, i1, i2, ...)`` a slice selecting non-contiguous indices to drop on the underlying expression +- :cpp:func:`xt::range(min, max) `, a slice representing the interval [min, max) +- :cpp:func:`xt::range(min, max, step) `, a slice representing the stepped interval [min, max) +- :cpp:func:`xt::all`, a slice representing all the elements of a dimension +- :cpp:func:`xt::newaxis`, a slice representing an additional dimension of length one +- :cpp:func:`xt::keep(i0, i1, i2, ...) ` a slice selecting non-contiguous indices to keep on the underlying expression +- :cpp:func:`xt::drop(i0, i1, i2, ...) ` a slice selecting non-contiguous indices to drop on the underlying expression .. code:: @@ -80,7 +80,8 @@ The range function supports the placeholder ``_`` syntax: // The previous line is equivalent to auto v2 = xt::view(a, xt::range(0, 2), xt::all(), xt::range(1, 4)); -``xview`` does not perform a copy of the underlying expression. This means if you modify an element of the ``xview``, +:cpp:type:`xt::xview` does not perform a copy of the underlying expression. +This means if you modify an element of the :cpp:type:`xt::xview`, you are actually also altering the underlying expression. .. code:: @@ -96,7 +97,7 @@ you are actually also altering the underlying expression. v1(0, 0) = 1; // => a(1, 0, 1) = 1 -The convenient methods ``row`` and ``col`` are available for 2-D expressions: +The convenient methods :cpp:func:`xt::row` and :cpp:func:`xt::col` are available for 2-D expressions: .. code:: @@ -109,14 +110,18 @@ The convenient methods ``row`` and ``col`` are available for 2-D expressions: // => r = {1, 2} auto c = xt::col(a, -1); // => c = { 2, 4 } - + Strided views ------------- -While the ``xt::view`` is a compile-time static expression, xtensor also contains a dynamic strided view in ``xstrided_view.hpp``. -The strided view and the slice vector allow to dynamically push_back slices, so when the dimension is unknown at compile time, the slice -vector can be built dynamically at runtime. Note that the slice vector is actually a type-alias for a ``std::vector`` of a ``variant`` for -all the slice types. The strided view does not support the slices returned by the ``keep`` and ``drop`` functions. +While the :cpp:func:`xt::view` is a compile-time static expression, xtensor also contains a dynamic +strided view in ``xstrided_view.hpp``. +The strided view and the slice vector allow to dynamically push_back slices, so when the dimension +is unknown at compile time, the slice vector can be built dynamically at runtime. +Note that the slice vector is actually a type-alias for a ``std::vector`` of a ``variant`` for +all the slice types. +The strided view does not support the slices returned by the :cpp:func:`xt::keep` and +:cpp:func:`xt::drop` functions. .. code:: @@ -154,13 +159,15 @@ Since ``xtensor 0.16.3``, a new range syntax can be used with strided views: // The previous line is equivalent to auto v2 = xt::strided_view(a, {xt::range(0, 1), 1, xt::range(_, 2), xt::range(_, _, -1)}); -The ``xstrided_view`` is very efficient on contigous memory (e.g. ``xtensor`` or ``xarray``) but less efficient on xexpressions. +The :cpp:type:`xt::xstrided_view` is very efficient on contigous memory +(e.g. :cpp:type:`xt::xtensor` or :cpp:type:`xt::xarray`) but less efficient on\ +:cpp:type:`xt::xexpression`s. Transposed views ---------------- -``xtensor`` provides a lazy transposed view on any expression, whose layout is either row-major order or column major order. Trying to build -a transposed view on a expression with a dynamic layout throws an exception. +``xtensor`` provides a lazy transposed view on any expression, whose layout is either row-major order or column major order. +Trying to build a transposed view on a expression with a dynamic layout throws an exception. .. code:: @@ -175,13 +182,14 @@ a transposed view on a expression with a dynamic layout throws an exception. auto tr2 = xt::transpose(b); // => throw transpose_error -Like the strided view, the transposed view is built upon the ``xstrided_view``. +Like the strided view, the transposed view is built upon the :cpp:type:`xt::xstrided_view`. Flatten views ------------- -It is sometimes useful to have a one-dimensional view of all the elements of an expression. ``xtensor`` provides two functions -for that, ``ravel`` and ``flatten``. The former one lets you specify the order used to read the elements while the latter one +It is sometimes useful to have a one-dimensional view of all the elements of an expression. +``xtensor`` provides two functions for that, :cpp:func:`xt::ravel` and :cpp:func:`xt::flatten`. +The former one lets you specify the order used to read the elements while the latter one uses the layout of the expression. .. code:: @@ -198,7 +206,7 @@ uses the layout of the expression. std::cout << fl << std::endl; // => prints { 0, 1, 2, 3, 4, 5 } -Like the strided view and the transposed view, the flatten view is built upon the ``xstrided_view``. +Like the strided view and the transposed view, the flatten view is built upon the :cpp:type:`xt::xstrided_view`. Reshape views ------------- @@ -220,14 +228,15 @@ the view modifies the underlying expression. v(0, 2, 0) = 4; // a(0, 1, 2) == 4 -Like the strided view and the transposed view, the reshape view is built upon the ``xstrided_view``. +Like the strided view and the transposed view, the reshape view is built upon the :cpp:type:`xt::xstrided_view`. Dynamic views ------------- -The dynamic view is like the strided view, but with support of the slices returned by the ``keep`` and ``drop`` functions. -However, this support has a cost and the dynamic view is slower than the strided view, even when no keeping or dropping of a -slice is involved. +The dynamic view is like the strided view, but with support of the slices returned by the +:cpp:func:`xt::keep` and :cpp:func:`xt::drop` functions. +However, this support has a cost and the dynamic view is slower than the strided view, even when no +keeping or dropping of a slice is involved. .. code:: @@ -250,9 +259,10 @@ slice is involved. 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. +Index views are one-dimensional views of an :cpp:type:`xt::xexpression`, containing the elements +whose positions are specified by a list of indices. +Like for sliced views, the elements of the underlying :cpp:type:`xt::xexpression` are not copied. +Index views should be built with the :cpp:func:`xt::index_view` helper function. .. code:: @@ -265,8 +275,8 @@ with the ``index_view`` helper function. b += 100; // => a = {{101, 5, 3}, {104, 105, 6}} -The type used for representing indices can be any 1-D container providing an std::vector-like API. The same stands for the type -of the list of indices: +The type used for representing indices can be any 1-D container providing an ``std::vector``-like API. +The same stands for the type of the list of indices: .. code:: @@ -284,8 +294,9 @@ of the list of indices: 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. +Filters are one-dimensional views holding elements of an :cpp:type:`xt::xexpression` that verify a given condition. +Like for other views, the elements of the underlying :cpp:type:`xt::xexpression` are not copied. +Filters should be built with the :cpp:func:`xt::filter` helper function. .. code:: @@ -301,9 +312,10 @@ the elements of the underlying ``xexpression`` are not copied. Filters should be 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 +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 :cpp:type:`xt::xexpression`, the only methods it provides are scalar and computed scalar assignments. .. code:: @@ -318,7 +330,7 @@ computed scalar assignments. Masked view ----------- -Masked views are multidimensional views that apply a mask on an ``xexpression``. +Masked views are multidimensional views that apply a mask on an :cpp:type:`xt::xexpression`. .. code:: @@ -337,9 +349,10 @@ Masked views are multidimensional views that apply a mask on an ``xexpression``. Broadcasting views ------------------ -Another type of view provided by `xtensor` is *broadcasting view*. Such a view broadcasts 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. +Another type of view provided by `xtensor` is *broadcasting view*. +Such a view broadcasts 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 :cpp:func:`xt::broadcast` helper function. .. code:: @@ -357,16 +370,22 @@ built with the ``broadcast`` helper function. Complex views ------------- -In the case of a 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. +In the case of a tensor containing complex numbers, `xtensor` provides views returning +:cpp:type:`xt::xexpression` corresponding to the real and imaginary parts of the complex numbers. +Like for other views, the elements of the underlying :cpp:type:`xt::xexpression` are not copied. -Functions ``xt::real`` and ``xt::imag`` respectively return views on the real and imaginary part of a complex expression. +Functions :cpp:func:`xt::real` and :cpp:func:`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())``. +- The constness and value category (rvalue / lvalue) of :cpp:func:`xt::real(a) ` is the same + as that of ``a``. + Hence, if ``a`` is a non-const lvalue, :cpp:func:`xt::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 :cpp:func:`xt::imag(a) `. + The constness and value category of :cpp:func:`xt::imag(a) ` is the same as that of ``a``. +- If ``a`` has real values, :cpp:func:`xt::imag(a) ` returns + :cpp:func:`xt::zeros(a.shape()) `. .. code:: @@ -386,8 +405,9 @@ The returned value is an expression holding a closure on the passed argument. Assigning to a view ------------------- -When assigning an expression ``rhs`` to a container such as ``xarray``, the container is resized so its shape is the same as the one -of ``rhs``. However, since views *cannot be resized*, when assigning an expression to a view, broadcasting rules are applied: +When assigning an expression ``rhs`` to a container such as :cpp:type:`xt::xarray`, the container +is resized so its shape is the same as the one of ``rhs``. +However, since views *cannot be resized*, when assigning an expression to a view, broadcasting rules are applied: .. code:: diff --git a/include/xtensor/xrandom.hpp b/include/xtensor/xrandom.hpp index 6135ea2c1..12ece9951 100644 --- a/include/xtensor/xrandom.hpp +++ b/include/xtensor/xrandom.hpp @@ -159,7 +159,7 @@ namespace xt template auto chi_squared(const I (&shape)[L], T deg = 1.0, E& engine = random::get_default_random_engine()); - + template auto cauchy(const I (&shape)[L], T a = 0.0, T b = 1.0, E& engine = random::get_default_random_engine());