Chris@49
|
1 // Copyright (C) 2011-2013 Ryan Curtin
|
Chris@49
|
2 // Copyright (C) 2012-2013 Conrad Sanderson
|
Chris@49
|
3 // Copyright (C) 2011 Matthew Amidon
|
Chris@49
|
4 //
|
Chris@49
|
5 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
8
|
Chris@49
|
9 //! \addtogroup SpMat
|
Chris@49
|
10 //! @{
|
Chris@49
|
11
|
Chris@49
|
12 /**
|
Chris@49
|
13 * Initialize a sparse matrix with size 0x0 (empty).
|
Chris@49
|
14 */
|
Chris@49
|
15 template<typename eT>
|
Chris@49
|
16 inline
|
Chris@49
|
17 SpMat<eT>::SpMat()
|
Chris@49
|
18 : n_rows(0)
|
Chris@49
|
19 , n_cols(0)
|
Chris@49
|
20 , n_elem(0)
|
Chris@49
|
21 , n_nonzero(0)
|
Chris@49
|
22 , vec_state(0)
|
Chris@49
|
23 , values(memory::acquire_chunked<eT>(1))
|
Chris@49
|
24 , row_indices(memory::acquire_chunked<uword>(1))
|
Chris@49
|
25 , col_ptrs(memory::acquire<uword>(2))
|
Chris@49
|
26 {
|
Chris@49
|
27 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
28
|
Chris@49
|
29 access::rw(values[0]) = 0;
|
Chris@49
|
30 access::rw(row_indices[0]) = 0;
|
Chris@49
|
31
|
Chris@49
|
32 access::rw(col_ptrs[0]) = 0; // No elements.
|
Chris@49
|
33 access::rw(col_ptrs[1]) = std::numeric_limits<uword>::max();
|
Chris@49
|
34 }
|
Chris@49
|
35
|
Chris@49
|
36
|
Chris@49
|
37
|
Chris@49
|
38 /**
|
Chris@49
|
39 * Clean up the memory of a sparse matrix and destruct it.
|
Chris@49
|
40 */
|
Chris@49
|
41 template<typename eT>
|
Chris@49
|
42 inline
|
Chris@49
|
43 SpMat<eT>::~SpMat()
|
Chris@49
|
44 {
|
Chris@49
|
45 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
46
|
Chris@49
|
47 // If necessary, release the memory.
|
Chris@49
|
48 if (values)
|
Chris@49
|
49 {
|
Chris@49
|
50 // values being non-NULL implies row_indices is non-NULL.
|
Chris@49
|
51 memory::release(access::rw(values));
|
Chris@49
|
52 memory::release(access::rw(row_indices));
|
Chris@49
|
53 }
|
Chris@49
|
54
|
Chris@49
|
55 // Column pointers always must be deleted.
|
Chris@49
|
56 memory::release(access::rw(col_ptrs));
|
Chris@49
|
57 }
|
Chris@49
|
58
|
Chris@49
|
59
|
Chris@49
|
60
|
Chris@49
|
61 /**
|
Chris@49
|
62 * Constructor with size given.
|
Chris@49
|
63 */
|
Chris@49
|
64 template<typename eT>
|
Chris@49
|
65 inline
|
Chris@49
|
66 SpMat<eT>::SpMat(const uword in_rows, const uword in_cols)
|
Chris@49
|
67 : n_rows(0)
|
Chris@49
|
68 , n_cols(0)
|
Chris@49
|
69 , n_elem(0)
|
Chris@49
|
70 , n_nonzero(0)
|
Chris@49
|
71 , vec_state(0)
|
Chris@49
|
72 , values(NULL)
|
Chris@49
|
73 , row_indices(NULL)
|
Chris@49
|
74 , col_ptrs(NULL)
|
Chris@49
|
75 {
|
Chris@49
|
76 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
77
|
Chris@49
|
78 init(in_rows, in_cols);
|
Chris@49
|
79 }
|
Chris@49
|
80
|
Chris@49
|
81
|
Chris@49
|
82
|
Chris@49
|
83 /**
|
Chris@49
|
84 * Assemble from text.
|
Chris@49
|
85 */
|
Chris@49
|
86 template<typename eT>
|
Chris@49
|
87 inline
|
Chris@49
|
88 SpMat<eT>::SpMat(const char* text)
|
Chris@49
|
89 : n_rows(0)
|
Chris@49
|
90 , n_cols(0)
|
Chris@49
|
91 , n_elem(0)
|
Chris@49
|
92 , n_nonzero(0)
|
Chris@49
|
93 , vec_state(0)
|
Chris@49
|
94 , values(NULL)
|
Chris@49
|
95 , row_indices(NULL)
|
Chris@49
|
96 , col_ptrs(NULL)
|
Chris@49
|
97 {
|
Chris@49
|
98 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
99
|
Chris@49
|
100 init(std::string(text));
|
Chris@49
|
101 }
|
Chris@49
|
102
|
Chris@49
|
103
|
Chris@49
|
104
|
Chris@49
|
105 template<typename eT>
|
Chris@49
|
106 inline
|
Chris@49
|
107 const SpMat<eT>&
|
Chris@49
|
108 SpMat<eT>::operator=(const char* text)
|
Chris@49
|
109 {
|
Chris@49
|
110 arma_extra_debug_sigprint();
|
Chris@49
|
111
|
Chris@49
|
112 init(std::string(text));
|
Chris@49
|
113 }
|
Chris@49
|
114
|
Chris@49
|
115
|
Chris@49
|
116
|
Chris@49
|
117 template<typename eT>
|
Chris@49
|
118 inline
|
Chris@49
|
119 SpMat<eT>::SpMat(const std::string& text)
|
Chris@49
|
120 : n_rows(0)
|
Chris@49
|
121 , n_cols(0)
|
Chris@49
|
122 , n_elem(0)
|
Chris@49
|
123 , n_nonzero(0)
|
Chris@49
|
124 , vec_state(0)
|
Chris@49
|
125 , values(NULL)
|
Chris@49
|
126 , row_indices(NULL)
|
Chris@49
|
127 , col_ptrs(NULL)
|
Chris@49
|
128 {
|
Chris@49
|
129 arma_extra_debug_sigprint();
|
Chris@49
|
130
|
Chris@49
|
131 init(text);
|
Chris@49
|
132 }
|
Chris@49
|
133
|
Chris@49
|
134
|
Chris@49
|
135
|
Chris@49
|
136 template<typename eT>
|
Chris@49
|
137 inline
|
Chris@49
|
138 const SpMat<eT>&
|
Chris@49
|
139 SpMat<eT>::operator=(const std::string& text)
|
Chris@49
|
140 {
|
Chris@49
|
141 arma_extra_debug_sigprint();
|
Chris@49
|
142
|
Chris@49
|
143 init(text);
|
Chris@49
|
144 }
|
Chris@49
|
145
|
Chris@49
|
146
|
Chris@49
|
147
|
Chris@49
|
148 template<typename eT>
|
Chris@49
|
149 inline
|
Chris@49
|
150 SpMat<eT>::SpMat(const SpMat<eT>& x)
|
Chris@49
|
151 : n_rows(0)
|
Chris@49
|
152 , n_cols(0)
|
Chris@49
|
153 , n_elem(0)
|
Chris@49
|
154 , n_nonzero(0)
|
Chris@49
|
155 , vec_state(0)
|
Chris@49
|
156 , values(NULL)
|
Chris@49
|
157 , row_indices(NULL)
|
Chris@49
|
158 , col_ptrs(NULL)
|
Chris@49
|
159 {
|
Chris@49
|
160 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
161
|
Chris@49
|
162 init(x);
|
Chris@49
|
163 }
|
Chris@49
|
164
|
Chris@49
|
165
|
Chris@49
|
166
|
Chris@49
|
167 //! Insert a large number of values at once.
|
Chris@49
|
168 //! locations.row[0] should be row indices, locations.row[1] should be column indices,
|
Chris@49
|
169 //! and values should be the corresponding values.
|
Chris@49
|
170 //! If sort_locations is false, then it is assumed that the locations and values
|
Chris@49
|
171 //! are already sorted in column-major ordering.
|
Chris@49
|
172 template<typename eT>
|
Chris@49
|
173 template<typename T1, typename T2>
|
Chris@49
|
174 inline
|
Chris@49
|
175 SpMat<eT>::SpMat(const Base<uword,T1>& locations_expr, const Base<eT,T2>& vals_expr, const bool sort_locations)
|
Chris@49
|
176 : n_rows(0)
|
Chris@49
|
177 , n_cols(0)
|
Chris@49
|
178 , n_elem(0)
|
Chris@49
|
179 , n_nonzero(0)
|
Chris@49
|
180 , vec_state(0)
|
Chris@49
|
181 , values(NULL)
|
Chris@49
|
182 , row_indices(NULL)
|
Chris@49
|
183 , col_ptrs(NULL)
|
Chris@49
|
184 {
|
Chris@49
|
185 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
186
|
Chris@49
|
187 const unwrap<T1> locs_tmp( locations_expr.get_ref() );
|
Chris@49
|
188 const Mat<uword>& locs = locs_tmp.M;
|
Chris@49
|
189
|
Chris@49
|
190 const unwrap<T2> vals_tmp( vals_expr.get_ref() );
|
Chris@49
|
191 const Mat<eT>& vals = vals_tmp.M;
|
Chris@49
|
192
|
Chris@49
|
193 arma_debug_check( (vals.is_vec() == false), "SpMat::SpMat(): given 'values' object is not a vector" );
|
Chris@49
|
194
|
Chris@49
|
195 arma_debug_check((locs.n_cols != vals.n_elem), "SpMat::SpMat(): number of locations is different than number of values");
|
Chris@49
|
196
|
Chris@49
|
197 // If there are no elements in the list, max() will fail.
|
Chris@49
|
198 if (locs.n_cols == 0)
|
Chris@49
|
199 {
|
Chris@49
|
200 init(0, 0);
|
Chris@49
|
201 return;
|
Chris@49
|
202 }
|
Chris@49
|
203
|
Chris@49
|
204 arma_debug_check((locs.n_rows != 2), "SpMat::SpMat(): locations matrix must have two rows");
|
Chris@49
|
205
|
Chris@49
|
206 // Automatically determine size (and check if it's sorted).
|
Chris@49
|
207 uvec bounds = arma::max(locs, 1);
|
Chris@49
|
208 init(bounds[0] + 1, bounds[1] + 1);
|
Chris@49
|
209
|
Chris@49
|
210 // Resize to correct number of elements.
|
Chris@49
|
211 mem_resize(vals.n_elem);
|
Chris@49
|
212
|
Chris@49
|
213 // Reset column pointers to zero.
|
Chris@49
|
214 arrayops::inplace_set(access::rwp(col_ptrs), uword(0), n_cols + 1);
|
Chris@49
|
215
|
Chris@49
|
216 bool actually_sorted = true;
|
Chris@49
|
217 if(sort_locations == true)
|
Chris@49
|
218 {
|
Chris@49
|
219 // sort_index() uses std::sort() which may use quicksort... so we better
|
Chris@49
|
220 // make sure it's not already sorted before taking an O(N^2) sort penalty.
|
Chris@49
|
221 for (uword i = 1; i < locs.n_cols; ++i)
|
Chris@49
|
222 {
|
Chris@49
|
223 if ((locs.at(1, i) < locs.at(1, i - 1)) || (locs.at(1, i) == locs.at(1, i - 1) && locs.at(0, i) <= locs.at(0, i - 1)))
|
Chris@49
|
224 {
|
Chris@49
|
225 actually_sorted = false;
|
Chris@49
|
226 break;
|
Chris@49
|
227 }
|
Chris@49
|
228 }
|
Chris@49
|
229
|
Chris@49
|
230 if(actually_sorted == false)
|
Chris@49
|
231 {
|
Chris@49
|
232 // This may not be the fastest possible implementation but it maximizes code reuse.
|
Chris@49
|
233 Col<uword> abslocs(locs.n_cols);
|
Chris@49
|
234
|
Chris@49
|
235 for (uword i = 0; i < locs.n_cols; ++i)
|
Chris@49
|
236 {
|
Chris@49
|
237 abslocs[i] = locs.at(1, i) * n_rows + locs.at(0, i);
|
Chris@49
|
238 }
|
Chris@49
|
239
|
Chris@49
|
240 // Now we will sort with sort_index().
|
Chris@49
|
241 uvec sorted_indices = sort_index(abslocs); // Ascending sort.
|
Chris@49
|
242
|
Chris@49
|
243 // Now we add the elements in this sorted order.
|
Chris@49
|
244 for (uword i = 0; i < sorted_indices.n_elem; ++i)
|
Chris@49
|
245 {
|
Chris@49
|
246 arma_debug_check((locs.at(0, sorted_indices[i]) >= n_rows), "SpMat::SpMat(): invalid row index");
|
Chris@49
|
247 arma_debug_check((locs.at(1, sorted_indices[i]) >= n_cols), "SpMat::SpMat(): invalid column index");
|
Chris@49
|
248
|
Chris@49
|
249 access::rw(values[i]) = vals[sorted_indices[i]];
|
Chris@49
|
250 access::rw(row_indices[i]) = locs.at(0, sorted_indices[i]);
|
Chris@49
|
251
|
Chris@49
|
252 access::rw(col_ptrs[locs.at(1, sorted_indices[i]) + 1])++;
|
Chris@49
|
253 }
|
Chris@49
|
254 }
|
Chris@49
|
255 }
|
Chris@49
|
256
|
Chris@49
|
257 if( (sort_locations == false) || (actually_sorted == true) )
|
Chris@49
|
258 {
|
Chris@49
|
259 // Now set the values and row indices correctly.
|
Chris@49
|
260 // Increment the column pointers in each column (so they are column "counts").
|
Chris@49
|
261 for (uword i = 0; i < vals.n_elem; ++i)
|
Chris@49
|
262 {
|
Chris@49
|
263 arma_debug_check((locs.at(0, i) >= n_rows), "SpMat::SpMat(): invalid row index");
|
Chris@49
|
264 arma_debug_check((locs.at(1, i) >= n_cols), "SpMat::SpMat(): invalid column index");
|
Chris@49
|
265
|
Chris@49
|
266 // Check ordering in debug mode.
|
Chris@49
|
267 if(i > 0)
|
Chris@49
|
268 {
|
Chris@49
|
269 arma_debug_check
|
Chris@49
|
270 (
|
Chris@49
|
271 ( (locs.at(1, i) < locs.at(1, i - 1)) || (locs.at(1, i) == locs.at(1, i - 1) && locs.at(0, i) < locs.at(0, i - 1)) ),
|
Chris@49
|
272 "SpMat::SpMat(): out of order points; either pass sort_locations = true, or sort points in column-major ordering"
|
Chris@49
|
273 );
|
Chris@49
|
274 arma_debug_check((locs.at(1, i) == locs.at(1, i - 1) && locs.at(0, i) == locs.at(0, i - 1)), "SpMat::SpMat(): two identical point locations in list");
|
Chris@49
|
275 }
|
Chris@49
|
276
|
Chris@49
|
277 access::rw(values[i]) = vals[i];
|
Chris@49
|
278 access::rw(row_indices[i]) = locs.at(0, i);
|
Chris@49
|
279
|
Chris@49
|
280 access::rw(col_ptrs[locs.at(1, i) + 1])++;
|
Chris@49
|
281 }
|
Chris@49
|
282 }
|
Chris@49
|
283
|
Chris@49
|
284 // Now fix the column pointers.
|
Chris@49
|
285 for (uword i = 0; i <= n_cols; ++i)
|
Chris@49
|
286 {
|
Chris@49
|
287 access::rw(col_ptrs[i + 1]) += col_ptrs[i];
|
Chris@49
|
288 }
|
Chris@49
|
289 }
|
Chris@49
|
290
|
Chris@49
|
291
|
Chris@49
|
292
|
Chris@49
|
293 //! Insert a large number of values at once.
|
Chris@49
|
294 //! locations.row[0] should be row indices, locations.row[1] should be column indices,
|
Chris@49
|
295 //! and values should be the corresponding values.
|
Chris@49
|
296 //! If sort_locations is false, then it is assumed that the locations and values
|
Chris@49
|
297 //! are already sorted in column-major ordering.
|
Chris@49
|
298 //! In this constructor the size is explicitly given.
|
Chris@49
|
299 template<typename eT>
|
Chris@49
|
300 template<typename T1, typename T2>
|
Chris@49
|
301 inline
|
Chris@49
|
302 SpMat<eT>::SpMat(const Base<uword,T1>& locations_expr, const Base<eT,T2>& vals_expr, const uword in_n_rows, const uword in_n_cols, const bool sort_locations)
|
Chris@49
|
303 : n_rows(0)
|
Chris@49
|
304 , n_cols(0)
|
Chris@49
|
305 , n_elem(0)
|
Chris@49
|
306 , n_nonzero(0)
|
Chris@49
|
307 , vec_state(0)
|
Chris@49
|
308 , values(NULL)
|
Chris@49
|
309 , row_indices(NULL)
|
Chris@49
|
310 , col_ptrs(NULL)
|
Chris@49
|
311 {
|
Chris@49
|
312 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
313
|
Chris@49
|
314 init(in_n_rows, in_n_cols);
|
Chris@49
|
315
|
Chris@49
|
316 const unwrap<T1> locs_tmp( locations_expr.get_ref() );
|
Chris@49
|
317 const Mat<uword>& locs = locs_tmp.M;
|
Chris@49
|
318
|
Chris@49
|
319 const unwrap<T2> vals_tmp( vals_expr.get_ref() );
|
Chris@49
|
320 const Mat<eT>& vals = vals_tmp.M;
|
Chris@49
|
321
|
Chris@49
|
322 arma_debug_check( (vals.is_vec() == false), "SpMat::SpMat(): given 'values' object is not a vector" );
|
Chris@49
|
323
|
Chris@49
|
324 arma_debug_check((locs.n_rows != 2), "SpMat::SpMat(): locations matrix must have two rows");
|
Chris@49
|
325
|
Chris@49
|
326 arma_debug_check((locs.n_cols != vals.n_elem), "SpMat::SpMat(): number of locations is different than number of values");
|
Chris@49
|
327
|
Chris@49
|
328 // Resize to correct number of elements.
|
Chris@49
|
329 mem_resize(vals.n_elem);
|
Chris@49
|
330
|
Chris@49
|
331 // Reset column pointers to zero.
|
Chris@49
|
332 arrayops::inplace_set(access::rwp(col_ptrs), uword(0), n_cols + 1);
|
Chris@49
|
333
|
Chris@49
|
334 bool actually_sorted = true;
|
Chris@49
|
335 if(sort_locations == true)
|
Chris@49
|
336 {
|
Chris@49
|
337 // sort_index() uses std::sort() which may use quicksort... so we better
|
Chris@49
|
338 // make sure it's not already sorted before taking an O(N^2) sort penalty.
|
Chris@49
|
339 for (uword i = 1; i < locs.n_cols; ++i)
|
Chris@49
|
340 {
|
Chris@49
|
341 if ((locs.at(1, i) < locs.at(1, i - 1)) || (locs.at(1, i) == locs.at(1, i - 1) && locs.at(0, i) <= locs.at(0, i - 1)))
|
Chris@49
|
342 {
|
Chris@49
|
343 actually_sorted = false;
|
Chris@49
|
344 break;
|
Chris@49
|
345 }
|
Chris@49
|
346 }
|
Chris@49
|
347
|
Chris@49
|
348 if(actually_sorted == false)
|
Chris@49
|
349 {
|
Chris@49
|
350 // This may not be the fastest possible implementation but it maximizes code reuse.
|
Chris@49
|
351 Col<uword> abslocs(locs.n_cols);
|
Chris@49
|
352
|
Chris@49
|
353 for (uword i = 0; i < locs.n_cols; ++i)
|
Chris@49
|
354 {
|
Chris@49
|
355 abslocs[i] = locs.at(1, i) * n_rows + locs.at(0, i);
|
Chris@49
|
356 }
|
Chris@49
|
357
|
Chris@49
|
358 // Now we will sort with sort_index().
|
Chris@49
|
359 uvec sorted_indices = sort_index(abslocs); // Ascending sort.
|
Chris@49
|
360
|
Chris@49
|
361 // Now we add the elements in this sorted order.
|
Chris@49
|
362 for (uword i = 0; i < sorted_indices.n_elem; ++i)
|
Chris@49
|
363 {
|
Chris@49
|
364 arma_debug_check((locs.at(0, sorted_indices[i]) >= n_rows), "SpMat::SpMat(): invalid row index");
|
Chris@49
|
365 arma_debug_check((locs.at(1, sorted_indices[i]) >= n_cols), "SpMat::SpMat(): invalid column index");
|
Chris@49
|
366
|
Chris@49
|
367 access::rw(values[i]) = vals[sorted_indices[i]];
|
Chris@49
|
368 access::rw(row_indices[i]) = locs.at(0, sorted_indices[i]);
|
Chris@49
|
369
|
Chris@49
|
370 access::rw(col_ptrs[locs.at(1, sorted_indices[i]) + 1])++;
|
Chris@49
|
371 }
|
Chris@49
|
372 }
|
Chris@49
|
373 }
|
Chris@49
|
374
|
Chris@49
|
375 if( (sort_locations == false) || (actually_sorted == true) )
|
Chris@49
|
376 {
|
Chris@49
|
377 // Now set the values and row indices correctly.
|
Chris@49
|
378 // Increment the column pointers in each column (so they are column "counts").
|
Chris@49
|
379 for (uword i = 0; i < vals.n_elem; ++i)
|
Chris@49
|
380 {
|
Chris@49
|
381 arma_debug_check((locs.at(0, i) >= n_rows), "SpMat::SpMat(): invalid row index");
|
Chris@49
|
382 arma_debug_check((locs.at(1, i) >= n_cols), "SpMat::SpMat(): invalid column index");
|
Chris@49
|
383
|
Chris@49
|
384 // Check ordering in debug mode.
|
Chris@49
|
385 if(i > 0)
|
Chris@49
|
386 {
|
Chris@49
|
387 arma_debug_check
|
Chris@49
|
388 (
|
Chris@49
|
389 ( (locs.at(1, i) < locs.at(1, i - 1)) || (locs.at(1, i) == locs.at(1, i - 1) && locs.at(0, i) < locs.at(0, i - 1)) ),
|
Chris@49
|
390 "SpMat::SpMat(): out of order points; either pass sort_locations = true or sort points in column-major ordering"
|
Chris@49
|
391 );
|
Chris@49
|
392 arma_debug_check((locs.at(1, i) == locs.at(1, i - 1) && locs.at(0, i) == locs.at(0, i - 1)), "SpMat::SpMat(): two identical point locations in list");
|
Chris@49
|
393 }
|
Chris@49
|
394
|
Chris@49
|
395 access::rw(values[i]) = vals[i];
|
Chris@49
|
396 access::rw(row_indices[i]) = locs.at(0, i);
|
Chris@49
|
397
|
Chris@49
|
398 access::rw(col_ptrs[locs.at(1, i) + 1])++;
|
Chris@49
|
399 }
|
Chris@49
|
400 }
|
Chris@49
|
401
|
Chris@49
|
402 // Now fix the column pointers.
|
Chris@49
|
403 for (uword i = 0; i <= n_cols; ++i)
|
Chris@49
|
404 {
|
Chris@49
|
405 access::rw(col_ptrs[i + 1]) += col_ptrs[i];
|
Chris@49
|
406 }
|
Chris@49
|
407 }
|
Chris@49
|
408
|
Chris@49
|
409
|
Chris@49
|
410
|
Chris@49
|
411 /**
|
Chris@49
|
412 * Simple operators with plain values. These operate on every value in the
|
Chris@49
|
413 * matrix, so a sparse matrix += 1 will turn all those zeroes into ones. Be
|
Chris@49
|
414 * careful and make sure that's what you really want!
|
Chris@49
|
415 */
|
Chris@49
|
416 template<typename eT>
|
Chris@49
|
417 inline
|
Chris@49
|
418 const SpMat<eT>&
|
Chris@49
|
419 SpMat<eT>::operator=(const eT val)
|
Chris@49
|
420 {
|
Chris@49
|
421 arma_extra_debug_sigprint();
|
Chris@49
|
422
|
Chris@49
|
423 // Resize to 1x1 then set that to the right value.
|
Chris@49
|
424 init(1, 1); // Sets col_ptrs to 0.
|
Chris@49
|
425 mem_resize(1); // One element.
|
Chris@49
|
426
|
Chris@49
|
427 // Manually set element.
|
Chris@49
|
428 access::rw(values[0]) = val;
|
Chris@49
|
429 access::rw(row_indices[0]) = 0;
|
Chris@49
|
430 access::rw(col_ptrs[1]) = 1;
|
Chris@49
|
431
|
Chris@49
|
432 return *this;
|
Chris@49
|
433 }
|
Chris@49
|
434
|
Chris@49
|
435
|
Chris@49
|
436
|
Chris@49
|
437 template<typename eT>
|
Chris@49
|
438 inline
|
Chris@49
|
439 const SpMat<eT>&
|
Chris@49
|
440 SpMat<eT>::operator*=(const eT val)
|
Chris@49
|
441 {
|
Chris@49
|
442 arma_extra_debug_sigprint();
|
Chris@49
|
443
|
Chris@49
|
444 if(val == eT(0))
|
Chris@49
|
445 {
|
Chris@49
|
446 // Everything will be zero.
|
Chris@49
|
447 init(n_rows, n_cols);
|
Chris@49
|
448 return *this;
|
Chris@49
|
449 }
|
Chris@49
|
450
|
Chris@49
|
451 arrayops::inplace_mul( access::rwp(values), val, n_nonzero );
|
Chris@49
|
452
|
Chris@49
|
453 return *this;
|
Chris@49
|
454 }
|
Chris@49
|
455
|
Chris@49
|
456
|
Chris@49
|
457
|
Chris@49
|
458 template<typename eT>
|
Chris@49
|
459 inline
|
Chris@49
|
460 const SpMat<eT>&
|
Chris@49
|
461 SpMat<eT>::operator/=(const eT val)
|
Chris@49
|
462 {
|
Chris@49
|
463 arma_extra_debug_sigprint();
|
Chris@49
|
464
|
Chris@49
|
465 arma_debug_check( (val == eT(0)), "element-wise division: division by zero" );
|
Chris@49
|
466
|
Chris@49
|
467 arrayops::inplace_div( access::rwp(values), val, n_nonzero );
|
Chris@49
|
468
|
Chris@49
|
469 return *this;
|
Chris@49
|
470 }
|
Chris@49
|
471
|
Chris@49
|
472
|
Chris@49
|
473
|
Chris@49
|
474 template<typename eT>
|
Chris@49
|
475 inline
|
Chris@49
|
476 const SpMat<eT>&
|
Chris@49
|
477 SpMat<eT>::operator=(const SpMat<eT>& x)
|
Chris@49
|
478 {
|
Chris@49
|
479 arma_extra_debug_sigprint();
|
Chris@49
|
480
|
Chris@49
|
481 init(x);
|
Chris@49
|
482
|
Chris@49
|
483 return *this;
|
Chris@49
|
484 }
|
Chris@49
|
485
|
Chris@49
|
486
|
Chris@49
|
487
|
Chris@49
|
488 template<typename eT>
|
Chris@49
|
489 inline
|
Chris@49
|
490 const SpMat<eT>&
|
Chris@49
|
491 SpMat<eT>::operator+=(const SpMat<eT>& x)
|
Chris@49
|
492 {
|
Chris@49
|
493 arma_extra_debug_sigprint();
|
Chris@49
|
494
|
Chris@49
|
495 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "addition");
|
Chris@49
|
496
|
Chris@49
|
497 // Iterate over nonzero values of other matrix.
|
Chris@49
|
498 for (const_iterator it = x.begin(); it != x.end(); it++)
|
Chris@49
|
499 {
|
Chris@49
|
500 get_value(it.row(), it.col()) += *it;
|
Chris@49
|
501 }
|
Chris@49
|
502
|
Chris@49
|
503 return *this;
|
Chris@49
|
504 }
|
Chris@49
|
505
|
Chris@49
|
506
|
Chris@49
|
507
|
Chris@49
|
508 template<typename eT>
|
Chris@49
|
509 inline
|
Chris@49
|
510 const SpMat<eT>&
|
Chris@49
|
511 SpMat<eT>::operator-=(const SpMat<eT>& x)
|
Chris@49
|
512 {
|
Chris@49
|
513 arma_extra_debug_sigprint();
|
Chris@49
|
514
|
Chris@49
|
515 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "subtraction");
|
Chris@49
|
516
|
Chris@49
|
517 // Iterate over nonzero values of other matrix.
|
Chris@49
|
518 for (const_iterator it = x.begin(); it != x.end(); it++)
|
Chris@49
|
519 {
|
Chris@49
|
520 get_value(it.row(), it.col()) -= *it;
|
Chris@49
|
521 }
|
Chris@49
|
522
|
Chris@49
|
523 return *this;
|
Chris@49
|
524 }
|
Chris@49
|
525
|
Chris@49
|
526
|
Chris@49
|
527
|
Chris@49
|
528 template<typename eT>
|
Chris@49
|
529 inline
|
Chris@49
|
530 const SpMat<eT>&
|
Chris@49
|
531 SpMat<eT>::operator*=(const SpMat<eT>& y)
|
Chris@49
|
532 {
|
Chris@49
|
533 arma_extra_debug_sigprint();
|
Chris@49
|
534
|
Chris@49
|
535 arma_debug_assert_mul_size(n_rows, n_cols, y.n_rows, y.n_cols, "matrix multiplication");
|
Chris@49
|
536
|
Chris@49
|
537 SpMat<eT> z;
|
Chris@49
|
538 z = (*this) * y;
|
Chris@49
|
539 steal_mem(z);
|
Chris@49
|
540
|
Chris@49
|
541 return *this;
|
Chris@49
|
542 }
|
Chris@49
|
543
|
Chris@49
|
544
|
Chris@49
|
545
|
Chris@49
|
546 // This is in-place element-wise matrix multiplication.
|
Chris@49
|
547 template<typename eT>
|
Chris@49
|
548 inline
|
Chris@49
|
549 const SpMat<eT>&
|
Chris@49
|
550 SpMat<eT>::operator%=(const SpMat<eT>& x)
|
Chris@49
|
551 {
|
Chris@49
|
552 arma_extra_debug_sigprint();
|
Chris@49
|
553
|
Chris@49
|
554 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise multiplication");
|
Chris@49
|
555
|
Chris@49
|
556 // We can do this with two iterators rather simply.
|
Chris@49
|
557 iterator it = begin();
|
Chris@49
|
558 const_iterator x_it = x.begin();
|
Chris@49
|
559
|
Chris@49
|
560 while (it != end() && x_it != x.end())
|
Chris@49
|
561 {
|
Chris@49
|
562 // One of these will be further advanced than the other (or they will be at the same place).
|
Chris@49
|
563 if ((it.row() == x_it.row()) && (it.col() == x_it.col()))
|
Chris@49
|
564 {
|
Chris@49
|
565 // There is an element at this place in both matrices. Multiply.
|
Chris@49
|
566 (*it) *= (*x_it);
|
Chris@49
|
567
|
Chris@49
|
568 // Now move on to the next position.
|
Chris@49
|
569 it++;
|
Chris@49
|
570 x_it++;
|
Chris@49
|
571 }
|
Chris@49
|
572
|
Chris@49
|
573 else if ((it.col() < x_it.col()) || ((it.col() == x_it.col()) && (it.row() < x_it.row())))
|
Chris@49
|
574 {
|
Chris@49
|
575 // This case is when our matrix has an element which the other matrix does not.
|
Chris@49
|
576 // So we must delete this element.
|
Chris@49
|
577 (*it) = 0;
|
Chris@49
|
578
|
Chris@49
|
579 // Because we have deleted the element, we now have to manually set the position...
|
Chris@49
|
580 it.internal_pos--;
|
Chris@49
|
581
|
Chris@49
|
582 // Now we can increment our iterator.
|
Chris@49
|
583 it++;
|
Chris@49
|
584 }
|
Chris@49
|
585
|
Chris@49
|
586 else /* if our iterator is ahead of the other matrix */
|
Chris@49
|
587 {
|
Chris@49
|
588 // In this case we don't need to set anything to 0; our element is already 0.
|
Chris@49
|
589 // We can just increment the iterator of the other matrix.
|
Chris@49
|
590 x_it++;
|
Chris@49
|
591 }
|
Chris@49
|
592
|
Chris@49
|
593 }
|
Chris@49
|
594
|
Chris@49
|
595 // If we are not at the end of our matrix, then we must terminate the remaining elements.
|
Chris@49
|
596 while (it != end())
|
Chris@49
|
597 {
|
Chris@49
|
598 (*it) = 0;
|
Chris@49
|
599
|
Chris@49
|
600 // Hack to manually set the position right...
|
Chris@49
|
601 it.internal_pos--;
|
Chris@49
|
602 it++; // ...and then an increment.
|
Chris@49
|
603 }
|
Chris@49
|
604
|
Chris@49
|
605 return *this;
|
Chris@49
|
606 }
|
Chris@49
|
607
|
Chris@49
|
608
|
Chris@49
|
609
|
Chris@49
|
610 // Construct a complex matrix out of two non-complex matrices
|
Chris@49
|
611 template<typename eT>
|
Chris@49
|
612 template<typename T1, typename T2>
|
Chris@49
|
613 inline
|
Chris@49
|
614 SpMat<eT>::SpMat
|
Chris@49
|
615 (
|
Chris@49
|
616 const SpBase<typename SpMat<eT>::pod_type, T1>& A,
|
Chris@49
|
617 const SpBase<typename SpMat<eT>::pod_type, T2>& B
|
Chris@49
|
618 )
|
Chris@49
|
619 : n_rows(0)
|
Chris@49
|
620 , n_cols(0)
|
Chris@49
|
621 , n_elem(0)
|
Chris@49
|
622 , n_nonzero(0)
|
Chris@49
|
623 , vec_state(0)
|
Chris@49
|
624 , values(NULL) // extra element is set when mem_resize is called
|
Chris@49
|
625 , row_indices(NULL)
|
Chris@49
|
626 , col_ptrs(NULL)
|
Chris@49
|
627 {
|
Chris@49
|
628 arma_extra_debug_sigprint();
|
Chris@49
|
629
|
Chris@49
|
630 typedef typename T1::elem_type T;
|
Chris@49
|
631
|
Chris@49
|
632 // Make sure eT is complex and T is not (compile-time check).
|
Chris@49
|
633 arma_type_check(( is_complex<eT>::value == false ));
|
Chris@49
|
634 arma_type_check(( is_complex< T>::value == true ));
|
Chris@49
|
635
|
Chris@49
|
636 // Compile-time abort if types are not compatible.
|
Chris@49
|
637 arma_type_check(( is_same_type< std::complex<T>, eT >::value == false ));
|
Chris@49
|
638
|
Chris@49
|
639 const unwrap_spmat<T1> tmp1(A.get_ref());
|
Chris@49
|
640 const unwrap_spmat<T2> tmp2(B.get_ref());
|
Chris@49
|
641
|
Chris@49
|
642 const SpMat<T>& X = tmp1.M;
|
Chris@49
|
643 const SpMat<T>& Y = tmp2.M;
|
Chris@49
|
644
|
Chris@49
|
645 arma_debug_assert_same_size(X.n_rows, X.n_cols, Y.n_rows, Y.n_cols, "SpMat()");
|
Chris@49
|
646
|
Chris@49
|
647 const uword l_n_rows = X.n_rows;
|
Chris@49
|
648 const uword l_n_cols = X.n_cols;
|
Chris@49
|
649
|
Chris@49
|
650 // Set size of matrix correctly.
|
Chris@49
|
651 init(l_n_rows, l_n_cols);
|
Chris@49
|
652 mem_resize(n_unique(X, Y, op_n_unique_count()));
|
Chris@49
|
653
|
Chris@49
|
654 // Now on a second iteration, fill it.
|
Chris@49
|
655 typename SpMat<T>::const_iterator x_it = X.begin();
|
Chris@49
|
656 typename SpMat<T>::const_iterator x_end = X.end();
|
Chris@49
|
657
|
Chris@49
|
658 typename SpMat<T>::const_iterator y_it = Y.begin();
|
Chris@49
|
659 typename SpMat<T>::const_iterator y_end = Y.end();
|
Chris@49
|
660
|
Chris@49
|
661 uword cur_pos = 0;
|
Chris@49
|
662
|
Chris@49
|
663 while ((x_it != x_end) || (y_it != y_end))
|
Chris@49
|
664 {
|
Chris@49
|
665 if(x_it == y_it) // if we are at the same place
|
Chris@49
|
666 {
|
Chris@49
|
667 access::rw(values[cur_pos]) = std::complex<T>((T) *x_it, (T) *y_it);
|
Chris@49
|
668 access::rw(row_indices[cur_pos]) = x_it.row();
|
Chris@49
|
669 ++access::rw(col_ptrs[x_it.col() + 1]);
|
Chris@49
|
670
|
Chris@49
|
671 ++x_it;
|
Chris@49
|
672 ++y_it;
|
Chris@49
|
673 }
|
Chris@49
|
674 else
|
Chris@49
|
675 {
|
Chris@49
|
676 if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.row() < y_it.row()))) // if y is closer to the end
|
Chris@49
|
677 {
|
Chris@49
|
678 access::rw(values[cur_pos]) = std::complex<T>((T) *x_it, T(0));
|
Chris@49
|
679 access::rw(row_indices[cur_pos]) = x_it.row();
|
Chris@49
|
680 ++access::rw(col_ptrs[x_it.col() + 1]);
|
Chris@49
|
681
|
Chris@49
|
682 ++x_it;
|
Chris@49
|
683 }
|
Chris@49
|
684 else // x is closer to the end
|
Chris@49
|
685 {
|
Chris@49
|
686 access::rw(values[cur_pos]) = std::complex<T>(T(0), (T) *y_it);
|
Chris@49
|
687 access::rw(row_indices[cur_pos]) = y_it.row();
|
Chris@49
|
688 ++access::rw(col_ptrs[y_it.col() + 1]);
|
Chris@49
|
689
|
Chris@49
|
690 ++y_it;
|
Chris@49
|
691 }
|
Chris@49
|
692 }
|
Chris@49
|
693
|
Chris@49
|
694 ++cur_pos;
|
Chris@49
|
695 }
|
Chris@49
|
696
|
Chris@49
|
697 // Now fix the column pointers; they are supposed to be a sum.
|
Chris@49
|
698 for (uword c = 1; c <= n_cols; ++c)
|
Chris@49
|
699 {
|
Chris@49
|
700 access::rw(col_ptrs[c]) += col_ptrs[c - 1];
|
Chris@49
|
701 }
|
Chris@49
|
702
|
Chris@49
|
703 }
|
Chris@49
|
704
|
Chris@49
|
705
|
Chris@49
|
706
|
Chris@49
|
707 template<typename eT>
|
Chris@49
|
708 inline
|
Chris@49
|
709 const SpMat<eT>&
|
Chris@49
|
710 SpMat<eT>::operator/=(const SpMat<eT>& x)
|
Chris@49
|
711 {
|
Chris@49
|
712 arma_extra_debug_sigprint();
|
Chris@49
|
713
|
Chris@49
|
714 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise division");
|
Chris@49
|
715
|
Chris@49
|
716 // If you use this method, you are probably stupid or misguided, but for compatibility with Mat, we have implemented it anyway.
|
Chris@49
|
717 // We have to loop over every element, which is not good. In fact, it makes me physically sad to write this.
|
Chris@49
|
718 for(uword c = 0; c < n_cols; ++c)
|
Chris@49
|
719 {
|
Chris@49
|
720 for(uword r = 0; r < n_rows; ++r)
|
Chris@49
|
721 {
|
Chris@49
|
722 at(r, c) /= x.at(r, c);
|
Chris@49
|
723 }
|
Chris@49
|
724 }
|
Chris@49
|
725
|
Chris@49
|
726 return *this;
|
Chris@49
|
727 }
|
Chris@49
|
728
|
Chris@49
|
729
|
Chris@49
|
730
|
Chris@49
|
731 template<typename eT>
|
Chris@49
|
732 template<typename T1>
|
Chris@49
|
733 inline
|
Chris@49
|
734 SpMat<eT>::SpMat(const Base<eT, T1>& x)
|
Chris@49
|
735 : n_rows(0)
|
Chris@49
|
736 , n_cols(0)
|
Chris@49
|
737 , n_elem(0)
|
Chris@49
|
738 , n_nonzero(0)
|
Chris@49
|
739 , vec_state(0)
|
Chris@49
|
740 , values(NULL) // extra element is set when mem_resize is called in operator=()
|
Chris@49
|
741 , row_indices(NULL)
|
Chris@49
|
742 , col_ptrs(NULL)
|
Chris@49
|
743 {
|
Chris@49
|
744 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
745
|
Chris@49
|
746 (*this).operator=(x);
|
Chris@49
|
747 }
|
Chris@49
|
748
|
Chris@49
|
749
|
Chris@49
|
750
|
Chris@49
|
751 template<typename eT>
|
Chris@49
|
752 template<typename T1>
|
Chris@49
|
753 inline
|
Chris@49
|
754 const SpMat<eT>&
|
Chris@49
|
755 SpMat<eT>::operator=(const Base<eT, T1>& x)
|
Chris@49
|
756 {
|
Chris@49
|
757 arma_extra_debug_sigprint();
|
Chris@49
|
758
|
Chris@49
|
759 const Proxy<T1> p(x.get_ref());
|
Chris@49
|
760
|
Chris@49
|
761 const uword x_n_rows = p.get_n_rows();
|
Chris@49
|
762 const uword x_n_cols = p.get_n_cols();
|
Chris@49
|
763 const uword x_n_elem = p.get_n_elem();
|
Chris@49
|
764
|
Chris@49
|
765 init(x_n_rows, x_n_cols);
|
Chris@49
|
766
|
Chris@49
|
767 // Count number of nonzero elements in base object.
|
Chris@49
|
768 uword n = 0;
|
Chris@49
|
769 if(Proxy<T1>::prefer_at_accessor == true)
|
Chris@49
|
770 {
|
Chris@49
|
771 for(uword j = 0; j < x_n_cols; ++j)
|
Chris@49
|
772 for(uword i = 0; i < x_n_rows; ++i)
|
Chris@49
|
773 {
|
Chris@49
|
774 if(p.at(i, j) != eT(0)) { ++n; }
|
Chris@49
|
775 }
|
Chris@49
|
776 }
|
Chris@49
|
777 else
|
Chris@49
|
778 {
|
Chris@49
|
779 for(uword i = 0; i < x_n_elem; ++i)
|
Chris@49
|
780 {
|
Chris@49
|
781 if(p[i] != eT(0)) { ++n; }
|
Chris@49
|
782 }
|
Chris@49
|
783 }
|
Chris@49
|
784
|
Chris@49
|
785 mem_resize(n);
|
Chris@49
|
786
|
Chris@49
|
787 // Now the memory is resized correctly; add nonzero elements.
|
Chris@49
|
788 n = 0;
|
Chris@49
|
789 for(uword j = 0; j < x_n_cols; ++j)
|
Chris@49
|
790 for(uword i = 0; i < x_n_rows; ++i)
|
Chris@49
|
791 {
|
Chris@49
|
792 const eT val = p.at(i, j);
|
Chris@49
|
793
|
Chris@49
|
794 if(val != eT(0))
|
Chris@49
|
795 {
|
Chris@49
|
796 access::rw(values[n]) = val;
|
Chris@49
|
797 access::rw(row_indices[n]) = i;
|
Chris@49
|
798 access::rw(col_ptrs[j + 1])++;
|
Chris@49
|
799 ++n;
|
Chris@49
|
800 }
|
Chris@49
|
801 }
|
Chris@49
|
802
|
Chris@49
|
803 // Sum column counts to be column pointers.
|
Chris@49
|
804 for(uword c = 1; c <= n_cols; ++c)
|
Chris@49
|
805 {
|
Chris@49
|
806 access::rw(col_ptrs[c]) += col_ptrs[c - 1];
|
Chris@49
|
807 }
|
Chris@49
|
808
|
Chris@49
|
809 return *this;
|
Chris@49
|
810 }
|
Chris@49
|
811
|
Chris@49
|
812
|
Chris@49
|
813
|
Chris@49
|
814 template<typename eT>
|
Chris@49
|
815 template<typename T1>
|
Chris@49
|
816 inline
|
Chris@49
|
817 const SpMat<eT>&
|
Chris@49
|
818 SpMat<eT>::operator*=(const Base<eT, T1>& y)
|
Chris@49
|
819 {
|
Chris@49
|
820 arma_extra_debug_sigprint();
|
Chris@49
|
821
|
Chris@49
|
822 const Proxy<T1> p(y.get_ref());
|
Chris@49
|
823
|
Chris@49
|
824 arma_debug_assert_mul_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "matrix multiplication");
|
Chris@49
|
825
|
Chris@49
|
826 // We assume the matrix structure is such that we will end up with a sparse
|
Chris@49
|
827 // matrix. Assuming that every entry in the dense matrix is nonzero (which is
|
Chris@49
|
828 // a fairly valid assumption), each row with any nonzero elements in it (in this
|
Chris@49
|
829 // matrix) implies an entire nonzero column. Therefore, we iterate over all
|
Chris@49
|
830 // the row_indices and count the number of rows with any elements in them
|
Chris@49
|
831 // (using the quasi-linked-list idea from SYMBMM -- see operator_times.hpp).
|
Chris@49
|
832 podarray<uword> index(n_rows);
|
Chris@49
|
833 index.fill(n_rows); // Fill with invalid links.
|
Chris@49
|
834
|
Chris@49
|
835 uword last_index = n_rows + 1;
|
Chris@49
|
836 for(uword i = 0; i < n_nonzero; ++i)
|
Chris@49
|
837 {
|
Chris@49
|
838 if(index[row_indices[i]] == n_rows)
|
Chris@49
|
839 {
|
Chris@49
|
840 index[row_indices[i]] = last_index;
|
Chris@49
|
841 last_index = row_indices[i];
|
Chris@49
|
842 }
|
Chris@49
|
843 }
|
Chris@49
|
844
|
Chris@49
|
845 // Now count the number of rows which have nonzero elements.
|
Chris@49
|
846 uword nonzero_rows = 0;
|
Chris@49
|
847 while(last_index != n_rows + 1)
|
Chris@49
|
848 {
|
Chris@49
|
849 ++nonzero_rows;
|
Chris@49
|
850 last_index = index[last_index];
|
Chris@49
|
851 }
|
Chris@49
|
852
|
Chris@49
|
853 SpMat<eT> z(n_rows, p.get_n_cols());
|
Chris@49
|
854
|
Chris@49
|
855 z.mem_resize(nonzero_rows * p.get_n_cols()); // upper bound on size
|
Chris@49
|
856
|
Chris@49
|
857 // Now we have to fill all the elements using a modification of the NUMBMM algorithm.
|
Chris@49
|
858 uword cur_pos = 0;
|
Chris@49
|
859
|
Chris@49
|
860 podarray<eT> partial_sums(n_rows);
|
Chris@49
|
861 partial_sums.zeros();
|
Chris@49
|
862
|
Chris@49
|
863 for(uword lcol = 0; lcol < n_cols; ++lcol)
|
Chris@49
|
864 {
|
Chris@49
|
865 const_iterator it = begin();
|
Chris@49
|
866
|
Chris@49
|
867 while(it != end())
|
Chris@49
|
868 {
|
Chris@49
|
869 const eT value = (*it);
|
Chris@49
|
870
|
Chris@49
|
871 partial_sums[it.row()] += (value * p.at(it.col(), lcol));
|
Chris@49
|
872
|
Chris@49
|
873 ++it;
|
Chris@49
|
874 }
|
Chris@49
|
875
|
Chris@49
|
876 // Now add all partial sums to the matrix.
|
Chris@49
|
877 for(uword i = 0; i < n_rows; ++i)
|
Chris@49
|
878 {
|
Chris@49
|
879 if(partial_sums[i] != eT(0))
|
Chris@49
|
880 {
|
Chris@49
|
881 access::rw(z.values[cur_pos]) = partial_sums[i];
|
Chris@49
|
882 access::rw(z.row_indices[cur_pos]) = i;
|
Chris@49
|
883 ++access::rw(z.col_ptrs[lcol + 1]);
|
Chris@49
|
884 //printf("colptr %d now %d\n", lcol + 1, z.col_ptrs[lcol + 1]);
|
Chris@49
|
885 ++cur_pos;
|
Chris@49
|
886 partial_sums[i] = 0; // Would it be faster to do this in batch later?
|
Chris@49
|
887 }
|
Chris@49
|
888 }
|
Chris@49
|
889 }
|
Chris@49
|
890
|
Chris@49
|
891 // Now fix the column pointers.
|
Chris@49
|
892 for(uword c = 1; c <= z.n_cols; ++c)
|
Chris@49
|
893 {
|
Chris@49
|
894 access::rw(z.col_ptrs[c]) += z.col_ptrs[c - 1];
|
Chris@49
|
895 }
|
Chris@49
|
896
|
Chris@49
|
897 // Resize to final correct size.
|
Chris@49
|
898 z.mem_resize(z.col_ptrs[z.n_cols]);
|
Chris@49
|
899
|
Chris@49
|
900 // Now take the memory of the temporary matrix.
|
Chris@49
|
901 steal_mem(z);
|
Chris@49
|
902
|
Chris@49
|
903 return *this;
|
Chris@49
|
904 }
|
Chris@49
|
905
|
Chris@49
|
906
|
Chris@49
|
907
|
Chris@49
|
908 /**
|
Chris@49
|
909 * Don't use this function. It's not mathematically well-defined and wastes
|
Chris@49
|
910 * cycles to trash all your data. This is dumb.
|
Chris@49
|
911 */
|
Chris@49
|
912 template<typename eT>
|
Chris@49
|
913 template<typename T1>
|
Chris@49
|
914 inline
|
Chris@49
|
915 const SpMat<eT>&
|
Chris@49
|
916 SpMat<eT>::operator/=(const Base<eT, T1>& x)
|
Chris@49
|
917 {
|
Chris@49
|
918 arma_extra_debug_sigprint();
|
Chris@49
|
919
|
Chris@49
|
920 SpMat<eT> tmp = (*this) / x.get_ref();
|
Chris@49
|
921
|
Chris@49
|
922 steal_mem(tmp);
|
Chris@49
|
923
|
Chris@49
|
924 return *this;
|
Chris@49
|
925 }
|
Chris@49
|
926
|
Chris@49
|
927
|
Chris@49
|
928
|
Chris@49
|
929 template<typename eT>
|
Chris@49
|
930 template<typename T1>
|
Chris@49
|
931 inline
|
Chris@49
|
932 const SpMat<eT>&
|
Chris@49
|
933 SpMat<eT>::operator%=(const Base<eT, T1>& x)
|
Chris@49
|
934 {
|
Chris@49
|
935 arma_extra_debug_sigprint();
|
Chris@49
|
936
|
Chris@49
|
937 const Proxy<T1> p(x.get_ref());
|
Chris@49
|
938
|
Chris@49
|
939 arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise multiplication");
|
Chris@49
|
940
|
Chris@49
|
941 // Count the number of elements we will need.
|
Chris@49
|
942 SpMat<eT> tmp(n_rows, n_cols);
|
Chris@49
|
943 const_iterator it = begin();
|
Chris@49
|
944 uword new_n_nonzero = 0;
|
Chris@49
|
945
|
Chris@49
|
946 while(it != end())
|
Chris@49
|
947 {
|
Chris@49
|
948 // prefer_at_accessor == false can't save us any work here
|
Chris@49
|
949 if(((*it) * p.at(it.row(), it.col())) != eT(0))
|
Chris@49
|
950 {
|
Chris@49
|
951 ++new_n_nonzero;
|
Chris@49
|
952 }
|
Chris@49
|
953 ++it;
|
Chris@49
|
954 }
|
Chris@49
|
955
|
Chris@49
|
956 // Resize.
|
Chris@49
|
957 tmp.mem_resize(new_n_nonzero);
|
Chris@49
|
958
|
Chris@49
|
959 const_iterator c_it = begin();
|
Chris@49
|
960 uword cur_pos = 0;
|
Chris@49
|
961 while(c_it != end())
|
Chris@49
|
962 {
|
Chris@49
|
963 // prefer_at_accessor == false can't save us any work here
|
Chris@49
|
964 const eT val = (*c_it) * p.at(c_it.row(), c_it.col());
|
Chris@49
|
965 if(val != eT(0))
|
Chris@49
|
966 {
|
Chris@49
|
967 access::rw(tmp.values[cur_pos]) = val;
|
Chris@49
|
968 access::rw(tmp.row_indices[cur_pos]) = c_it.row();
|
Chris@49
|
969 ++access::rw(tmp.col_ptrs[c_it.col() + 1]);
|
Chris@49
|
970 ++cur_pos;
|
Chris@49
|
971 }
|
Chris@49
|
972
|
Chris@49
|
973 ++c_it;
|
Chris@49
|
974 }
|
Chris@49
|
975
|
Chris@49
|
976 // Fix column pointers.
|
Chris@49
|
977 for(uword c = 1; c <= n_cols; ++c)
|
Chris@49
|
978 {
|
Chris@49
|
979 access::rw(tmp.col_ptrs[c]) += tmp.col_ptrs[c - 1];
|
Chris@49
|
980 }
|
Chris@49
|
981
|
Chris@49
|
982 steal_mem(tmp);
|
Chris@49
|
983
|
Chris@49
|
984 return *this;
|
Chris@49
|
985 }
|
Chris@49
|
986
|
Chris@49
|
987
|
Chris@49
|
988
|
Chris@49
|
989 /**
|
Chris@49
|
990 * Functions on subviews.
|
Chris@49
|
991 */
|
Chris@49
|
992 template<typename eT>
|
Chris@49
|
993 inline
|
Chris@49
|
994 SpMat<eT>::SpMat(const SpSubview<eT>& X)
|
Chris@49
|
995 : n_rows(0)
|
Chris@49
|
996 , n_cols(0)
|
Chris@49
|
997 , n_elem(0)
|
Chris@49
|
998 , n_nonzero(0)
|
Chris@49
|
999 , vec_state(0)
|
Chris@49
|
1000 , values(NULL) // extra element added when mem_resize is called
|
Chris@49
|
1001 , row_indices(NULL)
|
Chris@49
|
1002 , col_ptrs(NULL)
|
Chris@49
|
1003 {
|
Chris@49
|
1004 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
1005
|
Chris@49
|
1006 (*this).operator=(X);
|
Chris@49
|
1007 }
|
Chris@49
|
1008
|
Chris@49
|
1009
|
Chris@49
|
1010
|
Chris@49
|
1011 template<typename eT>
|
Chris@49
|
1012 inline
|
Chris@49
|
1013 const SpMat<eT>&
|
Chris@49
|
1014 SpMat<eT>::operator=(const SpSubview<eT>& X)
|
Chris@49
|
1015 {
|
Chris@49
|
1016 arma_extra_debug_sigprint();
|
Chris@49
|
1017
|
Chris@49
|
1018 const uword in_n_cols = X.n_cols;
|
Chris@49
|
1019 const uword in_n_rows = X.n_rows;
|
Chris@49
|
1020
|
Chris@49
|
1021 const bool alias = (this == &(X.m));
|
Chris@49
|
1022
|
Chris@49
|
1023 if(alias == false)
|
Chris@49
|
1024 {
|
Chris@49
|
1025 init(in_n_rows, in_n_cols);
|
Chris@49
|
1026
|
Chris@49
|
1027 const uword x_n_nonzero = X.n_nonzero;
|
Chris@49
|
1028
|
Chris@49
|
1029 mem_resize(x_n_nonzero);
|
Chris@49
|
1030
|
Chris@49
|
1031 typename SpSubview<eT>::const_iterator it = X.begin();
|
Chris@49
|
1032
|
Chris@49
|
1033 while(it != X.end())
|
Chris@49
|
1034 {
|
Chris@49
|
1035 access::rw(row_indices[it.pos()]) = it.row();
|
Chris@49
|
1036 access::rw(values[it.pos()]) = (*it);
|
Chris@49
|
1037 ++access::rw(col_ptrs[it.col() + 1]);
|
Chris@49
|
1038 ++it;
|
Chris@49
|
1039 }
|
Chris@49
|
1040
|
Chris@49
|
1041 // Now sum column pointers.
|
Chris@49
|
1042 for(uword c = 1; c <= n_cols; ++c)
|
Chris@49
|
1043 {
|
Chris@49
|
1044 access::rw(col_ptrs[c]) += col_ptrs[c - 1];
|
Chris@49
|
1045 }
|
Chris@49
|
1046 }
|
Chris@49
|
1047 else
|
Chris@49
|
1048 {
|
Chris@49
|
1049 // Create it in a temporary.
|
Chris@49
|
1050 SpMat<eT> tmp(X);
|
Chris@49
|
1051
|
Chris@49
|
1052 steal_mem(tmp);
|
Chris@49
|
1053 }
|
Chris@49
|
1054
|
Chris@49
|
1055 return *this;
|
Chris@49
|
1056 }
|
Chris@49
|
1057
|
Chris@49
|
1058
|
Chris@49
|
1059
|
Chris@49
|
1060 template<typename eT>
|
Chris@49
|
1061 inline
|
Chris@49
|
1062 const SpMat<eT>&
|
Chris@49
|
1063 SpMat<eT>::operator+=(const SpSubview<eT>& X)
|
Chris@49
|
1064 {
|
Chris@49
|
1065 arma_extra_debug_sigprint();
|
Chris@49
|
1066
|
Chris@49
|
1067 arma_debug_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "addition");
|
Chris@49
|
1068
|
Chris@49
|
1069 typename SpSubview<eT>::const_iterator it = X.begin();
|
Chris@49
|
1070
|
Chris@49
|
1071 while(it != X.end())
|
Chris@49
|
1072 {
|
Chris@49
|
1073 at(it.row(), it.col()) += (*it);
|
Chris@49
|
1074 ++it;
|
Chris@49
|
1075 }
|
Chris@49
|
1076
|
Chris@49
|
1077 return *this;
|
Chris@49
|
1078 }
|
Chris@49
|
1079
|
Chris@49
|
1080
|
Chris@49
|
1081
|
Chris@49
|
1082 template<typename eT>
|
Chris@49
|
1083 inline
|
Chris@49
|
1084 const SpMat<eT>&
|
Chris@49
|
1085 SpMat<eT>::operator-=(const SpSubview<eT>& X)
|
Chris@49
|
1086 {
|
Chris@49
|
1087 arma_extra_debug_sigprint();
|
Chris@49
|
1088
|
Chris@49
|
1089 arma_debug_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "subtraction");
|
Chris@49
|
1090
|
Chris@49
|
1091 typename SpSubview<eT>::const_iterator it = X.begin();
|
Chris@49
|
1092
|
Chris@49
|
1093 while(it != X.end())
|
Chris@49
|
1094 {
|
Chris@49
|
1095 at(it.row(), it.col()) -= (*it);
|
Chris@49
|
1096 ++it;
|
Chris@49
|
1097 }
|
Chris@49
|
1098
|
Chris@49
|
1099 return *this;
|
Chris@49
|
1100 }
|
Chris@49
|
1101
|
Chris@49
|
1102
|
Chris@49
|
1103
|
Chris@49
|
1104 template<typename eT>
|
Chris@49
|
1105 inline
|
Chris@49
|
1106 const SpMat<eT>&
|
Chris@49
|
1107 SpMat<eT>::operator*=(const SpSubview<eT>& y)
|
Chris@49
|
1108 {
|
Chris@49
|
1109 arma_extra_debug_sigprint();
|
Chris@49
|
1110
|
Chris@49
|
1111 arma_debug_assert_mul_size(n_rows, n_cols, y.n_rows, y.n_cols, "matrix multiplication");
|
Chris@49
|
1112
|
Chris@49
|
1113 // Cannot be done in-place (easily).
|
Chris@49
|
1114 SpMat<eT> z = (*this) * y;
|
Chris@49
|
1115 steal_mem(z);
|
Chris@49
|
1116
|
Chris@49
|
1117 return *this;
|
Chris@49
|
1118 }
|
Chris@49
|
1119
|
Chris@49
|
1120
|
Chris@49
|
1121
|
Chris@49
|
1122 template<typename eT>
|
Chris@49
|
1123 inline
|
Chris@49
|
1124 const SpMat<eT>&
|
Chris@49
|
1125 SpMat<eT>::operator%=(const SpSubview<eT>& x)
|
Chris@49
|
1126 {
|
Chris@49
|
1127 arma_extra_debug_sigprint();
|
Chris@49
|
1128
|
Chris@49
|
1129 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise multiplication");
|
Chris@49
|
1130
|
Chris@49
|
1131 iterator it = begin();
|
Chris@49
|
1132 typename SpSubview<eT>::const_iterator xit = x.begin();
|
Chris@49
|
1133
|
Chris@49
|
1134 while((it != end()) || (xit != x.end()))
|
Chris@49
|
1135 {
|
Chris@49
|
1136 if((xit.row() == it.row()) && (xit.col() == it.col()))
|
Chris@49
|
1137 {
|
Chris@49
|
1138 (*it) *= (*xit);
|
Chris@49
|
1139 ++it;
|
Chris@49
|
1140 ++xit;
|
Chris@49
|
1141 }
|
Chris@49
|
1142 else
|
Chris@49
|
1143 {
|
Chris@49
|
1144 if((xit.col() > it.col()) || ((xit.col() == it.col()) && (xit.row() > it.row())))
|
Chris@49
|
1145 {
|
Chris@49
|
1146 // xit is "ahead"
|
Chris@49
|
1147 (*it) = eT(0); // erase element; x has a zero here
|
Chris@49
|
1148 it.internal_pos--; // update iterator so it still works
|
Chris@49
|
1149 ++it;
|
Chris@49
|
1150 }
|
Chris@49
|
1151 else
|
Chris@49
|
1152 {
|
Chris@49
|
1153 // it is "ahead"
|
Chris@49
|
1154 ++xit;
|
Chris@49
|
1155 }
|
Chris@49
|
1156 }
|
Chris@49
|
1157 }
|
Chris@49
|
1158
|
Chris@49
|
1159 return *this;
|
Chris@49
|
1160 }
|
Chris@49
|
1161
|
Chris@49
|
1162
|
Chris@49
|
1163 template<typename eT>
|
Chris@49
|
1164 inline
|
Chris@49
|
1165 const SpMat<eT>&
|
Chris@49
|
1166 SpMat<eT>::operator/=(const SpSubview<eT>& x)
|
Chris@49
|
1167 {
|
Chris@49
|
1168 arma_extra_debug_sigprint();
|
Chris@49
|
1169
|
Chris@49
|
1170 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise division");
|
Chris@49
|
1171
|
Chris@49
|
1172 // There is no pretty way to do this.
|
Chris@49
|
1173 for(uword elem = 0; elem < n_elem; elem++)
|
Chris@49
|
1174 {
|
Chris@49
|
1175 at(elem) /= x(elem);
|
Chris@49
|
1176 }
|
Chris@49
|
1177
|
Chris@49
|
1178 return *this;
|
Chris@49
|
1179 }
|
Chris@49
|
1180
|
Chris@49
|
1181
|
Chris@49
|
1182
|
Chris@49
|
1183 /**
|
Chris@49
|
1184 * Operators on regular subviews.
|
Chris@49
|
1185 */
|
Chris@49
|
1186 template<typename eT>
|
Chris@49
|
1187 inline
|
Chris@49
|
1188 SpMat<eT>::SpMat(const subview<eT>& x)
|
Chris@49
|
1189 : n_rows(0)
|
Chris@49
|
1190 , n_cols(0)
|
Chris@49
|
1191 , n_elem(0)
|
Chris@49
|
1192 , n_nonzero(0)
|
Chris@49
|
1193 , vec_state(0)
|
Chris@49
|
1194 , values(NULL) // extra value set in operator=()
|
Chris@49
|
1195 , row_indices(NULL)
|
Chris@49
|
1196 , col_ptrs(NULL)
|
Chris@49
|
1197 {
|
Chris@49
|
1198 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
1199
|
Chris@49
|
1200 (*this).operator=(x);
|
Chris@49
|
1201 }
|
Chris@49
|
1202
|
Chris@49
|
1203
|
Chris@49
|
1204
|
Chris@49
|
1205 template<typename eT>
|
Chris@49
|
1206 inline
|
Chris@49
|
1207 const SpMat<eT>&
|
Chris@49
|
1208 SpMat<eT>::operator=(const subview<eT>& x)
|
Chris@49
|
1209 {
|
Chris@49
|
1210 arma_extra_debug_sigprint();
|
Chris@49
|
1211
|
Chris@49
|
1212 const uword x_n_rows = x.n_rows;
|
Chris@49
|
1213 const uword x_n_cols = x.n_cols;
|
Chris@49
|
1214
|
Chris@49
|
1215 // Set the size correctly.
|
Chris@49
|
1216 init(x_n_rows, x_n_cols);
|
Chris@49
|
1217
|
Chris@49
|
1218 // Count number of nonzero elements.
|
Chris@49
|
1219 uword n = 0;
|
Chris@49
|
1220 for(uword c = 0; c < x_n_cols; ++c)
|
Chris@49
|
1221 {
|
Chris@49
|
1222 for(uword r = 0; r < x_n_rows; ++r)
|
Chris@49
|
1223 {
|
Chris@49
|
1224 if(x.at(r, c) != eT(0))
|
Chris@49
|
1225 {
|
Chris@49
|
1226 ++n;
|
Chris@49
|
1227 }
|
Chris@49
|
1228 }
|
Chris@49
|
1229 }
|
Chris@49
|
1230
|
Chris@49
|
1231 // Resize memory appropriately.
|
Chris@49
|
1232 mem_resize(n);
|
Chris@49
|
1233
|
Chris@49
|
1234 n = 0;
|
Chris@49
|
1235 for(uword c = 0; c < x_n_cols; ++c)
|
Chris@49
|
1236 {
|
Chris@49
|
1237 for(uword r = 0; r < x_n_rows; ++r)
|
Chris@49
|
1238 {
|
Chris@49
|
1239 const eT val = x.at(r, c);
|
Chris@49
|
1240
|
Chris@49
|
1241 if(val != eT(0))
|
Chris@49
|
1242 {
|
Chris@49
|
1243 access::rw(values[n]) = val;
|
Chris@49
|
1244 access::rw(row_indices[n]) = r;
|
Chris@49
|
1245 ++access::rw(col_ptrs[c + 1]);
|
Chris@49
|
1246 ++n;
|
Chris@49
|
1247 }
|
Chris@49
|
1248 }
|
Chris@49
|
1249 }
|
Chris@49
|
1250
|
Chris@49
|
1251 // Fix column counts into column pointers.
|
Chris@49
|
1252 for(uword c = 1; c <= n_cols; ++c)
|
Chris@49
|
1253 {
|
Chris@49
|
1254 access::rw(col_ptrs[c]) += col_ptrs[c - 1];
|
Chris@49
|
1255 }
|
Chris@49
|
1256
|
Chris@49
|
1257 return *this;
|
Chris@49
|
1258 }
|
Chris@49
|
1259
|
Chris@49
|
1260
|
Chris@49
|
1261
|
Chris@49
|
1262 template<typename eT>
|
Chris@49
|
1263 inline
|
Chris@49
|
1264 const SpMat<eT>&
|
Chris@49
|
1265 SpMat<eT>::operator+=(const subview<eT>& x)
|
Chris@49
|
1266 {
|
Chris@49
|
1267 arma_extra_debug_sigprint();
|
Chris@49
|
1268
|
Chris@49
|
1269 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "addition");
|
Chris@49
|
1270
|
Chris@49
|
1271 // Loop over every element. This could probably be written in a more
|
Chris@49
|
1272 // efficient way, by calculating the number of nonzero elements the output
|
Chris@49
|
1273 // matrix will have, allocating the memory correctly, and then filling the
|
Chris@49
|
1274 // matrix correctly. However... for now, this works okay.
|
Chris@49
|
1275 for(uword lcol = 0; lcol < n_cols; ++lcol)
|
Chris@49
|
1276 for(uword lrow = 0; lrow < n_rows; ++lrow)
|
Chris@49
|
1277 {
|
Chris@49
|
1278 at(lrow, lcol) += x.at(lrow, lcol);
|
Chris@49
|
1279 }
|
Chris@49
|
1280
|
Chris@49
|
1281 return *this;
|
Chris@49
|
1282 }
|
Chris@49
|
1283
|
Chris@49
|
1284
|
Chris@49
|
1285
|
Chris@49
|
1286 template<typename eT>
|
Chris@49
|
1287 inline
|
Chris@49
|
1288 const SpMat<eT>&
|
Chris@49
|
1289 SpMat<eT>::operator-=(const subview<eT>& x)
|
Chris@49
|
1290 {
|
Chris@49
|
1291 arma_extra_debug_sigprint();
|
Chris@49
|
1292
|
Chris@49
|
1293 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "subtraction");
|
Chris@49
|
1294
|
Chris@49
|
1295 // Loop over every element.
|
Chris@49
|
1296 for(uword lcol = 0; lcol < n_cols; ++lcol)
|
Chris@49
|
1297 for(uword lrow = 0; lrow < n_rows; ++lrow)
|
Chris@49
|
1298 {
|
Chris@49
|
1299 at(lrow, lcol) -= x.at(lrow, lcol);
|
Chris@49
|
1300 }
|
Chris@49
|
1301
|
Chris@49
|
1302 return *this;
|
Chris@49
|
1303 }
|
Chris@49
|
1304
|
Chris@49
|
1305
|
Chris@49
|
1306
|
Chris@49
|
1307 template<typename eT>
|
Chris@49
|
1308 inline
|
Chris@49
|
1309 const SpMat<eT>&
|
Chris@49
|
1310 SpMat<eT>::operator*=(const subview<eT>& y)
|
Chris@49
|
1311 {
|
Chris@49
|
1312 arma_extra_debug_sigprint();
|
Chris@49
|
1313
|
Chris@49
|
1314 arma_debug_assert_mul_size(n_rows, n_cols, y.n_rows, y.n_cols, "matrix multiplication");
|
Chris@49
|
1315
|
Chris@49
|
1316 SpMat<eT> z(n_rows, y.n_cols);
|
Chris@49
|
1317
|
Chris@49
|
1318 // Performed in the same fashion as operator*=(SpMat).
|
Chris@49
|
1319 for (const_row_iterator x_row_it = begin_row(); x_row_it.pos() < n_nonzero; ++x_row_it)
|
Chris@49
|
1320 {
|
Chris@49
|
1321 for (uword lcol = 0; lcol < y.n_cols; ++lcol)
|
Chris@49
|
1322 {
|
Chris@49
|
1323 // At this moment in the loop, we are calculating anything that is contributed to by *x_row_it and *y_col_it.
|
Chris@49
|
1324 // Given that our position is x_ab and y_bc, there will only be a contribution if x.col == y.row, and that
|
Chris@49
|
1325 // contribution will be in location z_ac.
|
Chris@49
|
1326 z.at(x_row_it.row, lcol) += (*x_row_it) * y.at(x_row_it.col, lcol);
|
Chris@49
|
1327 }
|
Chris@49
|
1328 }
|
Chris@49
|
1329
|
Chris@49
|
1330 steal_mem(z);
|
Chris@49
|
1331
|
Chris@49
|
1332 return *this;
|
Chris@49
|
1333 }
|
Chris@49
|
1334
|
Chris@49
|
1335
|
Chris@49
|
1336
|
Chris@49
|
1337 template<typename eT>
|
Chris@49
|
1338 inline
|
Chris@49
|
1339 const SpMat<eT>&
|
Chris@49
|
1340 SpMat<eT>::operator%=(const subview<eT>& x)
|
Chris@49
|
1341 {
|
Chris@49
|
1342 arma_extra_debug_sigprint();
|
Chris@49
|
1343
|
Chris@49
|
1344 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise multiplication");
|
Chris@49
|
1345
|
Chris@49
|
1346 // Loop over every element.
|
Chris@49
|
1347 for(uword lcol = 0; lcol < n_cols; ++lcol)
|
Chris@49
|
1348 for(uword lrow = 0; lrow < n_rows; ++lrow)
|
Chris@49
|
1349 {
|
Chris@49
|
1350 at(lrow, lcol) *= x.at(lrow, lcol);
|
Chris@49
|
1351 }
|
Chris@49
|
1352
|
Chris@49
|
1353 return *this;
|
Chris@49
|
1354 }
|
Chris@49
|
1355
|
Chris@49
|
1356
|
Chris@49
|
1357
|
Chris@49
|
1358 template<typename eT>
|
Chris@49
|
1359 inline
|
Chris@49
|
1360 const SpMat<eT>&
|
Chris@49
|
1361 SpMat<eT>::operator/=(const subview<eT>& x)
|
Chris@49
|
1362 {
|
Chris@49
|
1363 arma_extra_debug_sigprint();
|
Chris@49
|
1364
|
Chris@49
|
1365 arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise division");
|
Chris@49
|
1366
|
Chris@49
|
1367 // Loop over every element.
|
Chris@49
|
1368 for(uword lcol = 0; lcol < n_cols; ++lcol)
|
Chris@49
|
1369 for(uword lrow = 0; lrow < n_rows; ++lrow)
|
Chris@49
|
1370 {
|
Chris@49
|
1371 at(lrow, lcol) /= x.at(lrow, lcol);
|
Chris@49
|
1372 }
|
Chris@49
|
1373
|
Chris@49
|
1374 return *this;
|
Chris@49
|
1375 }
|
Chris@49
|
1376
|
Chris@49
|
1377
|
Chris@49
|
1378
|
Chris@49
|
1379 template<typename eT>
|
Chris@49
|
1380 template<typename T1, typename spop_type>
|
Chris@49
|
1381 inline
|
Chris@49
|
1382 SpMat<eT>::SpMat(const SpOp<T1, spop_type>& X)
|
Chris@49
|
1383 : n_rows(0)
|
Chris@49
|
1384 , n_cols(0)
|
Chris@49
|
1385 , n_elem(0)
|
Chris@49
|
1386 , n_nonzero(0)
|
Chris@49
|
1387 , vec_state(0)
|
Chris@49
|
1388 , values(NULL) // set in application of sparse operation
|
Chris@49
|
1389 , row_indices(NULL)
|
Chris@49
|
1390 , col_ptrs(NULL)
|
Chris@49
|
1391 {
|
Chris@49
|
1392 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
1393
|
Chris@49
|
1394 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1395
|
Chris@49
|
1396 spop_type::apply(*this, X);
|
Chris@49
|
1397 }
|
Chris@49
|
1398
|
Chris@49
|
1399
|
Chris@49
|
1400
|
Chris@49
|
1401 template<typename eT>
|
Chris@49
|
1402 template<typename T1, typename spop_type>
|
Chris@49
|
1403 inline
|
Chris@49
|
1404 const SpMat<eT>&
|
Chris@49
|
1405 SpMat<eT>::operator=(const SpOp<T1, spop_type>& X)
|
Chris@49
|
1406 {
|
Chris@49
|
1407 arma_extra_debug_sigprint();
|
Chris@49
|
1408
|
Chris@49
|
1409 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1410
|
Chris@49
|
1411 spop_type::apply(*this, X);
|
Chris@49
|
1412
|
Chris@49
|
1413 return *this;
|
Chris@49
|
1414 }
|
Chris@49
|
1415
|
Chris@49
|
1416
|
Chris@49
|
1417
|
Chris@49
|
1418 template<typename eT>
|
Chris@49
|
1419 template<typename T1, typename spop_type>
|
Chris@49
|
1420 inline
|
Chris@49
|
1421 const SpMat<eT>&
|
Chris@49
|
1422 SpMat<eT>::operator+=(const SpOp<T1, spop_type>& X)
|
Chris@49
|
1423 {
|
Chris@49
|
1424 arma_extra_debug_sigprint();
|
Chris@49
|
1425
|
Chris@49
|
1426 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1427
|
Chris@49
|
1428 const SpMat<eT> m(X);
|
Chris@49
|
1429
|
Chris@49
|
1430 return (*this).operator+=(m);
|
Chris@49
|
1431 }
|
Chris@49
|
1432
|
Chris@49
|
1433
|
Chris@49
|
1434
|
Chris@49
|
1435 template<typename eT>
|
Chris@49
|
1436 template<typename T1, typename spop_type>
|
Chris@49
|
1437 inline
|
Chris@49
|
1438 const SpMat<eT>&
|
Chris@49
|
1439 SpMat<eT>::operator-=(const SpOp<T1, spop_type>& X)
|
Chris@49
|
1440 {
|
Chris@49
|
1441 arma_extra_debug_sigprint();
|
Chris@49
|
1442
|
Chris@49
|
1443 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1444
|
Chris@49
|
1445 const SpMat<eT> m(X);
|
Chris@49
|
1446
|
Chris@49
|
1447 return (*this).operator-=(m);
|
Chris@49
|
1448 }
|
Chris@49
|
1449
|
Chris@49
|
1450
|
Chris@49
|
1451
|
Chris@49
|
1452 template<typename eT>
|
Chris@49
|
1453 template<typename T1, typename spop_type>
|
Chris@49
|
1454 inline
|
Chris@49
|
1455 const SpMat<eT>&
|
Chris@49
|
1456 SpMat<eT>::operator*=(const SpOp<T1, spop_type>& X)
|
Chris@49
|
1457 {
|
Chris@49
|
1458 arma_extra_debug_sigprint();
|
Chris@49
|
1459
|
Chris@49
|
1460 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1461
|
Chris@49
|
1462 const SpMat<eT> m(X);
|
Chris@49
|
1463
|
Chris@49
|
1464 return (*this).operator*=(m);
|
Chris@49
|
1465 }
|
Chris@49
|
1466
|
Chris@49
|
1467
|
Chris@49
|
1468
|
Chris@49
|
1469 template<typename eT>
|
Chris@49
|
1470 template<typename T1, typename spop_type>
|
Chris@49
|
1471 inline
|
Chris@49
|
1472 const SpMat<eT>&
|
Chris@49
|
1473 SpMat<eT>::operator%=(const SpOp<T1, spop_type>& X)
|
Chris@49
|
1474 {
|
Chris@49
|
1475 arma_extra_debug_sigprint();
|
Chris@49
|
1476
|
Chris@49
|
1477 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1478
|
Chris@49
|
1479 const SpMat<eT> m(X);
|
Chris@49
|
1480
|
Chris@49
|
1481 return (*this).operator%=(m);
|
Chris@49
|
1482 }
|
Chris@49
|
1483
|
Chris@49
|
1484
|
Chris@49
|
1485
|
Chris@49
|
1486 template<typename eT>
|
Chris@49
|
1487 template<typename T1, typename spop_type>
|
Chris@49
|
1488 inline
|
Chris@49
|
1489 const SpMat<eT>&
|
Chris@49
|
1490 SpMat<eT>::operator/=(const SpOp<T1, spop_type>& X)
|
Chris@49
|
1491 {
|
Chris@49
|
1492 arma_extra_debug_sigprint();
|
Chris@49
|
1493
|
Chris@49
|
1494 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1495
|
Chris@49
|
1496 const SpMat<eT> m(X);
|
Chris@49
|
1497
|
Chris@49
|
1498 return (*this).operator/=(m);
|
Chris@49
|
1499 }
|
Chris@49
|
1500
|
Chris@49
|
1501
|
Chris@49
|
1502
|
Chris@49
|
1503 template<typename eT>
|
Chris@49
|
1504 template<typename T1, typename T2, typename spglue_type>
|
Chris@49
|
1505 inline
|
Chris@49
|
1506 SpMat<eT>::SpMat(const SpGlue<T1, T2, spglue_type>& X)
|
Chris@49
|
1507 : n_rows(0)
|
Chris@49
|
1508 , n_cols(0)
|
Chris@49
|
1509 , n_elem(0)
|
Chris@49
|
1510 , n_nonzero(0)
|
Chris@49
|
1511 , vec_state(0)
|
Chris@49
|
1512 , values(NULL) // extra element set in application of sparse glue
|
Chris@49
|
1513 , row_indices(NULL)
|
Chris@49
|
1514 , col_ptrs(NULL)
|
Chris@49
|
1515 {
|
Chris@49
|
1516 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
1517
|
Chris@49
|
1518 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1519
|
Chris@49
|
1520 spglue_type::apply(*this, X);
|
Chris@49
|
1521 }
|
Chris@49
|
1522
|
Chris@49
|
1523
|
Chris@49
|
1524
|
Chris@49
|
1525 template<typename eT>
|
Chris@49
|
1526 template<typename T1, typename spop_type>
|
Chris@49
|
1527 inline
|
Chris@49
|
1528 SpMat<eT>::SpMat(const mtSpOp<eT, T1, spop_type>& X)
|
Chris@49
|
1529 : n_rows(0)
|
Chris@49
|
1530 , n_cols(0)
|
Chris@49
|
1531 , n_elem(0)
|
Chris@49
|
1532 , n_nonzero(0)
|
Chris@49
|
1533 , vec_state(0)
|
Chris@49
|
1534 , values(NULL) // extra element set in application of sparse glue
|
Chris@49
|
1535 , row_indices(NULL)
|
Chris@49
|
1536 , col_ptrs(NULL)
|
Chris@49
|
1537 {
|
Chris@49
|
1538 arma_extra_debug_sigprint_this(this);
|
Chris@49
|
1539
|
Chris@49
|
1540 spop_type::apply(*this, X);
|
Chris@49
|
1541 }
|
Chris@49
|
1542
|
Chris@49
|
1543
|
Chris@49
|
1544
|
Chris@49
|
1545 template<typename eT>
|
Chris@49
|
1546 template<typename T1, typename spop_type>
|
Chris@49
|
1547 inline
|
Chris@49
|
1548 const SpMat<eT>&
|
Chris@49
|
1549 SpMat<eT>::operator=(const mtSpOp<eT, T1, spop_type>& X)
|
Chris@49
|
1550 {
|
Chris@49
|
1551 arma_extra_debug_sigprint();
|
Chris@49
|
1552
|
Chris@49
|
1553 spop_type::apply(*this, X);
|
Chris@49
|
1554
|
Chris@49
|
1555 return *this;
|
Chris@49
|
1556 }
|
Chris@49
|
1557
|
Chris@49
|
1558
|
Chris@49
|
1559
|
Chris@49
|
1560 template<typename eT>
|
Chris@49
|
1561 template<typename T1, typename spop_type>
|
Chris@49
|
1562 inline
|
Chris@49
|
1563 const SpMat<eT>&
|
Chris@49
|
1564 SpMat<eT>::operator+=(const mtSpOp<eT, T1, spop_type>& X)
|
Chris@49
|
1565 {
|
Chris@49
|
1566 arma_extra_debug_sigprint();
|
Chris@49
|
1567
|
Chris@49
|
1568 const SpMat<eT> m(X);
|
Chris@49
|
1569
|
Chris@49
|
1570 return (*this).operator+=(m);
|
Chris@49
|
1571 }
|
Chris@49
|
1572
|
Chris@49
|
1573
|
Chris@49
|
1574
|
Chris@49
|
1575 template<typename eT>
|
Chris@49
|
1576 template<typename T1, typename spop_type>
|
Chris@49
|
1577 inline
|
Chris@49
|
1578 const SpMat<eT>&
|
Chris@49
|
1579 SpMat<eT>::operator-=(const mtSpOp<eT, T1, spop_type>& X)
|
Chris@49
|
1580 {
|
Chris@49
|
1581 arma_extra_debug_sigprint();
|
Chris@49
|
1582
|
Chris@49
|
1583 const SpMat<eT> m(X);
|
Chris@49
|
1584
|
Chris@49
|
1585 return (*this).operator-=(m);
|
Chris@49
|
1586 }
|
Chris@49
|
1587
|
Chris@49
|
1588
|
Chris@49
|
1589
|
Chris@49
|
1590 template<typename eT>
|
Chris@49
|
1591 template<typename T1, typename spop_type>
|
Chris@49
|
1592 inline
|
Chris@49
|
1593 const SpMat<eT>&
|
Chris@49
|
1594 SpMat<eT>::operator*=(const mtSpOp<eT, T1, spop_type>& X)
|
Chris@49
|
1595 {
|
Chris@49
|
1596 arma_extra_debug_sigprint();
|
Chris@49
|
1597
|
Chris@49
|
1598 const SpMat<eT> m(X);
|
Chris@49
|
1599
|
Chris@49
|
1600 return (*this).operator*=(m);
|
Chris@49
|
1601 }
|
Chris@49
|
1602
|
Chris@49
|
1603
|
Chris@49
|
1604
|
Chris@49
|
1605 template<typename eT>
|
Chris@49
|
1606 template<typename T1, typename spop_type>
|
Chris@49
|
1607 inline
|
Chris@49
|
1608 const SpMat<eT>&
|
Chris@49
|
1609 SpMat<eT>::operator%=(const mtSpOp<eT, T1, spop_type>& X)
|
Chris@49
|
1610 {
|
Chris@49
|
1611 arma_extra_debug_sigprint();
|
Chris@49
|
1612
|
Chris@49
|
1613 const SpMat<eT> m(X);
|
Chris@49
|
1614
|
Chris@49
|
1615 return (*this).operator%=(m);
|
Chris@49
|
1616 }
|
Chris@49
|
1617
|
Chris@49
|
1618
|
Chris@49
|
1619
|
Chris@49
|
1620 template<typename eT>
|
Chris@49
|
1621 template<typename T1, typename spop_type>
|
Chris@49
|
1622 inline
|
Chris@49
|
1623 const SpMat<eT>&
|
Chris@49
|
1624 SpMat<eT>::operator/=(const mtSpOp<eT, T1, spop_type>& X)
|
Chris@49
|
1625 {
|
Chris@49
|
1626 arma_extra_debug_sigprint();
|
Chris@49
|
1627
|
Chris@49
|
1628 const SpMat<eT> m(X);
|
Chris@49
|
1629
|
Chris@49
|
1630 return (*this).operator/=(m);
|
Chris@49
|
1631 }
|
Chris@49
|
1632
|
Chris@49
|
1633
|
Chris@49
|
1634
|
Chris@49
|
1635 template<typename eT>
|
Chris@49
|
1636 template<typename T1, typename T2, typename spglue_type>
|
Chris@49
|
1637 inline
|
Chris@49
|
1638 const SpMat<eT>&
|
Chris@49
|
1639 SpMat<eT>::operator=(const SpGlue<T1, T2, spglue_type>& X)
|
Chris@49
|
1640 {
|
Chris@49
|
1641 arma_extra_debug_sigprint();
|
Chris@49
|
1642
|
Chris@49
|
1643 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1644
|
Chris@49
|
1645 spglue_type::apply(*this, X);
|
Chris@49
|
1646
|
Chris@49
|
1647 return *this;
|
Chris@49
|
1648 }
|
Chris@49
|
1649
|
Chris@49
|
1650
|
Chris@49
|
1651
|
Chris@49
|
1652 template<typename eT>
|
Chris@49
|
1653 template<typename T1, typename T2, typename spglue_type>
|
Chris@49
|
1654 inline
|
Chris@49
|
1655 const SpMat<eT>&
|
Chris@49
|
1656 SpMat<eT>::operator+=(const SpGlue<T1, T2, spglue_type>& X)
|
Chris@49
|
1657 {
|
Chris@49
|
1658 arma_extra_debug_sigprint();
|
Chris@49
|
1659
|
Chris@49
|
1660 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1661
|
Chris@49
|
1662 const SpMat<eT> m(X);
|
Chris@49
|
1663
|
Chris@49
|
1664 return (*this).operator+=(m);
|
Chris@49
|
1665 }
|
Chris@49
|
1666
|
Chris@49
|
1667
|
Chris@49
|
1668
|
Chris@49
|
1669 template<typename eT>
|
Chris@49
|
1670 template<typename T1, typename T2, typename spglue_type>
|
Chris@49
|
1671 inline
|
Chris@49
|
1672 const SpMat<eT>&
|
Chris@49
|
1673 SpMat<eT>::operator-=(const SpGlue<T1, T2, spglue_type>& X)
|
Chris@49
|
1674 {
|
Chris@49
|
1675 arma_extra_debug_sigprint();
|
Chris@49
|
1676
|
Chris@49
|
1677 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1678
|
Chris@49
|
1679 const SpMat<eT> m(X);
|
Chris@49
|
1680
|
Chris@49
|
1681 return (*this).operator-=(m);
|
Chris@49
|
1682 }
|
Chris@49
|
1683
|
Chris@49
|
1684
|
Chris@49
|
1685
|
Chris@49
|
1686 template<typename eT>
|
Chris@49
|
1687 template<typename T1, typename T2, typename spglue_type>
|
Chris@49
|
1688 inline
|
Chris@49
|
1689 const SpMat<eT>&
|
Chris@49
|
1690 SpMat<eT>::operator*=(const SpGlue<T1, T2, spglue_type>& X)
|
Chris@49
|
1691 {
|
Chris@49
|
1692 arma_extra_debug_sigprint();
|
Chris@49
|
1693
|
Chris@49
|
1694 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1695
|
Chris@49
|
1696 const SpMat<eT> m(X);
|
Chris@49
|
1697
|
Chris@49
|
1698 return (*this).operator*=(m);
|
Chris@49
|
1699 }
|
Chris@49
|
1700
|
Chris@49
|
1701
|
Chris@49
|
1702
|
Chris@49
|
1703 template<typename eT>
|
Chris@49
|
1704 template<typename T1, typename T2, typename spglue_type>
|
Chris@49
|
1705 inline
|
Chris@49
|
1706 const SpMat<eT>&
|
Chris@49
|
1707 SpMat<eT>::operator%=(const SpGlue<T1, T2, spglue_type>& X)
|
Chris@49
|
1708 {
|
Chris@49
|
1709 arma_extra_debug_sigprint();
|
Chris@49
|
1710
|
Chris@49
|
1711 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1712
|
Chris@49
|
1713 const SpMat<eT> m(X);
|
Chris@49
|
1714
|
Chris@49
|
1715 return (*this).operator%=(m);
|
Chris@49
|
1716 }
|
Chris@49
|
1717
|
Chris@49
|
1718
|
Chris@49
|
1719
|
Chris@49
|
1720 template<typename eT>
|
Chris@49
|
1721 template<typename T1, typename T2, typename spglue_type>
|
Chris@49
|
1722 inline
|
Chris@49
|
1723 const SpMat<eT>&
|
Chris@49
|
1724 SpMat<eT>::operator/=(const SpGlue<T1, T2, spglue_type>& X)
|
Chris@49
|
1725 {
|
Chris@49
|
1726 arma_extra_debug_sigprint();
|
Chris@49
|
1727
|
Chris@49
|
1728 arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == false ));
|
Chris@49
|
1729
|
Chris@49
|
1730 const SpMat<eT> m(X);
|
Chris@49
|
1731
|
Chris@49
|
1732 return (*this).operator/=(m);
|
Chris@49
|
1733 }
|
Chris@49
|
1734
|
Chris@49
|
1735
|
Chris@49
|
1736
|
Chris@49
|
1737 template<typename eT>
|
Chris@49
|
1738 arma_inline
|
Chris@49
|
1739 SpSubview<eT>
|
Chris@49
|
1740 SpMat<eT>::row(const uword row_num)
|
Chris@49
|
1741 {
|
Chris@49
|
1742 arma_extra_debug_sigprint();
|
Chris@49
|
1743
|
Chris@49
|
1744 arma_debug_check(row_num >= n_rows, "SpMat::row(): out of bounds");
|
Chris@49
|
1745
|
Chris@49
|
1746 return SpSubview<eT>(*this, row_num, 0, 1, n_cols);
|
Chris@49
|
1747 }
|
Chris@49
|
1748
|
Chris@49
|
1749
|
Chris@49
|
1750
|
Chris@49
|
1751 template<typename eT>
|
Chris@49
|
1752 arma_inline
|
Chris@49
|
1753 const SpSubview<eT>
|
Chris@49
|
1754 SpMat<eT>::row(const uword row_num) const
|
Chris@49
|
1755 {
|
Chris@49
|
1756 arma_extra_debug_sigprint();
|
Chris@49
|
1757
|
Chris@49
|
1758 arma_debug_check(row_num >= n_rows, "SpMat::row(): out of bounds");
|
Chris@49
|
1759
|
Chris@49
|
1760 return SpSubview<eT>(*this, row_num, 0, 1, n_cols);
|
Chris@49
|
1761 }
|
Chris@49
|
1762
|
Chris@49
|
1763
|
Chris@49
|
1764
|
Chris@49
|
1765 template<typename eT>
|
Chris@49
|
1766 inline
|
Chris@49
|
1767 SpSubview<eT>
|
Chris@49
|
1768 SpMat<eT>::operator()(const uword row_num, const span& col_span)
|
Chris@49
|
1769 {
|
Chris@49
|
1770 arma_extra_debug_sigprint();
|
Chris@49
|
1771
|
Chris@49
|
1772 const bool col_all = col_span.whole;
|
Chris@49
|
1773
|
Chris@49
|
1774 const uword local_n_cols = n_cols;
|
Chris@49
|
1775
|
Chris@49
|
1776 const uword in_col1 = col_all ? 0 : col_span.a;
|
Chris@49
|
1777 const uword in_col2 = col_span.b;
|
Chris@49
|
1778 const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
|
Chris@49
|
1779
|
Chris@49
|
1780 arma_debug_check
|
Chris@49
|
1781 (
|
Chris@49
|
1782 (row_num >= n_rows)
|
Chris@49
|
1783 ||
|
Chris@49
|
1784 ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
|
Chris@49
|
1785 ,
|
Chris@49
|
1786 "SpMat::operator(): indices out of bounds or incorrectly used"
|
Chris@49
|
1787 );
|
Chris@49
|
1788
|
Chris@49
|
1789 return SpSubview<eT>(*this, row_num, in_col1, 1, submat_n_cols);
|
Chris@49
|
1790 }
|
Chris@49
|
1791
|
Chris@49
|
1792
|
Chris@49
|
1793
|
Chris@49
|
1794 template<typename eT>
|
Chris@49
|
1795 inline
|
Chris@49
|
1796 const SpSubview<eT>
|
Chris@49
|
1797 SpMat<eT>::operator()(const uword row_num, const span& col_span) const
|
Chris@49
|
1798 {
|
Chris@49
|
1799 arma_extra_debug_sigprint();
|
Chris@49
|
1800
|
Chris@49
|
1801 const bool col_all = col_span.whole;
|
Chris@49
|
1802
|
Chris@49
|
1803 const uword local_n_cols = n_cols;
|
Chris@49
|
1804
|
Chris@49
|
1805 const uword in_col1 = col_all ? 0 : col_span.a;
|
Chris@49
|
1806 const uword in_col2 = col_span.b;
|
Chris@49
|
1807 const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
|
Chris@49
|
1808
|
Chris@49
|
1809 arma_debug_check
|
Chris@49
|
1810 (
|
Chris@49
|
1811 (row_num >= n_rows)
|
Chris@49
|
1812 ||
|
Chris@49
|
1813 ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
|
Chris@49
|
1814 ,
|
Chris@49
|
1815 "SpMat::operator(): indices out of bounds or incorrectly used"
|
Chris@49
|
1816 );
|
Chris@49
|
1817
|
Chris@49
|
1818 return SpSubview<eT>(*this, row_num, in_col1, 1, submat_n_cols);
|
Chris@49
|
1819 }
|
Chris@49
|
1820
|
Chris@49
|
1821
|
Chris@49
|
1822
|
Chris@49
|
1823 template<typename eT>
|
Chris@49
|
1824 arma_inline
|
Chris@49
|
1825 SpSubview<eT>
|
Chris@49
|
1826 SpMat<eT>::col(const uword col_num)
|
Chris@49
|
1827 {
|
Chris@49
|
1828 arma_extra_debug_sigprint();
|
Chris@49
|
1829
|
Chris@49
|
1830 arma_debug_check(col_num >= n_cols, "SpMat::col(): out of bounds");
|
Chris@49
|
1831
|
Chris@49
|
1832 return SpSubview<eT>(*this, 0, col_num, n_rows, 1);
|
Chris@49
|
1833 }
|
Chris@49
|
1834
|
Chris@49
|
1835
|
Chris@49
|
1836
|
Chris@49
|
1837 template<typename eT>
|
Chris@49
|
1838 arma_inline
|
Chris@49
|
1839 const SpSubview<eT>
|
Chris@49
|
1840 SpMat<eT>::col(const uword col_num) const
|
Chris@49
|
1841 {
|
Chris@49
|
1842 arma_extra_debug_sigprint();
|
Chris@49
|
1843
|
Chris@49
|
1844 arma_debug_check(col_num >= n_cols, "SpMat::col(): out of bounds");
|
Chris@49
|
1845
|
Chris@49
|
1846 return SpSubview<eT>(*this, 0, col_num, n_rows, 1);
|
Chris@49
|
1847 }
|
Chris@49
|
1848
|
Chris@49
|
1849
|
Chris@49
|
1850
|
Chris@49
|
1851 template<typename eT>
|
Chris@49
|
1852 inline
|
Chris@49
|
1853 SpSubview<eT>
|
Chris@49
|
1854 SpMat<eT>::operator()(const span& row_span, const uword col_num)
|
Chris@49
|
1855 {
|
Chris@49
|
1856 arma_extra_debug_sigprint();
|
Chris@49
|
1857
|
Chris@49
|
1858 const bool row_all = row_span.whole;
|
Chris@49
|
1859
|
Chris@49
|
1860 const uword local_n_rows = n_rows;
|
Chris@49
|
1861
|
Chris@49
|
1862 const uword in_row1 = row_all ? 0 : row_span.a;
|
Chris@49
|
1863 const uword in_row2 = row_span.b;
|
Chris@49
|
1864 const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
|
Chris@49
|
1865
|
Chris@49
|
1866 arma_debug_check
|
Chris@49
|
1867 (
|
Chris@49
|
1868 (col_num >= n_cols)
|
Chris@49
|
1869 ||
|
Chris@49
|
1870 ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
|
Chris@49
|
1871 ,
|
Chris@49
|
1872 "SpMat::operator(): indices out of bounds or incorrectly used"
|
Chris@49
|
1873 );
|
Chris@49
|
1874
|
Chris@49
|
1875 return SpSubview<eT>(*this, in_row1, col_num, submat_n_rows, 1);
|
Chris@49
|
1876 }
|
Chris@49
|
1877
|
Chris@49
|
1878
|
Chris@49
|
1879
|
Chris@49
|
1880 template<typename eT>
|
Chris@49
|
1881 inline
|
Chris@49
|
1882 const SpSubview<eT>
|
Chris@49
|
1883 SpMat<eT>::operator()(const span& row_span, const uword col_num) const
|
Chris@49
|
1884 {
|
Chris@49
|
1885 arma_extra_debug_sigprint();
|
Chris@49
|
1886
|
Chris@49
|
1887 const bool row_all = row_span.whole;
|
Chris@49
|
1888
|
Chris@49
|
1889 const uword local_n_rows = n_rows;
|
Chris@49
|
1890
|
Chris@49
|
1891 const uword in_row1 = row_all ? 0 : row_span.a;
|
Chris@49
|
1892 const uword in_row2 = row_span.b;
|
Chris@49
|
1893 const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
|
Chris@49
|
1894
|
Chris@49
|
1895 arma_debug_check
|
Chris@49
|
1896 (
|
Chris@49
|
1897 (col_num >= n_cols)
|
Chris@49
|
1898 ||
|
Chris@49
|
1899 ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
|
Chris@49
|
1900 ,
|
Chris@49
|
1901 "SpMat::operator(): indices out of bounds or incorrectly used"
|
Chris@49
|
1902 );
|
Chris@49
|
1903
|
Chris@49
|
1904 return SpSubview<eT>(*this, in_row1, col_num, submat_n_rows, 1);
|
Chris@49
|
1905 }
|
Chris@49
|
1906
|
Chris@49
|
1907
|
Chris@49
|
1908
|
Chris@49
|
1909 /**
|
Chris@49
|
1910 * Swap in_row1 with in_row2.
|
Chris@49
|
1911 */
|
Chris@49
|
1912 template<typename eT>
|
Chris@49
|
1913 inline
|
Chris@49
|
1914 void
|
Chris@49
|
1915 SpMat<eT>::swap_rows(const uword in_row1, const uword in_row2)
|
Chris@49
|
1916 {
|
Chris@49
|
1917 arma_extra_debug_sigprint();
|
Chris@49
|
1918
|
Chris@49
|
1919 arma_debug_check
|
Chris@49
|
1920 (
|
Chris@49
|
1921 (in_row1 >= n_rows) || (in_row2 >= n_rows),
|
Chris@49
|
1922 "SpMat::swap_rows(): out of bounds"
|
Chris@49
|
1923 );
|
Chris@49
|
1924
|
Chris@49
|
1925 // Sanity check.
|
Chris@49
|
1926 if (in_row1 == in_row2)
|
Chris@49
|
1927 {
|
Chris@49
|
1928 return;
|
Chris@49
|
1929 }
|
Chris@49
|
1930
|
Chris@49
|
1931 // The easier way to do this, instead of collecting all the elements in one row and then swapping with the other, will be
|
Chris@49
|
1932 // to iterate over each column of the matrix (since we store in column-major format) and then swap the two elements in the two rows at that time.
|
Chris@49
|
1933 // We will try to avoid using the at() call since it is expensive, instead preferring to use an iterator to track our position.
|
Chris@49
|
1934 uword col1 = (in_row1 < in_row2) ? in_row1 : in_row2;
|
Chris@49
|
1935 uword col2 = (in_row1 < in_row2) ? in_row2 : in_row1;
|
Chris@49
|
1936
|
Chris@49
|
1937 for (uword lcol = 0; lcol < n_cols; lcol++)
|
Chris@49
|
1938 {
|
Chris@49
|
1939 // If there is nothing in this column we can ignore it.
|
Chris@49
|
1940 if (col_ptrs[lcol] == col_ptrs[lcol + 1])
|
Chris@49
|
1941 {
|
Chris@49
|
1942 continue;
|
Chris@49
|
1943 }
|
Chris@49
|
1944
|
Chris@49
|
1945 // These will represent the positions of the items themselves.
|
Chris@49
|
1946 uword loc1 = n_nonzero + 1;
|
Chris@49
|
1947 uword loc2 = n_nonzero + 1;
|
Chris@49
|
1948
|
Chris@49
|
1949 for (uword search_pos = col_ptrs[lcol]; search_pos < col_ptrs[lcol + 1]; search_pos++)
|
Chris@49
|
1950 {
|
Chris@49
|
1951 if (row_indices[search_pos] == col1)
|
Chris@49
|
1952 {
|
Chris@49
|
1953 loc1 = search_pos;
|
Chris@49
|
1954 }
|
Chris@49
|
1955
|
Chris@49
|
1956 if (row_indices[search_pos] == col2)
|
Chris@49
|
1957 {
|
Chris@49
|
1958 loc2 = search_pos;
|
Chris@49
|
1959 break; // No need to look any further.
|
Chris@49
|
1960 }
|
Chris@49
|
1961 }
|
Chris@49
|
1962
|
Chris@49
|
1963 // There are four cases: we found both elements; we found one element (loc1); we found one element (loc2); we found zero elements.
|
Chris@49
|
1964 // If we found zero elements no work needs to be done and we can continue to the next column.
|
Chris@49
|
1965 if ((loc1 != (n_nonzero + 1)) && (loc2 != (n_nonzero + 1)))
|
Chris@49
|
1966 {
|
Chris@49
|
1967 // This is an easy case: just swap the values. No index modifying necessary.
|
Chris@49
|
1968 eT tmp = values[loc1];
|
Chris@49
|
1969 access::rw(values[loc1]) = values[loc2];
|
Chris@49
|
1970 access::rw(values[loc2]) = tmp;
|
Chris@49
|
1971 }
|
Chris@49
|
1972 else if (loc1 != (n_nonzero + 1)) // We only found loc1 and not loc2.
|
Chris@49
|
1973 {
|
Chris@49
|
1974 // We need to find the correct place to move our value to. It will be forward (not backwards) because in_row2 > in_row1.
|
Chris@49
|
1975 // Each iteration of the loop swaps the current value (loc1) with (loc1 + 1); in this manner we move our value down to where it should be.
|
Chris@49
|
1976 while (((loc1 + 1) < col_ptrs[lcol + 1]) && (row_indices[loc1 + 1] < in_row2))
|
Chris@49
|
1977 {
|
Chris@49
|
1978 // Swap both the values and the indices. The column should not change.
|
Chris@49
|
1979 eT tmp = values[loc1];
|
Chris@49
|
1980 access::rw(values[loc1]) = values[loc1 + 1];
|
Chris@49
|
1981 access::rw(values[loc1 + 1]) = tmp;
|
Chris@49
|
1982
|
Chris@49
|
1983 uword tmp_index = row_indices[loc1];
|
Chris@49
|
1984 access::rw(row_indices[loc1]) = row_indices[loc1 + 1];
|
Chris@49
|
1985 access::rw(row_indices[loc1 + 1]) = tmp_index;
|
Chris@49
|
1986
|
Chris@49
|
1987 loc1++; // And increment the counter.
|
Chris@49
|
1988 }
|
Chris@49
|
1989
|
Chris@49
|
1990 // Now set the row index correctly.
|
Chris@49
|
1991 access::rw(row_indices[loc1]) = in_row2;
|
Chris@49
|
1992
|
Chris@49
|
1993 }
|
Chris@49
|
1994 else if (loc2 != (n_nonzero + 1))
|
Chris@49
|
1995 {
|
Chris@49
|
1996 // We need to find the correct place to move our value to. It will be backwards (not forwards) because in_row1 < in_row2.
|
Chris@49
|
1997 // Each iteration of the loop swaps the current value (loc2) with (loc2 - 1); in this manner we move our value up to where it should be.
|
Chris@49
|
1998 while (((loc2 - 1) >= col_ptrs[lcol]) && (row_indices[loc2 - 1] > in_row1))
|
Chris@49
|
1999 {
|
Chris@49
|
2000 // Swap both the values and the indices. The column should not change.
|
Chris@49
|
2001 eT tmp = values[loc2];
|
Chris@49
|
2002 access::rw(values[loc2]) = values[loc2 - 1];
|
Chris@49
|
2003 access::rw(values[loc2 - 1]) = tmp;
|
Chris@49
|
2004
|
Chris@49
|
2005 uword tmp_index = row_indices[loc2];
|
Chris@49
|
2006 access::rw(row_indices[loc2]) = row_indices[loc2 - 1];
|
Chris@49
|
2007 access::rw(row_indices[loc2 - 1]) = tmp_index;
|
Chris@49
|
2008
|
Chris@49
|
2009 loc2--; // And decrement the counter.
|
Chris@49
|
2010 }
|
Chris@49
|
2011
|
Chris@49
|
2012 // Now set the row index correctly.
|
Chris@49
|
2013 access::rw(row_indices[loc2]) = in_row1;
|
Chris@49
|
2014
|
Chris@49
|
2015 }
|
Chris@49
|
2016 /* else: no need to swap anything; both values are zero */
|
Chris@49
|
2017 }
|
Chris@49
|
2018 }
|
Chris@49
|
2019
|
Chris@49
|
2020 /**
|
Chris@49
|
2021 * Swap in_col1 with in_col2.
|
Chris@49
|
2022 */
|
Chris@49
|
2023 template<typename eT>
|
Chris@49
|
2024 inline
|
Chris@49
|
2025 void
|
Chris@49
|
2026 SpMat<eT>::swap_cols(const uword in_col1, const uword in_col2)
|
Chris@49
|
2027 {
|
Chris@49
|
2028 arma_extra_debug_sigprint();
|
Chris@49
|
2029
|
Chris@49
|
2030 // slow but works
|
Chris@49
|
2031 for(uword lrow = 0; lrow < n_rows; ++lrow)
|
Chris@49
|
2032 {
|
Chris@49
|
2033 eT tmp = at(lrow, in_col1);
|
Chris@49
|
2034 at(lrow, in_col1) = at(lrow, in_col2);
|
Chris@49
|
2035 at(lrow, in_col2) = tmp;
|
Chris@49
|
2036 }
|
Chris@49
|
2037 }
|
Chris@49
|
2038
|
Chris@49
|
2039 /**
|
Chris@49
|
2040 * Remove the row row_num.
|
Chris@49
|
2041 */
|
Chris@49
|
2042 template<typename eT>
|
Chris@49
|
2043 inline
|
Chris@49
|
2044 void
|
Chris@49
|
2045 SpMat<eT>::shed_row(const uword row_num)
|
Chris@49
|
2046 {
|
Chris@49
|
2047 arma_extra_debug_sigprint();
|
Chris@49
|
2048 arma_debug_check (row_num >= n_rows, "SpMat::shed_row(): out of bounds");
|
Chris@49
|
2049
|
Chris@49
|
2050 shed_rows (row_num, row_num);
|
Chris@49
|
2051 }
|
Chris@49
|
2052
|
Chris@49
|
2053 /**
|
Chris@49
|
2054 * Remove the column col_num.
|
Chris@49
|
2055 */
|
Chris@49
|
2056 template<typename eT>
|
Chris@49
|
2057 inline
|
Chris@49
|
2058 void
|
Chris@49
|
2059 SpMat<eT>::shed_col(const uword col_num)
|
Chris@49
|
2060 {
|
Chris@49
|
2061 arma_extra_debug_sigprint();
|
Chris@49
|
2062 arma_debug_check (col_num >= n_cols, "SpMat::shed_col(): out of bounds");
|
Chris@49
|
2063
|
Chris@49
|
2064 shed_cols(col_num, col_num);
|
Chris@49
|
2065 }
|
Chris@49
|
2066
|
Chris@49
|
2067 /**
|
Chris@49
|
2068 * Remove all rows between (and including) in_row1 and in_row2.
|
Chris@49
|
2069 */
|
Chris@49
|
2070 template<typename eT>
|
Chris@49
|
2071 inline
|
Chris@49
|
2072 void
|
Chris@49
|
2073 SpMat<eT>::shed_rows(const uword in_row1, const uword in_row2)
|
Chris@49
|
2074 {
|
Chris@49
|
2075 arma_extra_debug_sigprint();
|
Chris@49
|
2076
|
Chris@49
|
2077 arma_debug_check
|
Chris@49
|
2078 (
|
Chris@49
|
2079 (in_row1 > in_row2) || (in_row2 >= n_rows),
|
Chris@49
|
2080 "SpMat::shed_rows(): indices out of bounds or incorectly used"
|
Chris@49
|
2081 );
|
Chris@49
|
2082
|
Chris@49
|
2083 uword i, j;
|
Chris@49
|
2084 // Store the length of values
|
Chris@49
|
2085 uword vlength = n_nonzero;
|
Chris@49
|
2086 // Store the length of col_ptrs
|
Chris@49
|
2087 uword clength = n_cols + 1;
|
Chris@49
|
2088
|
Chris@49
|
2089 // This is O(n * n_cols) and inplace, there may be a faster way, though.
|
Chris@49
|
2090 for (i = 0, j = 0; i < vlength; ++i)
|
Chris@49
|
2091 {
|
Chris@49
|
2092 // Store the row of the ith element.
|
Chris@49
|
2093 const uword lrow = row_indices[i];
|
Chris@49
|
2094 // Is the ith element in the range of rows we want to remove?
|
Chris@49
|
2095 if (lrow >= in_row1 && lrow <= in_row2)
|
Chris@49
|
2096 {
|
Chris@49
|
2097 // Increment our "removed elements" counter.
|
Chris@49
|
2098 ++j;
|
Chris@49
|
2099
|
Chris@49
|
2100 // Adjust the values of col_ptrs each time we remove an element.
|
Chris@49
|
2101 // Basically, the length of one column reduces by one, and everything to
|
Chris@49
|
2102 // its right gets reduced by one to represent all the elements being
|
Chris@49
|
2103 // shifted to the left by one.
|
Chris@49
|
2104 for(uword k = 0; k < clength; ++k)
|
Chris@49
|
2105 {
|
Chris@49
|
2106 if (col_ptrs[k] > (i - j + 1))
|
Chris@49
|
2107 {
|
Chris@49
|
2108 --access::rw(col_ptrs[k]);
|
Chris@49
|
2109 }
|
Chris@49
|
2110 }
|
Chris@49
|
2111 }
|
Chris@49
|
2112 else
|
Chris@49
|
2113 {
|
Chris@49
|
2114 // We shift the element we checked to the left by how many elements
|
Chris@49
|
2115 // we have removed.
|
Chris@49
|
2116 // j = 0 until we remove the first element.
|
Chris@49
|
2117 if (j != 0)
|
Chris@49
|
2118 {
|
Chris@49
|
2119 access::rw(row_indices[i - j]) = (lrow > in_row2) ? (lrow - (in_row2 - in_row1 + 1)) : lrow;
|
Chris@49
|
2120 access::rw(values[i - j]) = values[i];
|
Chris@49
|
2121 }
|
Chris@49
|
2122 }
|
Chris@49
|
2123 }
|
Chris@49
|
2124
|
Chris@49
|
2125 // j is the number of elements removed.
|
Chris@49
|
2126
|
Chris@49
|
2127 // Shrink the vectors. This will copy the memory.
|
Chris@49
|
2128 mem_resize(n_nonzero - j);
|
Chris@49
|
2129
|
Chris@49
|
2130 // Adjust row and element counts.
|
Chris@49
|
2131 access::rw(n_rows) = n_rows - (in_row2 - in_row1) - 1;
|
Chris@49
|
2132 access::rw(n_elem) = n_rows * n_cols;
|
Chris@49
|
2133 }
|
Chris@49
|
2134
|
Chris@49
|
2135 /**
|
Chris@49
|
2136 * Remove all columns between (and including) in_col1 and in_col2.
|
Chris@49
|
2137 */
|
Chris@49
|
2138 template<typename eT>
|
Chris@49
|
2139 inline
|
Chris@49
|
2140 void
|
Chris@49
|
2141 SpMat<eT>::shed_cols(const uword in_col1, const uword in_col2)
|
Chris@49
|
2142 {
|
Chris@49
|
2143 arma_extra_debug_sigprint();
|
Chris@49
|
2144
|
Chris@49
|
2145 arma_debug_check
|
Chris@49
|
2146 (
|
Chris@49
|
2147 (in_col1 > in_col2) || (in_col2 >= n_cols),
|
Chris@49
|
2148 "SpMat::shed_cols(): indices out of bounds or incorrectly used"
|
Chris@49
|
2149 );
|
Chris@49
|
2150
|
Chris@49
|
2151 // First we find the locations in values and row_indices for the column entries.
|
Chris@49
|
2152 uword col_beg = col_ptrs[in_col1];
|
Chris@49
|
2153 uword col_end = col_ptrs[in_col2 + 1];
|
Chris@49
|
2154
|
Chris@49
|
2155 // Then we find the number of entries in the column.
|
Chris@49
|
2156 uword diff = col_end - col_beg;
|
Chris@49
|
2157
|
Chris@49
|
2158 if (diff > 0)
|
Chris@49
|
2159 {
|
Chris@49
|
2160 eT* new_values = memory::acquire_chunked<eT> (n_nonzero - diff);
|
Chris@49
|
2161 uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero - diff);
|
Chris@49
|
2162
|
Chris@49
|
2163 // Copy first part.
|
Chris@49
|
2164 if (col_beg != 0)
|
Chris@49
|
2165 {
|
Chris@49
|
2166 arrayops::copy(new_values, values, col_beg);
|
Chris@49
|
2167 arrayops::copy(new_row_indices, row_indices, col_beg);
|
Chris@49
|
2168 }
|
Chris@49
|
2169
|
Chris@49
|
2170 // Copy second part.
|
Chris@49
|
2171 if (col_end != n_nonzero)
|
Chris@49
|
2172 {
|
Chris@49
|
2173 arrayops::copy(new_values + col_beg, values + col_end, n_nonzero - col_end);
|
Chris@49
|
2174 arrayops::copy(new_row_indices + col_beg, row_indices + col_end, n_nonzero - col_end);
|
Chris@49
|
2175 }
|
Chris@49
|
2176
|
Chris@49
|
2177 memory::release(values);
|
Chris@49
|
2178 memory::release(row_indices);
|
Chris@49
|
2179
|
Chris@49
|
2180 access::rw(values) = new_values;
|
Chris@49
|
2181 access::rw(row_indices) = new_row_indices;
|
Chris@49
|
2182
|
Chris@49
|
2183 // Update counts and such.
|
Chris@49
|
2184 access::rw(n_nonzero) -= diff;
|
Chris@49
|
2185 }
|
Chris@49
|
2186
|
Chris@49
|
2187 // Update column pointers.
|
Chris@49
|
2188 const uword new_n_cols = n_cols - ((in_col2 - in_col1) + 1);
|
Chris@49
|
2189
|
Chris@49
|
2190 uword* new_col_ptrs = memory::acquire<uword>(new_n_cols + 2);
|
Chris@49
|
2191 new_col_ptrs[new_n_cols + 1] = std::numeric_limits<uword>::max();
|
Chris@49
|
2192
|
Chris@49
|
2193 // Copy first set of columns (no manipulation required).
|
Chris@49
|
2194 if (in_col1 != 0)
|
Chris@49
|
2195 {
|
Chris@49
|
2196 arrayops::copy(new_col_ptrs, col_ptrs, in_col1);
|
Chris@49
|
2197 }
|
Chris@49
|
2198
|
Chris@49
|
2199 // Copy second set of columns (manipulation required).
|
Chris@49
|
2200 uword cur_col = in_col1;
|
Chris@49
|
2201 for (uword i = in_col2 + 1; i <= n_cols; ++i, ++cur_col)
|
Chris@49
|
2202 {
|
Chris@49
|
2203 new_col_ptrs[cur_col] = col_ptrs[i] - diff;
|
Chris@49
|
2204 }
|
Chris@49
|
2205
|
Chris@49
|
2206 memory::release(col_ptrs);
|
Chris@49
|
2207 access::rw(col_ptrs) = new_col_ptrs;
|
Chris@49
|
2208
|
Chris@49
|
2209 // We update the element and column counts, and we're done.
|
Chris@49
|
2210 access::rw(n_cols) = new_n_cols;
|
Chris@49
|
2211 access::rw(n_elem) = n_cols * n_rows;
|
Chris@49
|
2212 }
|
Chris@49
|
2213
|
Chris@49
|
2214
|
Chris@49
|
2215
|
Chris@49
|
2216 template<typename eT>
|
Chris@49
|
2217 arma_inline
|
Chris@49
|
2218 SpSubview<eT>
|
Chris@49
|
2219 SpMat<eT>::rows(const uword in_row1, const uword in_row2)
|
Chris@49
|
2220 {
|
Chris@49
|
2221 arma_extra_debug_sigprint();
|
Chris@49
|
2222
|
Chris@49
|
2223 arma_debug_check
|
Chris@49
|
2224 (
|
Chris@49
|
2225 (in_row1 > in_row2) || (in_row2 >= n_rows),
|
Chris@49
|
2226 "SpMat::rows(): indices out of bounds or incorrectly used"
|
Chris@49
|
2227 );
|
Chris@49
|
2228
|
Chris@49
|
2229 const uword subview_n_rows = in_row2 - in_row1 + 1;
|
Chris@49
|
2230
|
Chris@49
|
2231 return SpSubview<eT>(*this, in_row1, 0, subview_n_rows, n_cols);
|
Chris@49
|
2232 }
|
Chris@49
|
2233
|
Chris@49
|
2234
|
Chris@49
|
2235
|
Chris@49
|
2236 template<typename eT>
|
Chris@49
|
2237 arma_inline
|
Chris@49
|
2238 const SpSubview<eT>
|
Chris@49
|
2239 SpMat<eT>::rows(const uword in_row1, const uword in_row2) const
|
Chris@49
|
2240 {
|
Chris@49
|
2241 arma_extra_debug_sigprint();
|
Chris@49
|
2242
|
Chris@49
|
2243 arma_debug_check
|
Chris@49
|
2244 (
|
Chris@49
|
2245 (in_row1 > in_row2) || (in_row2 >= n_rows),
|
Chris@49
|
2246 "SpMat::rows(): indices out of bounds or incorrectly used"
|
Chris@49
|
2247 );
|
Chris@49
|
2248
|
Chris@49
|
2249 const uword subview_n_rows = in_row2 - in_row1 + 1;
|
Chris@49
|
2250
|
Chris@49
|
2251 return SpSubview<eT>(*this, in_row1, 0, subview_n_rows, n_cols);
|
Chris@49
|
2252 }
|
Chris@49
|
2253
|
Chris@49
|
2254
|
Chris@49
|
2255
|
Chris@49
|
2256 template<typename eT>
|
Chris@49
|
2257 arma_inline
|
Chris@49
|
2258 SpSubview<eT>
|
Chris@49
|
2259 SpMat<eT>::cols(const uword in_col1, const uword in_col2)
|
Chris@49
|
2260 {
|
Chris@49
|
2261 arma_extra_debug_sigprint();
|
Chris@49
|
2262
|
Chris@49
|
2263 arma_debug_check
|
Chris@49
|
2264 (
|
Chris@49
|
2265 (in_col1 > in_col2) || (in_col2 >= n_cols),
|
Chris@49
|
2266 "SpMat::cols(): indices out of bounds or incorrectly used"
|
Chris@49
|
2267 );
|
Chris@49
|
2268
|
Chris@49
|
2269 const uword subview_n_cols = in_col2 - in_col1 + 1;
|
Chris@49
|
2270
|
Chris@49
|
2271 return SpSubview<eT>(*this, 0, in_col1, n_rows, subview_n_cols);
|
Chris@49
|
2272 }
|
Chris@49
|
2273
|
Chris@49
|
2274
|
Chris@49
|
2275
|
Chris@49
|
2276 template<typename eT>
|
Chris@49
|
2277 arma_inline
|
Chris@49
|
2278 const SpSubview<eT>
|
Chris@49
|
2279 SpMat<eT>::cols(const uword in_col1, const uword in_col2) const
|
Chris@49
|
2280 {
|
Chris@49
|
2281 arma_extra_debug_sigprint();
|
Chris@49
|
2282
|
Chris@49
|
2283 arma_debug_check
|
Chris@49
|
2284 (
|
Chris@49
|
2285 (in_col1 > in_col2) || (in_col2 >= n_cols),
|
Chris@49
|
2286 "SpMat::cols(): indices out of bounds or incorrectly used"
|
Chris@49
|
2287 );
|
Chris@49
|
2288
|
Chris@49
|
2289 const uword subview_n_cols = in_col2 - in_col1 + 1;
|
Chris@49
|
2290
|
Chris@49
|
2291 return SpSubview<eT>(*this, 0, in_col1, n_rows, subview_n_cols);
|
Chris@49
|
2292 }
|
Chris@49
|
2293
|
Chris@49
|
2294
|
Chris@49
|
2295
|
Chris@49
|
2296 template<typename eT>
|
Chris@49
|
2297 arma_inline
|
Chris@49
|
2298 SpSubview<eT>
|
Chris@49
|
2299 SpMat<eT>::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2)
|
Chris@49
|
2300 {
|
Chris@49
|
2301 arma_extra_debug_sigprint();
|
Chris@49
|
2302
|
Chris@49
|
2303 arma_debug_check
|
Chris@49
|
2304 (
|
Chris@49
|
2305 (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols),
|
Chris@49
|
2306 "SpMat::submat(): indices out of bounds or incorrectly used"
|
Chris@49
|
2307 );
|
Chris@49
|
2308
|
Chris@49
|
2309 const uword subview_n_rows = in_row2 - in_row1 + 1;
|
Chris@49
|
2310 const uword subview_n_cols = in_col2 - in_col1 + 1;
|
Chris@49
|
2311
|
Chris@49
|
2312 return SpSubview<eT>(*this, in_row1, in_col1, subview_n_rows, subview_n_cols);
|
Chris@49
|
2313 }
|
Chris@49
|
2314
|
Chris@49
|
2315
|
Chris@49
|
2316
|
Chris@49
|
2317 template<typename eT>
|
Chris@49
|
2318 arma_inline
|
Chris@49
|
2319 const SpSubview<eT>
|
Chris@49
|
2320 SpMat<eT>::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const
|
Chris@49
|
2321 {
|
Chris@49
|
2322 arma_extra_debug_sigprint();
|
Chris@49
|
2323
|
Chris@49
|
2324 arma_debug_check
|
Chris@49
|
2325 (
|
Chris@49
|
2326 (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols),
|
Chris@49
|
2327 "SpMat::submat(): indices out of bounds or incorrectly used"
|
Chris@49
|
2328 );
|
Chris@49
|
2329
|
Chris@49
|
2330 const uword subview_n_rows = in_row2 - in_row1 + 1;
|
Chris@49
|
2331 const uword subview_n_cols = in_col2 - in_col1 + 1;
|
Chris@49
|
2332
|
Chris@49
|
2333 return SpSubview<eT>(*this, in_row1, in_col1, subview_n_rows, subview_n_cols);
|
Chris@49
|
2334 }
|
Chris@49
|
2335
|
Chris@49
|
2336
|
Chris@49
|
2337
|
Chris@49
|
2338 template<typename eT>
|
Chris@49
|
2339 inline
|
Chris@49
|
2340 SpSubview<eT>
|
Chris@49
|
2341 SpMat<eT>::submat (const span& row_span, const span& col_span)
|
Chris@49
|
2342 {
|
Chris@49
|
2343 arma_extra_debug_sigprint();
|
Chris@49
|
2344
|
Chris@49
|
2345 const bool row_all = row_span.whole;
|
Chris@49
|
2346 const bool col_all = col_span.whole;
|
Chris@49
|
2347
|
Chris@49
|
2348 const uword local_n_rows = n_rows;
|
Chris@49
|
2349 const uword local_n_cols = n_cols;
|
Chris@49
|
2350
|
Chris@49
|
2351 const uword in_row1 = row_all ? 0 : row_span.a;
|
Chris@49
|
2352 const uword in_row2 = row_span.b;
|
Chris@49
|
2353 const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
|
Chris@49
|
2354
|
Chris@49
|
2355 const uword in_col1 = col_all ? 0 : col_span.a;
|
Chris@49
|
2356 const uword in_col2 = col_span.b;
|
Chris@49
|
2357 const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
|
Chris@49
|
2358
|
Chris@49
|
2359 arma_debug_check
|
Chris@49
|
2360 (
|
Chris@49
|
2361 ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
|
Chris@49
|
2362 ||
|
Chris@49
|
2363 ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
|
Chris@49
|
2364 ,
|
Chris@49
|
2365 "SpMat::submat(): indices out of bounds or incorrectly used"
|
Chris@49
|
2366 );
|
Chris@49
|
2367
|
Chris@49
|
2368 return SpSubview<eT>(*this, in_row1, in_col1, submat_n_rows, submat_n_cols);
|
Chris@49
|
2369 }
|
Chris@49
|
2370
|
Chris@49
|
2371
|
Chris@49
|
2372
|
Chris@49
|
2373 template<typename eT>
|
Chris@49
|
2374 inline
|
Chris@49
|
2375 const SpSubview<eT>
|
Chris@49
|
2376 SpMat<eT>::submat (const span& row_span, const span& col_span) const
|
Chris@49
|
2377 {
|
Chris@49
|
2378 arma_extra_debug_sigprint();
|
Chris@49
|
2379
|
Chris@49
|
2380 const bool row_all = row_span.whole;
|
Chris@49
|
2381 const bool col_all = col_span.whole;
|
Chris@49
|
2382
|
Chris@49
|
2383 const uword local_n_rows = n_rows;
|
Chris@49
|
2384 const uword local_n_cols = n_cols;
|
Chris@49
|
2385
|
Chris@49
|
2386 const uword in_row1 = row_all ? 0 : row_span.a;
|
Chris@49
|
2387 const uword in_row2 = row_span.b;
|
Chris@49
|
2388 const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
|
Chris@49
|
2389
|
Chris@49
|
2390 const uword in_col1 = col_all ? 0 : col_span.a;
|
Chris@49
|
2391 const uword in_col2 = col_span.b;
|
Chris@49
|
2392 const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
|
Chris@49
|
2393
|
Chris@49
|
2394 arma_debug_check
|
Chris@49
|
2395 (
|
Chris@49
|
2396 ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
|
Chris@49
|
2397 ||
|
Chris@49
|
2398 ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
|
Chris@49
|
2399 ,
|
Chris@49
|
2400 "SpMat::submat(): indices out of bounds or incorrectly used"
|
Chris@49
|
2401 );
|
Chris@49
|
2402
|
Chris@49
|
2403 return SpSubview<eT>(*this, in_row1, in_col1, submat_n_rows, submat_n_cols);
|
Chris@49
|
2404 }
|
Chris@49
|
2405
|
Chris@49
|
2406
|
Chris@49
|
2407
|
Chris@49
|
2408 template<typename eT>
|
Chris@49
|
2409 inline
|
Chris@49
|
2410 SpSubview<eT>
|
Chris@49
|
2411 SpMat<eT>::operator()(const span& row_span, const span& col_span)
|
Chris@49
|
2412 {
|
Chris@49
|
2413 arma_extra_debug_sigprint();
|
Chris@49
|
2414
|
Chris@49
|
2415 return submat(row_span, col_span);
|
Chris@49
|
2416 }
|
Chris@49
|
2417
|
Chris@49
|
2418
|
Chris@49
|
2419
|
Chris@49
|
2420 template<typename eT>
|
Chris@49
|
2421 inline
|
Chris@49
|
2422 const SpSubview<eT>
|
Chris@49
|
2423 SpMat<eT>::operator()(const span& row_span, const span& col_span) const
|
Chris@49
|
2424 {
|
Chris@49
|
2425 arma_extra_debug_sigprint();
|
Chris@49
|
2426
|
Chris@49
|
2427 return submat(row_span, col_span);
|
Chris@49
|
2428 }
|
Chris@49
|
2429
|
Chris@49
|
2430
|
Chris@49
|
2431
|
Chris@49
|
2432 /**
|
Chris@49
|
2433 * Element access; acces the i'th element (works identically to the Mat accessors).
|
Chris@49
|
2434 * If there is nothing at element i, 0 is returned.
|
Chris@49
|
2435 *
|
Chris@49
|
2436 * @param i Element to access.
|
Chris@49
|
2437 */
|
Chris@49
|
2438
|
Chris@49
|
2439 template<typename eT>
|
Chris@49
|
2440 arma_inline
|
Chris@49
|
2441 arma_warn_unused
|
Chris@49
|
2442 SpValProxy<SpMat<eT> >
|
Chris@49
|
2443 SpMat<eT>::operator[](const uword i)
|
Chris@49
|
2444 {
|
Chris@49
|
2445 return get_value(i);
|
Chris@49
|
2446 }
|
Chris@49
|
2447
|
Chris@49
|
2448
|
Chris@49
|
2449
|
Chris@49
|
2450 template<typename eT>
|
Chris@49
|
2451 arma_inline
|
Chris@49
|
2452 arma_warn_unused
|
Chris@49
|
2453 eT
|
Chris@49
|
2454 SpMat<eT>::operator[](const uword i) const
|
Chris@49
|
2455 {
|
Chris@49
|
2456 return get_value(i);
|
Chris@49
|
2457 }
|
Chris@49
|
2458
|
Chris@49
|
2459
|
Chris@49
|
2460
|
Chris@49
|
2461 template<typename eT>
|
Chris@49
|
2462 arma_inline
|
Chris@49
|
2463 arma_warn_unused
|
Chris@49
|
2464 SpValProxy<SpMat<eT> >
|
Chris@49
|
2465 SpMat<eT>::at(const uword i)
|
Chris@49
|
2466 {
|
Chris@49
|
2467 return get_value(i);
|
Chris@49
|
2468 }
|
Chris@49
|
2469
|
Chris@49
|
2470
|
Chris@49
|
2471
|
Chris@49
|
2472 template<typename eT>
|
Chris@49
|
2473 arma_inline
|
Chris@49
|
2474 arma_warn_unused
|
Chris@49
|
2475 eT
|
Chris@49
|
2476 SpMat<eT>::at(const uword i) const
|
Chris@49
|
2477 {
|
Chris@49
|
2478 return get_value(i);
|
Chris@49
|
2479 }
|
Chris@49
|
2480
|
Chris@49
|
2481
|
Chris@49
|
2482
|
Chris@49
|
2483 template<typename eT>
|
Chris@49
|
2484 arma_inline
|
Chris@49
|
2485 arma_warn_unused
|
Chris@49
|
2486 SpValProxy<SpMat<eT> >
|
Chris@49
|
2487 SpMat<eT>::operator()(const uword i)
|
Chris@49
|
2488 {
|
Chris@49
|
2489 arma_debug_check( (i >= n_elem), "SpMat::operator(): out of bounds");
|
Chris@49
|
2490 return get_value(i);
|
Chris@49
|
2491 }
|
Chris@49
|
2492
|
Chris@49
|
2493
|
Chris@49
|
2494
|
Chris@49
|
2495 template<typename eT>
|
Chris@49
|
2496 arma_inline
|
Chris@49
|
2497 arma_warn_unused
|
Chris@49
|
2498 eT
|
Chris@49
|
2499 SpMat<eT>::operator()(const uword i) const
|
Chris@49
|
2500 {
|
Chris@49
|
2501 arma_debug_check( (i >= n_elem), "SpMat::operator(): out of bounds");
|
Chris@49
|
2502 return get_value(i);
|
Chris@49
|
2503 }
|
Chris@49
|
2504
|
Chris@49
|
2505
|
Chris@49
|
2506
|
Chris@49
|
2507 /**
|
Chris@49
|
2508 * Element access; access the element at row in_rows and column in_col.
|
Chris@49
|
2509 * If there is nothing at that position, 0 is returned.
|
Chris@49
|
2510 */
|
Chris@49
|
2511
|
Chris@49
|
2512 template<typename eT>
|
Chris@49
|
2513 arma_inline
|
Chris@49
|
2514 arma_warn_unused
|
Chris@49
|
2515 SpValProxy<SpMat<eT> >
|
Chris@49
|
2516 SpMat<eT>::at(const uword in_row, const uword in_col)
|
Chris@49
|
2517 {
|
Chris@49
|
2518 return get_value(in_row, in_col);
|
Chris@49
|
2519 }
|
Chris@49
|
2520
|
Chris@49
|
2521
|
Chris@49
|
2522
|
Chris@49
|
2523 template<typename eT>
|
Chris@49
|
2524 arma_inline
|
Chris@49
|
2525 arma_warn_unused
|
Chris@49
|
2526 eT
|
Chris@49
|
2527 SpMat<eT>::at(const uword in_row, const uword in_col) const
|
Chris@49
|
2528 {
|
Chris@49
|
2529 return get_value(in_row, in_col);
|
Chris@49
|
2530 }
|
Chris@49
|
2531
|
Chris@49
|
2532
|
Chris@49
|
2533
|
Chris@49
|
2534 template<typename eT>
|
Chris@49
|
2535 arma_inline
|
Chris@49
|
2536 arma_warn_unused
|
Chris@49
|
2537 SpValProxy<SpMat<eT> >
|
Chris@49
|
2538 SpMat<eT>::operator()(const uword in_row, const uword in_col)
|
Chris@49
|
2539 {
|
Chris@49
|
2540 arma_debug_check( ((in_row >= n_rows) || (in_col >= n_cols)), "SpMat::operator(): out of bounds");
|
Chris@49
|
2541 return get_value(in_row, in_col);
|
Chris@49
|
2542 }
|
Chris@49
|
2543
|
Chris@49
|
2544
|
Chris@49
|
2545
|
Chris@49
|
2546 template<typename eT>
|
Chris@49
|
2547 arma_inline
|
Chris@49
|
2548 arma_warn_unused
|
Chris@49
|
2549 eT
|
Chris@49
|
2550 SpMat<eT>::operator()(const uword in_row, const uword in_col) const
|
Chris@49
|
2551 {
|
Chris@49
|
2552 arma_debug_check( ((in_row >= n_rows) || (in_col >= n_cols)), "SpMat::operator(): out of bounds");
|
Chris@49
|
2553 return get_value(in_row, in_col);
|
Chris@49
|
2554 }
|
Chris@49
|
2555
|
Chris@49
|
2556
|
Chris@49
|
2557
|
Chris@49
|
2558 /**
|
Chris@49
|
2559 * Check if matrix is empty (no size, no values).
|
Chris@49
|
2560 */
|
Chris@49
|
2561 template<typename eT>
|
Chris@49
|
2562 arma_inline
|
Chris@49
|
2563 arma_warn_unused
|
Chris@49
|
2564 bool
|
Chris@49
|
2565 SpMat<eT>::is_empty() const
|
Chris@49
|
2566 {
|
Chris@49
|
2567 return(n_elem == 0);
|
Chris@49
|
2568 }
|
Chris@49
|
2569
|
Chris@49
|
2570
|
Chris@49
|
2571
|
Chris@49
|
2572 //! returns true if the object can be interpreted as a column or row vector
|
Chris@49
|
2573 template<typename eT>
|
Chris@49
|
2574 arma_inline
|
Chris@49
|
2575 arma_warn_unused
|
Chris@49
|
2576 bool
|
Chris@49
|
2577 SpMat<eT>::is_vec() const
|
Chris@49
|
2578 {
|
Chris@49
|
2579 return ( (n_rows == 1) || (n_cols == 1) );
|
Chris@49
|
2580 }
|
Chris@49
|
2581
|
Chris@49
|
2582
|
Chris@49
|
2583
|
Chris@49
|
2584 //! returns true if the object can be interpreted as a row vector
|
Chris@49
|
2585 template<typename eT>
|
Chris@49
|
2586 arma_inline
|
Chris@49
|
2587 arma_warn_unused
|
Chris@49
|
2588 bool
|
Chris@49
|
2589 SpMat<eT>::is_rowvec() const
|
Chris@49
|
2590 {
|
Chris@49
|
2591 return (n_rows == 1);
|
Chris@49
|
2592 }
|
Chris@49
|
2593
|
Chris@49
|
2594
|
Chris@49
|
2595
|
Chris@49
|
2596 //! returns true if the object can be interpreted as a column vector
|
Chris@49
|
2597 template<typename eT>
|
Chris@49
|
2598 arma_inline
|
Chris@49
|
2599 arma_warn_unused
|
Chris@49
|
2600 bool
|
Chris@49
|
2601 SpMat<eT>::is_colvec() const
|
Chris@49
|
2602 {
|
Chris@49
|
2603 return (n_cols == 1);
|
Chris@49
|
2604 }
|
Chris@49
|
2605
|
Chris@49
|
2606
|
Chris@49
|
2607
|
Chris@49
|
2608 //! returns true if the object has the same number of non-zero rows and columnns
|
Chris@49
|
2609 template<typename eT>
|
Chris@49
|
2610 arma_inline
|
Chris@49
|
2611 arma_warn_unused
|
Chris@49
|
2612 bool
|
Chris@49
|
2613 SpMat<eT>::is_square() const
|
Chris@49
|
2614 {
|
Chris@49
|
2615 return (n_rows == n_cols);
|
Chris@49
|
2616 }
|
Chris@49
|
2617
|
Chris@49
|
2618
|
Chris@49
|
2619
|
Chris@49
|
2620 //! returns true if all of the elements are finite
|
Chris@49
|
2621 template<typename eT>
|
Chris@49
|
2622 inline
|
Chris@49
|
2623 arma_warn_unused
|
Chris@49
|
2624 bool
|
Chris@49
|
2625 SpMat<eT>::is_finite() const
|
Chris@49
|
2626 {
|
Chris@49
|
2627 for(uword i = 0; i < n_nonzero; i++)
|
Chris@49
|
2628 {
|
Chris@49
|
2629 if(arma_isfinite(values[i]) == false)
|
Chris@49
|
2630 {
|
Chris@49
|
2631 return false;
|
Chris@49
|
2632 }
|
Chris@49
|
2633 }
|
Chris@49
|
2634
|
Chris@49
|
2635 return true; // No infinite values.
|
Chris@49
|
2636 }
|
Chris@49
|
2637
|
Chris@49
|
2638
|
Chris@49
|
2639
|
Chris@49
|
2640 //! returns true if the given index is currently in range
|
Chris@49
|
2641 template<typename eT>
|
Chris@49
|
2642 arma_inline
|
Chris@49
|
2643 arma_warn_unused
|
Chris@49
|
2644 bool
|
Chris@49
|
2645 SpMat<eT>::in_range(const uword i) const
|
Chris@49
|
2646 {
|
Chris@49
|
2647 return (i < n_elem);
|
Chris@49
|
2648 }
|
Chris@49
|
2649
|
Chris@49
|
2650
|
Chris@49
|
2651 //! returns true if the given start and end indices are currently in range
|
Chris@49
|
2652 template<typename eT>
|
Chris@49
|
2653 arma_inline
|
Chris@49
|
2654 arma_warn_unused
|
Chris@49
|
2655 bool
|
Chris@49
|
2656 SpMat<eT>::in_range(const span& x) const
|
Chris@49
|
2657 {
|
Chris@49
|
2658 arma_extra_debug_sigprint();
|
Chris@49
|
2659
|
Chris@49
|
2660 if(x.whole == true)
|
Chris@49
|
2661 {
|
Chris@49
|
2662 return true;
|
Chris@49
|
2663 }
|
Chris@49
|
2664 else
|
Chris@49
|
2665 {
|
Chris@49
|
2666 const uword a = x.a;
|
Chris@49
|
2667 const uword b = x.b;
|
Chris@49
|
2668
|
Chris@49
|
2669 return ( (a <= b) && (b < n_elem) );
|
Chris@49
|
2670 }
|
Chris@49
|
2671 }
|
Chris@49
|
2672
|
Chris@49
|
2673
|
Chris@49
|
2674
|
Chris@49
|
2675 //! returns true if the given location is currently in range
|
Chris@49
|
2676 template<typename eT>
|
Chris@49
|
2677 arma_inline
|
Chris@49
|
2678 arma_warn_unused
|
Chris@49
|
2679 bool
|
Chris@49
|
2680 SpMat<eT>::in_range(const uword in_row, const uword in_col) const
|
Chris@49
|
2681 {
|
Chris@49
|
2682 return ( (in_row < n_rows) && (in_col < n_cols) );
|
Chris@49
|
2683 }
|
Chris@49
|
2684
|
Chris@49
|
2685
|
Chris@49
|
2686
|
Chris@49
|
2687 template<typename eT>
|
Chris@49
|
2688 arma_inline
|
Chris@49
|
2689 arma_warn_unused
|
Chris@49
|
2690 bool
|
Chris@49
|
2691 SpMat<eT>::in_range(const span& row_span, const uword in_col) const
|
Chris@49
|
2692 {
|
Chris@49
|
2693 arma_extra_debug_sigprint();
|
Chris@49
|
2694
|
Chris@49
|
2695 if(row_span.whole == true)
|
Chris@49
|
2696 {
|
Chris@49
|
2697 return (in_col < n_cols);
|
Chris@49
|
2698 }
|
Chris@49
|
2699 else
|
Chris@49
|
2700 {
|
Chris@49
|
2701 const uword in_row1 = row_span.a;
|
Chris@49
|
2702 const uword in_row2 = row_span.b;
|
Chris@49
|
2703
|
Chris@49
|
2704 return ( (in_row1 <= in_row2) && (in_row2 < n_rows) && (in_col < n_cols) );
|
Chris@49
|
2705 }
|
Chris@49
|
2706 }
|
Chris@49
|
2707
|
Chris@49
|
2708
|
Chris@49
|
2709
|
Chris@49
|
2710 template<typename eT>
|
Chris@49
|
2711 arma_inline
|
Chris@49
|
2712 arma_warn_unused
|
Chris@49
|
2713 bool
|
Chris@49
|
2714 SpMat<eT>::in_range(const uword in_row, const span& col_span) const
|
Chris@49
|
2715 {
|
Chris@49
|
2716 arma_extra_debug_sigprint();
|
Chris@49
|
2717
|
Chris@49
|
2718 if(col_span.whole == true)
|
Chris@49
|
2719 {
|
Chris@49
|
2720 return (in_row < n_rows);
|
Chris@49
|
2721 }
|
Chris@49
|
2722 else
|
Chris@49
|
2723 {
|
Chris@49
|
2724 const uword in_col1 = col_span.a;
|
Chris@49
|
2725 const uword in_col2 = col_span.b;
|
Chris@49
|
2726
|
Chris@49
|
2727 return ( (in_row < n_rows) && (in_col1 <= in_col2) && (in_col2 < n_cols) );
|
Chris@49
|
2728 }
|
Chris@49
|
2729 }
|
Chris@49
|
2730
|
Chris@49
|
2731
|
Chris@49
|
2732
|
Chris@49
|
2733 template<typename eT>
|
Chris@49
|
2734 arma_inline
|
Chris@49
|
2735 arma_warn_unused
|
Chris@49
|
2736 bool
|
Chris@49
|
2737 SpMat<eT>::in_range(const span& row_span, const span& col_span) const
|
Chris@49
|
2738 {
|
Chris@49
|
2739 arma_extra_debug_sigprint();
|
Chris@49
|
2740
|
Chris@49
|
2741 const uword in_row1 = row_span.a;
|
Chris@49
|
2742 const uword in_row2 = row_span.b;
|
Chris@49
|
2743
|
Chris@49
|
2744 const uword in_col1 = col_span.a;
|
Chris@49
|
2745 const uword in_col2 = col_span.b;
|
Chris@49
|
2746
|
Chris@49
|
2747 const bool rows_ok = row_span.whole ? true : ( (in_row1 <= in_row2) && (in_row2 < n_rows) );
|
Chris@49
|
2748 const bool cols_ok = col_span.whole ? true : ( (in_col1 <= in_col2) && (in_col2 < n_cols) );
|
Chris@49
|
2749
|
Chris@49
|
2750 return ( (rows_ok == true) && (cols_ok == true) );
|
Chris@49
|
2751 }
|
Chris@49
|
2752
|
Chris@49
|
2753
|
Chris@49
|
2754
|
Chris@49
|
2755 template<typename eT>
|
Chris@49
|
2756 inline
|
Chris@49
|
2757 void
|
Chris@49
|
2758 SpMat<eT>::impl_print(const std::string& extra_text) const
|
Chris@49
|
2759 {
|
Chris@49
|
2760 arma_extra_debug_sigprint();
|
Chris@49
|
2761
|
Chris@49
|
2762 if(extra_text.length() != 0)
|
Chris@49
|
2763 {
|
Chris@49
|
2764 const std::streamsize orig_width = ARMA_DEFAULT_OSTREAM.width();
|
Chris@49
|
2765
|
Chris@49
|
2766 ARMA_DEFAULT_OSTREAM << extra_text << '\n';
|
Chris@49
|
2767
|
Chris@49
|
2768 ARMA_DEFAULT_OSTREAM.width(orig_width);
|
Chris@49
|
2769 }
|
Chris@49
|
2770
|
Chris@49
|
2771 arma_ostream::print(ARMA_DEFAULT_OSTREAM, *this, true);
|
Chris@49
|
2772 }
|
Chris@49
|
2773
|
Chris@49
|
2774
|
Chris@49
|
2775
|
Chris@49
|
2776 template<typename eT>
|
Chris@49
|
2777 inline
|
Chris@49
|
2778 void
|
Chris@49
|
2779 SpMat<eT>::impl_print(std::ostream& user_stream, const std::string& extra_text) const
|
Chris@49
|
2780 {
|
Chris@49
|
2781 arma_extra_debug_sigprint();
|
Chris@49
|
2782
|
Chris@49
|
2783 if(extra_text.length() != 0)
|
Chris@49
|
2784 {
|
Chris@49
|
2785 const std::streamsize orig_width = user_stream.width();
|
Chris@49
|
2786
|
Chris@49
|
2787 user_stream << extra_text << '\n';
|
Chris@49
|
2788
|
Chris@49
|
2789 user_stream.width(orig_width);
|
Chris@49
|
2790 }
|
Chris@49
|
2791
|
Chris@49
|
2792 arma_ostream::print(user_stream, *this, true);
|
Chris@49
|
2793 }
|
Chris@49
|
2794
|
Chris@49
|
2795
|
Chris@49
|
2796
|
Chris@49
|
2797 template<typename eT>
|
Chris@49
|
2798 inline
|
Chris@49
|
2799 void
|
Chris@49
|
2800 SpMat<eT>::impl_raw_print(const std::string& extra_text) const
|
Chris@49
|
2801 {
|
Chris@49
|
2802 arma_extra_debug_sigprint();
|
Chris@49
|
2803
|
Chris@49
|
2804 if(extra_text.length() != 0)
|
Chris@49
|
2805 {
|
Chris@49
|
2806 const std::streamsize orig_width = ARMA_DEFAULT_OSTREAM.width();
|
Chris@49
|
2807
|
Chris@49
|
2808 ARMA_DEFAULT_OSTREAM << extra_text << '\n';
|
Chris@49
|
2809
|
Chris@49
|
2810 ARMA_DEFAULT_OSTREAM.width(orig_width);
|
Chris@49
|
2811 }
|
Chris@49
|
2812
|
Chris@49
|
2813 arma_ostream::print(ARMA_DEFAULT_OSTREAM, *this, false);
|
Chris@49
|
2814 }
|
Chris@49
|
2815
|
Chris@49
|
2816
|
Chris@49
|
2817 template<typename eT>
|
Chris@49
|
2818 inline
|
Chris@49
|
2819 void
|
Chris@49
|
2820 SpMat<eT>::impl_raw_print(std::ostream& user_stream, const std::string& extra_text) const
|
Chris@49
|
2821 {
|
Chris@49
|
2822 arma_extra_debug_sigprint();
|
Chris@49
|
2823
|
Chris@49
|
2824 if(extra_text.length() != 0)
|
Chris@49
|
2825 {
|
Chris@49
|
2826 const std::streamsize orig_width = user_stream.width();
|
Chris@49
|
2827
|
Chris@49
|
2828 user_stream << extra_text << '\n';
|
Chris@49
|
2829
|
Chris@49
|
2830 user_stream.width(orig_width);
|
Chris@49
|
2831 }
|
Chris@49
|
2832
|
Chris@49
|
2833 arma_ostream::print(user_stream, *this, false);
|
Chris@49
|
2834 }
|
Chris@49
|
2835
|
Chris@49
|
2836
|
Chris@49
|
2837
|
Chris@49
|
2838 /**
|
Chris@49
|
2839 * Matrix printing, prepends supplied text.
|
Chris@49
|
2840 * Prints 0 wherever no element exists.
|
Chris@49
|
2841 */
|
Chris@49
|
2842 template<typename eT>
|
Chris@49
|
2843 inline
|
Chris@49
|
2844 void
|
Chris@49
|
2845 SpMat<eT>::impl_print_dense(const std::string& extra_text) const
|
Chris@49
|
2846 {
|
Chris@49
|
2847 arma_extra_debug_sigprint();
|
Chris@49
|
2848
|
Chris@49
|
2849 if(extra_text.length() != 0)
|
Chris@49
|
2850 {
|
Chris@49
|
2851 const std::streamsize orig_width = ARMA_DEFAULT_OSTREAM.width();
|
Chris@49
|
2852
|
Chris@49
|
2853 ARMA_DEFAULT_OSTREAM << extra_text << '\n';
|
Chris@49
|
2854
|
Chris@49
|
2855 ARMA_DEFAULT_OSTREAM.width(orig_width);
|
Chris@49
|
2856 }
|
Chris@49
|
2857
|
Chris@49
|
2858 arma_ostream::print_dense(ARMA_DEFAULT_OSTREAM, *this, true);
|
Chris@49
|
2859 }
|
Chris@49
|
2860
|
Chris@49
|
2861
|
Chris@49
|
2862
|
Chris@49
|
2863 template<typename eT>
|
Chris@49
|
2864 inline
|
Chris@49
|
2865 void
|
Chris@49
|
2866 SpMat<eT>::impl_print_dense(std::ostream& user_stream, const std::string& extra_text) const
|
Chris@49
|
2867 {
|
Chris@49
|
2868 arma_extra_debug_sigprint();
|
Chris@49
|
2869
|
Chris@49
|
2870 if(extra_text.length() != 0)
|
Chris@49
|
2871 {
|
Chris@49
|
2872 const std::streamsize orig_width = user_stream.width();
|
Chris@49
|
2873
|
Chris@49
|
2874 user_stream << extra_text << '\n';
|
Chris@49
|
2875
|
Chris@49
|
2876 user_stream.width(orig_width);
|
Chris@49
|
2877 }
|
Chris@49
|
2878
|
Chris@49
|
2879 arma_ostream::print_dense(user_stream, *this, true);
|
Chris@49
|
2880 }
|
Chris@49
|
2881
|
Chris@49
|
2882
|
Chris@49
|
2883
|
Chris@49
|
2884 template<typename eT>
|
Chris@49
|
2885 inline
|
Chris@49
|
2886 void
|
Chris@49
|
2887 SpMat<eT>::impl_raw_print_dense(const std::string& extra_text) const
|
Chris@49
|
2888 {
|
Chris@49
|
2889 arma_extra_debug_sigprint();
|
Chris@49
|
2890
|
Chris@49
|
2891 if(extra_text.length() != 0)
|
Chris@49
|
2892 {
|
Chris@49
|
2893 const std::streamsize orig_width = ARMA_DEFAULT_OSTREAM.width();
|
Chris@49
|
2894
|
Chris@49
|
2895 ARMA_DEFAULT_OSTREAM << extra_text << '\n';
|
Chris@49
|
2896
|
Chris@49
|
2897 ARMA_DEFAULT_OSTREAM.width(orig_width);
|
Chris@49
|
2898 }
|
Chris@49
|
2899
|
Chris@49
|
2900 arma_ostream::print_dense(ARMA_DEFAULT_OSTREAM, *this, false);
|
Chris@49
|
2901 }
|
Chris@49
|
2902
|
Chris@49
|
2903
|
Chris@49
|
2904
|
Chris@49
|
2905 template<typename eT>
|
Chris@49
|
2906 inline
|
Chris@49
|
2907 void
|
Chris@49
|
2908 SpMat<eT>::impl_raw_print_dense(std::ostream& user_stream, const std::string& extra_text) const
|
Chris@49
|
2909 {
|
Chris@49
|
2910 arma_extra_debug_sigprint();
|
Chris@49
|
2911
|
Chris@49
|
2912 if(extra_text.length() != 0)
|
Chris@49
|
2913 {
|
Chris@49
|
2914 const std::streamsize orig_width = user_stream.width();
|
Chris@49
|
2915
|
Chris@49
|
2916 user_stream << extra_text << '\n';
|
Chris@49
|
2917
|
Chris@49
|
2918 user_stream.width(orig_width);
|
Chris@49
|
2919 }
|
Chris@49
|
2920
|
Chris@49
|
2921 arma_ostream::print_dense(user_stream, *this, false);
|
Chris@49
|
2922 }
|
Chris@49
|
2923
|
Chris@49
|
2924
|
Chris@49
|
2925
|
Chris@49
|
2926 //! Set the size to the size of another matrix.
|
Chris@49
|
2927 template<typename eT>
|
Chris@49
|
2928 template<typename eT2>
|
Chris@49
|
2929 inline
|
Chris@49
|
2930 void
|
Chris@49
|
2931 SpMat<eT>::copy_size(const SpMat<eT2>& m)
|
Chris@49
|
2932 {
|
Chris@49
|
2933 arma_extra_debug_sigprint();
|
Chris@49
|
2934
|
Chris@49
|
2935 init(m.n_rows, m.n_cols);
|
Chris@49
|
2936 }
|
Chris@49
|
2937
|
Chris@49
|
2938
|
Chris@49
|
2939
|
Chris@49
|
2940 template<typename eT>
|
Chris@49
|
2941 template<typename eT2>
|
Chris@49
|
2942 inline
|
Chris@49
|
2943 void
|
Chris@49
|
2944 SpMat<eT>::copy_size(const Mat<eT2>& m)
|
Chris@49
|
2945 {
|
Chris@49
|
2946 arma_extra_debug_sigprint();
|
Chris@49
|
2947
|
Chris@49
|
2948 init(m.n_rows, m.n_cols);
|
Chris@49
|
2949 }
|
Chris@49
|
2950
|
Chris@49
|
2951
|
Chris@49
|
2952
|
Chris@49
|
2953 /**
|
Chris@49
|
2954 * Resize the matrix to a given size. The matrix will be resized to be a column vector (i.e. in_elem columns, 1 row).
|
Chris@49
|
2955 *
|
Chris@49
|
2956 * @param in_elem Number of elements to allow.
|
Chris@49
|
2957 */
|
Chris@49
|
2958 template<typename eT>
|
Chris@49
|
2959 inline
|
Chris@49
|
2960 void
|
Chris@49
|
2961 SpMat<eT>::set_size(const uword in_elem)
|
Chris@49
|
2962 {
|
Chris@49
|
2963 arma_extra_debug_sigprint();
|
Chris@49
|
2964
|
Chris@49
|
2965 // If this is a row vector, we resize to a row vector.
|
Chris@49
|
2966 if(vec_state == 2)
|
Chris@49
|
2967 {
|
Chris@49
|
2968 init(1, in_elem);
|
Chris@49
|
2969 }
|
Chris@49
|
2970 else
|
Chris@49
|
2971 {
|
Chris@49
|
2972 init(in_elem, 1);
|
Chris@49
|
2973 }
|
Chris@49
|
2974 }
|
Chris@49
|
2975
|
Chris@49
|
2976
|
Chris@49
|
2977
|
Chris@49
|
2978 /**
|
Chris@49
|
2979 * Resize the matrix to a given size.
|
Chris@49
|
2980 *
|
Chris@49
|
2981 * @param in_rows Number of rows to allow.
|
Chris@49
|
2982 * @param in_cols Number of columns to allow.
|
Chris@49
|
2983 */
|
Chris@49
|
2984 template<typename eT>
|
Chris@49
|
2985 inline
|
Chris@49
|
2986 void
|
Chris@49
|
2987 SpMat<eT>::set_size(const uword in_rows, const uword in_cols)
|
Chris@49
|
2988 {
|
Chris@49
|
2989 arma_extra_debug_sigprint();
|
Chris@49
|
2990
|
Chris@49
|
2991 init(in_rows, in_cols);
|
Chris@49
|
2992 }
|
Chris@49
|
2993
|
Chris@49
|
2994
|
Chris@49
|
2995
|
Chris@49
|
2996 template<typename eT>
|
Chris@49
|
2997 inline
|
Chris@49
|
2998 void
|
Chris@49
|
2999 SpMat<eT>::reshape(const uword in_rows, const uword in_cols, const uword dim)
|
Chris@49
|
3000 {
|
Chris@49
|
3001 arma_extra_debug_sigprint();
|
Chris@49
|
3002
|
Chris@49
|
3003 if (dim == 0)
|
Chris@49
|
3004 {
|
Chris@49
|
3005 // We have to modify all of the relevant row indices and the relevant column pointers.
|
Chris@49
|
3006 // Iterate over all the points to do this. We won't be deleting any points, but we will be modifying
|
Chris@49
|
3007 // columns and rows. We'll have to store a new set of column vectors.
|
Chris@49
|
3008 uword* new_col_ptrs = memory::acquire<uword>(in_cols + 2);
|
Chris@49
|
3009 new_col_ptrs[in_cols + 1] = std::numeric_limits<uword>::max();
|
Chris@49
|
3010
|
Chris@49
|
3011 uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero + 1);
|
Chris@49
|
3012 access::rw(new_row_indices[n_nonzero]) = 0;
|
Chris@49
|
3013
|
Chris@49
|
3014 arrayops::inplace_set(new_col_ptrs, uword(0), in_cols + 1);
|
Chris@49
|
3015
|
Chris@49
|
3016 for(const_iterator it = begin(); it != end(); it++)
|
Chris@49
|
3017 {
|
Chris@49
|
3018 uword vector_position = (it.col() * n_rows) + it.row();
|
Chris@49
|
3019 new_row_indices[it.pos()] = vector_position % in_rows;
|
Chris@49
|
3020 ++new_col_ptrs[vector_position / in_rows + 1];
|
Chris@49
|
3021 }
|
Chris@49
|
3022
|
Chris@49
|
3023 // Now sum the column counts to get the new column pointers.
|
Chris@49
|
3024 for(uword i = 1; i <= in_cols; i++)
|
Chris@49
|
3025 {
|
Chris@49
|
3026 access::rw(new_col_ptrs[i]) += new_col_ptrs[i - 1];
|
Chris@49
|
3027 }
|
Chris@49
|
3028
|
Chris@49
|
3029 // Copy the new row indices.
|
Chris@49
|
3030 memory::release(row_indices);
|
Chris@49
|
3031 access::rw(row_indices) = new_row_indices;
|
Chris@49
|
3032
|
Chris@49
|
3033 memory::release(col_ptrs);
|
Chris@49
|
3034 access::rw(col_ptrs) = new_col_ptrs;
|
Chris@49
|
3035
|
Chris@49
|
3036 // Now set the size.
|
Chris@49
|
3037 access::rw(n_rows) = in_rows;
|
Chris@49
|
3038 access::rw(n_cols) = in_cols;
|
Chris@49
|
3039 }
|
Chris@49
|
3040 else
|
Chris@49
|
3041 {
|
Chris@49
|
3042 // Row-wise reshaping. This is more tedious and we will use a separate sparse matrix to do it.
|
Chris@49
|
3043 SpMat<eT> tmp(in_rows, in_cols);
|
Chris@49
|
3044
|
Chris@49
|
3045 for(const_row_iterator it = begin_row(); it.pos() < n_nonzero; it++)
|
Chris@49
|
3046 {
|
Chris@49
|
3047 uword vector_position = (it.row() * n_cols) + it.col();
|
Chris@49
|
3048
|
Chris@49
|
3049 tmp((vector_position / in_cols), (vector_position % in_cols)) = (*it);
|
Chris@49
|
3050 }
|
Chris@49
|
3051
|
Chris@49
|
3052 (*this).operator=(tmp);
|
Chris@49
|
3053 }
|
Chris@49
|
3054 }
|
Chris@49
|
3055
|
Chris@49
|
3056
|
Chris@49
|
3057
|
Chris@49
|
3058 template<typename eT>
|
Chris@49
|
3059 inline
|
Chris@49
|
3060 const SpMat<eT>&
|
Chris@49
|
3061 SpMat<eT>::zeros()
|
Chris@49
|
3062 {
|
Chris@49
|
3063 arma_extra_debug_sigprint();
|
Chris@49
|
3064
|
Chris@49
|
3065 if (n_nonzero > 0)
|
Chris@49
|
3066 {
|
Chris@49
|
3067 memory::release(values);
|
Chris@49
|
3068 memory::release(row_indices);
|
Chris@49
|
3069
|
Chris@49
|
3070 access::rw(values) = memory::acquire_chunked<eT>(1);
|
Chris@49
|
3071 access::rw(row_indices) = memory::acquire_chunked<uword>(1);
|
Chris@49
|
3072
|
Chris@49
|
3073 access::rw(values[0]) = 0;
|
Chris@49
|
3074 access::rw(row_indices[0]) = 0;
|
Chris@49
|
3075 }
|
Chris@49
|
3076
|
Chris@49
|
3077 access::rw(n_nonzero) = 0;
|
Chris@49
|
3078 arrayops::inplace_set(access::rwp(col_ptrs), uword(0), n_cols + 1);
|
Chris@49
|
3079
|
Chris@49
|
3080 return *this;
|
Chris@49
|
3081 }
|
Chris@49
|
3082
|
Chris@49
|
3083
|
Chris@49
|
3084
|
Chris@49
|
3085 template<typename eT>
|
Chris@49
|
3086 inline
|
Chris@49
|
3087 const SpMat<eT>&
|
Chris@49
|
3088 SpMat<eT>::zeros(const uword in_elem)
|
Chris@49
|
3089 {
|
Chris@49
|
3090 arma_extra_debug_sigprint();
|
Chris@49
|
3091
|
Chris@49
|
3092 if(vec_state == 2)
|
Chris@49
|
3093 {
|
Chris@49
|
3094 init(1, in_elem); // Row vector
|
Chris@49
|
3095 }
|
Chris@49
|
3096 else
|
Chris@49
|
3097 {
|
Chris@49
|
3098 init(in_elem, 1);
|
Chris@49
|
3099 }
|
Chris@49
|
3100
|
Chris@49
|
3101 return *this;
|
Chris@49
|
3102 }
|
Chris@49
|
3103
|
Chris@49
|
3104
|
Chris@49
|
3105
|
Chris@49
|
3106 template<typename eT>
|
Chris@49
|
3107 inline
|
Chris@49
|
3108 const SpMat<eT>&
|
Chris@49
|
3109 SpMat<eT>::zeros(const uword in_rows, const uword in_cols)
|
Chris@49
|
3110 {
|
Chris@49
|
3111 arma_extra_debug_sigprint();
|
Chris@49
|
3112
|
Chris@49
|
3113 init(in_rows, in_cols);
|
Chris@49
|
3114
|
Chris@49
|
3115 return *this;
|
Chris@49
|
3116 }
|
Chris@49
|
3117
|
Chris@49
|
3118
|
Chris@49
|
3119
|
Chris@49
|
3120 template<typename eT>
|
Chris@49
|
3121 inline
|
Chris@49
|
3122 const SpMat<eT>&
|
Chris@49
|
3123 SpMat<eT>::eye()
|
Chris@49
|
3124 {
|
Chris@49
|
3125 arma_extra_debug_sigprint();
|
Chris@49
|
3126
|
Chris@49
|
3127 return (*this).eye(n_rows, n_cols);
|
Chris@49
|
3128 }
|
Chris@49
|
3129
|
Chris@49
|
3130
|
Chris@49
|
3131
|
Chris@49
|
3132 template<typename eT>
|
Chris@49
|
3133 inline
|
Chris@49
|
3134 const SpMat<eT>&
|
Chris@49
|
3135 SpMat<eT>::eye(const uword in_rows, const uword in_cols)
|
Chris@49
|
3136 {
|
Chris@49
|
3137 arma_extra_debug_sigprint();
|
Chris@49
|
3138
|
Chris@49
|
3139 const uword N = (std::min)(in_rows, in_cols);
|
Chris@49
|
3140
|
Chris@49
|
3141 init(in_rows, in_cols);
|
Chris@49
|
3142
|
Chris@49
|
3143 mem_resize(N);
|
Chris@49
|
3144
|
Chris@49
|
3145 arrayops::inplace_set(access::rwp(values), eT(1), N);
|
Chris@49
|
3146
|
Chris@49
|
3147 for(uword i = 0; i < N; ++i) { access::rw(row_indices[i]) = i; }
|
Chris@49
|
3148
|
Chris@49
|
3149 for(uword i = 0; i <= N; ++i) { access::rw(col_ptrs[i]) = i; }
|
Chris@49
|
3150
|
Chris@49
|
3151 access::rw(n_nonzero) = N;
|
Chris@49
|
3152
|
Chris@49
|
3153 return *this;
|
Chris@49
|
3154 }
|
Chris@49
|
3155
|
Chris@49
|
3156
|
Chris@49
|
3157
|
Chris@49
|
3158 template<typename eT>
|
Chris@49
|
3159 inline
|
Chris@49
|
3160 const SpMat<eT>&
|
Chris@49
|
3161 SpMat<eT>::speye()
|
Chris@49
|
3162 {
|
Chris@49
|
3163 arma_extra_debug_sigprint();
|
Chris@49
|
3164
|
Chris@49
|
3165 return (*this).eye(n_rows, n_cols);
|
Chris@49
|
3166 }
|
Chris@49
|
3167
|
Chris@49
|
3168
|
Chris@49
|
3169
|
Chris@49
|
3170 template<typename eT>
|
Chris@49
|
3171 inline
|
Chris@49
|
3172 const SpMat<eT>&
|
Chris@49
|
3173 SpMat<eT>::speye(const uword in_n_rows, const uword in_n_cols)
|
Chris@49
|
3174 {
|
Chris@49
|
3175 arma_extra_debug_sigprint();
|
Chris@49
|
3176
|
Chris@49
|
3177 return (*this).eye(in_n_rows, in_n_cols);
|
Chris@49
|
3178 }
|
Chris@49
|
3179
|
Chris@49
|
3180
|
Chris@49
|
3181
|
Chris@49
|
3182 template<typename eT>
|
Chris@49
|
3183 inline
|
Chris@49
|
3184 const SpMat<eT>&
|
Chris@49
|
3185 SpMat<eT>::sprandu(const uword in_rows, const uword in_cols, const double density)
|
Chris@49
|
3186 {
|
Chris@49
|
3187 arma_extra_debug_sigprint();
|
Chris@49
|
3188
|
Chris@49
|
3189 arma_debug_check( ( (density < double(0)) || (density > double(1)) ), "sprandu(): density must be in the [0,1] interval" );
|
Chris@49
|
3190
|
Chris@49
|
3191 zeros(in_rows, in_cols);
|
Chris@49
|
3192
|
Chris@49
|
3193 mem_resize( uword(density * double(in_rows) * double(in_cols) + 0.5) );
|
Chris@49
|
3194
|
Chris@49
|
3195 if(n_nonzero == 0)
|
Chris@49
|
3196 {
|
Chris@49
|
3197 return *this;
|
Chris@49
|
3198 }
|
Chris@49
|
3199
|
Chris@49
|
3200 eop_aux_randu<eT>::fill( access::rwp(values), n_nonzero );
|
Chris@49
|
3201
|
Chris@49
|
3202 uvec indices = linspace<uvec>( 0u, in_rows*in_cols-1, n_nonzero );
|
Chris@49
|
3203
|
Chris@49
|
3204 // perturb the indices
|
Chris@49
|
3205 for(uword i=1; i < n_nonzero-1; ++i)
|
Chris@49
|
3206 {
|
Chris@49
|
3207 const uword index_left = indices[i-1];
|
Chris@49
|
3208 const uword index_right = indices[i+1];
|
Chris@49
|
3209
|
Chris@49
|
3210 const uword center = (index_left + index_right) / 2;
|
Chris@49
|
3211
|
Chris@49
|
3212 const uword delta1 = center - index_left - 1;
|
Chris@49
|
3213 const uword delta2 = index_right - center - 1;
|
Chris@49
|
3214
|
Chris@49
|
3215 const uword min_delta = (std::min)(delta1, delta2);
|
Chris@49
|
3216
|
Chris@49
|
3217 uword index_new = uword( double(center) + double(min_delta) * (2.0*randu()-1.0) );
|
Chris@49
|
3218
|
Chris@49
|
3219 // paranoia, but better be safe than sorry
|
Chris@49
|
3220 if( (index_left < index_new) && (index_new < index_right) )
|
Chris@49
|
3221 {
|
Chris@49
|
3222 indices[i] = index_new;
|
Chris@49
|
3223 }
|
Chris@49
|
3224 }
|
Chris@49
|
3225
|
Chris@49
|
3226 uword cur_index = 0;
|
Chris@49
|
3227 uword count = 0;
|
Chris@49
|
3228
|
Chris@49
|
3229 for(uword lcol = 0; lcol < in_cols; ++lcol)
|
Chris@49
|
3230 for(uword lrow = 0; lrow < in_rows; ++lrow)
|
Chris@49
|
3231 {
|
Chris@49
|
3232 if(count == indices[cur_index])
|
Chris@49
|
3233 {
|
Chris@49
|
3234 access::rw(row_indices[cur_index]) = lrow;
|
Chris@49
|
3235 access::rw(col_ptrs[lcol + 1])++;
|
Chris@49
|
3236 ++cur_index;
|
Chris@49
|
3237 }
|
Chris@49
|
3238
|
Chris@49
|
3239 ++count;
|
Chris@49
|
3240 }
|
Chris@49
|
3241
|
Chris@49
|
3242 if(cur_index != n_nonzero)
|
Chris@49
|
3243 {
|
Chris@49
|
3244 // Fix size to correct size.
|
Chris@49
|
3245 mem_resize(cur_index);
|
Chris@49
|
3246 }
|
Chris@49
|
3247
|
Chris@49
|
3248 // Sum column pointers.
|
Chris@49
|
3249 for(uword lcol = 1; lcol <= in_cols; ++lcol)
|
Chris@49
|
3250 {
|
Chris@49
|
3251 access::rw(col_ptrs[lcol]) += col_ptrs[lcol - 1];
|
Chris@49
|
3252 }
|
Chris@49
|
3253
|
Chris@49
|
3254 return *this;
|
Chris@49
|
3255 }
|
Chris@49
|
3256
|
Chris@49
|
3257
|
Chris@49
|
3258
|
Chris@49
|
3259 template<typename eT>
|
Chris@49
|
3260 inline
|
Chris@49
|
3261 const SpMat<eT>&
|
Chris@49
|
3262 SpMat<eT>::sprandn(const uword in_rows, const uword in_cols, const double density)
|
Chris@49
|
3263 {
|
Chris@49
|
3264 arma_extra_debug_sigprint();
|
Chris@49
|
3265
|
Chris@49
|
3266 arma_debug_check( ( (density < double(0)) || (density > double(1)) ), "sprandn(): density must be in the [0,1] interval" );
|
Chris@49
|
3267
|
Chris@49
|
3268 zeros(in_rows, in_cols);
|
Chris@49
|
3269
|
Chris@49
|
3270 mem_resize( uword(density * double(in_rows) * double(in_cols) + 0.5) );
|
Chris@49
|
3271
|
Chris@49
|
3272 if(n_nonzero == 0)
|
Chris@49
|
3273 {
|
Chris@49
|
3274 return *this;
|
Chris@49
|
3275 }
|
Chris@49
|
3276
|
Chris@49
|
3277 eop_aux_randn<eT>::fill( access::rwp(values), n_nonzero );
|
Chris@49
|
3278
|
Chris@49
|
3279 uvec indices = linspace<uvec>( 0u, in_rows*in_cols-1, n_nonzero );
|
Chris@49
|
3280
|
Chris@49
|
3281 // perturb the indices
|
Chris@49
|
3282 for(uword i=1; i < n_nonzero-1; ++i)
|
Chris@49
|
3283 {
|
Chris@49
|
3284 const uword index_left = indices[i-1];
|
Chris@49
|
3285 const uword index_right = indices[i+1];
|
Chris@49
|
3286
|
Chris@49
|
3287 const uword center = (index_left + index_right) / 2;
|
Chris@49
|
3288
|
Chris@49
|
3289 const uword delta1 = center - index_left - 1;
|
Chris@49
|
3290 const uword delta2 = index_right - center - 1;
|
Chris@49
|
3291
|
Chris@49
|
3292 const uword min_delta = (std::min)(delta1, delta2);
|
Chris@49
|
3293
|
Chris@49
|
3294 uword index_new = uword( double(center) + double(min_delta) * (2.0*randu()-1.0) );
|
Chris@49
|
3295
|
Chris@49
|
3296 // paranoia, but better be safe than sorry
|
Chris@49
|
3297 if( (index_left < index_new) && (index_new < index_right) )
|
Chris@49
|
3298 {
|
Chris@49
|
3299 indices[i] = index_new;
|
Chris@49
|
3300 }
|
Chris@49
|
3301 }
|
Chris@49
|
3302
|
Chris@49
|
3303 uword cur_index = 0;
|
Chris@49
|
3304 uword count = 0;
|
Chris@49
|
3305
|
Chris@49
|
3306 for(uword lcol = 0; lcol < in_cols; ++lcol)
|
Chris@49
|
3307 for(uword lrow = 0; lrow < in_rows; ++lrow)
|
Chris@49
|
3308 {
|
Chris@49
|
3309 if(count == indices[cur_index])
|
Chris@49
|
3310 {
|
Chris@49
|
3311 access::rw(row_indices[cur_index]) = lrow;
|
Chris@49
|
3312 access::rw(col_ptrs[lcol + 1])++;
|
Chris@49
|
3313 ++cur_index;
|
Chris@49
|
3314 }
|
Chris@49
|
3315
|
Chris@49
|
3316 ++count;
|
Chris@49
|
3317 }
|
Chris@49
|
3318
|
Chris@49
|
3319 if(cur_index != n_nonzero)
|
Chris@49
|
3320 {
|
Chris@49
|
3321 // Fix size to correct size.
|
Chris@49
|
3322 mem_resize(cur_index);
|
Chris@49
|
3323 }
|
Chris@49
|
3324
|
Chris@49
|
3325 // Sum column pointers.
|
Chris@49
|
3326 for(uword lcol = 1; lcol <= in_cols; ++lcol)
|
Chris@49
|
3327 {
|
Chris@49
|
3328 access::rw(col_ptrs[lcol]) += col_ptrs[lcol - 1];
|
Chris@49
|
3329 }
|
Chris@49
|
3330
|
Chris@49
|
3331 return *this;
|
Chris@49
|
3332 }
|
Chris@49
|
3333
|
Chris@49
|
3334
|
Chris@49
|
3335
|
Chris@49
|
3336 template<typename eT>
|
Chris@49
|
3337 inline
|
Chris@49
|
3338 void
|
Chris@49
|
3339 SpMat<eT>::reset()
|
Chris@49
|
3340 {
|
Chris@49
|
3341 arma_extra_debug_sigprint();
|
Chris@49
|
3342
|
Chris@49
|
3343 set_size(0, 0);
|
Chris@49
|
3344 }
|
Chris@49
|
3345
|
Chris@49
|
3346
|
Chris@49
|
3347
|
Chris@49
|
3348 /**
|
Chris@49
|
3349 * Get the minimum or the maximum of the matrix.
|
Chris@49
|
3350 */
|
Chris@49
|
3351 template<typename eT>
|
Chris@49
|
3352 inline
|
Chris@49
|
3353 arma_warn_unused
|
Chris@49
|
3354 eT
|
Chris@49
|
3355 SpMat<eT>::min() const
|
Chris@49
|
3356 {
|
Chris@49
|
3357 arma_extra_debug_sigprint();
|
Chris@49
|
3358
|
Chris@49
|
3359 arma_debug_check((n_elem == 0), "min(): object has no elements");
|
Chris@49
|
3360
|
Chris@49
|
3361 if (n_nonzero == 0)
|
Chris@49
|
3362 {
|
Chris@49
|
3363 return 0;
|
Chris@49
|
3364 }
|
Chris@49
|
3365
|
Chris@49
|
3366 eT val = op_min::direct_min(values, n_nonzero);
|
Chris@49
|
3367
|
Chris@49
|
3368 if ((val > 0) && (n_nonzero < n_elem)) // A sparse 0 is less.
|
Chris@49
|
3369 {
|
Chris@49
|
3370 val = 0;
|
Chris@49
|
3371 }
|
Chris@49
|
3372
|
Chris@49
|
3373 return val;
|
Chris@49
|
3374 }
|
Chris@49
|
3375
|
Chris@49
|
3376
|
Chris@49
|
3377
|
Chris@49
|
3378 template<typename eT>
|
Chris@49
|
3379 inline
|
Chris@49
|
3380 eT
|
Chris@49
|
3381 SpMat<eT>::min(uword& index_of_min_val) const
|
Chris@49
|
3382 {
|
Chris@49
|
3383 arma_extra_debug_sigprint();
|
Chris@49
|
3384
|
Chris@49
|
3385 arma_debug_check((n_elem == 0), "min(): object has no elements");
|
Chris@49
|
3386
|
Chris@49
|
3387 eT val = 0;
|
Chris@49
|
3388
|
Chris@49
|
3389 if (n_nonzero == 0) // There are no other elements. It must be 0.
|
Chris@49
|
3390 {
|
Chris@49
|
3391 index_of_min_val = 0;
|
Chris@49
|
3392 }
|
Chris@49
|
3393 else
|
Chris@49
|
3394 {
|
Chris@49
|
3395 uword location;
|
Chris@49
|
3396 val = op_min::direct_min(values, n_nonzero, location);
|
Chris@49
|
3397
|
Chris@49
|
3398 if ((val > 0) && (n_nonzero < n_elem)) // A sparse 0 is less.
|
Chris@49
|
3399 {
|
Chris@49
|
3400 val = 0;
|
Chris@49
|
3401
|
Chris@49
|
3402 // Give back the index to the first zero position.
|
Chris@49
|
3403 index_of_min_val = 0;
|
Chris@49
|
3404 while (get_position(index_of_min_val) == index_of_min_val) // An element exists at that position.
|
Chris@49
|
3405 {
|
Chris@49
|
3406 index_of_min_val++;
|
Chris@49
|
3407 }
|
Chris@49
|
3408
|
Chris@49
|
3409 }
|
Chris@49
|
3410 else
|
Chris@49
|
3411 {
|
Chris@49
|
3412 index_of_min_val = get_position(location);
|
Chris@49
|
3413 }
|
Chris@49
|
3414 }
|
Chris@49
|
3415
|
Chris@49
|
3416 return val;
|
Chris@49
|
3417
|
Chris@49
|
3418 }
|
Chris@49
|
3419
|
Chris@49
|
3420
|
Chris@49
|
3421
|
Chris@49
|
3422 template<typename eT>
|
Chris@49
|
3423 inline
|
Chris@49
|
3424 eT
|
Chris@49
|
3425 SpMat<eT>::min(uword& row_of_min_val, uword& col_of_min_val) const
|
Chris@49
|
3426 {
|
Chris@49
|
3427 arma_extra_debug_sigprint();
|
Chris@49
|
3428
|
Chris@49
|
3429 arma_debug_check((n_elem == 0), "min(): object has no elements");
|
Chris@49
|
3430
|
Chris@49
|
3431 eT val = 0;
|
Chris@49
|
3432
|
Chris@49
|
3433 if (n_nonzero == 0) // There are no other elements. It must be 0.
|
Chris@49
|
3434 {
|
Chris@49
|
3435 row_of_min_val = 0;
|
Chris@49
|
3436 col_of_min_val = 0;
|
Chris@49
|
3437 }
|
Chris@49
|
3438 else
|
Chris@49
|
3439 {
|
Chris@49
|
3440 uword location;
|
Chris@49
|
3441 val = op_min::direct_min(values, n_nonzero, location);
|
Chris@49
|
3442
|
Chris@49
|
3443 if ((val > 0) && (n_nonzero < n_elem)) // A sparse 0 is less.
|
Chris@49
|
3444 {
|
Chris@49
|
3445 val = 0;
|
Chris@49
|
3446
|
Chris@49
|
3447 location = 0;
|
Chris@49
|
3448 while (get_position(location) == location) // An element exists at that position.
|
Chris@49
|
3449 {
|
Chris@49
|
3450 location++;
|
Chris@49
|
3451 }
|
Chris@49
|
3452
|
Chris@49
|
3453 row_of_min_val = location % n_rows;
|
Chris@49
|
3454 col_of_min_val = location / n_rows;
|
Chris@49
|
3455 }
|
Chris@49
|
3456 else
|
Chris@49
|
3457 {
|
Chris@49
|
3458 get_position(location, row_of_min_val, col_of_min_val);
|
Chris@49
|
3459 }
|
Chris@49
|
3460 }
|
Chris@49
|
3461
|
Chris@49
|
3462 return val;
|
Chris@49
|
3463
|
Chris@49
|
3464 }
|
Chris@49
|
3465
|
Chris@49
|
3466
|
Chris@49
|
3467
|
Chris@49
|
3468 template<typename eT>
|
Chris@49
|
3469 inline
|
Chris@49
|
3470 arma_warn_unused
|
Chris@49
|
3471 eT
|
Chris@49
|
3472 SpMat<eT>::max() const
|
Chris@49
|
3473 {
|
Chris@49
|
3474 arma_extra_debug_sigprint();
|
Chris@49
|
3475
|
Chris@49
|
3476 arma_debug_check((n_elem == 0), "max(): object has no elements");
|
Chris@49
|
3477
|
Chris@49
|
3478 if (n_nonzero == 0)
|
Chris@49
|
3479 {
|
Chris@49
|
3480 return 0;
|
Chris@49
|
3481 }
|
Chris@49
|
3482
|
Chris@49
|
3483 eT val = op_max::direct_max(values, n_nonzero);
|
Chris@49
|
3484
|
Chris@49
|
3485 if ((val < 0) && (n_nonzero < n_elem)) // A sparse 0 is more.
|
Chris@49
|
3486 {
|
Chris@49
|
3487 return 0;
|
Chris@49
|
3488 }
|
Chris@49
|
3489
|
Chris@49
|
3490 return val;
|
Chris@49
|
3491
|
Chris@49
|
3492 }
|
Chris@49
|
3493
|
Chris@49
|
3494
|
Chris@49
|
3495
|
Chris@49
|
3496 template<typename eT>
|
Chris@49
|
3497 inline
|
Chris@49
|
3498 eT
|
Chris@49
|
3499 SpMat<eT>::max(uword& index_of_max_val) const
|
Chris@49
|
3500 {
|
Chris@49
|
3501 arma_extra_debug_sigprint();
|
Chris@49
|
3502
|
Chris@49
|
3503 arma_debug_check((n_elem == 0), "max(): object has no elements");
|
Chris@49
|
3504
|
Chris@49
|
3505 eT val = 0;
|
Chris@49
|
3506
|
Chris@49
|
3507 if (n_nonzero == 0)
|
Chris@49
|
3508 {
|
Chris@49
|
3509 index_of_max_val = 0;
|
Chris@49
|
3510 }
|
Chris@49
|
3511 else
|
Chris@49
|
3512 {
|
Chris@49
|
3513 uword location;
|
Chris@49
|
3514 val = op_max::direct_max(values, n_nonzero, location);
|
Chris@49
|
3515
|
Chris@49
|
3516 if ((val < 0) && (n_nonzero < n_elem)) // A sparse 0 is more.
|
Chris@49
|
3517 {
|
Chris@49
|
3518 val = 0;
|
Chris@49
|
3519
|
Chris@49
|
3520 location = 0;
|
Chris@49
|
3521 while (get_position(location) == location) // An element exists at that position.
|
Chris@49
|
3522 {
|
Chris@49
|
3523 location++;
|
Chris@49
|
3524 }
|
Chris@49
|
3525
|
Chris@49
|
3526 }
|
Chris@49
|
3527 else
|
Chris@49
|
3528 {
|
Chris@49
|
3529 index_of_max_val = get_position(location);
|
Chris@49
|
3530 }
|
Chris@49
|
3531
|
Chris@49
|
3532 }
|
Chris@49
|
3533
|
Chris@49
|
3534 return val;
|
Chris@49
|
3535
|
Chris@49
|
3536 }
|
Chris@49
|
3537
|
Chris@49
|
3538
|
Chris@49
|
3539
|
Chris@49
|
3540 template<typename eT>
|
Chris@49
|
3541 inline
|
Chris@49
|
3542 eT
|
Chris@49
|
3543 SpMat<eT>::max(uword& row_of_max_val, uword& col_of_max_val) const
|
Chris@49
|
3544 {
|
Chris@49
|
3545 arma_extra_debug_sigprint();
|
Chris@49
|
3546
|
Chris@49
|
3547 arma_debug_check((n_elem == 0), "max(): object has no elements");
|
Chris@49
|
3548
|
Chris@49
|
3549 eT val = 0;
|
Chris@49
|
3550
|
Chris@49
|
3551 if (n_nonzero == 0)
|
Chris@49
|
3552 {
|
Chris@49
|
3553 row_of_max_val = 0;
|
Chris@49
|
3554 col_of_max_val = 0;
|
Chris@49
|
3555 }
|
Chris@49
|
3556 else
|
Chris@49
|
3557 {
|
Chris@49
|
3558 uword location;
|
Chris@49
|
3559 val = op_max::direct_max(values, n_nonzero, location);
|
Chris@49
|
3560
|
Chris@49
|
3561 if ((val < 0) && (n_nonzero < n_elem)) // A sparse 0 is more.
|
Chris@49
|
3562 {
|
Chris@49
|
3563 val = 0;
|
Chris@49
|
3564
|
Chris@49
|
3565 location = 0;
|
Chris@49
|
3566 while (get_position(location) == location) // An element exists at that position.
|
Chris@49
|
3567 {
|
Chris@49
|
3568 location++;
|
Chris@49
|
3569 }
|
Chris@49
|
3570
|
Chris@49
|
3571 row_of_max_val = location % n_rows;
|
Chris@49
|
3572 col_of_max_val = location / n_rows;
|
Chris@49
|
3573
|
Chris@49
|
3574 }
|
Chris@49
|
3575 else
|
Chris@49
|
3576 {
|
Chris@49
|
3577 get_position(location, row_of_max_val, col_of_max_val);
|
Chris@49
|
3578 }
|
Chris@49
|
3579
|
Chris@49
|
3580 }
|
Chris@49
|
3581
|
Chris@49
|
3582 return val;
|
Chris@49
|
3583
|
Chris@49
|
3584 }
|
Chris@49
|
3585
|
Chris@49
|
3586
|
Chris@49
|
3587
|
Chris@49
|
3588 //! save the matrix to a file
|
Chris@49
|
3589 template<typename eT>
|
Chris@49
|
3590 inline
|
Chris@49
|
3591 bool
|
Chris@49
|
3592 SpMat<eT>::save(const std::string name, const file_type type, const bool print_status) const
|
Chris@49
|
3593 {
|
Chris@49
|
3594 arma_extra_debug_sigprint();
|
Chris@49
|
3595
|
Chris@49
|
3596 bool save_okay;
|
Chris@49
|
3597
|
Chris@49
|
3598 switch(type)
|
Chris@49
|
3599 {
|
Chris@49
|
3600 // case raw_ascii:
|
Chris@49
|
3601 // save_okay = diskio::save_raw_ascii(*this, name);
|
Chris@49
|
3602 // break;
|
Chris@49
|
3603
|
Chris@49
|
3604 // case csv_ascii:
|
Chris@49
|
3605 // save_okay = diskio::save_csv_ascii(*this, name);
|
Chris@49
|
3606 // break;
|
Chris@49
|
3607
|
Chris@49
|
3608 case arma_binary:
|
Chris@49
|
3609 save_okay = diskio::save_arma_binary(*this, name);
|
Chris@49
|
3610 break;
|
Chris@49
|
3611
|
Chris@49
|
3612 case coord_ascii:
|
Chris@49
|
3613 save_okay = diskio::save_coord_ascii(*this, name);
|
Chris@49
|
3614 break;
|
Chris@49
|
3615
|
Chris@49
|
3616 default:
|
Chris@49
|
3617 arma_warn(true, "SpMat::save(): unsupported file type");
|
Chris@49
|
3618 save_okay = false;
|
Chris@49
|
3619 }
|
Chris@49
|
3620
|
Chris@49
|
3621 arma_warn( (save_okay == false), "SpMat::save(): couldn't write to ", name);
|
Chris@49
|
3622
|
Chris@49
|
3623 return save_okay;
|
Chris@49
|
3624 }
|
Chris@49
|
3625
|
Chris@49
|
3626
|
Chris@49
|
3627
|
Chris@49
|
3628 //! save the matrix to a stream
|
Chris@49
|
3629 template<typename eT>
|
Chris@49
|
3630 inline
|
Chris@49
|
3631 bool
|
Chris@49
|
3632 SpMat<eT>::save(std::ostream& os, const file_type type, const bool print_status) const
|
Chris@49
|
3633 {
|
Chris@49
|
3634 arma_extra_debug_sigprint();
|
Chris@49
|
3635
|
Chris@49
|
3636 bool save_okay;
|
Chris@49
|
3637
|
Chris@49
|
3638 switch(type)
|
Chris@49
|
3639 {
|
Chris@49
|
3640 // case raw_ascii:
|
Chris@49
|
3641 // save_okay = diskio::save_raw_ascii(*this, os);
|
Chris@49
|
3642 // break;
|
Chris@49
|
3643
|
Chris@49
|
3644 // case csv_ascii:
|
Chris@49
|
3645 // save_okay = diskio::save_csv_ascii(*this, os);
|
Chris@49
|
3646 // break;
|
Chris@49
|
3647
|
Chris@49
|
3648 case arma_binary:
|
Chris@49
|
3649 save_okay = diskio::save_arma_binary(*this, os);
|
Chris@49
|
3650 break;
|
Chris@49
|
3651
|
Chris@49
|
3652 case coord_ascii:
|
Chris@49
|
3653 save_okay = diskio::save_coord_ascii(*this, os);
|
Chris@49
|
3654 break;
|
Chris@49
|
3655
|
Chris@49
|
3656 default:
|
Chris@49
|
3657 arma_warn(true, "SpMat::save(): unsupported file type");
|
Chris@49
|
3658 save_okay = false;
|
Chris@49
|
3659 }
|
Chris@49
|
3660
|
Chris@49
|
3661 arma_warn( (save_okay == false), "SpMat::save(): couldn't write to the given stream");
|
Chris@49
|
3662
|
Chris@49
|
3663 return save_okay;
|
Chris@49
|
3664 }
|
Chris@49
|
3665
|
Chris@49
|
3666
|
Chris@49
|
3667
|
Chris@49
|
3668 //! load a matrix from a file
|
Chris@49
|
3669 template<typename eT>
|
Chris@49
|
3670 inline
|
Chris@49
|
3671 bool
|
Chris@49
|
3672 SpMat<eT>::load(const std::string name, const file_type type, const bool print_status)
|
Chris@49
|
3673 {
|
Chris@49
|
3674 arma_extra_debug_sigprint();
|
Chris@49
|
3675
|
Chris@49
|
3676 bool load_okay;
|
Chris@49
|
3677 std::string err_msg;
|
Chris@49
|
3678
|
Chris@49
|
3679 switch(type)
|
Chris@49
|
3680 {
|
Chris@49
|
3681 // case auto_detect:
|
Chris@49
|
3682 // load_okay = diskio::load_auto_detect(*this, name, err_msg);
|
Chris@49
|
3683 // break;
|
Chris@49
|
3684
|
Chris@49
|
3685 // case raw_ascii:
|
Chris@49
|
3686 // load_okay = diskio::load_raw_ascii(*this, name, err_msg);
|
Chris@49
|
3687 // break;
|
Chris@49
|
3688
|
Chris@49
|
3689 // case csv_ascii:
|
Chris@49
|
3690 // load_okay = diskio::load_csv_ascii(*this, name, err_msg);
|
Chris@49
|
3691 // break;
|
Chris@49
|
3692
|
Chris@49
|
3693 case arma_binary:
|
Chris@49
|
3694 load_okay = diskio::load_arma_binary(*this, name, err_msg);
|
Chris@49
|
3695 break;
|
Chris@49
|
3696
|
Chris@49
|
3697 case coord_ascii:
|
Chris@49
|
3698 load_okay = diskio::load_coord_ascii(*this, name, err_msg);
|
Chris@49
|
3699 break;
|
Chris@49
|
3700
|
Chris@49
|
3701 default:
|
Chris@49
|
3702 arma_warn(true, "SpMat::load(): unsupported file type");
|
Chris@49
|
3703 load_okay = false;
|
Chris@49
|
3704 }
|
Chris@49
|
3705
|
Chris@49
|
3706 if(load_okay == false)
|
Chris@49
|
3707 {
|
Chris@49
|
3708 if(err_msg.length() > 0)
|
Chris@49
|
3709 {
|
Chris@49
|
3710 arma_warn(true, "SpMat::load(): ", err_msg, name);
|
Chris@49
|
3711 }
|
Chris@49
|
3712 else
|
Chris@49
|
3713 {
|
Chris@49
|
3714 arma_warn(true, "SpMat::load(): couldn't read ", name);
|
Chris@49
|
3715 }
|
Chris@49
|
3716 }
|
Chris@49
|
3717
|
Chris@49
|
3718 if(load_okay == false)
|
Chris@49
|
3719 {
|
Chris@49
|
3720 (*this).reset();
|
Chris@49
|
3721 }
|
Chris@49
|
3722
|
Chris@49
|
3723 return load_okay;
|
Chris@49
|
3724 }
|
Chris@49
|
3725
|
Chris@49
|
3726
|
Chris@49
|
3727
|
Chris@49
|
3728 //! load a matrix from a stream
|
Chris@49
|
3729 template<typename eT>
|
Chris@49
|
3730 inline
|
Chris@49
|
3731 bool
|
Chris@49
|
3732 SpMat<eT>::load(std::istream& is, const file_type type, const bool print_status)
|
Chris@49
|
3733 {
|
Chris@49
|
3734 arma_extra_debug_sigprint();
|
Chris@49
|
3735
|
Chris@49
|
3736 bool load_okay;
|
Chris@49
|
3737 std::string err_msg;
|
Chris@49
|
3738
|
Chris@49
|
3739 switch(type)
|
Chris@49
|
3740 {
|
Chris@49
|
3741 // case auto_detect:
|
Chris@49
|
3742 // load_okay = diskio::load_auto_detect(*this, is, err_msg);
|
Chris@49
|
3743 // break;
|
Chris@49
|
3744
|
Chris@49
|
3745 // case raw_ascii:
|
Chris@49
|
3746 // load_okay = diskio::load_raw_ascii(*this, is, err_msg);
|
Chris@49
|
3747 // break;
|
Chris@49
|
3748
|
Chris@49
|
3749 // case csv_ascii:
|
Chris@49
|
3750 // load_okay = diskio::load_csv_ascii(*this, is, err_msg);
|
Chris@49
|
3751 // break;
|
Chris@49
|
3752
|
Chris@49
|
3753 case arma_binary:
|
Chris@49
|
3754 load_okay = diskio::load_arma_binary(*this, is, err_msg);
|
Chris@49
|
3755 break;
|
Chris@49
|
3756
|
Chris@49
|
3757 case coord_ascii:
|
Chris@49
|
3758 load_okay = diskio::load_coord_ascii(*this, is, err_msg);
|
Chris@49
|
3759 break;
|
Chris@49
|
3760
|
Chris@49
|
3761 default:
|
Chris@49
|
3762 arma_warn(true, "SpMat::load(): unsupported file type");
|
Chris@49
|
3763 load_okay = false;
|
Chris@49
|
3764 }
|
Chris@49
|
3765
|
Chris@49
|
3766
|
Chris@49
|
3767 if(load_okay == false)
|
Chris@49
|
3768 {
|
Chris@49
|
3769 if(err_msg.length() > 0)
|
Chris@49
|
3770 {
|
Chris@49
|
3771 arma_warn(true, "SpMat::load(): ", err_msg, "the given stream");
|
Chris@49
|
3772 }
|
Chris@49
|
3773 else
|
Chris@49
|
3774 {
|
Chris@49
|
3775 arma_warn(true, "SpMat::load(): couldn't load from the given stream");
|
Chris@49
|
3776 }
|
Chris@49
|
3777 }
|
Chris@49
|
3778
|
Chris@49
|
3779 if(load_okay == false)
|
Chris@49
|
3780 {
|
Chris@49
|
3781 (*this).reset();
|
Chris@49
|
3782 }
|
Chris@49
|
3783
|
Chris@49
|
3784 return load_okay;
|
Chris@49
|
3785 }
|
Chris@49
|
3786
|
Chris@49
|
3787
|
Chris@49
|
3788
|
Chris@49
|
3789 //! save the matrix to a file, without printing any error messages
|
Chris@49
|
3790 template<typename eT>
|
Chris@49
|
3791 inline
|
Chris@49
|
3792 bool
|
Chris@49
|
3793 SpMat<eT>::quiet_save(const std::string name, const file_type type) const
|
Chris@49
|
3794 {
|
Chris@49
|
3795 arma_extra_debug_sigprint();
|
Chris@49
|
3796
|
Chris@49
|
3797 return (*this).save(name, type, false);
|
Chris@49
|
3798 }
|
Chris@49
|
3799
|
Chris@49
|
3800
|
Chris@49
|
3801
|
Chris@49
|
3802 //! save the matrix to a stream, without printing any error messages
|
Chris@49
|
3803 template<typename eT>
|
Chris@49
|
3804 inline
|
Chris@49
|
3805 bool
|
Chris@49
|
3806 SpMat<eT>::quiet_save(std::ostream& os, const file_type type) const
|
Chris@49
|
3807 {
|
Chris@49
|
3808 arma_extra_debug_sigprint();
|
Chris@49
|
3809
|
Chris@49
|
3810 return (*this).save(os, type, false);
|
Chris@49
|
3811 }
|
Chris@49
|
3812
|
Chris@49
|
3813
|
Chris@49
|
3814
|
Chris@49
|
3815 //! load a matrix from a file, without printing any error messages
|
Chris@49
|
3816 template<typename eT>
|
Chris@49
|
3817 inline
|
Chris@49
|
3818 bool
|
Chris@49
|
3819 SpMat<eT>::quiet_load(const std::string name, const file_type type)
|
Chris@49
|
3820 {
|
Chris@49
|
3821 arma_extra_debug_sigprint();
|
Chris@49
|
3822
|
Chris@49
|
3823 return (*this).load(name, type, false);
|
Chris@49
|
3824 }
|
Chris@49
|
3825
|
Chris@49
|
3826
|
Chris@49
|
3827
|
Chris@49
|
3828 //! load a matrix from a stream, without printing any error messages
|
Chris@49
|
3829 template<typename eT>
|
Chris@49
|
3830 inline
|
Chris@49
|
3831 bool
|
Chris@49
|
3832 SpMat<eT>::quiet_load(std::istream& is, const file_type type)
|
Chris@49
|
3833 {
|
Chris@49
|
3834 arma_extra_debug_sigprint();
|
Chris@49
|
3835
|
Chris@49
|
3836 return (*this).load(is, type, false);
|
Chris@49
|
3837 }
|
Chris@49
|
3838
|
Chris@49
|
3839
|
Chris@49
|
3840
|
Chris@49
|
3841 /**
|
Chris@49
|
3842 * Initialize the matrix to the specified size. Data is not preserved, so the matrix is assumed to be entirely sparse (empty).
|
Chris@49
|
3843 */
|
Chris@49
|
3844 template<typename eT>
|
Chris@49
|
3845 inline
|
Chris@49
|
3846 void
|
Chris@49
|
3847 SpMat<eT>::init(uword in_rows, uword in_cols)
|
Chris@49
|
3848 {
|
Chris@49
|
3849 arma_extra_debug_sigprint();
|
Chris@49
|
3850
|
Chris@49
|
3851 // Verify that we are allowed to do this.
|
Chris@49
|
3852 if(vec_state > 0)
|
Chris@49
|
3853 {
|
Chris@49
|
3854 if((in_rows == 0) && (in_cols == 0))
|
Chris@49
|
3855 {
|
Chris@49
|
3856 if(vec_state == 1)
|
Chris@49
|
3857 {
|
Chris@49
|
3858 in_cols = 1;
|
Chris@49
|
3859 }
|
Chris@49
|
3860 else
|
Chris@49
|
3861 if(vec_state == 2)
|
Chris@49
|
3862 {
|
Chris@49
|
3863 in_rows = 1;
|
Chris@49
|
3864 }
|
Chris@49
|
3865 }
|
Chris@49
|
3866 else
|
Chris@49
|
3867 {
|
Chris@49
|
3868 arma_debug_check
|
Chris@49
|
3869 (
|
Chris@49
|
3870 ( ((vec_state == 1) && (in_cols != 1)) || ((vec_state == 2) && (in_rows != 1)) ),
|
Chris@49
|
3871 "SpMat::init(): object is a row or column vector; requested size is not compatible"
|
Chris@49
|
3872 );
|
Chris@49
|
3873 }
|
Chris@49
|
3874 }
|
Chris@49
|
3875
|
Chris@49
|
3876 // Ensure that n_elem can hold the result of (n_rows * n_cols)
|
Chris@49
|
3877 arma_debug_check
|
Chris@49
|
3878 (
|
Chris@49
|
3879 (
|
Chris@49
|
3880 ( (in_rows > ARMA_MAX_UHWORD) || (in_cols > ARMA_MAX_UHWORD) )
|
Chris@49
|
3881 ? ( (float(in_rows) * float(in_cols)) > float(ARMA_MAX_UWORD) )
|
Chris@49
|
3882 : false
|
Chris@49
|
3883 ),
|
Chris@49
|
3884 "SpMat::init(): requested size is too large"
|
Chris@49
|
3885 );
|
Chris@49
|
3886
|
Chris@49
|
3887 // Clean out the existing memory.
|
Chris@49
|
3888 if (values)
|
Chris@49
|
3889 {
|
Chris@49
|
3890 memory::release(values);
|
Chris@49
|
3891 memory::release(row_indices);
|
Chris@49
|
3892 }
|
Chris@49
|
3893
|
Chris@49
|
3894 access::rw(values) = memory::acquire_chunked<eT> (1);
|
Chris@49
|
3895 access::rw(row_indices) = memory::acquire_chunked<uword>(1);
|
Chris@49
|
3896
|
Chris@49
|
3897 access::rw(values[0]) = 0;
|
Chris@49
|
3898 access::rw(row_indices[0]) = 0;
|
Chris@49
|
3899
|
Chris@49
|
3900 memory::release(col_ptrs);
|
Chris@49
|
3901
|
Chris@49
|
3902 // Set the new size accordingly.
|
Chris@49
|
3903 access::rw(n_rows) = in_rows;
|
Chris@49
|
3904 access::rw(n_cols) = in_cols;
|
Chris@49
|
3905 access::rw(n_elem) = (in_rows * in_cols);
|
Chris@49
|
3906 access::rw(n_nonzero) = 0;
|
Chris@49
|
3907
|
Chris@49
|
3908 // Try to allocate the column pointers, filling them with 0, except for the
|
Chris@49
|
3909 // last element which contains the maximum possible element (so iterators
|
Chris@49
|
3910 // terminate correctly).
|
Chris@49
|
3911 access::rw(col_ptrs) = memory::acquire<uword>(in_cols + 2);
|
Chris@49
|
3912 access::rw(col_ptrs[in_cols + 1]) = std::numeric_limits<uword>::max();
|
Chris@49
|
3913
|
Chris@49
|
3914 arrayops::inplace_set(access::rwp(col_ptrs), uword(0), in_cols + 1);
|
Chris@49
|
3915 }
|
Chris@49
|
3916
|
Chris@49
|
3917
|
Chris@49
|
3918
|
Chris@49
|
3919 /**
|
Chris@49
|
3920 * Initialize the matrix from a string.
|
Chris@49
|
3921 */
|
Chris@49
|
3922 template<typename eT>
|
Chris@49
|
3923 inline
|
Chris@49
|
3924 void
|
Chris@49
|
3925 SpMat<eT>::init(const std::string& text)
|
Chris@49
|
3926 {
|
Chris@49
|
3927 arma_extra_debug_sigprint();
|
Chris@49
|
3928
|
Chris@49
|
3929 // Figure out the size first.
|
Chris@49
|
3930 uword t_n_rows = 0;
|
Chris@49
|
3931 uword t_n_cols = 0;
|
Chris@49
|
3932
|
Chris@49
|
3933 bool t_n_cols_found = false;
|
Chris@49
|
3934
|
Chris@49
|
3935 std::string token;
|
Chris@49
|
3936
|
Chris@49
|
3937 std::string::size_type line_start = 0;
|
Chris@49
|
3938 std::string::size_type line_end = 0;
|
Chris@49
|
3939
|
Chris@49
|
3940 while (line_start < text.length())
|
Chris@49
|
3941 {
|
Chris@49
|
3942
|
Chris@49
|
3943 line_end = text.find(';', line_start);
|
Chris@49
|
3944
|
Chris@49
|
3945 if (line_end == std::string::npos)
|
Chris@49
|
3946 line_end = text.length() - 1;
|
Chris@49
|
3947
|
Chris@49
|
3948 std::string::size_type line_len = line_end - line_start + 1;
|
Chris@49
|
3949 std::stringstream line_stream(text.substr(line_start, line_len));
|
Chris@49
|
3950
|
Chris@49
|
3951 // Step through each column.
|
Chris@49
|
3952 uword line_n_cols = 0;
|
Chris@49
|
3953
|
Chris@49
|
3954 while (line_stream >> token)
|
Chris@49
|
3955 {
|
Chris@49
|
3956 ++line_n_cols;
|
Chris@49
|
3957 }
|
Chris@49
|
3958
|
Chris@49
|
3959 if (line_n_cols > 0)
|
Chris@49
|
3960 {
|
Chris@49
|
3961 if (t_n_cols_found == false)
|
Chris@49
|
3962 {
|
Chris@49
|
3963 t_n_cols = line_n_cols;
|
Chris@49
|
3964 t_n_cols_found = true;
|
Chris@49
|
3965 }
|
Chris@49
|
3966 else // Check it each time through, just to make sure.
|
Chris@49
|
3967 arma_check((line_n_cols != t_n_cols), "SpMat::init(): inconsistent number of columns in given string");
|
Chris@49
|
3968
|
Chris@49
|
3969 ++t_n_rows;
|
Chris@49
|
3970 }
|
Chris@49
|
3971
|
Chris@49
|
3972 line_start = line_end + 1;
|
Chris@49
|
3973
|
Chris@49
|
3974 }
|
Chris@49
|
3975
|
Chris@49
|
3976 set_size(t_n_rows, t_n_cols);
|
Chris@49
|
3977
|
Chris@49
|
3978 // Second time through will pick up all the values.
|
Chris@49
|
3979 line_start = 0;
|
Chris@49
|
3980 line_end = 0;
|
Chris@49
|
3981
|
Chris@49
|
3982 uword lrow = 0;
|
Chris@49
|
3983
|
Chris@49
|
3984 while (line_start < text.length())
|
Chris@49
|
3985 {
|
Chris@49
|
3986
|
Chris@49
|
3987 line_end = text.find(';', line_start);
|
Chris@49
|
3988
|
Chris@49
|
3989 if (line_end == std::string::npos)
|
Chris@49
|
3990 line_end = text.length() - 1;
|
Chris@49
|
3991
|
Chris@49
|
3992 std::string::size_type line_len = line_end - line_start + 1;
|
Chris@49
|
3993 std::stringstream line_stream(text.substr(line_start, line_len));
|
Chris@49
|
3994
|
Chris@49
|
3995 uword lcol = 0;
|
Chris@49
|
3996 eT val;
|
Chris@49
|
3997
|
Chris@49
|
3998 while (line_stream >> val)
|
Chris@49
|
3999 {
|
Chris@49
|
4000 // Only add nonzero elements.
|
Chris@49
|
4001 if (val != eT(0))
|
Chris@49
|
4002 {
|
Chris@49
|
4003 get_value(lrow, lcol) = val;
|
Chris@49
|
4004 }
|
Chris@49
|
4005
|
Chris@49
|
4006 ++lcol;
|
Chris@49
|
4007 }
|
Chris@49
|
4008
|
Chris@49
|
4009 ++lrow;
|
Chris@49
|
4010 line_start = line_end + 1;
|
Chris@49
|
4011
|
Chris@49
|
4012 }
|
Chris@49
|
4013
|
Chris@49
|
4014 }
|
Chris@49
|
4015
|
Chris@49
|
4016 /**
|
Chris@49
|
4017 * Copy from another matrix.
|
Chris@49
|
4018 */
|
Chris@49
|
4019 template<typename eT>
|
Chris@49
|
4020 inline
|
Chris@49
|
4021 void
|
Chris@49
|
4022 SpMat<eT>::init(const SpMat<eT>& x)
|
Chris@49
|
4023 {
|
Chris@49
|
4024 arma_extra_debug_sigprint();
|
Chris@49
|
4025
|
Chris@49
|
4026 // Ensure we are not initializing to ourselves.
|
Chris@49
|
4027 if (this != &x)
|
Chris@49
|
4028 {
|
Chris@49
|
4029 init(x.n_rows, x.n_cols);
|
Chris@49
|
4030
|
Chris@49
|
4031 // values and row_indices may not be null.
|
Chris@49
|
4032 if (values != NULL)
|
Chris@49
|
4033 {
|
Chris@49
|
4034 memory::release(values);
|
Chris@49
|
4035 memory::release(row_indices);
|
Chris@49
|
4036 }
|
Chris@49
|
4037
|
Chris@49
|
4038 access::rw(values) = memory::acquire_chunked<eT> (x.n_nonzero + 1);
|
Chris@49
|
4039 access::rw(row_indices) = memory::acquire_chunked<uword>(x.n_nonzero + 1);
|
Chris@49
|
4040
|
Chris@49
|
4041 // Now copy over the elements.
|
Chris@49
|
4042 arrayops::copy(access::rwp(values), x.values, x.n_nonzero + 1);
|
Chris@49
|
4043 arrayops::copy(access::rwp(row_indices), x.row_indices, x.n_nonzero + 1);
|
Chris@49
|
4044 arrayops::copy(access::rwp(col_ptrs), x.col_ptrs, x.n_cols + 1);
|
Chris@49
|
4045
|
Chris@49
|
4046 access::rw(n_nonzero) = x.n_nonzero;
|
Chris@49
|
4047 }
|
Chris@49
|
4048 }
|
Chris@49
|
4049
|
Chris@49
|
4050
|
Chris@49
|
4051
|
Chris@49
|
4052 template<typename eT>
|
Chris@49
|
4053 inline
|
Chris@49
|
4054 void
|
Chris@49
|
4055 SpMat<eT>::mem_resize(const uword new_n_nonzero)
|
Chris@49
|
4056 {
|
Chris@49
|
4057 arma_extra_debug_sigprint();
|
Chris@49
|
4058
|
Chris@49
|
4059 if(n_nonzero != new_n_nonzero)
|
Chris@49
|
4060 {
|
Chris@49
|
4061 if(new_n_nonzero == 0)
|
Chris@49
|
4062 {
|
Chris@49
|
4063 memory::release(values);
|
Chris@49
|
4064 memory::release(row_indices);
|
Chris@49
|
4065
|
Chris@49
|
4066 access::rw(values) = memory::acquire_chunked<eT> (1);
|
Chris@49
|
4067 access::rw(row_indices) = memory::acquire_chunked<uword>(1);
|
Chris@49
|
4068
|
Chris@49
|
4069 access::rw(values[0]) = 0;
|
Chris@49
|
4070 access::rw(row_indices[0]) = 0;
|
Chris@49
|
4071 }
|
Chris@49
|
4072 else
|
Chris@49
|
4073 {
|
Chris@49
|
4074 // Figure out the actual amount of memory currently allocated
|
Chris@49
|
4075 // NOTE: this relies on memory::acquire_chunked() being used for the 'values' and 'row_indices' arrays
|
Chris@49
|
4076 const uword n_alloc = memory::enlarge_to_mult_of_chunksize(n_nonzero);
|
Chris@49
|
4077
|
Chris@49
|
4078 if(n_alloc < new_n_nonzero)
|
Chris@49
|
4079 {
|
Chris@49
|
4080 eT* new_values = memory::acquire_chunked<eT> (new_n_nonzero + 1);
|
Chris@49
|
4081 uword* new_row_indices = memory::acquire_chunked<uword>(new_n_nonzero + 1);
|
Chris@49
|
4082
|
Chris@49
|
4083 if(n_nonzero > 0)
|
Chris@49
|
4084 {
|
Chris@49
|
4085 // Copy old elements.
|
Chris@49
|
4086 uword copy_len = std::min(n_nonzero, new_n_nonzero);
|
Chris@49
|
4087
|
Chris@49
|
4088 arrayops::copy(new_values, values, copy_len);
|
Chris@49
|
4089 arrayops::copy(new_row_indices, row_indices, copy_len);
|
Chris@49
|
4090 }
|
Chris@49
|
4091
|
Chris@49
|
4092 memory::release(values);
|
Chris@49
|
4093 memory::release(row_indices);
|
Chris@49
|
4094
|
Chris@49
|
4095 access::rw(values) = new_values;
|
Chris@49
|
4096 access::rw(row_indices) = new_row_indices;
|
Chris@49
|
4097 }
|
Chris@49
|
4098
|
Chris@49
|
4099 // Set the "fake end" of the matrix by setting the last value and row
|
Chris@49
|
4100 // index to 0. This helps the iterators work correctly.
|
Chris@49
|
4101 access::rw(values[new_n_nonzero]) = 0;
|
Chris@49
|
4102 access::rw(row_indices[new_n_nonzero]) = 0;
|
Chris@49
|
4103 }
|
Chris@49
|
4104
|
Chris@49
|
4105 access::rw(n_nonzero) = new_n_nonzero;
|
Chris@49
|
4106 }
|
Chris@49
|
4107 }
|
Chris@49
|
4108
|
Chris@49
|
4109
|
Chris@49
|
4110
|
Chris@49
|
4111 // Steal memory from another matrix.
|
Chris@49
|
4112 template<typename eT>
|
Chris@49
|
4113 inline
|
Chris@49
|
4114 void
|
Chris@49
|
4115 SpMat<eT>::steal_mem(SpMat<eT>& x)
|
Chris@49
|
4116 {
|
Chris@49
|
4117 arma_extra_debug_sigprint();
|
Chris@49
|
4118
|
Chris@49
|
4119 if(this != &x)
|
Chris@49
|
4120 {
|
Chris@49
|
4121 // Release all the memory.
|
Chris@49
|
4122 memory::release(values);
|
Chris@49
|
4123 memory::release(row_indices);
|
Chris@49
|
4124 memory::release(col_ptrs);
|
Chris@49
|
4125
|
Chris@49
|
4126 // We'll have to copy everything about the other matrix.
|
Chris@49
|
4127 const uword x_n_rows = x.n_rows;
|
Chris@49
|
4128 const uword x_n_cols = x.n_cols;
|
Chris@49
|
4129 const uword x_n_elem = x.n_elem;
|
Chris@49
|
4130 const uword x_n_nonzero = x.n_nonzero;
|
Chris@49
|
4131
|
Chris@49
|
4132 access::rw(n_rows) = x_n_rows;
|
Chris@49
|
4133 access::rw(n_cols) = x_n_cols;
|
Chris@49
|
4134 access::rw(n_elem) = x_n_elem;
|
Chris@49
|
4135 access::rw(n_nonzero) = x_n_nonzero;
|
Chris@49
|
4136
|
Chris@49
|
4137 access::rw(values) = x.values;
|
Chris@49
|
4138 access::rw(row_indices) = x.row_indices;
|
Chris@49
|
4139 access::rw(col_ptrs) = x.col_ptrs;
|
Chris@49
|
4140
|
Chris@49
|
4141 // Set other matrix to empty.
|
Chris@49
|
4142 access::rw(x.n_rows) = 0;
|
Chris@49
|
4143 access::rw(x.n_cols) = 0;
|
Chris@49
|
4144 access::rw(x.n_elem) = 0;
|
Chris@49
|
4145 access::rw(x.n_nonzero) = 0;
|
Chris@49
|
4146
|
Chris@49
|
4147 access::rw(x.values) = NULL;
|
Chris@49
|
4148 access::rw(x.row_indices) = NULL;
|
Chris@49
|
4149 access::rw(x.col_ptrs) = NULL;
|
Chris@49
|
4150 }
|
Chris@49
|
4151 }
|
Chris@49
|
4152
|
Chris@49
|
4153
|
Chris@49
|
4154
|
Chris@49
|
4155 template<typename eT>
|
Chris@49
|
4156 template<typename T1, typename Functor>
|
Chris@49
|
4157 arma_hot
|
Chris@49
|
4158 inline
|
Chris@49
|
4159 void
|
Chris@49
|
4160 SpMat<eT>::init_xform(const SpBase<eT,T1>& A, const Functor& func)
|
Chris@49
|
4161 {
|
Chris@49
|
4162 arma_extra_debug_sigprint();
|
Chris@49
|
4163
|
Chris@49
|
4164 // if possible, avoid doing a copy and instead apply func to the generated elements
|
Chris@49
|
4165 if(SpProxy<T1>::Q_created_by_proxy == true)
|
Chris@49
|
4166 {
|
Chris@49
|
4167 (*this) = A.get_ref();
|
Chris@49
|
4168
|
Chris@49
|
4169 const uword nnz = n_nonzero;
|
Chris@49
|
4170
|
Chris@49
|
4171 eT* t_values = access::rwp(values);
|
Chris@49
|
4172
|
Chris@49
|
4173 for(uword i=0; i < nnz; ++i)
|
Chris@49
|
4174 {
|
Chris@49
|
4175 t_values[i] = func(t_values[i]);
|
Chris@49
|
4176 }
|
Chris@49
|
4177 }
|
Chris@49
|
4178 else
|
Chris@49
|
4179 {
|
Chris@49
|
4180 init_xform_mt(A.get_ref(), func);
|
Chris@49
|
4181 }
|
Chris@49
|
4182 }
|
Chris@49
|
4183
|
Chris@49
|
4184
|
Chris@49
|
4185
|
Chris@49
|
4186 template<typename eT>
|
Chris@49
|
4187 template<typename eT2, typename T1, typename Functor>
|
Chris@49
|
4188 arma_hot
|
Chris@49
|
4189 inline
|
Chris@49
|
4190 void
|
Chris@49
|
4191 SpMat<eT>::init_xform_mt(const SpBase<eT2,T1>& A, const Functor& func)
|
Chris@49
|
4192 {
|
Chris@49
|
4193 arma_extra_debug_sigprint();
|
Chris@49
|
4194
|
Chris@49
|
4195 const SpProxy<T1> P(A.get_ref());
|
Chris@49
|
4196
|
Chris@49
|
4197 if( (P.is_alias(*this) == true) || (is_SpMat<typename SpProxy<T1>::stored_type>::value == true) )
|
Chris@49
|
4198 {
|
Chris@49
|
4199 // NOTE: unwrap_spmat will convert a submatrix to a matrix, which in effect takes care of aliasing with submatrices;
|
Chris@49
|
4200 // NOTE: however, when more delayed ops are implemented, more elaborate handling of aliasing will be necessary
|
Chris@49
|
4201 const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q);
|
Chris@49
|
4202
|
Chris@49
|
4203 const SpMat<eT2>& x = tmp.M;
|
Chris@49
|
4204
|
Chris@49
|
4205 if(void_ptr(this) != void_ptr(&x))
|
Chris@49
|
4206 {
|
Chris@49
|
4207 init(x.n_rows, x.n_cols);
|
Chris@49
|
4208
|
Chris@49
|
4209 // values and row_indices may not be null.
|
Chris@49
|
4210 if(values != NULL)
|
Chris@49
|
4211 {
|
Chris@49
|
4212 memory::release(values);
|
Chris@49
|
4213 memory::release(row_indices);
|
Chris@49
|
4214 }
|
Chris@49
|
4215
|
Chris@49
|
4216 access::rw(values) = memory::acquire_chunked<eT> (x.n_nonzero + 1);
|
Chris@49
|
4217 access::rw(row_indices) = memory::acquire_chunked<uword>(x.n_nonzero + 1);
|
Chris@49
|
4218
|
Chris@49
|
4219 arrayops::copy(access::rwp(row_indices), x.row_indices, x.n_nonzero + 1);
|
Chris@49
|
4220 arrayops::copy(access::rwp(col_ptrs), x.col_ptrs, x.n_cols + 1);
|
Chris@49
|
4221
|
Chris@49
|
4222 access::rw(n_nonzero) = x.n_nonzero;
|
Chris@49
|
4223 }
|
Chris@49
|
4224
|
Chris@49
|
4225
|
Chris@49
|
4226 // initialise the elements array with a transformed version of the elements from x
|
Chris@49
|
4227
|
Chris@49
|
4228 const uword nnz = n_nonzero;
|
Chris@49
|
4229
|
Chris@49
|
4230 const eT2* x_values = x.values;
|
Chris@49
|
4231 eT* t_values = access::rwp(values);
|
Chris@49
|
4232
|
Chris@49
|
4233 for(uword i=0; i < nnz; ++i)
|
Chris@49
|
4234 {
|
Chris@49
|
4235 t_values[i] = func(x_values[i]); // NOTE: func() must produce a value of type eT (ie. act as a convertor between eT2 and eT)
|
Chris@49
|
4236 }
|
Chris@49
|
4237 }
|
Chris@49
|
4238 else
|
Chris@49
|
4239 {
|
Chris@49
|
4240 init(P.get_n_rows(), P.get_n_cols());
|
Chris@49
|
4241
|
Chris@49
|
4242 mem_resize(P.get_n_nonzero());
|
Chris@49
|
4243
|
Chris@49
|
4244 typename SpProxy<T1>::const_iterator_type it = P.begin();
|
Chris@49
|
4245
|
Chris@49
|
4246 while(it != P.end())
|
Chris@49
|
4247 {
|
Chris@49
|
4248 access::rw(row_indices[it.pos()]) = it.row();
|
Chris@49
|
4249 access::rw(values[it.pos()]) = func(*it); // NOTE: func() must produce a value of type eT (ie. act as a convertor between eT2 and eT)
|
Chris@49
|
4250 ++access::rw(col_ptrs[it.col() + 1]);
|
Chris@49
|
4251 ++it;
|
Chris@49
|
4252 }
|
Chris@49
|
4253
|
Chris@49
|
4254 // Now sum column pointers.
|
Chris@49
|
4255 for(uword c = 1; c <= n_cols; ++c)
|
Chris@49
|
4256 {
|
Chris@49
|
4257 access::rw(col_ptrs[c]) += col_ptrs[c - 1];
|
Chris@49
|
4258 }
|
Chris@49
|
4259 }
|
Chris@49
|
4260 }
|
Chris@49
|
4261
|
Chris@49
|
4262
|
Chris@49
|
4263
|
Chris@49
|
4264 template<typename eT>
|
Chris@49
|
4265 inline
|
Chris@49
|
4266 typename SpMat<eT>::iterator
|
Chris@49
|
4267 SpMat<eT>::begin()
|
Chris@49
|
4268 {
|
Chris@49
|
4269 return iterator(*this);
|
Chris@49
|
4270 }
|
Chris@49
|
4271
|
Chris@49
|
4272
|
Chris@49
|
4273
|
Chris@49
|
4274 template<typename eT>
|
Chris@49
|
4275 inline
|
Chris@49
|
4276 typename SpMat<eT>::const_iterator
|
Chris@49
|
4277 SpMat<eT>::begin() const
|
Chris@49
|
4278 {
|
Chris@49
|
4279 return const_iterator(*this);
|
Chris@49
|
4280 }
|
Chris@49
|
4281
|
Chris@49
|
4282
|
Chris@49
|
4283
|
Chris@49
|
4284 template<typename eT>
|
Chris@49
|
4285 inline
|
Chris@49
|
4286 typename SpMat<eT>::iterator
|
Chris@49
|
4287 SpMat<eT>::end()
|
Chris@49
|
4288 {
|
Chris@49
|
4289 return iterator(*this, 0, n_cols, n_nonzero);
|
Chris@49
|
4290 }
|
Chris@49
|
4291
|
Chris@49
|
4292
|
Chris@49
|
4293
|
Chris@49
|
4294 template<typename eT>
|
Chris@49
|
4295 inline
|
Chris@49
|
4296 typename SpMat<eT>::const_iterator
|
Chris@49
|
4297 SpMat<eT>::end() const
|
Chris@49
|
4298 {
|
Chris@49
|
4299 return const_iterator(*this, 0, n_cols, n_nonzero);
|
Chris@49
|
4300 }
|
Chris@49
|
4301
|
Chris@49
|
4302
|
Chris@49
|
4303
|
Chris@49
|
4304 template<typename eT>
|
Chris@49
|
4305 inline
|
Chris@49
|
4306 typename SpMat<eT>::iterator
|
Chris@49
|
4307 SpMat<eT>::begin_col(const uword col_num)
|
Chris@49
|
4308 {
|
Chris@49
|
4309 return iterator(*this, 0, col_num);
|
Chris@49
|
4310 }
|
Chris@49
|
4311
|
Chris@49
|
4312
|
Chris@49
|
4313
|
Chris@49
|
4314 template<typename eT>
|
Chris@49
|
4315 inline
|
Chris@49
|
4316 typename SpMat<eT>::const_iterator
|
Chris@49
|
4317 SpMat<eT>::begin_col(const uword col_num) const
|
Chris@49
|
4318 {
|
Chris@49
|
4319 return const_iterator(*this, 0, col_num);
|
Chris@49
|
4320 }
|
Chris@49
|
4321
|
Chris@49
|
4322
|
Chris@49
|
4323
|
Chris@49
|
4324 template<typename eT>
|
Chris@49
|
4325 inline
|
Chris@49
|
4326 typename SpMat<eT>::iterator
|
Chris@49
|
4327 SpMat<eT>::end_col(const uword col_num)
|
Chris@49
|
4328 {
|
Chris@49
|
4329 return iterator(*this, 0, col_num + 1);
|
Chris@49
|
4330 }
|
Chris@49
|
4331
|
Chris@49
|
4332
|
Chris@49
|
4333
|
Chris@49
|
4334 template<typename eT>
|
Chris@49
|
4335 inline
|
Chris@49
|
4336 typename SpMat<eT>::const_iterator
|
Chris@49
|
4337 SpMat<eT>::end_col(const uword col_num) const
|
Chris@49
|
4338 {
|
Chris@49
|
4339 return const_iterator(*this, 0, col_num + 1);
|
Chris@49
|
4340 }
|
Chris@49
|
4341
|
Chris@49
|
4342
|
Chris@49
|
4343
|
Chris@49
|
4344 template<typename eT>
|
Chris@49
|
4345 inline
|
Chris@49
|
4346 typename SpMat<eT>::row_iterator
|
Chris@49
|
4347 SpMat<eT>::begin_row(const uword row_num)
|
Chris@49
|
4348 {
|
Chris@49
|
4349 return row_iterator(*this, row_num, 0);
|
Chris@49
|
4350 }
|
Chris@49
|
4351
|
Chris@49
|
4352
|
Chris@49
|
4353
|
Chris@49
|
4354 template<typename eT>
|
Chris@49
|
4355 inline
|
Chris@49
|
4356 typename SpMat<eT>::const_row_iterator
|
Chris@49
|
4357 SpMat<eT>::begin_row(const uword row_num) const
|
Chris@49
|
4358 {
|
Chris@49
|
4359 return const_row_iterator(*this, row_num, 0);
|
Chris@49
|
4360 }
|
Chris@49
|
4361
|
Chris@49
|
4362
|
Chris@49
|
4363
|
Chris@49
|
4364 template<typename eT>
|
Chris@49
|
4365 inline
|
Chris@49
|
4366 typename SpMat<eT>::row_iterator
|
Chris@49
|
4367 SpMat<eT>::end_row()
|
Chris@49
|
4368 {
|
Chris@49
|
4369 return row_iterator(*this, n_nonzero);
|
Chris@49
|
4370 }
|
Chris@49
|
4371
|
Chris@49
|
4372
|
Chris@49
|
4373
|
Chris@49
|
4374 template<typename eT>
|
Chris@49
|
4375 inline
|
Chris@49
|
4376 typename SpMat<eT>::const_row_iterator
|
Chris@49
|
4377 SpMat<eT>::end_row() const
|
Chris@49
|
4378 {
|
Chris@49
|
4379 return const_row_iterator(*this, n_nonzero);
|
Chris@49
|
4380 }
|
Chris@49
|
4381
|
Chris@49
|
4382
|
Chris@49
|
4383
|
Chris@49
|
4384 template<typename eT>
|
Chris@49
|
4385 inline
|
Chris@49
|
4386 typename SpMat<eT>::row_iterator
|
Chris@49
|
4387 SpMat<eT>::end_row(const uword row_num)
|
Chris@49
|
4388 {
|
Chris@49
|
4389 return row_iterator(*this, row_num + 1, 0);
|
Chris@49
|
4390 }
|
Chris@49
|
4391
|
Chris@49
|
4392
|
Chris@49
|
4393
|
Chris@49
|
4394 template<typename eT>
|
Chris@49
|
4395 inline
|
Chris@49
|
4396 typename SpMat<eT>::const_row_iterator
|
Chris@49
|
4397 SpMat<eT>::end_row(const uword row_num) const
|
Chris@49
|
4398 {
|
Chris@49
|
4399 return const_row_iterator(*this, row_num + 1, 0);
|
Chris@49
|
4400 }
|
Chris@49
|
4401
|
Chris@49
|
4402
|
Chris@49
|
4403
|
Chris@49
|
4404 template<typename eT>
|
Chris@49
|
4405 inline
|
Chris@49
|
4406 void
|
Chris@49
|
4407 SpMat<eT>::clear()
|
Chris@49
|
4408 {
|
Chris@49
|
4409 if (values)
|
Chris@49
|
4410 {
|
Chris@49
|
4411 memory::release(values);
|
Chris@49
|
4412 memory::release(row_indices);
|
Chris@49
|
4413
|
Chris@49
|
4414 access::rw(values) = memory::acquire_chunked<eT> (1);
|
Chris@49
|
4415 access::rw(row_indices) = memory::acquire_chunked<uword>(1);
|
Chris@49
|
4416
|
Chris@49
|
4417 access::rw(values[0]) = 0;
|
Chris@49
|
4418 access::rw(row_indices[0]) = 0;
|
Chris@49
|
4419 }
|
Chris@49
|
4420
|
Chris@49
|
4421 memory::release(col_ptrs);
|
Chris@49
|
4422
|
Chris@49
|
4423 access::rw(col_ptrs) = memory::acquire<uword>(n_cols + 2);
|
Chris@49
|
4424 access::rw(col_ptrs[n_cols + 1]) = std::numeric_limits<uword>::max();
|
Chris@49
|
4425
|
Chris@49
|
4426 arrayops::inplace_set(col_ptrs, eT(0), n_cols + 1);
|
Chris@49
|
4427
|
Chris@49
|
4428 access::rw(n_nonzero) = 0;
|
Chris@49
|
4429 }
|
Chris@49
|
4430
|
Chris@49
|
4431
|
Chris@49
|
4432
|
Chris@49
|
4433 template<typename eT>
|
Chris@49
|
4434 inline
|
Chris@49
|
4435 bool
|
Chris@49
|
4436 SpMat<eT>::empty() const
|
Chris@49
|
4437 {
|
Chris@49
|
4438 return (n_elem == 0);
|
Chris@49
|
4439 }
|
Chris@49
|
4440
|
Chris@49
|
4441
|
Chris@49
|
4442
|
Chris@49
|
4443 template<typename eT>
|
Chris@49
|
4444 inline
|
Chris@49
|
4445 uword
|
Chris@49
|
4446 SpMat<eT>::size() const
|
Chris@49
|
4447 {
|
Chris@49
|
4448 return n_elem;
|
Chris@49
|
4449 }
|
Chris@49
|
4450
|
Chris@49
|
4451
|
Chris@49
|
4452
|
Chris@49
|
4453 template<typename eT>
|
Chris@49
|
4454 inline
|
Chris@49
|
4455 arma_hot
|
Chris@49
|
4456 arma_warn_unused
|
Chris@49
|
4457 SpValProxy<SpMat<eT> >
|
Chris@49
|
4458 SpMat<eT>::get_value(const uword i)
|
Chris@49
|
4459 {
|
Chris@49
|
4460 // First convert to the actual location.
|
Chris@49
|
4461 uword lcol = i / n_rows; // Integer division.
|
Chris@49
|
4462 uword lrow = i % n_rows;
|
Chris@49
|
4463
|
Chris@49
|
4464 return get_value(lrow, lcol);
|
Chris@49
|
4465 }
|
Chris@49
|
4466
|
Chris@49
|
4467
|
Chris@49
|
4468
|
Chris@49
|
4469 template<typename eT>
|
Chris@49
|
4470 inline
|
Chris@49
|
4471 arma_hot
|
Chris@49
|
4472 arma_warn_unused
|
Chris@49
|
4473 eT
|
Chris@49
|
4474 SpMat<eT>::get_value(const uword i) const
|
Chris@49
|
4475 {
|
Chris@49
|
4476 // First convert to the actual location.
|
Chris@49
|
4477 uword lcol = i / n_rows; // Integer division.
|
Chris@49
|
4478 uword lrow = i % n_rows;
|
Chris@49
|
4479
|
Chris@49
|
4480 return get_value(lrow, lcol);
|
Chris@49
|
4481 }
|
Chris@49
|
4482
|
Chris@49
|
4483
|
Chris@49
|
4484
|
Chris@49
|
4485 template<typename eT>
|
Chris@49
|
4486 inline
|
Chris@49
|
4487 arma_hot
|
Chris@49
|
4488 arma_warn_unused
|
Chris@49
|
4489 SpValProxy<SpMat<eT> >
|
Chris@49
|
4490 SpMat<eT>::get_value(const uword in_row, const uword in_col)
|
Chris@49
|
4491 {
|
Chris@49
|
4492 const uword colptr = col_ptrs[in_col];
|
Chris@49
|
4493 const uword next_colptr = col_ptrs[in_col + 1];
|
Chris@49
|
4494
|
Chris@49
|
4495 // Step through the row indices to see if our element exists.
|
Chris@49
|
4496 for (uword i = colptr; i < next_colptr; ++i)
|
Chris@49
|
4497 {
|
Chris@49
|
4498 const uword row_index = row_indices[i];
|
Chris@49
|
4499
|
Chris@49
|
4500 // First check that we have not stepped past it.
|
Chris@49
|
4501 if (in_row < row_index) // If we have, then it doesn't exist: return 0.
|
Chris@49
|
4502 {
|
Chris@49
|
4503 return SpValProxy<SpMat<eT> >(in_row, in_col, *this); // Proxy for a zero value.
|
Chris@49
|
4504 }
|
Chris@49
|
4505
|
Chris@49
|
4506 // Now check if we are at the correct place.
|
Chris@49
|
4507 if (in_row == row_index) // If we are, return a reference to the value.
|
Chris@49
|
4508 {
|
Chris@49
|
4509 return SpValProxy<SpMat<eT> >(in_row, in_col, *this, &access::rw(values[i]));
|
Chris@49
|
4510 }
|
Chris@49
|
4511
|
Chris@49
|
4512 }
|
Chris@49
|
4513
|
Chris@49
|
4514 // We did not find it, so it does not exist: return 0.
|
Chris@49
|
4515 return SpValProxy<SpMat<eT> >(in_row, in_col, *this);
|
Chris@49
|
4516 }
|
Chris@49
|
4517
|
Chris@49
|
4518
|
Chris@49
|
4519
|
Chris@49
|
4520 template<typename eT>
|
Chris@49
|
4521 inline
|
Chris@49
|
4522 arma_hot
|
Chris@49
|
4523 arma_warn_unused
|
Chris@49
|
4524 eT
|
Chris@49
|
4525 SpMat<eT>::get_value(const uword in_row, const uword in_col) const
|
Chris@49
|
4526 {
|
Chris@49
|
4527 const uword colptr = col_ptrs[in_col];
|
Chris@49
|
4528 const uword next_colptr = col_ptrs[in_col + 1];
|
Chris@49
|
4529
|
Chris@49
|
4530 // Step through the row indices to see if our element exists.
|
Chris@49
|
4531 for (uword i = colptr; i < next_colptr; ++i)
|
Chris@49
|
4532 {
|
Chris@49
|
4533 const uword row_index = row_indices[i];
|
Chris@49
|
4534
|
Chris@49
|
4535 // First check that we have not stepped past it.
|
Chris@49
|
4536 if (in_row < row_index) // If we have, then it doesn't exist: return 0.
|
Chris@49
|
4537 {
|
Chris@49
|
4538 return eT(0);
|
Chris@49
|
4539 }
|
Chris@49
|
4540
|
Chris@49
|
4541 // Now check if we are at the correct place.
|
Chris@49
|
4542 if (in_row == row_index) // If we are, return the value.
|
Chris@49
|
4543 {
|
Chris@49
|
4544 return values[i];
|
Chris@49
|
4545 }
|
Chris@49
|
4546 }
|
Chris@49
|
4547
|
Chris@49
|
4548 // We did not find it, so it does not exist: return 0.
|
Chris@49
|
4549 return eT(0);
|
Chris@49
|
4550 }
|
Chris@49
|
4551
|
Chris@49
|
4552
|
Chris@49
|
4553
|
Chris@49
|
4554 /**
|
Chris@49
|
4555 * Given the index representing which of the nonzero values this is, return its
|
Chris@49
|
4556 * actual location, either in row/col or just the index.
|
Chris@49
|
4557 */
|
Chris@49
|
4558 template<typename eT>
|
Chris@49
|
4559 arma_hot
|
Chris@49
|
4560 arma_inline
|
Chris@49
|
4561 arma_warn_unused
|
Chris@49
|
4562 uword
|
Chris@49
|
4563 SpMat<eT>::get_position(const uword i) const
|
Chris@49
|
4564 {
|
Chris@49
|
4565 uword lrow, lcol;
|
Chris@49
|
4566
|
Chris@49
|
4567 get_position(i, lrow, lcol);
|
Chris@49
|
4568
|
Chris@49
|
4569 // Assemble the row/col into the element's location in the matrix.
|
Chris@49
|
4570 return (lrow + n_rows * lcol);
|
Chris@49
|
4571 }
|
Chris@49
|
4572
|
Chris@49
|
4573
|
Chris@49
|
4574
|
Chris@49
|
4575 template<typename eT>
|
Chris@49
|
4576 arma_hot
|
Chris@49
|
4577 arma_inline
|
Chris@49
|
4578 void
|
Chris@49
|
4579 SpMat<eT>::get_position(const uword i, uword& row_of_i, uword& col_of_i) const
|
Chris@49
|
4580 {
|
Chris@49
|
4581 arma_debug_check((i >= n_nonzero), "SpMat::get_position(): index out of bounds");
|
Chris@49
|
4582
|
Chris@49
|
4583 col_of_i = 0;
|
Chris@49
|
4584 while (col_ptrs[col_of_i + 1] <= i)
|
Chris@49
|
4585 {
|
Chris@49
|
4586 col_of_i++;
|
Chris@49
|
4587 }
|
Chris@49
|
4588
|
Chris@49
|
4589 row_of_i = row_indices[i];
|
Chris@49
|
4590
|
Chris@49
|
4591 return;
|
Chris@49
|
4592 }
|
Chris@49
|
4593
|
Chris@49
|
4594
|
Chris@49
|
4595
|
Chris@49
|
4596 /**
|
Chris@49
|
4597 * Add an element at the given position, and return a reference to it. The
|
Chris@49
|
4598 * element will be set to 0 (unless otherwise specified). If the element
|
Chris@49
|
4599 * already exists, its value will be overwritten.
|
Chris@49
|
4600 *
|
Chris@49
|
4601 * @param in_row Row of new element.
|
Chris@49
|
4602 * @param in_col Column of new element.
|
Chris@49
|
4603 * @param in_val Value to set new element to (default 0.0).
|
Chris@49
|
4604 */
|
Chris@49
|
4605 template<typename eT>
|
Chris@49
|
4606 inline
|
Chris@49
|
4607 arma_hot
|
Chris@49
|
4608 arma_warn_unused
|
Chris@49
|
4609 eT&
|
Chris@49
|
4610 SpMat<eT>::add_element(const uword in_row, const uword in_col, const eT val)
|
Chris@49
|
4611 {
|
Chris@49
|
4612 arma_extra_debug_sigprint();
|
Chris@49
|
4613
|
Chris@49
|
4614 // We will assume the new element does not exist and begin the search for
|
Chris@49
|
4615 // where to insert it. If we find that it already exists, we will then
|
Chris@49
|
4616 // overwrite it.
|
Chris@49
|
4617 uword colptr = col_ptrs[in_col ];
|
Chris@49
|
4618 uword next_colptr = col_ptrs[in_col + 1];
|
Chris@49
|
4619
|
Chris@49
|
4620 uword pos = colptr; // The position in the matrix of this value.
|
Chris@49
|
4621
|
Chris@49
|
4622 if (colptr != next_colptr)
|
Chris@49
|
4623 {
|
Chris@49
|
4624 // There are other elements in this column, so we must find where this
|
Chris@49
|
4625 // element will fit as compared to those.
|
Chris@49
|
4626 while (pos < next_colptr && in_row > row_indices[pos])
|
Chris@49
|
4627 {
|
Chris@49
|
4628 pos++;
|
Chris@49
|
4629 }
|
Chris@49
|
4630
|
Chris@49
|
4631 // We aren't inserting into the last position, so it is still possible
|
Chris@49
|
4632 // that the element may exist.
|
Chris@49
|
4633 if (pos != next_colptr && row_indices[pos] == in_row)
|
Chris@49
|
4634 {
|
Chris@49
|
4635 // It already exists. Then, just overwrite it.
|
Chris@49
|
4636 access::rw(values[pos]) = val;
|
Chris@49
|
4637
|
Chris@49
|
4638 return access::rw(values[pos]);
|
Chris@49
|
4639 }
|
Chris@49
|
4640 }
|
Chris@49
|
4641
|
Chris@49
|
4642
|
Chris@49
|
4643 //
|
Chris@49
|
4644 // Element doesn't exist, so we have to insert it
|
Chris@49
|
4645 //
|
Chris@49
|
4646
|
Chris@49
|
4647 // We have to update the rest of the column pointers.
|
Chris@49
|
4648 for (uword i = in_col + 1; i < n_cols + 1; i++)
|
Chris@49
|
4649 {
|
Chris@49
|
4650 access::rw(col_ptrs[i])++; // We are only inserting one new element.
|
Chris@49
|
4651 }
|
Chris@49
|
4652
|
Chris@49
|
4653
|
Chris@49
|
4654 // Figure out the actual amount of memory currently allocated
|
Chris@49
|
4655 // NOTE: this relies on memory::acquire_chunked() being used for the 'values' and 'row_indices' arrays
|
Chris@49
|
4656 const uword n_alloc = memory::enlarge_to_mult_of_chunksize(n_nonzero + 1);
|
Chris@49
|
4657
|
Chris@49
|
4658 // If possible, avoid time-consuming memory allocation
|
Chris@49
|
4659 if(n_alloc > (n_nonzero + 1))
|
Chris@49
|
4660 {
|
Chris@49
|
4661 arrayops::copy_backwards(access::rwp(values) + pos + 1, values + pos, (n_nonzero - pos) + 1);
|
Chris@49
|
4662 arrayops::copy_backwards(access::rwp(row_indices) + pos + 1, row_indices + pos, (n_nonzero - pos) + 1);
|
Chris@49
|
4663
|
Chris@49
|
4664 // Insert the new element.
|
Chris@49
|
4665 access::rw(values[pos]) = val;
|
Chris@49
|
4666 access::rw(row_indices[pos]) = in_row;
|
Chris@49
|
4667
|
Chris@49
|
4668 access::rw(n_nonzero)++;
|
Chris@49
|
4669 }
|
Chris@49
|
4670 else
|
Chris@49
|
4671 {
|
Chris@49
|
4672 const uword old_n_nonzero = n_nonzero;
|
Chris@49
|
4673
|
Chris@49
|
4674 access::rw(n_nonzero)++; // Add to count of nonzero elements.
|
Chris@49
|
4675
|
Chris@49
|
4676 // Allocate larger memory.
|
Chris@49
|
4677 eT* new_values = memory::acquire_chunked<eT> (n_nonzero + 1);
|
Chris@49
|
4678 uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero + 1);
|
Chris@49
|
4679
|
Chris@49
|
4680 // Copy things over, before the new element.
|
Chris@49
|
4681 if (pos > 0)
|
Chris@49
|
4682 {
|
Chris@49
|
4683 arrayops::copy(new_values, values, pos);
|
Chris@49
|
4684 arrayops::copy(new_row_indices, row_indices, pos);
|
Chris@49
|
4685 }
|
Chris@49
|
4686
|
Chris@49
|
4687 // Insert the new element.
|
Chris@49
|
4688 new_values[pos] = val;
|
Chris@49
|
4689 new_row_indices[pos] = in_row;
|
Chris@49
|
4690
|
Chris@49
|
4691 // Copy the rest of things over (including the extra element at the end).
|
Chris@49
|
4692 arrayops::copy(new_values + pos + 1, values + pos, (old_n_nonzero - pos) + 1);
|
Chris@49
|
4693 arrayops::copy(new_row_indices + pos + 1, row_indices + pos, (old_n_nonzero - pos) + 1);
|
Chris@49
|
4694
|
Chris@49
|
4695 // Assign new pointers.
|
Chris@49
|
4696 memory::release(values);
|
Chris@49
|
4697 memory::release(row_indices);
|
Chris@49
|
4698
|
Chris@49
|
4699 access::rw(values) = new_values;
|
Chris@49
|
4700 access::rw(row_indices) = new_row_indices;
|
Chris@49
|
4701 }
|
Chris@49
|
4702
|
Chris@49
|
4703 return access::rw(values[pos]);
|
Chris@49
|
4704 }
|
Chris@49
|
4705
|
Chris@49
|
4706
|
Chris@49
|
4707
|
Chris@49
|
4708 /**
|
Chris@49
|
4709 * Delete an element at the given position.
|
Chris@49
|
4710 *
|
Chris@49
|
4711 * @param in_row Row of element to be deleted.
|
Chris@49
|
4712 * @param in_col Column of element to be deleted.
|
Chris@49
|
4713 */
|
Chris@49
|
4714 template<typename eT>
|
Chris@49
|
4715 inline
|
Chris@49
|
4716 arma_hot
|
Chris@49
|
4717 void
|
Chris@49
|
4718 SpMat<eT>::delete_element(const uword in_row, const uword in_col)
|
Chris@49
|
4719 {
|
Chris@49
|
4720 arma_extra_debug_sigprint();
|
Chris@49
|
4721
|
Chris@49
|
4722 // We assume the element exists (although... it may not) and look for its
|
Chris@49
|
4723 // exact position. If it doesn't exist... well, we don't need to do anything.
|
Chris@49
|
4724 uword colptr = col_ptrs[in_col];
|
Chris@49
|
4725 uword next_colptr = col_ptrs[in_col + 1];
|
Chris@49
|
4726
|
Chris@49
|
4727 if (colptr != next_colptr)
|
Chris@49
|
4728 {
|
Chris@49
|
4729 // There's at least one element in this column.
|
Chris@49
|
4730 // Let's see if we are one of them.
|
Chris@49
|
4731 for (uword pos = colptr; pos < next_colptr; pos++)
|
Chris@49
|
4732 {
|
Chris@49
|
4733 if (in_row == row_indices[pos])
|
Chris@49
|
4734 {
|
Chris@49
|
4735 const uword old_n_nonzero = n_nonzero;
|
Chris@49
|
4736
|
Chris@49
|
4737 --access::rw(n_nonzero); // Remove one from the count of nonzero elements.
|
Chris@49
|
4738
|
Chris@49
|
4739 // Found it. Now remove it.
|
Chris@49
|
4740
|
Chris@49
|
4741 // Figure out the actual amount of memory currently allocated and the actual amount that will be required
|
Chris@49
|
4742 // NOTE: this relies on memory::acquire_chunked() being used for the 'values' and 'row_indices' arrays
|
Chris@49
|
4743
|
Chris@49
|
4744 const uword n_alloc = memory::enlarge_to_mult_of_chunksize(old_n_nonzero + 1);
|
Chris@49
|
4745 const uword n_alloc_mod = memory::enlarge_to_mult_of_chunksize(n_nonzero + 1);
|
Chris@49
|
4746
|
Chris@49
|
4747 // If possible, avoid time-consuming memory allocation
|
Chris@49
|
4748 if(n_alloc_mod == n_alloc)
|
Chris@49
|
4749 {
|
Chris@49
|
4750 if (pos < n_nonzero) // remember, we decremented n_nonzero
|
Chris@49
|
4751 {
|
Chris@49
|
4752 arrayops::copy_forwards(access::rwp(values) + pos, values + pos + 1, (n_nonzero - pos) + 1);
|
Chris@49
|
4753 arrayops::copy_forwards(access::rwp(row_indices) + pos, row_indices + pos + 1, (n_nonzero - pos) + 1);
|
Chris@49
|
4754 }
|
Chris@49
|
4755 }
|
Chris@49
|
4756 else
|
Chris@49
|
4757 {
|
Chris@49
|
4758 // Make new arrays.
|
Chris@49
|
4759 eT* new_values = memory::acquire_chunked<eT> (n_nonzero + 1);
|
Chris@49
|
4760 uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero + 1);
|
Chris@49
|
4761
|
Chris@49
|
4762 if (pos > 0)
|
Chris@49
|
4763 {
|
Chris@49
|
4764 arrayops::copy(new_values, values, pos);
|
Chris@49
|
4765 arrayops::copy(new_row_indices, row_indices, pos);
|
Chris@49
|
4766 }
|
Chris@49
|
4767
|
Chris@49
|
4768 arrayops::copy(new_values + pos, values + pos + 1, (n_nonzero - pos) + 1);
|
Chris@49
|
4769 arrayops::copy(new_row_indices + pos, row_indices + pos + 1, (n_nonzero - pos) + 1);
|
Chris@49
|
4770
|
Chris@49
|
4771 memory::release(values);
|
Chris@49
|
4772 memory::release(row_indices);
|
Chris@49
|
4773
|
Chris@49
|
4774 access::rw(values) = new_values;
|
Chris@49
|
4775 access::rw(row_indices) = new_row_indices;
|
Chris@49
|
4776 }
|
Chris@49
|
4777
|
Chris@49
|
4778 // And lastly, update all the column pointers (decrement by one).
|
Chris@49
|
4779 for (uword i = in_col + 1; i < n_cols + 1; i++)
|
Chris@49
|
4780 {
|
Chris@49
|
4781 --access::rw(col_ptrs[i]); // We only removed one element.
|
Chris@49
|
4782 }
|
Chris@49
|
4783
|
Chris@49
|
4784 return; // There is nothing left to do.
|
Chris@49
|
4785 }
|
Chris@49
|
4786 }
|
Chris@49
|
4787 }
|
Chris@49
|
4788
|
Chris@49
|
4789 return; // The element does not exist, so there's nothing for us to do.
|
Chris@49
|
4790 }
|
Chris@49
|
4791
|
Chris@49
|
4792
|
Chris@49
|
4793
|
Chris@49
|
4794 #ifdef ARMA_EXTRA_SPMAT_MEAT
|
Chris@49
|
4795 #include ARMA_INCFILE_WRAP(ARMA_EXTRA_SPMAT_MEAT)
|
Chris@49
|
4796 #endif
|
Chris@49
|
4797
|
Chris@49
|
4798
|
Chris@49
|
4799
|
Chris@49
|
4800 //! @}
|