Skip to content

Commit

Permalink
add documentation for dynamic view
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfv committed Oct 17, 2017
1 parent 7a22e41 commit cecd3e6
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 14 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,22 +234,21 @@ xtensor's documentation is built with three tools
While doxygen must be installed separately, you can install breathe by typing

```bash
pip install breathe
```
pip install breathe sphinx_rtd_theme
```

Breathe can also be installed with `conda`

```bash
conda install -c conda-forge breathe
```

Finally, build the documentation with
Finally, go to `docs` subdirectory and build the documentation with the following command:

```bash
make html
```

from the `docs` subdirectory.

## License

Expand Down
1 change: 1 addition & 0 deletions docs/source/api/container_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Containers and views
xtensor
xtensor_adaptor
xview
xstridedview
xbroadcast
xindexview
xfunctorview
26 changes: 26 additions & 0 deletions docs/source/view.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,32 @@ you are actually also altering the underlying expression.
v1(0, 0) = 1;
// => a(1, 0, 1) = 1
Dynamic views
-------------

While the ``xt::view`` is a compile-time static expression, xtensor also contains a dynamic view in ``xstridedview.hpp``. The dynamic 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. All the same slices as in xview can be used.

.. code::
#include "xtensor/xarray.hpp"
#include "xtensor/xstridedview.hpp"
auto a = xt::xarray<int>::from_shape({3, 2, 3, 4, 5});
// note that `a` has to be passed into the slice_vector constructor
xt::slice_vector sv(a, xt::range(0, 1), xt::newaxis());
sv.push_back(1);
sv.push_back(xt::all());
// there is also a shorthand syntax: sv.append(1, xt::all());
auto v1 = xt::dynamic_view(a, sv);
// v1 has the same behavior as the static view
The dynamic_view is implemented on top of the strided_view, which is very efficient on contigous memory (e.g. xtensor or xarray)
but less efficient on xexpressions.


Index views
-----------

Expand Down
90 changes: 80 additions & 10 deletions include/xtensor/xstridedview.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ namespace xt
* @class xstrided_view
* @brief View of an xexpression using strides
*
* The xstrided_view class implements a view utilizing an offset and strides
* into a multidimensional xcontainer. The xstridedview is currently used
* The xstrided_view class implements a view utilizing an offset and strides
* into a multidimensional xcontainer. The xstridedview is currently used
* to implement `transpose`.
* @tparam CT the closure type of the \ref xexpression type underlying this view
* @tparam CD the closure type of the underlying data container
*
* @sa stridedview, transpose
*
* @sa strided_view, transpose
*/
template <class CT, class S, class CD>
class xstrided_view : public xview_semantic<xstrided_view<CT, S, CD>>,
Expand Down Expand Up @@ -202,8 +202,8 @@ namespace xt
*/
//@{
/**
* Constructs an xstrided_view
*
* Constructs an xstrided_view
*
* @param e the underlying xexpression for this view
* @param shape the shape of the view
* @param strides the strides of the view
Expand Down Expand Up @@ -360,8 +360,8 @@ namespace xt
}

/**
* Returns the element at the specified position in the xstrided_view.
*
* Returns the element at the specified position in the xstrided_view.
*
* @param args a list of indices specifying the position in the view. Indices
* must be unsigned integers, the number of indices should be equal or greater than
* the number of dimensions of the view.
Expand Down Expand Up @@ -635,6 +635,7 @@ namespace xt
}
}

/// @cond DOXYGEN_INCLUDE_SFINAE
template <class E>
inline auto transpose(E&& e) noexcept
{
Expand All @@ -651,6 +652,7 @@ namespace xt
using view_type = xstrided_view<xclosure_t<E>, shape_type, decltype(e.data())>;
return view_type(std::forward<E>(e), std::move(shape), std::move(strides), 0);
}
/// @endcond

/**
* Returns a transpose view by permuting the xexpression e with @p permutation.
Expand All @@ -665,6 +667,7 @@ namespace xt
return detail::transpose_impl(std::forward<E>(e), std::forward<S>(permutation), check_policy);
}

/// @cond DOXYGEN_INCLUDE_SFINAE
#ifdef X_OLD_CLANG
template <class E, class I, class Tag = check_policy::none>
inline auto transpose(E&& e, std::initializer_list<I> permutation, Tag check_policy = Tag())
Expand All @@ -679,6 +682,7 @@ namespace xt
return detail::transpose_impl(std::forward<E>(e), permutation, check_policy);
}
#endif
/// @endcond

namespace detail
{
Expand Down Expand Up @@ -726,6 +730,28 @@ namespace xt
};
}

/**
* The slice_vector is used as part of the dynamic_view interface.
* It offers an interface to dynamically push_back or append slices
* to dynamically create a view into a xexpression.
*
* This data structure is necessary as the slices of xview are
* compile-time static. If you do not know how many dimensions
* your expression has at compile-time, using dynamic_view can be
* useful.
*
* Internally, the dynamic_view is implemented using the strided_view
* adapter, which is very fast for data structures in contigous
* memory (such as xarrays and xtensors).
*
* Usage example:
*
* \code{.cpp}
* xt::xarray<double> a = {{1, 2, 3}, {4, 5, 6}};
* xt::slice_vector sv(a, xt::range(0, 1));
* sv.push_back(xt::all());
* \endcode
*/
class slice_vector : private std::vector<std::array<long int, 3>>
{

Expand All @@ -744,6 +770,12 @@ namespace xt

inline slice_vector() = default;

/**
* Constructor for slice vector
*
* @param e xexpression
* @param args xslices, integer, all or newaxis
*/
template <class E, class... Args>
inline slice_vector(const xexpression<E>& e, Args... args)
{
Expand All @@ -753,31 +785,52 @@ namespace xt
append(args...);
}

/**
* @brief Alternative constructor taking a shape
* @param shape the shape
*/
template <class... Args>
inline slice_vector(const std::vector<std::size_t>& shape, Args... args)
{
m_shape = shape;
append(args...);
}

/**
* Convenience function to append one or multiple
* slices to the slice_vector
*
* \code{.cpp}
* xt::slice_vector sv(a, xt::range(0, 1));
* sv.append(xt::all(), xt::newaxis(), 0, 12));
* \endcode
*/
template <class T, class... Args>
inline void append(const T& s, Args... args)
{
push_back(s);
append(args...);
}

///@cond DOXYGEN_INCLUDE_SFINAE
inline void append()
{
}
/// @endcond

/**
* Push back a single slice, integer, all or newaxis.
*
* @param s slice
*/
template <class T>
inline void push_back(const xslice<T>& s)
{
auto ds = s.derived_cast();
base_type::push_back({(index_type)ds(0), (index_type)ds.size(), (index_type)ds.step_size()});
}

///@cond DOXYGEN_INCLUDE_SFINAE
template <class A, class B, class C>
inline void push_back(const xrange_adaptor<A, B, C>& s)
{
Expand Down Expand Up @@ -810,6 +863,7 @@ namespace xt
{
base_type::push_back({i, 0, 0});
}
/// @endcond

private:

Expand Down Expand Up @@ -846,7 +900,7 @@ namespace xt
template <class E, std::enable_if_t<!has_raw_data_interface<std::decay_t<E>>::value>* = nullptr>
inline std::size_t get_offset(E&& /*e*/)
{
return 0;
return std::size_t(0);
}

template <class E, std::enable_if_t<!has_raw_data_interface<std::decay_t<E>>::value>* = nullptr>
Expand All @@ -859,6 +913,23 @@ namespace xt
}
}

/**
* Function to create a dynamic view from
* a xexpression and a slice_vector.
*
* @param e xexpression
* @param slices the slice vector
*
* @return initialized strided_view according to slices
*
* \code{.cpp}
* xt::xarray<double> a = {{1, 2, 3}, {4, 5, 6}};
* xt::slice_vector sv(a, xt::range(0, 1));
* sv.push_back(xt::range(0, 3, 2));
* auto v = xt::dynamic_view(a, sv);
* // ==> {{1, 3}}
* \endcode
*/
template <class E, class S>
inline auto dynamic_view(E&& e, S&& slices)
{
Expand All @@ -880,7 +951,6 @@ namespace xt
}

// Compute strided view

std::size_t offset = detail::get_offset(e);
using shape_type = typename std::vector<std::size_t>;

Expand Down

0 comments on commit cecd3e6

Please sign in to comment.