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  * <http://shark-ml.org/>
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 
42 namespace shark{
43 
44 namespace detail{
45 
46 /// \brief default implementation of a batch where BatchType is a proper sequence
47 template<class BatchType>
48 struct 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 
124 ///\brief Wrapper for a matrix row, which offers a conversion operator to
125 /// to the Vector Type.
126 template<class Matrix>
127 class MatrixRowReference: public blas::temporary_proxy<blas::matrix_row<Matrix> >{
128 private:
129  typedef blas::temporary_proxy<blas::matrix_row<Matrix> > base_type;
130 public:
131  typedef typename blas::vector_temporary<Matrix>::type Vector;
132 
133  MatrixRowReference( Matrix& matrix, std::size_t i)
134  :base_type(blas::matrix_row<Matrix>(matrix,i)){}
135  template<class T>//special version allows for const-conversion
136  MatrixRowReference(T const& matrixrow)
137  :base_type(blas::matrix_row<Matrix>(matrixrow.expression(),matrixrow.index())){}
138 
139  template<class T>
140  const MatrixRowReference& operator=(const T& argument){
141  static_cast<base_type&>(*this)=argument;
142  return *this;
143  }
144 
145  operator Vector(){
146  return Vector(*this);
147  }
148 };
149 
150 template<class M>
151 void swap(MatrixRowReference<M> ref1, MatrixRowReference<M> ref2){
152  swap_rows(ref1.expression().expression(),ref1.index(),ref2.expression().expression(),ref2.index());
153 }
154 
155 template<class M1, class M2>
156 void swap(MatrixRowReference<M1> ref1, MatrixRowReference<M2> ref2){
157  swap_rows(ref1.expression().expression(),ref1.index(),ref2.expression().expression(),ref2.index());
158 }
159 
160 template<class Matrix>
161 struct VectorBatch{
162  /// \brief Type of a batch of elements.
163  typedef typename blas::matrix_temporary<Matrix>::type type;
164 
165  /// \brief The type of the elements stored in the batch
166  typedef typename blas::vector_temporary<Matrix>::type value_type;
167 
168 
169  /// \brief Type of a single element.
170  typedef detail::MatrixRowReference<Matrix> reference;
171  /// \brief Type of a single immutable element.
172  typedef detail::MatrixRowReference<const Matrix> const_reference;
173 
174 
175  /// \brief the iterator type of the object
176  typedef ProxyIterator<Matrix, value_type, reference > iterator;
177  /// \brief the const_iterator type of the object
178  typedef ProxyIterator<const Matrix, value_type, const_reference > const_iterator;
179 
180  ///\brief creates a batch with input as size blueprint
181  template<class Element>
182  static type createBatch(Element const& input, std::size_t size = 1){
183  return type(size,input.size());
184  }
185  ///\brief creates a batch storing the elements referenced by the provided range
186  template<class Iterator>
187  static type createBatchFromRange(Iterator const& pos, Iterator const& end){
188  type batch(end - pos,pos->size());
189  std::copy(pos,end,begin(batch));
190  return batch;
191  }
192 
193 
194  static void resize(Matrix& batch, std::size_t batchSize, std::size_t elements){
195  ensure_size(batch,batchSize,elements);
196  }
197 
198  static std::size_t size(Matrix const& batch){return batch.size1();}
199  static reference get( Matrix& batch, std::size_t i){
200  return reference(batch,i);
201  }
202  static const_reference get( Matrix const& batch, std::size_t i){
203  return const_reference(batch,i);
204  }
205 
206  static iterator begin(Matrix& batch){
207  return iterator(batch,0);
208  }
209  static const_iterator begin(Matrix const& batch){
210  return const_iterator(batch,0);
211  }
212 
213  static iterator end(Matrix& batch){
214  return iterator(batch,batch.size1());
215  }
216  static const_iterator end(Matrix const& batch){
217  return const_iterator(batch,batch.size1());
218  }
219 };
220 
221 
222 }
223 
224 ///\brief class which helps using different batch types
225 ///
226 /// e.g. creating a batch of a single element or returning a single element
227 /// when the element type is arithmetic, like int,double, std::complex,...
228 /// the return value will be a linear algebra compatible vector, like RealVector.
229 /// If it is not, for example a string, the return value will be a std::vector<T>.
230 template<class T>
231 //see detail above for implementations, we just choose the correct implementations based on
232 //whether T is arithmetic or not
233 struct Batch
234 :public std::conditional<
235  std::is_arithmetic<T>::value,
236  detail::SimpleBatch<blas::vector<T> >,
237  detail::SimpleBatch<std::vector<T> >
238 >::type{};
239 
240 /// \brief specialization for vectors which should be matrices in batch mode!
241 template<class T>
242 struct Batch<blas::vector<T> >: public detail::VectorBatch<blas::matrix<T> >{};
243 
244 /// \brief specialization for ublas compressed vectors which are compressed matrices in batch mode!
245 template<class T>
246 struct Batch<shark::blas::compressed_vector<T> >{
247  /// \brief Type of a batch of elements.
248  typedef shark::blas::compressed_matrix<T> type;
249 
250  /// \brief The type of the elements stored in the batch
251  typedef shark::blas::compressed_vector<T> value_type;
252 
253 
254  /// \brief Type of a single element.
255  typedef detail::MatrixRowReference<type> reference;
256  /// \brief Type of a single immutable element.
257  typedef detail::MatrixRowReference<const type> const_reference;
258 
259 
260  /// \brief the iterator type of the object
262  /// \brief the const_iterator type of the object
264 
265  ///\brief creates a batch with input as size blueprint
266  template<class Element>
267  static type createBatch(Element const& input, std::size_t size = 1){
268  return type(size,input.size());
269  }
270  ///\brief creates a batch storing the elements referenced by the provided range
271  template<class Iterator>
272  static type createBatchFromRange(Iterator const& start, Iterator const& end){
273  //before creating the batch, we need the number of nonzero elements
274  std::size_t nonzeros = 0;
275  for(Iterator pos = start; pos != end; ++pos){
276  nonzeros += pos->nnz();
277  }
278 
279  type batch(end - start,start->size(),nonzeros);
280  std::copy(start,end,begin(batch));
281  return batch;
282  }
283 
284 
285  static void resize(type& batch, std::size_t batchSize, std::size_t elements){
286  ensure_size(batch,batchSize,elements);
287  }
288 
289  static std::size_t size(type const& batch){return batch.size1();}
290  static reference get( type& batch, std::size_t i){
291  return reference(batch,i);
292  }
293  static const_reference get( type const& batch, std::size_t i){
294  return const_reference(batch,i);
295  }
296 
297  static iterator begin(type& batch){
298  return iterator(batch,0);
299  }
300  static const_iterator begin(type const& batch){
301  return const_iterator(batch,0);
302  }
303 
304  static iterator end(type& batch){
305  return iterator(batch,batch.size1());
306  }
307  static const_iterator end(type const& batch){
308  return const_iterator(batch,batch.size1());
309  }
310 };
311 
312 template<class M>
313 struct Batch<detail::MatrixRowReference<M> >
314 :public Batch<typename detail::MatrixRowReference<M>::Vector>{};
315 
316 
317 template<class BatchType>
318 struct BatchTraits{
320 };
321 
322 template<class T>
323 struct BatchTraits<blas::matrix<T> >{
324  typedef Batch<blas::vector<T> > type;
325 };
326 template<class T>
327 struct BatchTraits<blas::compressed_matrix<T> >{
328  typedef Batch<blas::compressed_vector<T> > type;
329 };
330 template<class T>
331 struct BatchTraits<blas::dense_matrix_adaptor<T, blas::row_major> >{
332  typedef detail::VectorBatch<blas::dense_matrix_adaptor<T, blas::row_major> > type;
333 };
334 
335 namespace detail{
336 template<class T>
337 struct batch_to_element{
338  typedef typename BatchTraits<T>::type::value_type type;
339 };
340 template<class T>
341 struct batch_to_element<T&>{
342  //~ typedef typename BatchTraits<T>::type::reference type;
343  typedef typename BatchTraits<T>::type::value_type type;
344 };
345 template<class T>
346 struct batch_to_element<T const&>{
347  //~ typedef typename BatchTraits<T>::type::const_reference type;
348  typedef typename BatchTraits<T>::type::value_type type;
349 };
350 
351 template<class T>
352 struct batch_to_reference{
353  typedef typename BatchTraits<T>::type::reference type;
354 };
355 template<class T>
356 struct batch_to_reference<T&>{
357  typedef typename BatchTraits<T>::type::reference type;
358 };
359 template<class T>
360 struct batch_to_reference<T const&>{
361  typedef typename BatchTraits<T>::type::const_reference type;
362 };
363 
364 template<class T>
365 struct element_to_batch{
366  typedef typename Batch<T>::type type;
367 };
368 template<class T>
369 struct element_to_batch<T&>{
370  typedef typename Batch<T>::type& type;
371 };
372 template<class T>
373 struct element_to_batch<T const&>{
374  typedef typename Batch<T>::type const& type;
375 };
376 template<class M>
377 struct element_to_batch<detail::MatrixRowReference<M> >{
378  typedef typename Batch<typename detail::MatrixRowReference<M>::Vector>::type& type;
379 };
380 template<class M>
381 struct element_to_batch<detail::MatrixRowReference<M const> >{
382  typedef typename Batch<typename detail::MatrixRowReference<M>::Vector>::type const& type;
383 };
384 }
385 
386 
387 ///\brief creates a batch from a range of inputs
388 template<class T, class Range>
389 typename Batch<T>::type createBatch(Range const& range){
390  return Batch<T>::createBatchFromRange(range.begin(),range.end());
391 }
392 
393 ///\brief creates a batch from a range of inputs
394 template<class Range>
396  return Batch<typename Range::value_type>::createBatchFromRange(range.begin(),range.end());
397 }
398 
399 template<class T, class Iterator>
400 typename Batch<T>::type createBatch(Iterator const& begin, Iterator const& end){
401  return Batch<T>::createBatchFromRange(begin,end);
402 }
403 
404 template<class BatchT>
405 auto getBatchElement(BatchT& batch, std::size_t i)->decltype(BatchTraits<BatchT>::type::get(std::declval<BatchT&>(),i)){
406  return BatchTraits<BatchT>::type::get(batch,i);
407 }
408 
409 template<class BatchT>
410 auto getBatchElement(BatchT const& batch, std::size_t i)->decltype(BatchTraits<BatchT>::type::get(std::declval<BatchT const&>(),i)){
411  return BatchTraits<BatchT>::type::get(batch,i);
412 }
413 
414 template<class BatchT>
415 std::size_t batchSize(BatchT const& batch){
416  return BatchTraits<BatchT>::type::size(batch);
417 }
418 
419 template<class BatchT>
420 auto batchBegin(BatchT& batch)->decltype(BatchTraits<BatchT>::type::begin(batch)){
421  return BatchTraits<BatchT>::type::begin(batch);
422 }
423 
424 template<class BatchT>
425 auto batchBegin(BatchT const& batch)->decltype(BatchTraits<BatchT>::type::begin(batch)){
426  return BatchTraits<BatchT>::type::begin(batch);
427 }
428 
429 template<class BatchT>
430 auto batchEnd(BatchT& batch)->decltype(BatchTraits<BatchT>::type::end(batch)){
431  return BatchTraits<BatchT>::type::end(batch);
432 }
433 
434 template<class BatchT>
435 auto batchEnd(BatchT const& batch)->decltype(BatchTraits<BatchT>::type::end(batch)){
436  return BatchTraits<BatchT>::type::end(batch);
437 }
438 
439 
440 }
441 #endif