/*! * * * \brief Defines the Batch Interface for a type, e.g., for every type a container with optimal structure. * * * * \author O.Krause * \date 2012 * * * \par Copyright 1995-2017 Shark Development Team * *

* This file is part of Shark. * * * Shark is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Shark is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Shark. If not, see . * */ #ifndef SHARK_DATA_BATCHINTERFACE_H #define SHARK_DATA_BATCHINTERFACE_H #include #include #include #include #include namespace shark{ namespace detail{ /// \brief default implementation of a batch where BatchType is a proper sequence template struct SimpleBatch{ /// \brief Type of a batch of elements. typedef BatchType type; /// \brief Type of a single element. typedef typename type::reference reference; /// \brief Type of a single immutable element. typedef typename type::const_reference const_reference; /// \brief The type of the elements stored in the batch typedef typename type::value_type value_type; /// \brief the iterator type of the object typedef typename type::iterator iterator; /// \brief the const_iterator type of the object typedef typename type::const_iterator const_iterator; ///\brief creates a batch able to store elements of the structure of input (e.g. same dimensionality) static type createBatch(value_type const& input, std::size_t size = 1){ return type(size,input); } ///\brief creates a batch storing the elements referenced by the provided range template static type createBatchFromRange(Iterator const& begin, Iterator const& end){ type batch = createBatch(*begin,end-begin); typename type::reference c=batch[0]; c=*begin; std::copy(begin,end,batch.begin()); return batch; } template static void resize(T& batch, std::size_t batchSize, std::size_t elements){ batch.resize(batchSize); } //~ ///\brief Swaps the ith element in the first batch with the jth element in the second batch //~ template //~ static void swap(T& batchi, U& batchj, std::size_t i, std::size_t j){ //~ using std::swap; //~ swap(batchi[i],batchj[j]); //~ } template static std::size_t size(T const& batch){return batch.size();} template static typename T::reference get(T& batch, std::size_t i){ return batch[i]; } template static typename T::const_reference get(T const& batch, std::size_t i){ return batch[i]; } template static typename T::iterator begin(T& batch){ return batch.begin(); } template static typename T::const_iterator begin(T const& batch){ return batch.begin(); } template static typename T::iterator end(T& batch){ return batch.end(); } template static typename T::const_iterator end(T const& batch){ return batch.end(); } }; ///\brief Wrapper for a matrix row, which offers a conversion operator to /// to the Vector Type. template class MatrixRowReference: public blas::detail::matrix_row_optimizer< typename blas::closure::type >::type{ private: typedef typename blas::detail::matrix_row_optimizer< typename blas::closure::type >::type row_type; public: typedef typename blas::vector_temporary::type Vector; MatrixRowReference( Matrix& matrix, std::size_t i) :row_type(row(matrix,i)){} MatrixRowReference(row_type const& matrixrow) :row_type(matrixrow){} template MatrixRowReference(MatrixRowReference const& matrixrow) :row_type(matrixrow){} template const MatrixRowReference& operator=(const T& argument){ static_cast(*this)=argument; return *this; } operator Vector(){ return Vector(*this); } }; //~ template //~ void swap(MatrixRowReference ref1, MatrixRowReference ref2){ //~ swap_rows(ref1.expression().expression(),ref1.index(),ref2.expression().expression(),ref2.index()); //~ } //~ template //~ void swap(MatrixRowReference ref1, MatrixRowReference ref2){ //~ swap_rows(ref1.expression().expression(),ref1.index(),ref2.expression().expression(),ref2.index()); //~ } template struct VectorBatch{ /// \brief Type of a batch of elements. typedef typename blas::matrix_temporary::type type; /// \brief The type of the elements stored in the batch typedef typename blas::vector_temporary::type value_type; /// \brief Type of a single element. typedef detail::MatrixRowReference reference; /// \brief Type of a single immutable element. typedef detail::MatrixRowReference const_reference; /// \brief the iterator type of the object typedef ProxyIterator iterator; /// \brief the const_iterator type of the object typedef ProxyIterator const_iterator; ///\brief creates a batch with input as size blueprint template static type createBatch(Element const& input, std::size_t size = 1){ return type(size,input.size()); } ///\brief creates a batch storing the elements referenced by the provided range template static type createBatchFromRange(Iterator const& pos, Iterator const& end){ type batch(end - pos,pos->size()); std::copy(pos,end,begin(batch)); return batch; } static void resize(Matrix& batch, std::size_t batchSize, std::size_t elements){ ensure_size(batch,batchSize,elements); } static std::size_t size(Matrix const& batch){return batch.size1();} static reference get( Matrix& batch, std::size_t i){ return reference(batch,i); } static const_reference get( Matrix const& batch, std::size_t i){ return const_reference(batch,i); } static iterator begin(Matrix& batch){ return iterator(batch,0); } static const_iterator begin(Matrix const& batch){ return const_iterator(batch,0); } static iterator end(Matrix& batch){ return iterator(batch,batch.size1()); } static const_iterator end(Matrix const& batch){ return const_iterator(batch,batch.size1()); } }; } ///\brief class which helps using different batch types /// /// e.g. creating a batch of a single element or returning a single element /// when the element type is arithmetic, like int,double, std::complex,... /// the return value will be a linear algebra compatible vector, like RealVector. /// If it is not, for example a string, the return value will be a std::vector. template //see detail above for implementations, we just choose the correct implementations based on //whether T is arithmetic or not struct Batch :public std::conditional< std::is_arithmetic::value, detail::SimpleBatch >, detail::SimpleBatch > >::type{}; /// \brief specialization for vectors which should be matrices in batch mode! template struct Batch >: public detail::VectorBatch >{}; /// \brief specialization for ublas compressed vectors which are compressed matrices in batch mode! template struct Batch >{ /// \brief Type of a batch of elements. typedef shark::blas::compressed_matrix type; /// \brief The type of the elements stored in the batch typedef shark::blas::compressed_vector value_type; /// \brief Type of a single element. typedef detail::MatrixRowReference reference; /// \brief Type of a single immutable element. typedef detail::MatrixRowReference const_reference; /// \brief the iterator type of the object typedef ProxyIterator iterator; /// \brief the const_iterator type of the object typedef ProxyIterator const_iterator; ///\brief creates a batch with input as size blueprint template static type createBatch(Element const& input, std::size_t size = 1){ return type(size,input.size()); } ///\brief creates a batch storing the elements referenced by the provided range template static type createBatchFromRange(Iterator const& start, Iterator const& end){ //before creating the batch, we need the number of nonzero elements std::size_t nonzeros = 0; for(Iterator pos = start; pos != end; ++pos){ nonzeros += pos->nnz(); } std::size_t size = end - start; type batch(size,start->size(),nonzeros); Iterator pos = start; for(std::size_t i = 0; i != size; ++i, ++pos){ auto row_start = batch.major_end(i); for(auto elem_pos = pos->begin(); elem_pos != pos->end(); ++elem_pos){ row_start = batch.set_element(row_start, elem_pos.index(), *elem_pos); } } //~ std::copy(start,end,begin(batch)); return batch; } static void resize(type& batch, std::size_t batchSize, std::size_t elements){ ensure_size(batch,batchSize,elements); } static std::size_t size(type const& batch){return batch.size1();} static reference get( type& batch, std::size_t i){ return reference(batch,i); } static const_reference get( type const& batch, std::size_t i){ return const_reference(batch,i); } static iterator begin(type& batch){ return iterator(batch,0); } static const_iterator begin(type const& batch){ return const_iterator(batch,0); } static iterator end(type& batch){ return iterator(batch,batch.size1()); } static const_iterator end(type const& batch){ return const_iterator(batch,batch.size1()); } }; template struct Batch > :public Batch::Vector>{}; template struct BatchTraits{ typedef Batch::type::value_type> type; }; template struct BatchTraits >{ typedef Batch > type; }; template struct BatchTraits >{ typedef Batch > type; }; template struct BatchTraits >{ typedef detail::VectorBatch > type; }; namespace detail{ template struct batch_to_element{ typedef typename BatchTraits::type::value_type type; }; template struct batch_to_element{ //~ typedef typename BatchTraits::type::reference type; typedef typename BatchTraits::type::value_type type; }; template struct batch_to_element{ //~ typedef typename BatchTraits::type::const_reference type; typedef typename BatchTraits::type::value_type type; }; template struct batch_to_reference{ typedef typename BatchTraits::type::reference type; }; template struct batch_to_reference{ typedef typename BatchTraits::type::reference type; }; template struct batch_to_reference{ typedef typename BatchTraits::type::const_reference type; }; template struct element_to_batch{ typedef typename Batch::type type; }; template struct element_to_batch{ typedef typename Batch::type& type; }; template struct element_to_batch{ typedef typename Batch::type const& type; }; template struct element_to_batch >{ typedef typename Batch::Vector>::type& type; }; template struct element_to_batch >{ typedef typename Batch::Vector>::type const& type; }; } ///\brief creates a batch from a range of inputs template typename Batch::type createBatch(Range const& range){ return Batch::createBatchFromRange(range.begin(),range.end()); } ///\brief creates a batch from a range of inputs template typename Batch::type createBatch(Range const& range){ return Batch::createBatchFromRange(range.begin(),range.end()); } template typename Batch::type createBatch(Iterator const& begin, Iterator const& end){ return Batch::createBatchFromRange(begin,end); } template auto getBatchElement(BatchT& batch, std::size_t i)->decltype(BatchTraits::type::get(std::declval(),i)){ return BatchTraits::type::get(batch,i); } template auto getBatchElement(BatchT const& batch, std::size_t i)->decltype(BatchTraits::type::get(std::declval(),i)){ return BatchTraits::type::get(batch,i); } template std::size_t batchSize(BatchT const& batch){ return BatchTraits::type::size(batch); } template auto batchBegin(BatchT& batch)->decltype(BatchTraits::type::begin(batch)){ return BatchTraits::type::begin(batch); } template auto batchBegin(BatchT const& batch)->decltype(BatchTraits::type::begin(batch)){ return BatchTraits::type::begin(batch); } template auto batchEnd(BatchT& batch)->decltype(BatchTraits::type::end(batch)){ return BatchTraits::type::end(batch); } template auto batchEnd(BatchT const& batch)->decltype(BatchTraits::type::end(batch)){ return BatchTraits::type::end(batch); } } #endif