Skip to content

Commit d5a5c63

Browse files
authored
Merge pull request #2415 from DerThorsten/feature/blockwise_reducer
blockwise reducers intital implementation
2 parents cc23f11 + a06be68 commit d5a5c63

11 files changed

+1662
-43
lines changed

include/xtensor/xblockwise_reducer.hpp

Lines changed: 504 additions & 0 deletions
Large diffs are not rendered by default.

include/xtensor/xblockwise_reducer_functors.hpp

Lines changed: 587 additions & 0 deletions
Large diffs are not rendered by default.

include/xtensor/xchunked_assign.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ namespace xt
135135
struct xchunk_iterator_base
136136
: std::conditional_t<is_xchunked_array<std::decay_t<T>>::value,
137137
xchunk_iterator_array<T>,
138-
std::conditional_t<is_xchunked_view<T>::value,
138+
std::conditional_t<is_xchunked_view<std::decay_t<T>>::value,
139139
xchunk_iterator_view<T>,
140140
invalid_chunk_iterator>>
141141
{
@@ -172,6 +172,8 @@ namespace xt
172172
bool operator==(const self_type& rhs) const;
173173
bool operator!=(const self_type& rhs) const;
174174

175+
const shape_type& chunk_index() const;
176+
175177
const slice_vector& get_slice_vector() const;
176178
slice_vector get_chunk_slice_vector() const;
177179

@@ -338,6 +340,12 @@ namespace xt
338340
{
339341
return m_slice_vector;
340342
}
343+
344+
template <class E>
345+
auto xchunk_iterator<E>::chunk_index() const -> const shape_type&
346+
{
347+
return m_chunk_index;
348+
}
341349

342350
template <class E>
343351
inline auto xchunk_iterator<E>::get_chunk_slice_vector() const -> slice_vector

include/xtensor/xmath.hpp

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -365,46 +365,46 @@ namespace detail {
365365
}
366366
}
367367

368-
#define XTENSOR_REDUCER_FUNCTION(NAME, FUNCTOR, INIT_VALUE_TYPE, INIT) \
369-
template <class T = void, class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
370-
XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::negation<xtl::is_integral<X>>)> \
371-
inline auto NAME(E&& e, X&& axes, EVS es = EVS()) \
372-
{ \
373-
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
374-
using functor_type = FUNCTOR; \
375-
using init_value_fct = xt::const_value<init_value_type>; \
376-
return xt::reduce(make_xreducer_functor(functor_type(), \
377-
init_value_fct(detail::fill_init<init_value_type>(INIT))), \
378-
std::forward<E>(e), \
379-
std::forward<X>(axes), es); \
380-
} \
381-
\
382-
template <class T = void, class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
383-
XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::is_integral<X>)> \
384-
inline auto NAME(E&& e, X axis, EVS es = EVS()) \
385-
{ \
386-
return NAME(std::forward<E>(e), {axis}, es); \
387-
} \
388-
\
389-
template <class T = void, class E, class EVS = DEFAULT_STRATEGY_REDUCERS, \
390-
XTL_REQUIRES(is_reducer_options<EVS>)> \
391-
inline auto NAME(E&& e, EVS es = EVS()) \
392-
{ \
393-
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
394-
using functor_type = FUNCTOR; \
395-
using init_value_fct = xt::const_value<init_value_type >; \
396-
return xt::reduce(make_xreducer_functor(functor_type(), \
397-
init_value_fct(detail::fill_init<init_value_type >(INIT))), std::forward<E>(e), es); \
398-
} \
399-
\
400-
template <class T = void, class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS> \
401-
inline auto NAME(E&& e, const I (&axes)[N], EVS es = EVS()) \
402-
{ \
403-
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
404-
using functor_type = FUNCTOR; \
405-
using init_value_fct = xt::const_value<init_value_type >; \
406-
return xt::reduce(make_xreducer_functor(functor_type(), \
407-
init_value_fct(detail::fill_init<init_value_type >(INIT))), std::forward<E>(e), axes, es); \
368+
#define XTENSOR_REDUCER_FUNCTION(NAME, FUNCTOR, INIT_VALUE_TYPE, INIT) \
369+
template <class T = void, class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
370+
XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::negation<xtl::is_integral<std::decay_t<X> >> )> \
371+
inline auto NAME(E&& e, X&& axes, EVS es = EVS()) \
372+
{ \
373+
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
374+
using functor_type = FUNCTOR; \
375+
using init_value_fct = xt::const_value<init_value_type>; \
376+
return xt::reduce(make_xreducer_functor(functor_type(), \
377+
init_value_fct(detail::fill_init<init_value_type>(INIT))), \
378+
std::forward<E>(e), \
379+
std::forward<X>(axes), es); \
380+
} \
381+
\
382+
template <class T = void, class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
383+
XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::is_integral<std::decay_t<X>>)> \
384+
inline auto NAME(E&& e, X axis, EVS es = EVS()) \
385+
{ \
386+
return NAME(std::forward<E>(e), {axis}, es); \
387+
} \
388+
\
389+
template <class T = void, class E, class EVS = DEFAULT_STRATEGY_REDUCERS, \
390+
XTL_REQUIRES(is_reducer_options<EVS>)> \
391+
inline auto NAME(E&& e, EVS es = EVS()) \
392+
{ \
393+
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
394+
using functor_type = FUNCTOR; \
395+
using init_value_fct = xt::const_value<init_value_type >; \
396+
return xt::reduce(make_xreducer_functor(functor_type(), \
397+
init_value_fct(detail::fill_init<init_value_type >(INIT))), std::forward<E>(e), es); \
398+
} \
399+
\
400+
template <class T = void, class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS> \
401+
inline auto NAME(E&& e, const I (&axes)[N], EVS es = EVS()) \
402+
{ \
403+
using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
404+
using functor_type = FUNCTOR; \
405+
using init_value_fct = xt::const_value<init_value_type >; \
406+
return xt::reduce(make_xreducer_functor(functor_type(), \
407+
init_value_fct(detail::fill_init<init_value_type >(INIT))), std::forward<E>(e), axes, es); \
408408
}
409409

