/*!
*
*
* \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