1 // Copyright (c) 2018-2019 Cem Bassoy
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // The authors gratefully acknowledge the support of
8 // Fraunhofer and Google in producing this work
9 // which started as a Google Summer of Code project.
14 #include <boost/numeric/ublas/tensor/expression_evaluation.hpp>
15 #include <boost/numeric/ublas/tensor/expression.hpp>
16 #include <boost/numeric/ublas/tensor/tensor.hpp>
17 #include <boost/test/unit_test.hpp>
18 #include "utility.hpp"
22 using test_types
= zip
<int,long,float,double,std::complex<float>>::with_t
<boost::numeric::ublas::first_order
, boost::numeric::ublas::last_order
>;
27 using extents_type
= boost::numeric::ublas::shape
;
32 extents_type
{1,1}, // 1
33 extents_type
{1,2}, // 2
34 extents_type
{2,1}, // 3
36 extents_type
{2,3}, // 4
37 extents_type
{2,3,1}, // 5
38 extents_type
{1,2,3}, // 6
39 extents_type
{1,1,2,3}, // 7
40 extents_type
{1,2,3,1,1}, // 8
42 extents_type
{4,2,3}, // 9
43 extents_type
{4,2,1,3}, // 10
44 extents_type
{4,2,1,3,1}, // 11
45 extents_type
{1,4,2,1,3,1}} // 12
48 std::vector
<extents_type
> extents
;
53 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_expression_retrieve_extents
, value
, test_types
, fixture
)
55 using namespace boost::numeric
;
56 using value_type
= typename
value::first_type
;
57 using layout_type
= typename
value::second_type
;
58 using tensor_type
= ublas::tensor
<value_type
, layout_type
>;
60 auto uplus1
= std::bind( std::plus
<value_type
>{}, std::placeholders::_1
, value_type(1) );
61 auto uplus2
= std::bind( std::plus
<value_type
>{}, value_type(2), std::placeholders::_2
);
62 auto bplus
= std::plus
<value_type
>{};
63 auto bminus
= std::minus
<value_type
>{};
65 for(auto const& e
: extents
) {
67 auto t
= tensor_type(e
);
68 auto v
= value_type
{};
69 for(auto& tt
: t
){ tt
= v
; v
+=value_type
{1}; }
72 BOOST_CHECK( ublas::detail::retrieve_extents( t
) == e
);
77 auto uexpr1
= ublas::detail::make_unary_tensor_expression
<tensor_type
>( t
, uplus1
);
78 auto uexpr2
= ublas::detail::make_unary_tensor_expression
<tensor_type
>( t
, uplus2
);
80 BOOST_CHECK( ublas::detail::retrieve_extents( uexpr1
) == e
);
81 BOOST_CHECK( ublas::detail::retrieve_extents( uexpr2
) == e
);
83 // bexpr_uexpr = (t+1) + (2+t)
84 auto bexpr_uexpr
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( uexpr1
, uexpr2
, bplus
);
86 BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_uexpr
) == e
);
89 // bexpr_bexpr_uexpr = ((t+1) + (2+t)) - t
90 auto bexpr_bexpr_uexpr
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( bexpr_uexpr
, t
, bminus
);
92 BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_bexpr_uexpr
) == e
);
97 for(auto i
= 0u; i
< extents
.size()-1; ++i
)
100 auto v
= value_type
{};
102 auto t1
= tensor_type(extents
[i
]);
103 for(auto& tt
: t1
){ tt
= v
; v
+=value_type
{1}; }
105 auto t2
= tensor_type(extents
[i
+1]);
106 for(auto& tt
: t2
){ tt
= v
; v
+=value_type
{2}; }
108 BOOST_CHECK( ublas::detail::retrieve_extents( t1
) != ublas::detail::retrieve_extents( t2
) );
112 auto uexpr1
= ublas::detail::make_unary_tensor_expression
<tensor_type
>( t1
, uplus1
);
113 auto uexpr2
= ublas::detail::make_unary_tensor_expression
<tensor_type
>( t2
, uplus2
);
115 BOOST_CHECK( ublas::detail::retrieve_extents( t1
) == ublas::detail::retrieve_extents( uexpr1
) );
116 BOOST_CHECK( ublas::detail::retrieve_extents( t2
) == ublas::detail::retrieve_extents( uexpr2
) );
117 BOOST_CHECK( ublas::detail::retrieve_extents( uexpr1
) != ublas::detail::retrieve_extents( uexpr2
) );
119 // bexpr_uexpr = (t1+1) + (2+t2)
120 auto bexpr_uexpr
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( uexpr1
, uexpr2
, bplus
);
122 BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_uexpr
) == ublas::detail::retrieve_extents(t1
) );
125 // bexpr_bexpr_uexpr = ((t1+1) + (2+t2)) - t2
126 auto bexpr_bexpr_uexpr1
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( bexpr_uexpr
, t2
, bminus
);
128 BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_bexpr_uexpr1
) == ublas::detail::retrieve_extents(t2
) );
131 // bexpr_bexpr_uexpr = t2 - ((t1+1) + (2+t2))
132 auto bexpr_bexpr_uexpr2
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( t2
, bexpr_uexpr
, bminus
);
134 BOOST_CHECK( ublas::detail::retrieve_extents( bexpr_bexpr_uexpr2
) == ublas::detail::retrieve_extents(t2
) );
144 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_expression_all_extents_equal
, value
, test_types
, fixture
)
146 using namespace boost::numeric
;
147 using value_type
= typename
value::first_type
;
148 using layout_type
= typename
value::second_type
;
149 using tensor_type
= ublas::tensor
<value_type
, layout_type
>;
151 auto uplus1
= std::bind( std::plus
<value_type
>{}, std::placeholders::_1
, value_type(1) );
152 auto uplus2
= std::bind( std::plus
<value_type
>{}, value_type(2), std::placeholders::_2
);
153 auto bplus
= std::plus
<value_type
>{};
154 auto bminus
= std::minus
<value_type
>{};
156 for(auto const& e
: extents
) {
158 auto t
= tensor_type(e
);
159 auto v
= value_type
{};
160 for(auto& tt
: t
){ tt
= v
; v
+=value_type
{1}; }
163 BOOST_CHECK( ublas::detail::all_extents_equal( t
, e
) );
168 auto uexpr1
= ublas::detail::make_unary_tensor_expression
<tensor_type
>( t
, uplus1
);
169 auto uexpr2
= ublas::detail::make_unary_tensor_expression
<tensor_type
>( t
, uplus2
);
171 BOOST_CHECK( ublas::detail::all_extents_equal( uexpr1
, e
) );
172 BOOST_CHECK( ublas::detail::all_extents_equal( uexpr2
, e
) );
174 // bexpr_uexpr = (t+1) + (2+t)
175 auto bexpr_uexpr
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( uexpr1
, uexpr2
, bplus
);
177 BOOST_CHECK( ublas::detail::all_extents_equal( bexpr_uexpr
, e
) );
180 // bexpr_bexpr_uexpr = ((t+1) + (2+t)) - t
181 auto bexpr_bexpr_uexpr
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( bexpr_uexpr
, t
, bminus
);
183 BOOST_CHECK( ublas::detail::all_extents_equal( bexpr_bexpr_uexpr
, e
) );
188 for(auto i
= 0u; i
< extents
.size()-1; ++i
)
191 auto v
= value_type
{};
193 auto t1
= tensor_type(extents
[i
]);
194 for(auto& tt
: t1
){ tt
= v
; v
+=value_type
{1}; }
196 auto t2
= tensor_type(extents
[i
+1]);
197 for(auto& tt
: t2
){ tt
= v
; v
+=value_type
{2}; }
199 BOOST_CHECK( ublas::detail::all_extents_equal( t1
, ublas::detail::retrieve_extents(t1
) ) );
200 BOOST_CHECK( ublas::detail::all_extents_equal( t2
, ublas::detail::retrieve_extents(t2
) ) );
204 auto uexpr1
= ublas::detail::make_unary_tensor_expression
<tensor_type
>( t1
, uplus1
);
205 auto uexpr2
= ublas::detail::make_unary_tensor_expression
<tensor_type
>( t2
, uplus2
);
207 BOOST_CHECK( ublas::detail::all_extents_equal( uexpr1
, ublas::detail::retrieve_extents(uexpr1
) ) );
208 BOOST_CHECK( ublas::detail::all_extents_equal( uexpr2
, ublas::detail::retrieve_extents(uexpr2
) ) );
210 // bexpr_uexpr = (t1+1) + (2+t2)
211 auto bexpr_uexpr
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( uexpr1
, uexpr2
, bplus
);
213 BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_uexpr
, ublas::detail::retrieve_extents( bexpr_uexpr
) ) );
215 // bexpr_bexpr_uexpr = ((t1+1) + (2+t2)) - t2
216 auto bexpr_bexpr_uexpr1
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( bexpr_uexpr
, t2
, bminus
);
218 BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_bexpr_uexpr1
, ublas::detail::retrieve_extents( bexpr_bexpr_uexpr1
) ) );
220 // bexpr_bexpr_uexpr = t2 - ((t1+1) + (2+t2))
221 auto bexpr_bexpr_uexpr2
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( t2
, bexpr_uexpr
, bminus
);
223 BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_bexpr_uexpr2
, ublas::detail::retrieve_extents( bexpr_bexpr_uexpr2
) ) );
226 // bexpr_uexpr2 = (t1+1) + t2
227 auto bexpr_uexpr2
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( uexpr1
, t2
, bplus
);
228 BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_uexpr2
, ublas::detail::retrieve_extents( bexpr_uexpr2
) ) );
231 // bexpr_uexpr2 = ((t1+1) + t2) + t1
232 auto bexpr_bexpr_uexpr3
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( bexpr_uexpr2
, t1
, bplus
);
233 BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_bexpr_uexpr3
, ublas::detail::retrieve_extents( bexpr_bexpr_uexpr3
) ) );
235 // bexpr_uexpr2 = t1 + (((t1+1) + t2) + t1)
236 auto bexpr_bexpr_uexpr4
= ublas::detail::make_binary_tensor_expression
<tensor_type
>( t1
, bexpr_bexpr_uexpr3
, bplus
);
237 BOOST_CHECK( ! ublas::detail::all_extents_equal( bexpr_bexpr_uexpr4
, ublas::detail::retrieve_extents( bexpr_bexpr_uexpr4
) ) );