410410
/*******************
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/***************************************************************************
2+
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
3+
* Copyright (c) QuantStack *
4+
* *
5+
* Distributed under the terms of the BSD 3-Clause License. *
6+
* *
7+
* The full license is in the file LICENSE, distributed with this software. *
8+
****************************************************************************/
9+
10+
#ifndef XTENSOR_XMULTIINDEX_ITERATOR
11+
#define XTENSOR_XMULTIINDEX_ITERATOR
12+
13+
#include "xtl/xsequence.hpp"
14+
15+
16+
#include "xstrided_view.hpp"
17+
18+
namespace xt
19+
{
20+
21+
template<class S>
22+
class xmultiindex_iterator
23+
{
24+
public:
25+
using self_type = xmultiindex_iterator<S>;
26+
using shape_type = S;
27+
28+
using value_type = shape_type;
29+
using reference = value_type &;
30+
using pointer = value_type*;
31+
using difference_type = std::size_t;
32+
using iterator_category = std::forward_iterator_tag;
33+
34+
xmultiindex_iterator() = default;
35+
36+
template<class B, class E, class C>
37+
xmultiindex_iterator(B && begin, E && end, C && current, const std::size_t linear_index)
38+
: m_begin(std::forward<B>(begin)),
39+
m_end(std::forward<E>(end)),
40+
m_current(std::forward<C>(current)),
41+
m_linear_index(linear_index)
42+
{
43+
44+
}
45+
46+
self_type& operator++()
47+
{
48+
std::size_t i = m_begin.size();
49+
while (i != 0)
50+
{
51+
--i;
52+
if (m_current[i] + 1u == m_end[i])
53+
{
54+
m_current[i] = m_begin[i];
55+
}
56+
else
57+
{
58+
m_current[i] += 1;
59+
break;
60+
}
61+
}
62+
m_linear_index++;
63+
return *this;
64+
}
65+
66+
self_type operator++(int)
67+
{
68+
self_type it = *this;
69+
++(*this);
70+
return it;
71+
}
72+
shape_type & operator*()
73+
{
74+
return m_current;
75+
}
76+
const shape_type & operator*() const
77+
{
78+
return m_current;
79+
}
80+
81+
bool operator==(const self_type& rhs) const
82+
{
83+
return m_linear_index == rhs.m_linear_index;
84+
}
85+
bool operator!=(const self_type& rhs) const
86+
{
87+
return !this->operator==(rhs);
88+
}
89+
90+
private:
91+
shape_type m_begin;
92+
shape_type m_end;
93+
shape_type m_current;
94+
std::size_t m_linear_index{0};
95+
};
96+
97+
98+
template<class S, class B, class E>
99+
auto multiindex_iterator_begin(B && roi_begin, E && roi_end)
100+
{
101+
S current;
102+
resize_container(current, roi_begin.size());
103+
std::copy(roi_begin.begin(), roi_begin.end(), current.begin());
104+
return xmultiindex_iterator<S>(
105+
std::forward<B>(roi_begin),
106+
std::forward<E>(roi_end),
107+
std::move(current),
108+
0
109+
);
110+
}
111+
112+
template<class S, class B, class E>
113+
auto multiindex_iterator_end(B && roi_begin, E && roi_end)
114+
{
115+
S current;
116+
resize_container(current, roi_begin.size());
117+
std::copy(roi_end.begin(), roi_end.end(), current.begin());
118+
119+
std::size_t linear_index = 1;
120+
for(std::size_t i=0; i<roi_begin.size(); ++i)
121+
{
122+
linear_index *= roi_end[i] - roi_begin[i];
123+
}
124+
125+
return xmultiindex_iterator<S>(
126+
std::forward<B>(roi_begin),
127+
std::forward<E>(roi_end),
128+
std::move(current),
129+
linear_index
130+
);
131+
}
132+
133+
}
134+
135+
#endif

