28#ifndef REMORA_CPU_SPARSE_HPP
29#define REMORA_CPU_SPARSE_HPP
35#include <boost/serialization/collection_size_type.hpp>
36#include <boost/serialization/nvp.hpp>
37#include <boost/serialization/vector.hpp>
39namespace remora{
namespace detail{
41template<
class T,
class I>
42struct VectorStorageReference{
43 typedef sparse_vector_storage<T,I> storage_type;
47 std::size_t max_capacity()
const{
48 return m_storage.capacity;
51 void reserve(size_type non_zeros){
52 assert(non_zeros <= max_capacity());
55 VectorStorageReference(storage_type
const& storage)
56 : m_storage(storage){}
58 storage_type m_storage;
62template<
class T,
class I>
64 typedef sparse_vector_storage<T,I> storage_type;
68 std::size_t max_capacity()
const{
69 return std::numeric_limits<std::size_t>::max()/
sizeof(T);
72 void reserve(size_type non_zeros){
73 if(non_zeros > m_storage.capacity){
74 m_indices.resize(non_zeros);
75 m_values.resize(non_zeros);
77 m_storage.values = m_values.data();
78 m_storage.indices = m_indices.data();
79 m_storage.capacity = non_zeros;
82 VectorStorage(): m_storage({
nullptr,
nullptr,0,0}){}
84 template<
class Archive>
85 void serialize(Archive& ar,
const unsigned int ) {
86 ar & boost::serialization::make_nvp(
"nnz", m_storage.nnz);
87 ar & boost::serialization::make_nvp(
"capacity", m_storage.capacity);
88 ar & boost::serialization::make_nvp(
"indices", m_indices);
89 ar & boost::serialization::make_nvp(
"values", m_values);
90 m_storage.values = m_values.data();
91 m_storage.indices = m_indices.data();
93 storage_type m_storage;
95 std::vector<T> m_values;
96 std::vector<I> m_indices;
99template<
class StorageManager>
100struct BaseSparseVector{
101 typedef typename StorageManager::storage_type storage_type;
102 typedef typename StorageManager::size_type size_type;
103 typedef typename StorageManager::value_type value_type;
105 BaseSparseVector(StorageManager
const& manager, std::size_t size, std::size_t nnz)
110 size_type size()
const {
115 size_type nnz()
const {
116 return m_manager.m_storage.nnz;
120 size_type nnz_capacity()
const{
121 return m_manager.m_storage.capacity;
125 size_type max_nnz_capacity()
const{
126 return std::min(size(), m_manager.max_capacity());
130 void reserve(size_type non_zeros) {
131 if(non_zeros <= nnz_capacity())
return;
132 m_manager.reserve(non_zeros);
140 typedef iterators::compressed_storage_iterator<value_type, size_type> iterator;
141 typedef iterators::compressed_storage_iterator<value_type const, size_type const> const_iterator;
144 const_iterator begin()
const {
145 return const_iterator(m_manager.m_storage.values, m_manager.m_storage.indices, 0);
149 const_iterator end()
const {
150 return const_iterator(m_manager.m_storage.values, m_manager.m_storage.indices, nnz());
155 return iterator(m_manager.m_storage.values, m_manager.m_storage.indices, 0);
160 return iterator(m_manager.m_storage.values, m_manager.m_storage.indices, nnz());
163 iterator set_element(iterator pos, size_type index, value_type value) {
164 REMORA_RANGE_CHECK(size_type(pos - begin()) <=m_size);
166 if(pos != end() && pos.index() == index){
171 std::ptrdiff_t arrayPos = pos - begin();
172 if(nnz() == nnz_capacity())
173 reserve(std::min(std::max<size_type>(5,2 * nnz_capacity()),max_nnz_capacity()));
176 auto values = m_manager.m_storage.values;
177 auto indices = m_manager.m_storage.indices;
178 std::copy_backward(values + arrayPos, values + nnz() , values + nnz() +1);
179 std::copy_backward(indices + arrayPos, indices + nnz(), indices + nnz() +1);
181 values[arrayPos] = value;
182 indices[arrayPos] = index;
183 m_manager.m_storage.nnz += 1;
186 return iterator(values,indices,arrayPos+1);
189 iterator clear_range(iterator start, iterator end) {
191 std::ptrdiff_t startPos = start - begin();
192 std::ptrdiff_t endPos = end - begin();
195 auto values = m_manager.m_storage.values;
196 auto indices = m_manager.m_storage.indices;
197 std::copy(values + endPos, values + nnz(), values + startPos);
198 std::copy(indices + endPos, indices + nnz() , indices + startPos);
199 m_manager.m_storage.nnz -= endPos - startPos;
201 return iterator(values, indices, startPos);
204 iterator clear_element(iterator pos){
206 return clear_range(pos, end);
210 clear_range(begin(),end());
213 StorageManager m_manager;
216 void do_resize(size_type size,
bool keep){
219 auto pos = keep? end() : begin();
220 auto start = begin();
222 auto new_pos = pos-1;
223 if(pos.index() < size)
227 clear_range(pos,end());
234class compressed_vector_reference:
public vector_expression<compressed_vector_reference<V>, cpu_tag >{
236 template<
class>
friend class compressed_vector_reference;
238 typedef typename V::size_type size_type;
239 typedef typename V::value_type value_type;
240 typedef typename V::const_reference const_reference;
241 typedef typename remora::reference<V>::type reference;
243 typedef compressed_vector_reference<V const> const_closure_type;
244 typedef compressed_vector_reference closure_type;
245 typedef typename remora::storage<V>::type storage_type;
246 typedef typename V::const_storage_type const_storage_type;
247 typedef elementwise<sparse_tag> evaluation_category;
250 compressed_vector_reference(V& v):m_vector(&v){}
252 compressed_vector_reference(compressed_vector_reference<
typename std::remove_const<V>::type >
const& ref):m_vector(ref.m_vector){}
256 compressed_vector_reference& operator=(matrix_expression<E, cpu_tag>
const& e){
257 return assign(*
this,
typename vector_temporary<E>::type(e));
260 compressed_vector_reference& operator=(compressed_vector_reference
const& e){
261 return assign(*
this,
typename vector_temporary<V>::type(e));
265 storage_type raw_storage(){
266 return m_vector->raw_storage();
270 const_storage_type raw_storage()
const{
271 return m_vector->raw_storage();
275 size_type size()
const {
276 return m_vector->size();
279 size_type nnz()
const {
280 return m_vector->nnz();
283 size_type nnz_capacity()
const {
284 return m_vector->nnz_capacity();
287 void reserve(size_type non_zeros) {
288 m_vector->reserve(non_zeros);
291 typename device_traits<cpu_tag>::queue_type& queue(){
292 return device_traits<cpu_tag>::default_queue();
299 typedef typename std::conditional<
300 std::is_const<V>::value,
301 typename V::const_iterator,
304 typedef iterator const_iterator;
307 iterator begin()
const {
308 return m_vector->begin();
312 iterator end()
const {
313 return m_vector->end();
316 iterator set_element(iterator pos, size_type index, value_type value) {
317 return m_vector->set_element(pos,index,value);
320 iterator clear_range(iterator start, iterator end) {
321 m_vector->clear_range(start,end);
324 iterator clear_element(iterator pos){
325 m_vector->clear_element(pos);