BatchInterface.h
Go to the documentation of this file.
1/*!
2 *
3 *
4 * \brief Defines the Batch Interface for a type, e.g., for every type a container with optimal structure.
5 *
6 *
7 *
8 * \author O.Krause
9 * \date 2012
10 *
11 *
12 * \par Copyright 1995-2017 Shark Development Team
13 *
14 * <BR><HR>
15 * This file is part of Shark.
16 * <https://shark-ml.github.io/Shark/>
17 *
18 * Shark is free software: you can redistribute it and/or modify
19 * it under the terms of the GNU Lesser General Public License as published
20 * by the Free Software Foundation, either version 3 of the License, or
21 * (at your option) any later version.
22 *
23 * Shark is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU Lesser General Public License for more details.
27 *
28 * You should have received a copy of the GNU Lesser General Public License
29 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
30 *
31 */
32#ifndef SHARK_DATA_BATCHINTERFACE_H
33#define SHARK_DATA_BATCHINTERFACE_H
34
35#include <shark/LinAlg/Base.h>
37
38#include <boost/utility/enable_if.hpp>
39#include <boost/mpl/if.hpp>
40#include <type_traits>
41
42namespace shark{
43
44namespace detail{
45
46/// \brief default implementation of a batch where BatchType is a proper sequence
47template<class BatchType>
48struct SimpleBatch{
49 /// \brief Type of a batch of elements.
50 typedef BatchType type;
51 /// \brief Type of a single element.
52 typedef typename type::reference reference;
53 /// \brief Type of a single immutable element.
54 typedef typename type::const_reference const_reference;
55
56
57 /// \brief The type of the elements stored in the batch
58 typedef typename type::value_type value_type;
59
60 /// \brief the iterator type of the object
61 typedef typename type::iterator iterator;
62 /// \brief the const_iterator type of the object
63 typedef typename type::const_iterator const_iterator;
64
65
66 ///\brief creates a batch able to store elements of the structure of input (e.g. same dimensionality)
67 static type createBatch(value_type const& input, std::size_t size = 1){
68 return type(size,input);
69 }
70
71 ///\brief creates a batch storing the elements referenced by the provided range
72 template<class Iterator>
73 static type createBatchFromRange(Iterator const& begin, Iterator const& end){
74 type batch = createBatch(*begin,end-begin);
75 typename type::reference c=batch[0];
76 c=*begin;
77 std::copy(begin,end,batch.begin());
78 return batch;
79 }
80
81 template<class T>
82 static void resize(T& batch, std::size_t batchSize, std::size_t elements){
83 batch.resize(batchSize);
84 }
85
86 //~ ///\brief Swaps the ith element in the first batch with the jth element in the second batch
87 //~ template<class T, class U>
88 //~ static void swap(T& batchi, U& batchj, std::size_t i, std::size_t j){
89 //~ using std::swap;
90 //~ swap(batchi[i],batchj[j]);
91 //~ }
92
93 template<class T>
94 static std::size_t size(T const& batch){return batch.size();}
95
96 template<class T>
97 static typename T::reference get(T& batch, std::size_t i){
98 return batch[i];
99 }
100 template<class T>
101 static typename T::const_reference get(T const& batch, std::size_t i){
102 return batch[i];
103 }
104 template<class T>
105 static typename T::iterator begin(T& batch){
106 return batch.begin();
107 }
108 template<class T>
109 static typename T::const_iterator begin(T const& batch){
110 return batch.begin();
111 }
112 template<class T>
113 static typename T::iterator end(T& batch){
114 return batch.end();
115 }
116 template<class T>
117 static typename T::const_iterator end(T const& batch){
118 return batch.end();
119 }
120};
121
122
123///\brief Wrapper for a matrix row, which offers a conversion operator to
124/// to the Vector Type.
125template<class Matrix>
126class MatrixRowReference: public blas::detail::matrix_row_optimizer<
127 typename blas::closure<Matrix>::type
128>::type{
129private:
130 typedef typename blas::detail::matrix_row_optimizer<
131 typename blas::closure<Matrix>::type
132 >::type row_type;
133public:
134 typedef typename blas::vector_temporary<Matrix>::type Vector;
135
136 MatrixRowReference( Matrix& matrix, std::size_t i)
137 :row_type(row(matrix,i)){}
138 MatrixRowReference(row_type const& matrixrow)
139 :row_type(matrixrow){}
140
141 template<class M2>
142 MatrixRowReference(MatrixRowReference<M2> const& matrixrow)
143 :row_type(matrixrow){}
144
145 template<class T>
146 const MatrixRowReference& operator=(const T& argument){
147 static_cast<row_type&>(*this)=argument;
148 return *this;
149 }
150
151 operator Vector(){
152 return Vector(*this);
153 }
154};
155
156//~ template<class M>
157//~ void swap(MatrixRowReference<M> ref1, MatrixRowReference<M> ref2){
158 //~ swap_rows(ref1.expression().expression(),ref1.index(),ref2.expression().expression(),ref2.index());
159//~ }
160
161//~ template<class M1, class M2>
162//~ void swap(MatrixRowReference<M1> ref1, MatrixRowReference<M2> ref2){
163 //~ swap_rows(ref1.expression().expression(),ref1.index(),ref2.expression().expression(),ref2.index());
164//~ }
165
166template<class Matrix>
167struct VectorBatch{
168 /// \brief Type of a batch of elements.
169 typedef typename blas::matrix_temporary<Matrix>::type type;
170
171 /// \brief The type of the elements stored in the batch
172 typedef typename blas::vector_temporary<Matrix>::type value_type;
173
174
175 /// \brief Type of a single element.
176 typedef detail::MatrixRowReference<Matrix> reference;
177 /// \brief Type of a single immutable element.
178 typedef detail::MatrixRowReference<const Matrix> const_reference;
179
180
181 /// \brief the iterator type of the object
182 typedef ProxyIterator<Matrix, value_type, reference > iterator;
183 /// \brief the const_iterator type of the object
184 typedef ProxyIterator<const Matrix, value_type, const_reference > const_iterator;
185
186 ///\brief creates a batch with input as size blueprint
187 template<class Element>
188 static type createBatch(Element const& input, std::size_t size = 1){
189 return type(size,input.size());
190 }
191 ///\brief creates a batch storing the elements referenced by the provided range
192 template<class Iterator>
193 static type createBatchFromRange(Iterator const& pos, Iterator const& end){
194 type batch(end - pos,pos->size());
195 std::copy(pos,end,begin(batch));
196 return batch;
197 }
198
199
200 static void resize(Matrix& batch, std::size_t batchSize, std::size_t elements){
201 ensure_size(batch,batchSize,elements);
202 }
203
204 static std::size_t size(Matrix const& batch){return batch.size1();}
205 static reference get( Matrix& batch, std::size_t i){
206 return reference(batch,i);
207 }
208 static const_reference get( Matrix const& batch, std::size_t i){
209 return const_reference(batch,i);
210 }
211
212 static iterator begin(Matrix& batch){
213 return iterator(batch,0);
214 }
215 static const_iterator begin(Matrix const& batch){
216 return const_iterator(batch,0);
217 }
218
219 static iterator end(Matrix& batch){
220 return iterator(batch,batch.size1());
221 }
222 static const_iterator end(Matrix const& batch){
223 return const_iterator(batch,batch.size1());
224 }
225};
226
227
228}
229
230///\brief class which helps using different batch types
231///
232/// e.g. creating a batch of a single element or returning a single element
233/// when the element type is arithmetic, like int,double, std::complex,...
234/// the return value will be a linear algebra compatible vector, like RealVector.
235/// If it is not, for example a string, the return value will be a std::vector<T>.
236template<class T>
237//see detail above for implementations, we just choose the correct implementations based on
238//whether T is arithmetic or not
239struct Batch
240:public std::conditional<
241 std::is_arithmetic<T>::value,
242 detail::SimpleBatch<blas::vector<T> >,
243 detail::SimpleBatch<std::vector<T> >
244>::type{};
245
246/// \brief specialization for vectors which should be matrices in batch mode!
247template<class T, class Device>
248struct Batch<blas::vector<T, Device> >: public detail::VectorBatch<blas::matrix<T, blas::row_major, Device> >{};
249
250/// \brief specialization for ublas compressed vectors which are compressed matrices in batch mode!
251template<class T>
252struct Batch<shark::blas::compressed_vector<T> >{
253 /// \brief Type of a batch of elements.
254 typedef shark::blas::compressed_matrix<T> type;
255
256 /// \brief The type of the elements stored in the batch
257 typedef shark::blas::compressed_vector<T> value_type;
258
259
260 /// \brief Type of a single element.
261 typedef detail::MatrixRowReference<type> reference;
262 /// \brief Type of a single immutable element.
263 typedef detail::MatrixRowReference<const type> const_reference;
264
265
266 /// \brief the iterator type of the object
268 /// \brief the const_iterator type of the object
270
271 ///\brief creates a batch with input as size blueprint
272 template<class Element>
273 static type createBatch(Element const& input, std::size_t size = 1){
274 return type(size,input.size());
275 }
276 ///\brief creates a batch storing the elements referenced by the provided range
277 template<class Iterator>
278 static type createBatchFromRange(Iterator const& start, Iterator const& end){
279 //before creating the batch, we need the number of nonzero elements
280 std::size_t nonzeros = 0;
281 for(Iterator pos = start; pos != end; ++pos){
282 nonzeros += pos->nnz();
283 }
284
285 std::size_t size = end - start;
286 type batch(size,start->size(),nonzeros);
287
288 Iterator pos = start;
289 for(std::size_t i = 0; i != size; ++i, ++pos){
290 auto row_start = batch.major_end(i);
291 for(auto elem_pos = pos->begin(); elem_pos != pos->end(); ++elem_pos){
292 row_start = batch.set_element(row_start, elem_pos.index(), *elem_pos);
293 }
294 }
295 //~ std::copy(start,end,begin(batch));
296 return batch;
297 }
298
299
300 static void resize(type& batch, std::size_t batchSize, std::size_t elements){
301 ensure_size(batch,batchSize,elements);
302 }
303
304 static std::size_t size(type const& batch){return batch.size1();}
305 static reference get( type& batch, std::size_t i){
306 return reference(batch,i);
307 }
308 static const_reference get( type const& batch, std::size_t i){
309 return const_reference(batch,i);
310 }
311
312 static iterator begin(type& batch){
313 return iterator(batch,0);
314 }
315 static const_iterator begin(type const& batch){
316 return const_iterator(batch,0);
317 }
318
319 static iterator end(type& batch){
320 return iterator(batch,batch.size1());
321 }
322 static const_iterator end(type const& batch){
323 return const_iterator(batch,batch.size1());
324 }
325};
326
327template<class M>
328struct Batch<detail::MatrixRowReference<M> >
329:public Batch<typename detail::MatrixRowReference<M>::Vector>{};
330
331
332template<class BatchType>
336
337template<class T, class Device>
338struct BatchTraits<blas::matrix<T, blas::row_major, Device> >{
340};
341template<class T>
342struct BatchTraits<blas::compressed_matrix<T> >{
344};
345template<class T, class Tag, class Device>
346struct BatchTraits<blas::dense_matrix_adaptor<T, blas::row_major, Tag, Device> >{
347 typedef detail::VectorBatch<blas::dense_matrix_adaptor<T, blas::row_major, Tag, Device> > type;
348};
349
350namespace detail{
351template<class T>
352struct batch_to_element{
353 typedef typename BatchTraits<T>::type::value_type type;
354};
355template<class T>
356struct batch_to_element<T&>{
357 //~ typedef typename BatchTraits<T>::type::reference type;
358 typedef typename BatchTraits<T>::type::value_type type;
359};
360template<class T>
361struct batch_to_element<T const&>{
362 //~ typedef typename BatchTraits<T>::type::const_reference type;
363 typedef typename BatchTraits<T>::type::value_type type;
364};
365
366template<class T>
367struct batch_to_reference{
368 typedef typename BatchTraits<T>::type::reference type;
369};
370template<class T>
371struct batch_to_reference<T&>{
372 typedef typename BatchTraits<T>::type::reference type;
373};
374template<class T>
375struct batch_to_reference<T const&>{
376 typedef typename BatchTraits<T>::type::const_reference type;
377};
378
379template<class T>
380struct element_to_batch{
381 typedef typename Batch<T>::type type;
382};
383template<class T>
384struct element_to_batch<T&>{
385 typedef typename Batch<T>::type& type;
386};
387template<class T>
388struct element_to_batch<T const&>{
389 typedef typename Batch<T>::type const& type;
390};
391template<class M>
392struct element_to_batch<detail::MatrixRowReference<M> >{
393 typedef typename Batch<typename detail::MatrixRowReference<M>::Vector>::type& type;
394};
395template<class M>
396struct element_to_batch<detail::MatrixRowReference<M const> >{
397 typedef typename Batch<typename detail::MatrixRowReference<M>::Vector>::type const& type;
398};
399}
400
401
402///\brief creates a batch from a range of inputs
403template<class T, class Range>
404typename Batch<T>::type createBatch(Range const& range){
405 return Batch<T>::createBatchFromRange(range.begin(),range.end());
406}
407
408///\brief creates a batch from a range of inputs
409template<class Range>
411 return Batch<typename Range::value_type>::createBatchFromRange(range.begin(),range.end());
412}
413
414template<class T, class Iterator>
415typename Batch<T>::type createBatch(Iterator const& begin, Iterator const& end){
416 return Batch<T>::createBatchFromRange(begin,end);
417}
418
419template<class BatchT>
420auto getBatchElement(BatchT& batch, std::size_t i)->decltype(BatchTraits<BatchT>::type::get(std::declval<BatchT&>(),i)){
421 return BatchTraits<BatchT>::type::get(batch,i);
422}
423
424template<class BatchT>
425auto getBatchElement(BatchT const& batch, std::size_t i)->decltype(BatchTraits<BatchT>::type::get(std::declval<BatchT const&>(),i)){
426 return BatchTraits<BatchT>::type::get(batch,i);
427}
428
429template<class BatchT>
430std::size_t batchSize(BatchT const& batch){
432}
433
434template<class BatchT>
435auto batchBegin(BatchT& batch)->decltype(BatchTraits<BatchT>::type::begin(batch)){
437}
438
439template<class BatchT>
440auto batchBegin(BatchT const& batch)->decltype(BatchTraits<BatchT>::type::begin(batch)){
442}
443
444template<class BatchT>
445auto batchEnd(BatchT& batch)->decltype(BatchTraits<BatchT>::type::end(batch)){
446 return BatchTraits<BatchT>::type::end(batch);
447}
448
449template<class BatchT>
450auto batchEnd(BatchT const& batch)->decltype(BatchTraits<BatchT>::type::end(batch)){
451 return BatchTraits<BatchT>::type::end(batch);
452}
453
454
455}
456#endif