• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Copyright (c) 2018-2019 Cem Bassoy
2 //
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)
6 //
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.
10 //
11 
12 
13 #include <iostream>
14 #include <algorithm>
15 #include <vector>
16 #include <boost/numeric/ublas/tensor/algorithms.hpp>
17 #include <boost/numeric/ublas/tensor/extents.hpp>
18 #include <boost/numeric/ublas/tensor/strides.hpp>
19 #include "utility.hpp"
20 
21 #include <boost/test/unit_test.hpp>
22 
23 
24 BOOST_AUTO_TEST_SUITE ( test_tensor_algorithms,
25                         * boost::unit_test::depends_on("test_extents")
26                         * boost::unit_test::depends_on("test_strides"))
27 
28 
29 using test_types  = zip<int,long,float,double,std::complex<float>>::with_t<boost::numeric::ublas::first_order, boost::numeric::ublas::last_order>;
30 using test_types2 = std::tuple<int,long,float,double,std::complex<float>>;
31 
32 struct fixture
33 {
34 	using extents_type = boost::numeric::ublas::shape;
fixturefixture35 	fixture()
36 	  : extents {
37 	      extents_type{1,1}, // 1
38 	      extents_type{1,2}, // 2
39 	      extents_type{2,1}, // 3
40 	      extents_type{2,3}, // 4
41 	      extents_type{2,3,1}, // 5
42 	      extents_type{4,1,3}, // 6
43 	      extents_type{1,2,3}, // 7
44 	      extents_type{4,2,3}, // 8
45 	      extents_type{4,2,3,5} } // 9
46 	{
47 	}
48 	std::vector<extents_type> extents;
49 };
50 
51 
52 
53 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_algorithms_copy,value,test_types2,fixture)54 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_copy, value,  test_types2, fixture )
55 {
56 	using namespace boost::numeric;
57 	using value_type   = value;
58 	using vector_type  = std::vector<value_type>;
59 
60 
61 	for(auto const& n : extents) {
62 
63 		auto a  = vector_type(n.product());
64 		auto b  = vector_type(n.product());
65 		auto c  = vector_type(n.product());
66 
67 		auto wa = ublas::strides<ublas::first_order>(n);
68 		auto wb = ublas::strides<ublas::last_order> (n);
69 		auto wc = ublas::strides<ublas::first_order>(n);
70 
71 		auto v = value_type{};
72 		for(auto i = 0ul; i < a.size(); ++i, v+=1){
73 			a[i]=v;
74 		}
75 
76 		ublas::copy( n.size(), n.data(), b.data(), wb.data(), a.data(), wa.data() );
77 		ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), wb.data() );
78 
79 		for(auto i = 1ul; i < c.size(); ++i)
80 			BOOST_CHECK_EQUAL( c[i], a[i] );
81 
82 		using size_type = typename ublas::strides<ublas::first_order>::value_type;
83 		size_type const*const p0 = nullptr;
84 		BOOST_CHECK_THROW( ublas::copy( n.size(), p0, c.data(), wc.data(), b.data(), wb.data() ), std::length_error );
85 		BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c.data(), p0, b.data(), wb.data() ), std::length_error );
86 		BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), p0 ), std::length_error );
87 
88 		value_type* c0 = nullptr;
89 		BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c0, wc.data(), b.data(), wb.data() ), std::length_error );
90 	}
91 
92 	// special case rank == 0
93 	{
94 		auto n = ublas::shape{};
95 
96 		auto a  = vector_type(n.product());
97 		auto b  = vector_type(n.product());
98 		auto c  = vector_type(n.product());
99 
100 
101 		auto wa = ublas::strides<ublas::first_order>(n);
102 		auto wb = ublas::strides<ublas::last_order> (n);
103 		auto wc = ublas::strides<ublas::first_order>(n);
104 
105 		ublas::copy( n.size(), n.data(), b.data(), wb.data(), a.data(), wa.data() );
106 		ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), wb.data() );
107 
108 
109 
110 		BOOST_CHECK_NO_THROW( ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), wb.data() ) );
111 
112 	}
113 
114 
115 
116 
117 
118 }
119 
120 
121 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_algorithms_transform,value,test_types2,fixture)122 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_transform, value,  test_types2, fixture )
123 {
124 	using namespace boost::numeric;
125 	using value_type   = value;
126 	using vector_type  = std::vector<value_type>;
127 
128 
129 	for(auto const& n : extents) {
130 
131 		auto a  = vector_type(n.product());
132 		auto b  = vector_type(n.product());
133 		auto c  = vector_type(n.product());
134 
135 		auto wa = ublas::strides<ublas::first_order>(n);
136 		auto wb = ublas::strides<ublas::last_order> (n);
137 		auto wc = ublas::strides<ublas::first_order>(n);
138 
139 		auto v = value_type{};
140 		for(auto i = 0ul; i < a.size(); ++i, v+=1){
141 			a[i]=v;
142 		}
143 
144 		ublas::transform( n.size(), n.data(), b.data(), wb.data(), a.data(), wa.data(), [](value_type const& a){ return a + value_type(1);} );
145 		ublas::transform( n.size(), n.data(), c.data(), wc.data(), b.data(), wb.data(), [](value_type const& a){ return a - value_type(1);} );
146 
147 		for(auto i = 1ul; i < c.size(); ++i)
148 			BOOST_CHECK_EQUAL( c[i], a[i] );
149 
150 	}
151 }
152 
153 
154 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_algorithms_accumulate,value,test_types2,fixture)155 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_accumulate, value,  test_types2, fixture )
156 {
157 	using namespace boost::numeric;
158 	using value_type   = value;
159 	using vector_type  = std::vector<value_type>;
160 
161 
162 	for(auto const& n : extents) {
163 
164 		auto const s = n.product();
165 
166 		auto a  = vector_type(n.product());
167 		//		auto b  = vector_type(n.product());
168 		//		auto c  = vector_type(n.product());
169 
170 		auto wa = ublas::strides<ublas::first_order>(n);
171 		//		auto wb = ublas::strides<ublas::last_order> (n);
172 		//		auto wc = ublas::strides<ublas::first_order>(n);
173 
174 		auto v = value_type{};
175 		for(auto i = 0ul; i < a.size(); ++i, v+=value_type(1)){
176 			a[i]=v;
177 		}
178 
179 		auto acc = ublas::accumulate( n.size(), n.data(), a.data(), wa.data(), v);
180 
181 		BOOST_CHECK_EQUAL( acc, value_type( s*(s+1) / 2 )  );
182 
183 
184 		auto acc2 = ublas::accumulate( n.size(), n.data(), a.data(), wa.data(), v,
185 		                               [](auto const& l, auto const& r){return l + r; });
186 
187 		BOOST_CHECK_EQUAL( acc2, value_type( s*(s+1) / 2 )  );
188 
189 	}
190 }
191 
192 
193 
194 
195 template<class V>
init(std::vector<V> & a)196 void init(std::vector<V>& a)
197 {
198 	auto v = V(1);
199 	for(auto i = 0u; i < a.size(); ++i, ++v){
200 		a[i] = v;
201 	}
202 }
203 
204 template<class V>
init(std::vector<std::complex<V>> & a)205 void init(std::vector<std::complex<V>>& a)
206 {
207 	auto v = std::complex<V>(1,1);
208 	for(auto i = 0u; i < a.size(); ++i){
209 		a[i] = v;
210 		v.real(v.real()+1);
211 		v.imag(v.imag()+1);
212 	}
213 }
214 
215 
BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_algorithms_trans,value,test_types,fixture)216 BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_trans, value,  test_types, fixture )
217 {
218 	using namespace boost::numeric;
219 	using value_type  = typename value::first_type;
220 	using layout_type = typename value::second_type;
221 	using vector_type  = std::vector<value_type>;
222 	using strides_type = ublas::strides<layout_type>;
223 	using extents_type = ublas::shape;
224 	using size_type = typename extents_type::value_type;
225 	using permutation_type = std::vector<size_type>;
226 
227 
228 	for(auto const& n : extents) {
229 
230 		auto p   = n.size();
231 		auto s   = n.product();
232 
233 		auto pi  = permutation_type(p);
234 		auto a   = vector_type(s);
235 		auto b1  = vector_type(s);
236 		auto b2  = vector_type(s);
237 		auto c1  = vector_type(s);
238 		auto c2  = vector_type(s);
239 
240 		auto wa = strides_type(n);
241 
242 		init(a);
243 
244 		// so wie last-order.
245 		for(auto i = size_type(0), j = p; i < n.size(); ++i, --j)
246 			pi[i] = j;
247 
248 		auto nc = typename extents_type::base_type (p);
249 		for(auto i = 0u; i < p; ++i)
250 			nc[pi[i]-1] = n[i];
251 
252 		auto wc = strides_type(extents_type(nc));
253 		auto wc_pi = typename strides_type::base_type (p);
254 		for(auto i = 0u; i < p; ++i)
255 			wc_pi[pi[i]-1] = wc[i];
256 
257 		ublas::copy ( p, n.data(),            c1.data(), wc_pi.data(), a.data(), wa.data());
258 		ublas::trans( p, n.data(), pi.data(), c2.data(), wc.data(),    a.data(), wa.data() );
259 
260 		if(!std::is_compound_v<value_type>)
261 			for(auto i = 0ul; i < s; ++i)
262 				BOOST_CHECK_EQUAL( c1[i], c2[i] );
263 
264 
265 		auto nb = typename extents_type::base_type (p);
266 		for(auto i = 0u; i < p; ++i)
267 			nb[pi[i]-1] = nc[i];
268 
269 		auto wb = strides_type (extents_type(nb));
270 		auto wb_pi = typename strides_type::base_type (p);
271 		for(auto i = 0u; i < p; ++i)
272 			wb_pi[pi[i]-1] = wb[i];
273 
274 		ublas::copy ( p, nc.data(),            b1.data(), wb_pi.data(), c1.data(), wc.data());
275 		ublas::trans( p, nc.data(), pi.data(), b2.data(), wb.data(),    c2.data(), wc.data() );
276 
277 		if(!std::is_compound_v<value_type>)
278 			for(auto i = 0ul; i < s; ++i)
279 				BOOST_CHECK_EQUAL( b1[i], b2[i] );
280 
281 		for(auto i = 0ul; i < s; ++i)
282 			BOOST_CHECK_EQUAL( a[i], b2[i] );
283 
284 	}
285 }
286 
287 
288 BOOST_AUTO_TEST_SUITE_END()
289