triangular_matrix.hpp
Go to the documentation of this file.
1/*!
2 * \brief Implements a matrix with triangular storage layout
3 *
4 * \author O. Krause
5 * \date 2015
6 *
7 *
8 * \par Copyright 1995-2015 Shark Development Team
9 *
10 * <BR><HR>
11 * This file is part of Shark.
12 * <http://image.diku.dk/shark/>
13 *
14 * Shark is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as published
16 * by the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Shark is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
26 *
27 */
28#ifndef REMORA_TRIANGULAR_MATRIX_HPP
29#define REMORA_TRIANGULAR_MATRIX_HPP
30
31
32#include "assignment.hpp"
33#include "detail/matrix_proxy_classes.hpp"
34
35#include <boost/serialization/collection_size_type.hpp>
36#include <boost/serialization/array.hpp>
37#include <boost/serialization/nvp.hpp>
38#include <boost/serialization/vector.hpp>
39
40namespace remora{
41
42template<class T, class Orientation, class TriangularType>
43class triangular_matrix:public matrix_container<triangular_matrix<T,Orientation,TriangularType>, cpu_tag > {
44 typedef triangular_matrix<T, Orientation,TriangularType> self_type;
45 typedef std::vector<T> array_type;
46public:
47 typedef typename array_type::value_type value_type;
48 typedef value_type const_reference;
49 typedef value_type reference;
50 typedef std::size_t size_type;
51
52 typedef const matrix_reference<const self_type> const_closure_type;
53 typedef matrix_reference<self_type> closure_type;
54 typedef packed_matrix_storage<T> storage_type;
55 typedef packed_matrix_storage<T const> const_storage_type;
56 typedef elementwise<packed_tag> evaluation_category;
57 typedef triangular<Orientation,TriangularType> orientation;
58
59 // Construction and destruction
60
61 /// Default triangular_matrix constructor. Make a dense matrix of size (0,0)
62 triangular_matrix():m_size(0){}
63
64 /** Packed matrix constructor with defined size
65 * \param size number of rows and columns
66 */
67 triangular_matrix(size_type size):m_size(size),m_data(size * (size+1)/2) {}
68
69 /** Packed matrix constructor with defined size and an initial value for all triangular matrix elements
70 * \param size number of rows and columns
71 * \param init initial value of the non-zero elements
72 */
73 triangular_matrix(size_type size, value_type init):m_size(size),m_data(size * (size+1)/2,init) {}
74
75 /** Copy-constructor of a dense matrix
76 * \param m is a dense matrix
77 */
78 triangular_matrix(triangular_matrix const& m):m_size(m.m_size), m_data(m.m_data) {}
79
80 /** Copy-constructor of a dense matrix from a matrix expression
81 * \param e is a matrix expression which has to be triangular
82 */
83 template<class E>
84 triangular_matrix(matrix_expression<E, cpu_tag> const& e)
85 :m_size(e().size1()), m_data(m_size * (m_size+1)/2)
86 {
87 assign(*this, e);
88 }
89
90 ///\brief Returns the number of rows of the matrix.
91 size_type size1() const {
92 return m_size;
93 }
94 ///\brief Returns the number of columns of the matrix.
95 size_type size2() const {
96 return m_size;
97 }
98
99 storage_type raw_storage(){
100 return {m_data.data(), m_data.size()};
101 }
102
103 const_storage_type raw_storage()const{
104 return {m_data.data(), m_data.size()};
105 }
106
107 typename device_traits<cpu_tag>::queue_type& queue(){
108 return device_traits<cpu_tag>::default_queue();
109 }
110
111
112 // Resizing
113 /** Resize a matrix to new dimensions. If resizing is performed, the data is not preserved.
114 * \param size the new number of rows and columns
115 */
116 void resize(size_type size) {
117 m_data.resize(size*(size+1)/2);
118 m_size = size;
119 }
120
121 void resize(size_type size1, size_type size2) {
122 REMORA_SIZE_CHECK(size1 == size2);
123 resize(size1);
124 (void)size2;
125 }
126
127 void clear(){
128 std::fill(m_data.begin(), m_data.end(), value_type/*zero*/());
129 }
130
131 // Element access read only
132 const_reference operator()(size_type i, size_type j) const {
133 REMORA_SIZE_CHECK(i < size1());
134 REMORA_SIZE_CHECK(j < size2());
135 if(!orientation::non_zero(i,j))
136 return value_type();
137 REMORA_SIZE_CHECK(orientation::element(i,j,size1(),packed_tag())<m_data.size());
138 return m_data [orientation::element(i,j,size1(),packed_tag())];
139 }
140
141 // separate write access
142 void set_element(size_type i,size_type j, value_type t){
143 REMORA_SIZE_CHECK(i < size1());
144 REMORA_SIZE_CHECK(j < size2());
145 REMORA_SIZE_CHECK(orientation::non_zero(i,j));
146 m_data [orientation::element(i,j,size1(),packed_tag())] = t;
147 }
148
149 bool non_zero(size_type i,size_type j)const{
150 REMORA_SIZE_CHECK(i < size1());
151 REMORA_SIZE_CHECK(j < size2());
152 return orientation::non_zero(i,j);
153 }
154
155 /*! @note "pass by value" the key idea to enable move semantics */
156 triangular_matrix& operator = (triangular_matrix m) {
157 swap(m);
158 return *this;
159 }
160 template<class C> // Container assignment without temporary
161 triangular_matrix& operator = (matrix_container<C, cpu_tag> const& m) {
162 REMORA_SIZE_CHECK(m().size1()==m().size2());
163 resize(m().size1());
164 assign(*this, m);
165 return *this;
166 }
167 template<class E>
168 triangular_matrix& operator = (matrix_expression<E, cpu_tag> const& e) {
169 self_type temporary(e);
170 swap(temporary);
171 return *this;
172 }
173
174 // Swapping
175 void swap(triangular_matrix& m) {
176 std::swap(m_size, m.m_size);
177 m_data.swap(m.m_data);
178 }
179 friend void swap(triangular_matrix& m1, triangular_matrix& m2) {
180 m1.swap(m2);
181 }
182 typedef iterators::dense_storage_iterator<value_type,iterators::packed_random_access_iterator_tag> major_iterator;
183 typedef iterators::dense_storage_iterator<value_type const,iterators::packed_random_access_iterator_tag> const_major_iterator;
184
185 const_major_iterator major_begin(size_type i) const {
186 bool is_row_major = std::is_same<Orientation, row_major>::value;
187 size_typ index = (TriangularType::is_upper == is_row_major)?i:0;
188 return const_major_iterator(m_data.data() + triangular<row_major,TriangularType>::element(i,index,major_size(*this),packed_tag()),index,1);
189 }
190 const_major_iterator major_end(size_type i) const {
191 bool is_row_major = std::is_same<Orientation, row_major>::value;
192 size_type index = (TriangularType::is_upper == is_row_major)? minor_size(): i + 1;
193 return const_major_iterator(m_data.data() + triangular<row_major,TriangularType>::element(i, index, major_size(*this),packed_tag()),index,1);
194 }
195 major_iterator major_begin(size_type i){
196 bool is_row_major = std::is_same<Orientation, row_major>::value;
197 size_typ index = (TriangularType::is_upper == is_row_major)?i:0;
198 return major_iterator(m_data.data() + triangular<row_major,TriangularType>::element(i, index, major_size(*this),packed_tag()),index,1);
199 }
200 major_iterator major_end(size_type i){
201 bool is_row_major = std::is_same<Orientation, row_major>::value;
202 size_type index = (TriangularType::is_upper == is_row_major)? minor_size(): i + 1;
203 return major_iterator(m_data.data() + triangular<row_major,TriangularType>::element(i, index, major_size(*this),packed_tag()),index,1);
204 }
205
206 // Serialization
207 template<class Archive>
208 void serialize(Archive& ar, const unsigned int /* file_version */) {
209 boost::serialization::collection_size_type s(m_size);
210
211 // serialize the sizes
212 ar & boost::serialization::make_nvp("size",s);
213
214 // copy the values back if loading
215 if (Archive::is_loading::value) {
216 m_size = s;
217 }
218 ar & boost::serialization::make_nvp("data",m_data);
219 }
220
221private:
222 size_type m_size;
223 array_type m_data;
224};
225
226template<class T, class Orientation, class TriangularType>
227struct matrix_temporary_type<T,triangular<Orientation, TriangularType >,packed_tag, cpu_tag> {
228 typedef triangular_matrix<T,Orientation, TriangularType> type;
229};
230
231}
232
233#endif