Skip to content

Commit

Permalink
blockwise reducers intital implementation
Browse files Browse the repository at this point in the history
cleanup

cleanup

cleanup

cleanup

cleanup

cleanup

cleanup

added explicit this

cleanup

const correctness

const correctness

more inline

fixed broken tests

...

added p norms

added p norms

fixed test

winfix

win fix

win fix
  • Loading branch information
DerThorsten committed Aug 25, 2021
1 parent 2618d5a commit 8fb97e6
Show file tree
Hide file tree
Showing 11 changed files with 1,726 additions and 43 deletions.
498 changes: 498 additions & 0 deletions include/xtensor/xblockwise_reducer.hpp

Large diffs are not rendered by default.

587 changes: 587 additions & 0 deletions include/xtensor/xblockwise_reducer_functors.hpp

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion include/xtensor/xchunked_assign.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ namespace xt
struct xchunk_iterator_base
: std::conditional_t<is_xchunked_array<std::decay_t<T>>::value,
xchunk_iterator_array<T>,
std::conditional_t<is_xchunked_view<T>::value,
std::conditional_t<is_xchunked_view<std::decay_t<T>>::value,
xchunk_iterator_view<T>,
invalid_chunk_iterator>>
{
Expand Down Expand Up @@ -172,6 +172,8 @@ namespace xt
bool operator==(const self_type& rhs) const;
bool operator!=(const self_type& rhs) const;

const shape_type& chunk_index() const;

const slice_vector& get_slice_vector() const;
slice_vector get_chunk_slice_vector() const;

Expand Down Expand Up @@ -338,6 +340,12 @@ namespace xt
{
return m_slice_vector;
}

template <class E>
auto xchunk_iterator<E>::chunk_index() const -> const shape_type&
{
return m_chunk_index;
}

template <class E>
inline auto xchunk_iterator<E>::get_chunk_slice_vector() const -> slice_vector
Expand Down
139 changes: 139 additions & 0 deletions include/xtensor/xgrid_iterator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/***************************************************************************
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* Copyright (c) QuantStack *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XTENSOR_XGRID_ITERATOR
#define XTENSOR_XGRID_ITERATOR

#include "xtl/xsequence.hpp"


#include "xstrided_view.hpp"

namespace xt
{

template<class S>
class xsubgrid_iterator
{
public:
using self_type = xsubgrid_iterator<S>;
using shape_type = S;

using value_type = shape_type;
using reference = value_type &;
using pointer = value_type*;
using difference_type = std::size_t;
using iterator_category = std::forward_iterator_tag;

xsubgrid_iterator() = default;
xsubgrid_iterator(const xsubgrid_iterator&) = default;
xsubgrid_iterator(xsubgrid_iterator&&) = default;
xsubgrid_iterator& operator=(const xsubgrid_iterator&) = default;
xsubgrid_iterator& operator=(xsubgrid_iterator&&) = default;

template<class B, class E, class C>
xsubgrid_iterator(B && begin, E && end, C && current, const std::size_t linear_index)
: m_begin(std::forward<B>(begin)),
m_end(std::forward<E>(end)),
m_current(std::forward<C>(current)),
m_linear_index(linear_index)
{

}

self_type& operator++()
{
std::size_t i = m_begin.size();
while (i != 0)
{
--i;
if (m_current[i] + 1u == m_end[i])
{
m_current[i] = m_begin[i];
}
else
{
m_current[i] += 1;
break;
}
}
m_linear_index++;
return *this;
}

self_type operator++(int)
{
self_type it = *this;
++(*this);
return it;
}
shape_type & operator*()
{
return m_current;
}
const shape_type & operator*() const
{
return m_current;
}

bool operator==(const self_type& rhs) const
{
return m_linear_index == rhs.m_linear_index;
}
bool operator!=(const self_type& rhs) const
{
return !this->operator==(rhs);
}

private:
shape_type m_begin;
shape_type m_end;
shape_type m_current;
std::size_t m_linear_index{0};
};


template<class S, class B, class E>
auto subgrid_iterator_begin(B && roi_begin, E && roi_end)
{
S current;
resize_container(current, roi_begin.size());
std::copy(roi_begin.begin(), roi_begin.end(), current.begin());
return xsubgrid_iterator<S>(
std::forward<B>(roi_begin),
std::forward<E>(roi_end),
std::move(current),
0
);
}

template<class S, class B, class E>
auto subgrid_iterator_end(B && roi_begin, E && roi_end)
{
S current;
resize_container(current, roi_begin.size());
std::copy(roi_end.begin(), roi_end.end(), current.begin());

std::size_t linear_index = 1;
for(std::size_t i=0; i<roi_begin.size(); ++i)
{
linear_index *= roi_end[i] - roi_begin[i];
}

return xsubgrid_iterator<S>(
std::forward<B>(roi_begin),
std::forward<E>(roi_end),
std::move(current),
linear_index
);
}

}

#endif
80 changes: 40 additions & 40 deletions include/xtensor/xmath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,46 +365,46 @@ namespace detail {
}
}

#define XTENSOR_REDUCER_FUNCTION(NAME, FUNCTOR, INIT_VALUE_TYPE, INIT) \
template <class T = void, class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::negation<xtl::is_integral<X>>)> \
inline auto NAME(E&& e, X&& axes, EVS es = EVS()) \
{ \
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
using functor_type = FUNCTOR; \
using init_value_fct = xt::const_value<init_value_type>; \
return xt::reduce(make_xreducer_functor(functor_type(), \
init_value_fct(detail::fill_init<init_value_type>(INIT))), \
std::forward<E>(e), \
std::forward<X>(axes), es); \
} \
\
template <class T = void, class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::is_integral<X>)> \
inline auto NAME(E&& e, X axis, EVS es = EVS()) \
{ \
return NAME(std::forward<E>(e), {axis}, es); \
} \
\
template <class T = void, class E, class EVS = DEFAULT_STRATEGY_REDUCERS, \
XTL_REQUIRES(is_reducer_options<EVS>)> \
inline auto NAME(E&& e, EVS es = EVS()) \
{ \
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
using functor_type = FUNCTOR; \
using init_value_fct = xt::const_value<init_value_type >; \
return xt::reduce(make_xreducer_functor(functor_type(), \
init_value_fct(detail::fill_init<init_value_type >(INIT))), std::forward<E>(e), es); \
} \
\
template <class T = void, class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS> \
inline auto NAME(E&& e, const I (&axes)[N], EVS es = EVS()) \
{ \
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
using functor_type = FUNCTOR; \
using init_value_fct = xt::const_value<init_value_type >; \
return xt::reduce(make_xreducer_functor(functor_type(), \
init_value_fct(detail::fill_init<init_value_type >(INIT))), std::forward<E>(e), axes, es); \
#define XTENSOR_REDUCER_FUNCTION(NAME, FUNCTOR, INIT_VALUE_TYPE, INIT) \
template <class T = void, class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::negation<xtl::is_integral<std::decay_t<X> >> )> \
inline auto NAME(E&& e, X&& axes, EVS es = EVS()) \
{ \
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
using functor_type = FUNCTOR; \
using init_value_fct = xt::const_value<init_value_type>; \
return xt::reduce(make_xreducer_functor(functor_type(), \
init_value_fct(detail::fill_init<init_value_type>(INIT))), \
std::forward<E>(e), \
std::forward<X>(axes), es); \
} \
\
template <class T = void, class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::is_integral<std::decay_t<X>>)> \
inline auto NAME(E&& e, X axis, EVS es = EVS()) \
{ \
return NAME(std::forward<E>(e), {axis}, es); \
} \
\
template <class T = void, class E, class EVS = DEFAULT_STRATEGY_REDUCERS, \
XTL_REQUIRES(is_reducer_options<EVS>)> \
inline auto NAME(E&& e, EVS es = EVS()) \
{ \
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
using functor_type = FUNCTOR; \
using init_value_fct = xt::const_value<init_value_type >; \
return xt::reduce(make_xreducer_functor(functor_type(), \
init_value_fct(detail::fill_init<init_value_type >(INIT))), std::forward<E>(e), es); \
} \
\
template <class T = void, class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS> \
inline auto NAME(E&& e, const I (&axes)[N], EVS es = EVS()) \
{ \
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
using functor_type = FUNCTOR; \
using init_value_fct = xt::const_value<init_value_type >; \
return xt::reduce(make_xreducer_functor(functor_type(), \
init_value_fct(detail::fill_init<init_value_type >(INIT))), std::forward<E>(e), axes, es); \
}

/*******************
Expand Down
67 changes: 66 additions & 1 deletion include/xtensor/xutils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,74 @@ namespace xt
}

/***********************************
* resize_container implementation *
* construct_container_with_size implementation *
***********************************/
namespace detail
{

template<class C>
struct construct_container_with_size_impl
{
static C op(typename C::size_type size)
{
C c;
const bool success = resize_container(c, size);
if(!success)
{
XTENSOR_THROW(std::runtime_error, "cannot resize container to given size");
}
c.resize(size);
return c;
}
};

template <class T, class A>
struct construct_container_with_size_impl<std::vector<T,A>>
{
using container_type = std::vector<T,A>;
static container_type op(typename container_type::size_type size)
{
return container_type(size);
}
};

template <class T, std::size_t N>
struct construct_container_with_size_impl<std::array<T, N>>
{
using container_type = std::array<T, N>;
static container_type op(typename container_type::size_type size)
{
if(size != N)
{
XTENSOR_THROW(std::runtime_error, "cannot resize container to given size");
}
return container_type{};
}
};

template <std::size_t... I>
struct construct_container_with_size_impl<xt::fixed_shape<I...>>
{
using container_type = xt::fixed_shape<I...>;
static container_type op(std::size_t size)
{
if(sizeof...(I) != size)
{
XTENSOR_THROW(std::runtime_error, "cannot resize container to given size");
}
return container_type{};
}
};
}

template <class C, class S>
inline C construct_container_with_size(S size)
{
return detail::construct_container_with_size_impl<C>::op(size);
}
/***********************************
* resize_container implementation *
***********************************/
template <class C>
inline bool resize_container(C& c, typename C::size_type size)
{
Expand Down
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ set(COMMON_BASE
test_xadaptor_semantic.cpp
test_xarray_adaptor.cpp
test_xarray.cpp
test_xblockwise_reducer.cpp
test_xbroadcast.cpp
test_xbuilder.cpp
test_xcontainer_semantic.cpp
Expand All @@ -142,6 +143,7 @@ set(COMMON_BASE
test_xexpression_traits.cpp
test_xfunction.cpp
test_xfunc_on_xexpression.cpp
test_xgrid_iterator.cpp
test_xiterator.cpp
test_xmath.cpp
test_xoperation.cpp
Expand Down
26 changes: 26 additions & 0 deletions test/test_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
#ifndef TEST_COMMON_HPP
#define TEST_COMMON_HPP

#include <sstream>

#include "xtensor/xlayout.hpp"
#include "xtensor/xmanipulation.hpp"
#include "xtensor/xreducer.hpp" // tuple_idx_of

#include "test_common_macros.hpp"

// the tests used to be implemented with gtest
Expand All @@ -28,6 +32,28 @@ namespace testing

namespace xt
{
template<class C>
std::string stringify(const C & container)
{
std::size_t i = 0;
std::stringstream ss;
ss << "[";
for(auto && c : container)
{
if(i + 1 == container.size())
{
ss<<c;
}
else
{
ss<<c<<",";
}
++i;
}
ss << "]";
return ss.str();
}

template <class T, class A, class AV>
bool operator==(const uvector<T, A>& lhs, const std::vector<T, AV>& rhs)
{
Expand Down
Loading

0 comments on commit 8fb97e6

Please sign in to comment.