include/xtensor/xutils.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,6 @@ namespace xt
334334
/***********************************
335335
* resize_container implementation *
336336
***********************************/
337-
338337
template <class C>
339338
inline bool resize_container(C& c, typename C::size_type size)
340339
{

test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ set(COMMON_BASE
133133
test_xadaptor_semantic.cpp
134134
test_xarray_adaptor.cpp
135135
test_xarray.cpp
136+
test_xblockwise_reducer.cpp
136137
test_xbroadcast.cpp
137138
test_xbuilder.cpp
138139
test_xcontainer_semantic.cpp
@@ -142,6 +143,7 @@ set(COMMON_BASE
142143
test_xexpression_traits.cpp
143144
test_xfunction.cpp
144145
test_xfunc_on_xexpression.cpp
146+
test_xmultiindex_iterator.cpp
145147
test_xiterator.cpp
146148
test_xmath.cpp
147149
test_xoperation.cpp

test/test_common.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010
#ifndef TEST_COMMON_HPP
1111
#define TEST_COMMON_HPP
1212

13+
#include <sstream>
14+
1315
#include "xtensor/xlayout.hpp"
1416
#include "xtensor/xmanipulation.hpp"
17+
#include "xtensor/xreducer.hpp" // tuple_idx_of
18+
1519
#include "test_common_macros.hpp"
1620

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

2933
namespace xt
3034
{
35+
template<class C>
36+
std::string stringify(const C & container)
37+
{
38+
std::size_t i = 0;
39+
std::stringstream ss;
40+
ss << "[";
41+
for(auto && c : container)
42+
{
43+
if(i + 1 == container.size())
44+
{
45+
ss<<c;
46+
}
47+
else
48+
{
49+
ss<<c<<",";
50+
}
51+
++i;
52+
}
53+
ss << "]";
54+
return ss.str();
55+
}
56+
3157
template <class T, class A, class AV>
3258
bool operator==(const uvector<T, A>& lhs, const std::vector<T, AV>& rhs)
3359
{

test/test_common_macros.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#define XT_ASSERT_NO_THROW(x) x;
2828
#endif
2929

30-
#endif
3130

3231
#define EXPECT_NO_THROW(x) XT_EXPECT_NO_THROW(x)
3332
#define EXPECT_THROW(x, y) XT_EXPECT_THROW(x,y)
@@ -55,3 +54,11 @@
5554

5655
#define TEST_F(FIXTURE_CLASS, NAME)\
5756
TEST_CASE_FIXTURE(FIXTURE_CLASS, #NAME)
57+
58+
#define HETEROGEN_PARAMETRIZED_DEFINE(ID)\
59+
TEST_CASE_TEMPLATE_DEFINE(#ID, TypeParam, ID)
60+
61+
#define HETEROGEN_PARAMETRIZED_TEST_APPLY(ID, TEST_FUNC)\
62+
TEST_CASE_TEMPLATE_APPLY(ID, augment_t<std::decay_t<decltype(TEST_FUNC())>>)
63+
64+
#endif

0 commit comments

Comments
 (0)