28#ifndef REMORA_CPU_DENSE_HPP
29#define REMORA_CPU_DENSE_HPP
32#include "../detail/proxy_optimizers_fwd.hpp"
33#include "../assignment.hpp"
36#include <initializer_list>
37#include <boost/serialization/collection_size_type.hpp>
38#include <boost/serialization/array.hpp>
39#include <boost/serialization/nvp.hpp>
40#include <boost/serialization/vector.hpp>
47template<
class T,
class Tag>
48class dense_vector_adaptor<T, Tag, cpu_tag>:
public vector_expression<dense_vector_adaptor<T, Tag, cpu_tag>, cpu_tag > {
51 typedef std::size_t size_type;
52 typedef typename std::remove_const<T>::type value_type;
53 typedef value_type
const& const_reference;
56 typedef dense_vector_adaptor<T const, Tag, cpu_tag> const_closure_type;
57 typedef dense_vector_adaptor closure_type;
58 typedef dense_vector_storage<T, Tag> storage_type;
59 typedef dense_vector_storage<value_type const, Tag> const_storage_type;
60 typedef elementwise<dense_tag> evaluation_category;
68 dense_vector_adaptor(vector<value_type, cpu_tag>
const& expression)
69 : m_values(expression.raw_storage().values)
70 , m_size(expression.size())
71 , m_stride(expression.raw_storage().stride){}
77 dense_vector_adaptor(vector<value_type, cpu_tag>& expression)
78 : m_values(expression.raw_storage().values)
79 , m_size(expression.size())
80 , m_stride(expression.raw_storage().stride){}
86 dense_vector_adaptor(T* values, size_type size, size_type stride = 1 ):
87 m_values(values),m_size(size),m_stride(stride){}
90 dense_vector_adaptor(storage_type
const& storage, no_queue, size_type size):
91 m_values(storage.values),m_size(size),m_stride(storage.stride){}
96 template<
class U,
class Tag2>
97 dense_vector_adaptor(dense_vector_adaptor<U, Tag2>
const& v)
98 : m_values(v.raw_storage().values)
100 , m_stride(v.raw_storage().stride){
101 static_assert(std::is_convertible<Tag2,Tag>::value,
"Can not convert storage type of argument to the given Tag");
104 dense_vector_adaptor& operator = (dense_vector_adaptor
const& e) {
105 return assign(*
this,
typename vector_temporary<dense_vector_adaptor>::type(e));
108 dense_vector_adaptor& operator = (vector_expression<E, cpu_tag>
const& e) {
109 return assign(*
this,
typename vector_temporary<E>::type(e));
113 size_type size()
const {
118 storage_type raw_storage()
const{
119 return {m_values,m_stride};
122 typename device_traits<cpu_tag>::queue_type& queue()
const{
123 return device_traits<cpu_tag>::default_queue();
131 const_reference operator()(size_type i)
const {
132 return m_values[i*m_stride];
137 reference operator()(size_type i) {
138 return m_values[i*m_stride];
143 const_reference operator[](size_type i)
const {
144 return m_values[i*m_stride];
149 reference operator[](size_type i) {
150 return m_values[i*m_stride];
154 std::fill(begin(), end(), value_type());
161 typedef iterators::dense_storage_iterator<T> iterator;
162 typedef iterators::dense_storage_iterator<value_type const> const_iterator;
165 const_iterator begin()
const {
166 return const_iterator(m_values, 0, m_stride);
170 const_iterator end()
const {
171 return const_iterator(m_values + size() * m_stride, size(), m_stride);
176 return iterator(m_values, 0, m_stride);
181 return iterator(m_values + size() * m_stride, size(), m_stride);
185 dense_vector_adaptor(vector<value_type, cpu_tag>&& expression);
192template<
class T,
class Orientation,
class Tag>
193class dense_matrix_adaptor<T,Orientation,Tag, cpu_tag>:
public matrix_expression<dense_matrix_adaptor<T,Orientation, Tag, cpu_tag>, cpu_tag > {
195 typedef std::size_t size_type;
196 typedef typename std::remove_const<T>::type value_type;
197 typedef value_type result_type;
198 typedef value_type
const& const_reference;
199 typedef T& reference;
201 typedef dense_matrix_adaptor<T,Orientation, Tag, cpu_tag> closure_type;
202 typedef dense_matrix_adaptor<value_type const,Orientation, Tag, cpu_tag> const_closure_type;
203 typedef dense_matrix_storage<T,Tag> storage_type;
204 typedef dense_matrix_storage<value_type const,Tag> const_storage_type;
205 typedef Orientation orientation;
206 typedef elementwise<dense_tag> evaluation_category;
208 template<
class,
class,
class,
class>
friend class dense_matrix_adaptor;
211 template<
class U,
class TagU>
212 dense_matrix_adaptor(dense_matrix_adaptor<U, Orientation, TagU, cpu_tag>
const& expression)
213 : m_values(expression.m_values)
214 , m_size1(expression.size1())
215 , m_size2(expression.size2())
216 , m_leading_dimension(expression.m_leading_dimension)
217 {
static_assert(std::is_convertible<TagU,Tag>::value,
"Can not convert storage type of argument to the given Tag");}
219 dense_matrix_adaptor(storage_type
const& storage, no_queue, std::size_t size1, std::size_t size2)
220 : m_values(storage.values)
223 , m_leading_dimension(storage.leading_dimension){}
229 dense_matrix_adaptor(matrix<value_type, Orientation, cpu_tag>
const& expression)
230 : m_size1(expression.size1())
231 , m_size2(expression.size2())
233 auto storage = expression.raw_storage();
234 m_values = storage.values;
235 m_leading_dimension = storage.leading_dimension;
242 dense_matrix_adaptor(matrix<value_type, Orientation, cpu_tag>& expression)
243 : m_size1(expression.size1())
244 , m_size2(expression.size2()){
245 auto storage = expression.raw_storage();
246 m_values = storage.values;
247 m_leading_dimension = storage.leading_dimension;
255 dense_matrix_adaptor(
257 size_type size1, size_type size2,
258 size_type leading_dimension = 0
263 , m_leading_dimension(leading_dimension)
265 if(!m_leading_dimension)
266 m_leading_dimension = orientation::index_m(m_size1,m_size2);
274 size_type size1()
const {
278 size_type size2()
const {
283 storage_type raw_storage()
const{
284 return {m_values, m_leading_dimension};
287 typename device_traits<cpu_tag>::queue_type& queue()
const{
288 return device_traits<cpu_tag>::default_queue();
299 dense_matrix_adaptor& operator = (dense_matrix_adaptor
const& e) {
300 REMORA_SIZE_CHECK(size1() == e.size1());
301 REMORA_SIZE_CHECK(size2() == e.size2());
302 return assign(*
this,
typename matrix_temporary<dense_matrix_adaptor>::type(e));
305 dense_matrix_adaptor& operator = (matrix_expression<E, cpu_tag>
const& e) {
306 REMORA_SIZE_CHECK(size1() == e().size1());
307 REMORA_SIZE_CHECK(size2() == e().size2());
308 return assign(*
this,
typename matrix_temporary<dense_matrix_adaptor>::type(e));
311 dense_matrix_adaptor& operator = (vector_set_expression<E, cpu_tag>
const& e) {
312 REMORA_SIZE_CHECK(size1() ==
typename E::point_orientation::index_M(e().size(), e().point_size()));
313 REMORA_SIZE_CHECK(size2() ==
typename E::point_orientation::index_M(e().size(), e().point_size()));
314 return assign(*
this,
typename matrix_temporary<dense_matrix_adaptor>::type(e));
321 reference operator() (size_type i, size_type j)
const {
322 REMORA_SIZE_CHECK( i < m_size1);
323 REMORA_SIZE_CHECK( j < m_size2);
324 return m_values[orientation::element(i, j, m_leading_dimension)];
326 void set_element(size_type i, size_type j,value_type t){
327 REMORA_SIZE_CHECK( i < m_size1);
328 REMORA_SIZE_CHECK( j < m_size2);
329 return m_values[orientation::element(i, j, m_leading_dimension)];
336 typedef iterators::dense_storage_iterator<T> major_iterator;
337 typedef iterators::dense_storage_iterator<value_type const> const_major_iterator;
339 const_major_iterator major_begin(size_type i)
const {
340 return const_major_iterator(m_values + i * m_leading_dimension, 0, 1);
342 const_major_iterator major_end(size_type i)
const {
343 return const_major_iterator(m_values + i * m_leading_dimension + minor_size(*
this), minor_size(*
this), 1);
345 major_iterator major_begin(size_type i){
346 return major_iterator(m_values + i * m_leading_dimension, 0, 1);
348 major_iterator major_end(size_type i){
349 return major_iterator(m_values + i * m_leading_dimension + minor_size(*
this), minor_size(*
this), 1);
352 void swap_rows(size_type i, size_type j){
353 for(std::size_t k = 0; k != size2(); ++k){
354 std::swap((*
this)(i,k),(*
this)(j,k));
358 void swap_columns(size_type i, size_type j){
359 for(std::size_t k = 0; k != size1(); ++k){
360 std::swap((*
this)(k,i),(*
this)(k,j));
364 major_iterator set_element(major_iterator pos, size_type index, value_type value) {
365 REMORA_RANGE_CHECK(index == pos.index());
373 for(size_type i = 0; i != major_size(*
this); ++i){
374 for(size_type j = 0; j != minor_size(*
this); ++j){
375 m_values[i * m_leading_dimension + j] = value_type();
380 dense_matrix_adaptor(matrix<value_type, Orientation, cpu_tag>&& expression);
384 size_type m_leading_dimension;
400template<
class T,
class L>
401class matrix<T,L,cpu_tag>:
public matrix_container<matrix<T, L, cpu_tag>, cpu_tag > {
402 typedef std::vector<T> array_type;
404 typedef typename array_type::value_type value_type;
405 typedef typename array_type::const_reference const_reference;
406 typedef typename array_type::reference reference;
407 typedef typename array_type::size_type size_type;
409 typedef dense_matrix_adaptor<T const,L, continuous_dense_tag, cpu_tag> const_closure_type;
410 typedef dense_matrix_adaptor<T,L, continuous_dense_tag, cpu_tag> closure_type;
411 typedef dense_matrix_storage<T, continuous_dense_tag> storage_type;
412 typedef dense_matrix_storage<T const, continuous_dense_tag> const_storage_type;
413 typedef elementwise<dense_tag> evaluation_category;
414 typedef L orientation;
419 matrix():m_size1(0), m_size2(0){}
425 matrix(std::initializer_list<std::initializer_list<T> > list)
426 : m_size1(list.size())
427 , m_size2(list.begin()->size())
428 , m_data(m_size1*m_size2){
429 auto pos = list.begin();
430 for(std::size_t i = 0; i != list.size(); ++i,++pos){
431 REMORA_SIZE_CHECK(pos->size() == m_size2);
432 std::copy(pos->begin(),pos->end(),major_begin(i));
439 matrix(size_type size1, size_type size2)
442 , m_data(size1 * size2) {}
448 matrix(size_type size1, size_type size2, value_type
const& init)
451 , m_data(size1 * size2, init) {}
455 matrix(matrix
const& m) =
default;
460 matrix(matrix&& m):m_size1(m.m_size1), m_size2(m.m_size2), m_data(std::move(m.m_data)){}
469 matrix(matrix_expression<E, cpu_tag>
const& e)
470 : m_size1(e().size1())
471 , m_size2(e().size2())
472 , m_data(m_size1 * m_size2) {
483 matrix(vector_set_expression<E, cpu_tag>
const& e)
484 : m_size1(E::point_orientation::index_M(e().size(), e().point_size()))
485 , m_size2(E::point_orientation::index_m(e().size(), e().point_size()))
486 , m_data(m_size1 * m_size2) {
487 assign(*
this,e().expression());
493 matrix& operator = (matrix
const& m) =
default;
497 matrix& operator = (matrix&& m) {
500 m_data = std::move(m.m_data);
513 matrix& operator = (matrix_container<C, cpu_tag>
const& m) {
514 resize(m().size1(), m().size2());
526 matrix& operator = (matrix_expression<E, cpu_tag>
const& e) {
540 matrix& operator = (vector_set_expression<E, cpu_tag>
const& e) {
547 size_type size1()
const {
551 size_type size2()
const {
556 storage_type raw_storage(){
557 return {m_data.data(), leading_dimension()};
561 const_storage_type raw_storage()
const{
562 return {m_data.data(), leading_dimension()};
564 typename device_traits<cpu_tag>::queue_type& queue()
const{
565 return device_traits<cpu_tag>::default_queue();
576 void resize(size_type size1, size_type size2) {
577 m_data.resize(size1* size2);
583 std::fill(m_data.begin(), m_data.end(), value_type());
587 const_reference operator()(size_type i, size_type j)
const {
588 REMORA_SIZE_CHECK(i < size1());
589 REMORA_SIZE_CHECK(j < size2());
590 return m_data[orientation::element(i, j, leading_dimension())];
592 reference operator()(size_type i, size_type j) {
593 REMORA_SIZE_CHECK(i < size1());
594 REMORA_SIZE_CHECK(j < size2());
595 return m_data[orientation::element(i, j, leading_dimension())];
598 void set_element(size_type i, size_type j,value_type t){
599 REMORA_SIZE_CHECK(i < size1());
600 REMORA_SIZE_CHECK(j < size2());
601 m_data[orientation::element(i, j, leading_dimension())] = t;
605 void swap(matrix& m) {
606 std::swap(m_size1, m.m_size1);
607 std::swap(m_size2, m.m_size2);
608 m_data.swap(m.m_data);
610 friend void swap(matrix& m1, matrix& m2) {
614 friend void swap_rows(matrix& a, size_type i, matrix& b, size_type j){
615 REMORA_SIZE_CHECK(i < a.size1());
616 REMORA_SIZE_CHECK(j < b.size1());
617 REMORA_SIZE_CHECK(a.size2() == b.size2());
618 for(std::size_t k = 0; k != a.size2(); ++k){
619 std::swap(a(i,k),b(j,k));
623 void swap_rows(size_type i, size_type j) {
625 for(std::size_t k = 0; k != size2(); ++k){
626 std::swap((*
this)(i,k),(*
this)(j,k));
631 friend void swap_columns(matrix& a, size_type i, matrix& b, size_type j){
632 REMORA_SIZE_CHECK(i < a.size2());
633 REMORA_SIZE_CHECK(j < b.size2());
634 REMORA_SIZE_CHECK(a.size1() == b.size1());
635 for(std::size_t k = 0; k != a.size1(); ++k){
636 std::swap(a(k,i),b(k,j));
640 void swap_columns(size_type i, size_type j) {
642 for(std::size_t k = 0; k != size1(); ++k){
643 std::swap((*
this)(k,i),(*
this)(k,j));
648 typedef iterators::dense_storage_iterator<T> major_iterator;
649 typedef iterators::dense_storage_iterator<value_type const> const_major_iterator;
651 const_major_iterator major_begin(size_type i)
const {
652 return const_major_iterator(m_data.data() + i * leading_dimension(), 0, 1);
654 const_major_iterator major_end(size_type i)
const {
655 return const_major_iterator(m_data.data() + i * leading_dimension() + minor_size(*
this), minor_size(*
this), 1);
657 major_iterator major_begin(size_type i){
658 return major_iterator(m_data.data() + i * leading_dimension(), 0, 1);
660 major_iterator major_end(size_type i){
661 return major_iterator(m_data.data() + i * leading_dimension() + minor_size(*
this), minor_size(*
this), 1);
664 major_iterator set_element(major_iterator pos, size_type index, value_type value) {
665 REMORA_RANGE_CHECK(index == pos.index());
672 template<
class Archive>
673 void serialize(Archive& ar,
const unsigned int ) {
677 boost::serialization::collection_size_type s1(m_size1);
678 boost::serialization::collection_size_type s2(m_size2);
681 ar& boost::serialization::make_nvp(
"size1",s1)
682 & boost::serialization::make_nvp(
"size2",s2);
685 if (Archive::is_loading::value) {
689 ar& boost::serialization::make_nvp(
"data",m_data);
693 size_type leading_dimension()
const {
694 return orientation::index_m(m_size1, m_size2);
703class vector<T,cpu_tag>:
public vector_container<vector<T, cpu_tag>, cpu_tag > {
705 typedef std::vector<typename std::conditional<std::is_same<T,bool>::value,char,T>::type > array_type;
707 typedef typename array_type::value_type value_type;
708 typedef typename array_type::const_reference const_reference;
709 typedef typename array_type::reference reference;
710 typedef typename array_type::size_type size_type;
712 typedef dense_vector_adaptor<T const, continuous_dense_tag, cpu_tag> const_closure_type;
713 typedef dense_vector_adaptor<T,continuous_dense_tag, cpu_tag> closure_type;
714 typedef dense_vector_storage<value_type, continuous_dense_tag> storage_type;
715 typedef dense_vector_storage<value_type const, continuous_dense_tag> const_storage_type;
716 typedef elementwise<dense_tag> evaluation_category;
727 explicit vector(size_type size):m_storage(size) {}
732 vector(size_type size,
const value_type& init):m_storage(size, init) {}
736 vector(vector
const& v) =
default;
741 vector(vector && v): m_storage(std::move(v.m_storage)){}
743 vector(std::initializer_list<T> list) : m_storage(list.begin(),list.end()){}
747 vector(Iter begin, Iter end):m_storage(begin,end){}
752 vector(vector_expression<E, cpu_tag>
const& e):m_storage(e().size()) {
764 vector& operator = (vector
const& v) =
default;
770 vector& operator = (vector && v){
771 m_storage = std::move(v.m_storage);
780 vector& operator = (vector_container<C, cpu_tag>
const& v) {
782 return assign(*
this, v);
790 vector& operator = (vector_expression<E, cpu_tag>
const& e) {
792 swap(*
this,temporary);
801 size_type size()
const {
802 return m_storage.size();
806 storage_type raw_storage(){
807 return {m_storage.data(),1};
811 const_storage_type raw_storage()
const{
812 return {m_storage.data(),1};
814 typename device_traits<cpu_tag>::queue_type& queue()
const{
815 return device_traits<cpu_tag>::default_queue();
824 size_type max_size()
const {
825 return m_storage.max_size();
831 return m_storage.empty();
836 void resize(size_type size) {
837 m_storage.resize(size);
847 const_reference operator()(size_type i)
const {
848 REMORA_RANGE_CHECK(i < size());
855 reference operator()(size_type i) {
856 REMORA_RANGE_CHECK(i < size());
862 const_reference operator [](size_type i)
const {
863 REMORA_RANGE_CHECK(i < size());
869 reference operator [](size_type i) {
870 REMORA_RANGE_CHECK(i < size());
879 const_reference front()
const{
884 return m_storage[size()-1];
887 const_reference back()
const{
888 return m_storage[size()-1];
892 void push_back(value_type
const& element){
893 m_storage.push_back(element);
898 std::fill(m_storage.begin(), m_storage.end(), value_type());
902 typedef iterators::dense_storage_iterator<value_type> iterator;
903 typedef iterators::dense_storage_iterator<value_type const> const_iterator;
906 const_iterator cbegin()
const {
907 return const_iterator(m_storage.data(),0);
911 const_iterator cend()
const {
912 return const_iterator(m_storage.data()+size(),size());
916 const_iterator begin()
const {
921 const_iterator end()
const {
927 return iterator(m_storage.data(),0);
932 return iterator(m_storage.data()+size(),size());
938 friend void swap(vector& v1, vector& v2) {
939 v1.m_storage.swap(v2.m_storage);
948 template<
class Archive>
949 void serialize(Archive &ar,
const unsigned int file_version) {
950 boost::serialization::collection_size_type count(size());
952 if(!Archive::is_saving::value){
956 ar & boost::serialization::make_array(m_storage.data(),size());
961 array_type m_storage;
965template<
class T,
class Orientation,
bool Upper,
bool Unit>
966class dense_triangular_proxy<T, Orientation, triangular_tag<Upper, Unit> , cpu_tag>
967:
public matrix_expression<dense_triangular_proxy<T, Orientation, triangular_tag<Upper, Unit>, cpu_tag>, cpu_tag> {
969 typedef std::size_t size_type;
970 typedef typename std::remove_const<T>::type value_type;
971 typedef value_type result_type;
972 typedef typename std::conditional<Unit, value_type const&, T&>::type reference;
973 typedef value_type
const& const_reference;
974 typedef dense_triangular_proxy<value_type const, Orientation, triangular_tag<Upper, Unit> , cpu_tag> const_closure_type;
975 typedef dense_triangular_proxy<T, Orientation, triangular_tag<Upper, Unit> , cpu_tag> closure_type;
977 typedef dense_matrix_storage<T, dense_tag> storage_type;
978 typedef dense_matrix_storage<value_type const, dense_tag> const_storage_type;
980 typedef elementwise<dense_tag> evaluation_category;
981 typedef triangular<Orientation,triangular_tag<Upper, Unit> > orientation;
985 dense_triangular_proxy(dense_triangular_proxy<U, Orientation, triangular_tag<Upper, Unit>, cpu_tag>
const& expression)
986 : m_values(expression.raw_storage().values)
987 , m_size1(expression.size1())
988 , m_size2(expression.size2())
989 , m_leading_dimension(expression.raw_storage().leading_dimension){}
995 dense_triangular_proxy(storage_type
const& storage, no_queue, std::size_t size1, std::size_t size2)
996 : m_values(storage.values)
999 , m_leading_dimension(storage.leading_dimension){}
1001 dense_matrix_adaptor<T, Orientation, dense_tag, cpu_tag> to_dense()
const{
1002 return {raw_storage(), queue(), m_size1, m_size2};
1007 size_type size1()
const {
1011 size_type size2()
const {
1016 storage_type raw_storage()
const{
1017 return {m_values, m_leading_dimension};
1020 typename device_traits<cpu_tag>::queue_type& queue()
const{
1021 return device_traits<cpu_tag>::default_queue();
1024 typedef iterators::dense_storage_iterator<value_type> major_iterator;
1025 typedef iterators::dense_storage_iterator<value_type const> const_major_iterator;
1027 const_major_iterator major_begin(size_type i)
const {
1028 std::size_t start = Upper? i + Unit: 0;
1029 return const_major_iterator(m_values + orientation::element(i,start, m_leading_dimension),start, 1);
1031 const_major_iterator major_end(size_type i)
const {
1032 std::size_t end = Upper? m_size2: i +1 - Unit;
1033 return const_major_iterator(m_values + orientation::element(i,end, m_leading_dimension),end, 1);
1035 major_iterator major_begin(size_type i){
1036 std::size_t start = Upper? i + Unit: 0;
1037 return major_iterator(m_values + orientation::element(i,start, m_leading_dimension),start, 1);
1039 major_iterator major_end(size_type i){
1040 std::size_t end = Upper? m_size2: i + 1 - Unit;
1041 return major_iterator(m_values + orientation::element(i,end, m_leading_dimension),end, 1);
1046 std::size_t m_size1;
1047 std::size_t m_size2;
1048 std::size_t m_leading_dimension;
1053template<
class T,
class Orientation>
1054struct vector_to_matrix_optimizer<dense_vector_adaptor<T, continuous_dense_tag, cpu_tag>, Orientation >{
1055 typedef dense_matrix_adaptor<T, Orientation, continuous_dense_tag, cpu_tag> type;
1058 dense_vector_adaptor<T, continuous_dense_tag, cpu_tag>
const& v,
1059 std::size_t size1, std::size_t size2
1061 dense_matrix_storage<T, continuous_dense_tag> storage = {v.raw_storage().values, Orientation::index_m(size1,size2)};
1062 return type(storage, v.queue(), size1, size2);