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-2015 Shark Development Team
13  *
14  * <BR><HR>
15  * This file is part of Shark.
16  * <http://image.diku.dk/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/preprocessor.hpp>
39 
40 #include <boost/type_traits/is_arithmetic.hpp>
41 #include <boost/type_traits/is_same.hpp>
42 #include <boost/utility/enable_if.hpp>
43 #include <boost/range/algorithm_ext/iota.hpp>
44 #include <boost/mpl/if.hpp>
45 
46 namespace shark{
47 
48 namespace detail{
49 
50 /// \brief default implementation of the Batch which maps it's type on std::vector<T>
51 template<class T>
52 struct DefaultBatch{
53  /// \brief Type of a single element.
54  typedef T& reference;
55  /// \brief Type of a single immutable element.
56  typedef T const& const_reference;
57  /// \brief Type of a batch of elements.
58  typedef std::vector<T> type;
59 
60  /// \brief The type of the elements stored in the batch
61  typedef T value_type;
62 
63  /// \brief the iterator type of the object
64  typedef typename type::iterator iterator;
65  /// \brief the const_iterator type of the object
66  typedef typename type::const_iterator const_iterator;
67 
68 
69  ///\brief creates a batch able to store elements of the structure of input (e.g. same dimensionality)
70  static type createBatch(T const& input, std::size_t size = 1){
71  return type(size,input);
72  }
73 
74  ///\brief creates a batch storing the elements referenced by the provided range
75  template<class Range>
76  static type createBatchFromRange(Range const& range){
77  return type(range.begin(),range.end());
78  }
79 
80  static void resize(type& batch, std::size_t batchSize, std::size_t elements){
81  batch.resize(batchSize);
82  }
83 };
84 
85 /// \brief default implementation of the Batch for arithmetic types, which are mapped on shark::blas::vector<T>
86 template<class T>
87 struct ArithmeticBatch{
88  /// \brief Type of a single element.
89  typedef T& reference;
90  /// \brief Type of a single immutable element.
91  typedef T const& const_reference;
92  /// \brief Type of a batch of elements.
93  typedef shark::blas::vector<T> type;
94 
95  /// \brief The type of the elements stored in the batch
96  typedef T value_type;
97 
98  /// \brief the iterator type of the object
99  typedef typename type::iterator iterator;
100  /// \brief the const_iterator type of the object
101  typedef typename type::const_iterator const_iterator;
102 
103 
104  ///\brief creates a batch which can storne size numbers of type T
105  static type createBatch(T const& input, std::size_t size = 1){
106  return type(size,input);
107  }
108  ///\brief creates a batch storing the elements referenced by the provided range
109  template<class Range>
110  static type createBatchFromRange(Range const& range){
111  type batch(range.size());
112  std::copy(range.begin(),range.end(),batch.begin());
113  return batch;
114  }
115 
116  static void resize(type& batch, std::size_t batchSize, std::size_t elements){
117  ensure_size(batch,batchSize);
118  }
119 };
120 
121 ///\brief Wrapper for a matrix row, which offers a conversion operator to
122 /// to the Vector Type.
123 template<class Matrix, class Vector>
124 class MatrixRowReference: public blas::temporary_proxy<blas::matrix_row<Matrix> >{
125 private:
126  typedef blas::temporary_proxy<blas::matrix_row<Matrix> > base_type;
127 public:
128  MatrixRowReference( Matrix& matrix, std::size_t i)
129  :base_type(blas::matrix_row<Matrix>(matrix,i)){}
130  template<class T>//special version allows for const-conversion
131  MatrixRowReference(T const& matrixrow)
132  :base_type(blas::matrix_row<Matrix>(matrixrow.expression().expression(),matrixrow.index())){}
133 
134  template<class T>
135  const MatrixRowReference& operator=(const T& argument){
136  static_cast<base_type&>(*this)=argument;
137  return *this;
138  }
139 
140  operator Vector(){
141  return Vector(*this);
142  }
143 };
144 
145 template<class M, class V>
146 void swap(MatrixRowReference<M,V> ref1, MatrixRowReference<M,V> ref2){
147  swap_rows(ref1.expression().expression(),ref1.index(),ref2.expression().expression(),ref2.index());
148 }
149 
150 }
151 
152 ///\brief class which helps using different batch types
153 ///
154 /// e.g. creating a batch of a single element or returning a single element
155 /// when the element type is arithmetic, like int,double, std::complex,...
156 /// the return value will be a linear algebra compatible vector, like RealVector.
157 /// If it is not, for example a string, the return value will be a std::vector<T>.
158 template<class T>
159 //see detail above for implementations, we just choose the correct implementations based on
160 //whether T is arithmetic or not
161 struct Batch
162 :public boost::mpl::if_<
163  boost::is_arithmetic<T>,
164  detail::ArithmeticBatch<T>,
165  detail::DefaultBatch<T>
166 >::type{};
167 
168 
169 ///\brief creates a batch from a range of inputs
170 template<class T, class Range>
171 typename Batch<T>::type createBatch(Range const& range){
172  return Batch<T>::createBatchFromRange(range);
173 }
174 
175 template< class Range>
178 }
179 
180 /// \cond
181 
182 /// \brief specialization for vectors which should be matrices in batch mode!
183 template<class T>
184 struct Batch<blas::vector<T> >{
185  /// \brief Type of a batch of elements.
186  typedef shark::blas::matrix<T> type;
187  /// \brief The type of the elements stored in the batch
188  typedef blas::vector<T> value_type;
189 
190 
191  /// \brief Reference to a single element.
192  typedef detail::MatrixRowReference<type,value_type> reference;
193  /// \brief Reference to a single immutable element.
194  typedef detail::MatrixRowReference<const type,value_type> const_reference;
195 
196 
197  /// \brief the iterator type of the object
199  /// \brief the const_iterator type of the object
201 
202  ///\brief creates a batch with input as size blueprint
203  template<class Element>
204  static type createBatch(Element const& input, std::size_t size = 1){
205  return type(size,input.size());
206  }
207  ///\brief creates a batch storing the elements referenced by the provided range
208  template<class Range>
209  static type createBatchFromRange(Range const& range){
210  type batch(range.size(),range.begin()->size());
211  std::copy(range.begin(),range.end(),boost::begin(batch));
212  return batch;
213  }
214 
215  static void resize(type& batch, std::size_t batchSize, std::size_t elements){
216  ensure_size(batch,batchSize,elements);
217  }
218 };
219 
220 /// \brief specialization for ublas compressed vectors which are compressed matrices in batch mode!
221 template<class T>
222 struct Batch<shark::blas::compressed_vector<T> >{
223  /// \brief Type of a batch of elements.
225 
226  /// \brief The type of the elements stored in the batch
227  typedef shark::blas::compressed_vector<T> value_type;
228 
229 
230  /// \brief Type of a single element.
231  //typedef shark::blas::matrix_row<type> reference;
232  typedef detail::MatrixRowReference<type,value_type> reference;
233  /// \brief Type of a single immutable element.
234  //typedef shark::blas::matrix_row<const type> const_reference;
235  typedef detail::MatrixRowReference<const type,value_type> const_reference;
236 
237 
238  /// \brief the iterator type of the object
240  /// \brief the const_iterator type of the object
242 
243  ///\brief creates a batch with input as size blueprint
244  template<class Element>
245  static type createBatch(Element const& input, std::size_t size = 1){
246  return type(size,input.size());
247  }
248  ///\brief creates a batch storing the elements referenced by the provided range
249  template<class Range>
250  static type createBatchFromRange(Range const& range){
251  //before creating the batch, we need the number of nonzero elements
252  std::size_t nonzeros = 0;
253  for(typename Range::const_iterator pos = range.begin(); pos != range.end(); ++pos){
254  nonzeros += pos->nnz();
255  }
256 
257  type batch(range.size(),range.begin()->size(),nonzeros);
258  std::copy(range.begin(),range.end(),boost::begin(batch));
259  return batch;
260  }
261 
262 
263  static void resize(type& batch, std::size_t batchSize, std::size_t elements){
264  ensure_size(batch,batchSize,elements);
265  }
266 };
267 /// \brief specialization for blas::matrix which become blas::matrix_set in batch mode!
268 template<class T>
269 struct Batch<blas::matrix<T> >{
270  /// \brief Type of a batch of elements.
272  /// \brief The type of the elements stored in the batch
273  typedef blas::matrix<T> value_type;
274 
275 
276  /// \brief Reference to a single element.
277  typedef typename type::reference reference;
278  /// \brief Reference to a single immutable element.
279  typedef typename type::const_reference const_reference;
280 
281 
282  /// \brief the iterator type of the object
283  typedef typename type::iterator iterator;
284  /// \brief the const_iterator type of the object
285  typedef typename type::const_iterator const_iterator;
286 
287  ///\brief creates a batch with input as size blueprint
288  template<class Element>
289  static type createBatch(Element const& input, std::size_t size = 1){
290  return type(size,input);
291  }
292  ///\brief creates a batch storing the elements referenced by the provided range
293  template<class Range>
294  static type createBatchFromRange(Range const& range){
295  type batch(range.size());
296  std::copy(range.begin(),range.end(),batch.begin());
297  return batch;
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 
305 
306 }
307 
308 //template specialization for boost::matrices so that they offer the iterator interface
309 
310 namespace boost{
311 //first the typedefs which tell boost::range which iterators to use. this needs to be done for all
312 //supported matrix types separately as well as for the matrix_container/matrix_expression base type
313 
314 //dense matrix
315 template< class T >
316 struct range_mutable_iterator< shark::blas::matrix<T> >{
317  typedef shark::blas::vector<T> Vector;
318  typedef typename shark::Batch<Vector>::iterator type;
319 };
320 
321 template< class T >
322 struct range_const_iterator< shark::blas::matrix<T> >{
323  typedef shark::blas::vector<T> Vector;
324  typedef typename shark::Batch<Vector>::const_iterator type;
325 };
326 //compressed matrix
327 template< class T >
328 struct range_mutable_iterator< shark::blas::compressed_matrix<T> >{
329  typedef shark::blas::compressed_vector<T> Vector;
330  typedef typename shark::Batch<Vector>::iterator type;
331 };
332 
333 template< class T >
334 struct range_const_iterator< shark::blas::compressed_matrix<T> >{
335  typedef shark::blas::compressed_vector<T> Vector;
336  typedef typename shark::Batch<Vector>::const_iterator type;
337 };
338 
339 //matrix container
340 template< class M >
341 struct range_mutable_iterator< shark::blas::matrix_container<M> >{
342  typedef typename range_mutable_iterator<M>::type type;
343 };
344 
345 template< class M >
346 struct range_const_iterator< shark::blas::matrix_container<M> >{
347  typedef typename range_const_iterator<M>::type type;
348 };
349 
350 //matrix expression
351 template< class M >
352 struct range_mutable_iterator< shark::blas::matrix_expression<M> >{
353  typedef typename range_mutable_iterator<M>::type type;
354 };
355 
356 template< class M >
357 struct range_const_iterator< shark::blas::matrix_expression<M> >{
358  typedef typename range_const_iterator<M>::type type;
359 };
360 
361 //matrix proxy
362 template< class T >
363 struct range_mutable_iterator< shark::blas::dense_matrix_adaptor<T> >{
365  typedef shark::detail::MatrixRowReference<shark::blas::dense_matrix_adaptor<T>,Vector> reference;
366  typedef shark::ProxyIterator<shark::blas::dense_matrix_adaptor<T>, Vector, reference > type;
367 };
368 
369 template< class T >
370 struct range_const_iterator< shark::blas::dense_matrix_adaptor<T> >{
372  typedef shark::detail::MatrixRowReference<shark::blas::dense_matrix_adaptor<T> const,Vector> reference;
373  typedef shark::ProxyIterator<shark::blas::dense_matrix_adaptor<T> const, Vector, reference > type;
374 };
375 }
376 
377 namespace shark{ namespace blas{
378 
379 //dense matrix
380 template< class T >
381 typename boost::range_iterator<matrix<T> const>::type
382 range_begin( matrix<T> const& m )
383 {
384  typedef typename boost::range_iterator<matrix<T> const>::type Iter;
385  return Iter(m,0);
386 }
387 template< class T >
388 typename boost::range_iterator<matrix<T> >::type
389 range_begin( matrix<T>& m )
390 {
391  typedef typename boost::range_iterator<matrix<T> >::type Iter;
392  return Iter(m,0);
393 }
394 
395 template< class T >
396 typename boost::range_iterator<matrix<T> const>::type
397 range_end( matrix<T> const& m )
398 {
399  typedef typename boost::range_iterator<matrix<T> const>::type Iter;
400  return Iter(m,m.size1());
401 }
402 template< class T >
403 typename boost::range_iterator<matrix<T> >::type
404 range_end( matrix<T>& m )
405 {
406  typedef typename boost::range_iterator<matrix<T> >::type Iter;
407  return Iter(m,m.size1());
408 }
409 
410 //compressed matrix
411 template< class T >
412 typename boost::range_iterator<compressed_matrix<T> const>::type
413 range_begin( compressed_matrix<T> const& m )
414 {
415  typedef typename boost::range_iterator<compressed_matrix<T> const>::type Iter;
416  return Iter(m,0);
417 }
418 template< class T >
419 typename boost::range_iterator<compressed_matrix<T> >::type
420 range_begin( compressed_matrix<T>& m )
421 {
422  typedef typename boost::range_iterator<compressed_matrix<T> >::type Iter;
423  return Iter(m,0);
424 }
425 
426 template< class T >
427 typename boost::range_iterator<compressed_matrix<T> const>::type
428 range_end( compressed_matrix<T> const& m )
429 {
430  typedef typename boost::range_iterator<compressed_matrix<T> const>::type Iter;
431  return Iter(m,m.size1());
432 }
433 template< class T >
434 typename boost::range_iterator<compressed_matrix<T> >::type
435 range_end( compressed_matrix<T>& m )
436 {
437  typedef typename boost::range_iterator<compressed_matrix<T> >::type Iter;
438  return Iter(m,m.size1());
439 }
440 
441 //matrix_container
442 template< class M >
443 typename boost::range_iterator<M const>::type
444 range_begin( matrix_container<M> const& m )
445 {
446  return range_begin(m());
447 }
448 template< class M >
449 typename boost::range_iterator<M>::type
450 range_begin( matrix_container<M>& m )
451 {
452  return range_begin(m());
453 }
454 
455 template< class M >
456 typename boost::range_iterator<M const>::type
457 range_end( matrix_container<M> const& m )
458 {
459  return range_end(m());
460 }
461 template< class M >
462 typename boost::range_iterator<M>::type
463 range_end( matrix_container<M>& m )
464 {
465  return range_end(m());
466 }
467 
468 //matrix_expression
469 template< class M >
470 typename boost::range_iterator<M const>::type
471 range_begin( matrix_expression<M> const& m )
472 {
473  return range_begin(m());
474 }
475 template< class M >
476 typename boost::range_iterator<M>::type
477 range_begin( matrix_expression<M>& m )
478 {
479  return range_begin(m());
480 }
481 
482 template< class M >
483 typename boost::range_iterator<M const>::type
484 range_end( matrix_expression<M> const& m )
485 {
486  return range_end(m());
487 }
488 template< class M >
489 typename boost::range_iterator<M>::type
490 range_end( matrix_expression<M>& m )
491 {
492  return range_end(m());
493 }
494 
495 //dense matrix proxy
496 template< class T >
497 typename boost::range_iterator<shark::blas::dense_matrix_adaptor<T> const>::type
498 range_begin( shark::blas::dense_matrix_adaptor<T> const& m )
499 {
500  typedef typename boost::range_iterator<shark::blas::dense_matrix_adaptor<T> const>::type Iter;
501  return Iter(m,0);
502 }
503 template< class T >
504 typename boost::range_iterator<shark::blas::dense_matrix_adaptor<T> >::type
505 range_begin( shark::blas::dense_matrix_adaptor<T>& m )
506 {
507  typedef typename boost::range_iterator<shark::blas::dense_matrix_adaptor<T> >::type Iter;
508  return Iter(m,0);
509 }
510 
511 template< class T >
512 typename boost::range_iterator<shark::blas::dense_matrix_adaptor<T> const>::type
513 range_end( shark::blas::dense_matrix_adaptor<T> const& m )
514 {
515  typedef typename boost::range_iterator<shark::blas::dense_matrix_adaptor<T> const>::type Iter;
516  return Iter(m,m.size1());
517 }
518 template< class T >
519 typename boost::range_iterator<shark::blas::dense_matrix_adaptor<T> >::type
521 {
522  typedef typename boost::range_iterator<shark::blas::dense_matrix_adaptor<T> >::type Iter;
523  return Iter(m,m.size1());
524 }
525 
526 /// \endcond
527 
528 }}
529 
530 #endif