Mercurial > octave-nkf
annotate liboctave/Sparse.cc @ 7573:755bf7ecc29b
eliminate one_zero stuff from idx_vector
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 08 Mar 2008 10:14:37 -0500 |
parents | 4249c6fb6e09 |
children | 36594d5bbe13 |
rev | line source |
---|---|
5164 | 1 // Template sparse array class |
2 /* | |
3 | |
7017 | 4 Copyright (C) 2004, 2005, 2006, 2007 David Bateman |
7016 | 5 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Andy Adler |
6 | |
7 This file is part of Octave. | |
5164 | 8 |
9 Octave is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
7016 | 11 Free Software Foundation; either version 3 of the License, or (at your |
12 option) any later version. | |
5164 | 13 |
14 Octave is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
7016 | 20 along with Octave; see the file COPYING. If not, see |
21 <http://www.gnu.org/licenses/>. | |
5164 | 22 |
23 */ | |
24 | |
25 #ifdef HAVE_CONFIG_H | |
26 #include <config.h> | |
27 #endif | |
28 | |
29 #include <cassert> | |
30 #include <climits> | |
31 | |
32 #include <iostream> | |
5765 | 33 #include <sstream> |
5164 | 34 #include <vector> |
35 | |
36 #include "Array.h" | |
37 #include "Array-util.h" | |
38 #include "Range.h" | |
39 #include "idx-vector.h" | |
40 #include "lo-error.h" | |
41 #include "quit.h" | |
42 | |
43 #include "Sparse.h" | |
44 #include "sparse-sort.h" | |
45 #include "oct-spparms.h" | |
46 | |
47 template <class T> | |
48 T& | |
5275 | 49 Sparse<T>::SparseRep::elem (octave_idx_type _r, octave_idx_type _c) |
5164 | 50 { |
5275 | 51 octave_idx_type i; |
5164 | 52 |
5604 | 53 if (nzmx > 0) |
5164 | 54 { |
55 for (i = c[_c]; i < c[_c + 1]; i++) | |
56 if (r[i] == _r) | |
57 return d[i]; | |
58 else if (r[i] > _r) | |
59 break; | |
60 | |
61 // Ok, If we've gotten here, we're in trouble.. Have to create a | |
62 // new element in the sparse array. This' gonna be slow!!! | |
5869 | 63 if (c[ncols] == nzmx) |
5164 | 64 { |
65 (*current_liboctave_error_handler) | |
5275 | 66 ("Sparse::SparseRep::elem (octave_idx_type, octave_idx_type): sparse matrix filled"); |
5164 | 67 return *d; |
68 } | |
69 | |
5275 | 70 octave_idx_type to_move = c[ncols] - i; |
5164 | 71 if (to_move != 0) |
72 { | |
5275 | 73 for (octave_idx_type j = c[ncols]; j > i; j--) |
5164 | 74 { |
75 d[j] = d[j-1]; | |
76 r[j] = r[j-1]; | |
77 } | |
78 } | |
79 | |
5275 | 80 for (octave_idx_type j = _c + 1; j < ncols + 1; j++) |
5164 | 81 c[j] = c[j] + 1; |
82 | |
83 d[i] = 0.; | |
84 r[i] = _r; | |
85 | |
86 return d[i]; | |
87 } | |
88 else | |
89 { | |
90 (*current_liboctave_error_handler) | |
5275 | 91 ("Sparse::SparseRep::elem (octave_idx_type, octave_idx_type): sparse matrix filled"); |
5164 | 92 return *d; |
93 } | |
94 } | |
95 | |
96 template <class T> | |
97 T | |
5275 | 98 Sparse<T>::SparseRep::celem (octave_idx_type _r, octave_idx_type _c) const |
5164 | 99 { |
5604 | 100 if (nzmx > 0) |
5275 | 101 for (octave_idx_type i = c[_c]; i < c[_c + 1]; i++) |
5164 | 102 if (r[i] == _r) |
103 return d[i]; | |
104 return T (); | |
105 } | |
106 | |
107 template <class T> | |
108 void | |
109 Sparse<T>::SparseRep::maybe_compress (bool remove_zeros) | |
110 { | |
5604 | 111 octave_idx_type ndel = nzmx - c[ncols]; |
5275 | 112 octave_idx_type nzero = 0; |
5164 | 113 |
114 if (remove_zeros) | |
5604 | 115 for (octave_idx_type i = 0; i < nzmx - ndel; i++) |
5164 | 116 if (d[i] == T ()) |
117 nzero++; | |
118 | |
119 if (!ndel && !nzero) | |
120 return; | |
121 | |
122 if (!nzero) | |
123 { | |
5604 | 124 octave_idx_type new_nzmx = nzmx - ndel; |
125 | |
126 T *new_data = new T [new_nzmx]; | |
127 for (octave_idx_type i = 0; i < new_nzmx; i++) | |
5164 | 128 new_data[i] = d[i]; |
129 delete [] d; | |
130 d = new_data; | |
131 | |
5604 | 132 octave_idx_type *new_ridx = new octave_idx_type [new_nzmx]; |
133 for (octave_idx_type i = 0; i < new_nzmx; i++) | |
5164 | 134 new_ridx[i] = r[i]; |
135 delete [] r; | |
136 r = new_ridx; | |
137 } | |
138 else | |
139 { | |
5604 | 140 octave_idx_type new_nzmx = nzmx - ndel - nzero; |
141 | |
142 T *new_data = new T [new_nzmx]; | |
143 octave_idx_type *new_ridx = new octave_idx_type [new_nzmx]; | |
5275 | 144 |
145 octave_idx_type ii = 0; | |
146 octave_idx_type ic = 0; | |
147 for (octave_idx_type j = 0; j < ncols; j++) | |
5164 | 148 { |
5275 | 149 for (octave_idx_type k = ic; k < c[j+1]; k++) |
5164 | 150 if (d[k] != T ()) |
151 { | |
152 new_data [ii] = d[k]; | |
153 new_ridx [ii++] = r[k]; | |
154 } | |
155 ic = c[j+1]; | |
156 c[j+1] = ii; | |
157 } | |
158 | |
159 delete [] d; | |
160 d = new_data; | |
161 | |
162 delete [] r; | |
163 r = new_ridx; | |
164 } | |
165 | |
5604 | 166 nzmx -= ndel + nzero; |
5164 | 167 } |
168 | |
169 template <class T> | |
170 void | |
5275 | 171 Sparse<T>::SparseRep::change_length (octave_idx_type nz) |
5164 | 172 { |
5604 | 173 if (nz != nzmx) |
5164 | 174 { |
5604 | 175 octave_idx_type min_nzmx = (nz < nzmx ? nz : nzmx); |
5275 | 176 |
177 octave_idx_type * new_ridx = new octave_idx_type [nz]; | |
5604 | 178 for (octave_idx_type i = 0; i < min_nzmx; i++) |
5164 | 179 new_ridx[i] = r[i]; |
180 | |
181 delete [] r; | |
182 r = new_ridx; | |
183 | |
184 T * new_data = new T [nz]; | |
5604 | 185 for (octave_idx_type i = 0; i < min_nzmx; i++) |
5164 | 186 new_data[i] = d[i]; |
187 | |
188 delete [] d; | |
189 d = new_data; | |
190 | |
5604 | 191 if (nz < nzmx) |
5275 | 192 for (octave_idx_type i = 0; i <= ncols; i++) |
5164 | 193 if (c[i] > nz) |
194 c[i] = nz; | |
195 | |
5604 | 196 nzmx = nz; |
5164 | 197 } |
198 } | |
199 | |
200 template <class T> | |
201 template <class U> | |
202 Sparse<T>::Sparse (const Sparse<U>& a) | |
203 : dimensions (a.dimensions), idx (0), idx_count (0) | |
204 { | |
5681 | 205 if (a.nnz () == 0) |
5164 | 206 rep = new typename Sparse<T>::SparseRep (rows (), cols()); |
207 else | |
208 { | |
5681 | 209 rep = new typename Sparse<T>::SparseRep (rows (), cols (), a.nnz ()); |
5164 | 210 |
5681 | 211 octave_idx_type nz = a.nnz (); |
5275 | 212 octave_idx_type nc = cols (); |
213 for (octave_idx_type i = 0; i < nz; i++) | |
5164 | 214 { |
215 xdata (i) = T (a.data (i)); | |
216 xridx (i) = a.ridx (i); | |
217 } | |
5275 | 218 for (octave_idx_type i = 0; i < nc + 1; i++) |
5164 | 219 xcidx (i) = a.cidx (i); |
220 } | |
221 } | |
222 | |
223 template <class T> | |
5275 | 224 Sparse<T>::Sparse (octave_idx_type nr, octave_idx_type nc, T val) |
5630 | 225 : dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) |
5164 | 226 { |
5630 | 227 if (val != T ()) |
5164 | 228 { |
5630 | 229 rep = new typename Sparse<T>::SparseRep (nr, nc, nr*nc); |
230 | |
231 octave_idx_type ii = 0; | |
232 xcidx (0) = 0; | |
233 for (octave_idx_type j = 0; j < nc; j++) | |
5164 | 234 { |
5630 | 235 for (octave_idx_type i = 0; i < nr; i++) |
236 { | |
237 xdata (ii) = val; | |
238 xridx (ii++) = i; | |
239 } | |
240 xcidx (j+1) = ii; | |
241 } | |
242 } | |
243 else | |
244 { | |
245 rep = new typename Sparse<T>::SparseRep (nr, nc, 0); | |
246 for (octave_idx_type j = 0; j < nc+1; j++) | |
247 xcidx(j) = 0; | |
5164 | 248 } |
249 } | |
250 | |
251 template <class T> | |
252 Sparse<T>::Sparse (const dim_vector& dv) | |
253 : dimensions (dv), idx (0), idx_count (0) | |
254 { | |
255 if (dv.length() != 2) | |
256 (*current_liboctave_error_handler) | |
257 ("Sparse::Sparse (const dim_vector&): dimension mismatch"); | |
258 else | |
259 rep = new typename Sparse<T>::SparseRep (dv(0), dv(1)); | |
260 } | |
261 | |
262 template <class T> | |
263 Sparse<T>::Sparse (const Sparse<T>& a, const dim_vector& dv) | |
264 : dimensions (dv), idx (0), idx_count (0) | |
265 { | |
266 | |
267 // Work in unsigned long long to avoid overflow issues with numel | |
268 unsigned long long a_nel = static_cast<unsigned long long>(a.rows ()) * | |
269 static_cast<unsigned long long>(a.cols ()); | |
270 unsigned long long dv_nel = static_cast<unsigned long long>(dv (0)) * | |
271 static_cast<unsigned long long>(dv (1)); | |
272 | |
273 if (a_nel != dv_nel) | |
274 (*current_liboctave_error_handler) | |
275 ("Sparse::Sparse (const Sparse&, const dim_vector&): dimension mismatch"); | |
276 else | |
277 { | |
278 dim_vector old_dims = a.dims(); | |
5681 | 279 octave_idx_type new_nzmx = a.nnz (); |
5275 | 280 octave_idx_type new_nr = dv (0); |
281 octave_idx_type new_nc = dv (1); | |
282 octave_idx_type old_nr = old_dims (0); | |
283 octave_idx_type old_nc = old_dims (1); | |
5164 | 284 |
5604 | 285 rep = new typename Sparse<T>::SparseRep (new_nr, new_nc, new_nzmx); |
5164 | 286 |
5275 | 287 octave_idx_type kk = 0; |
5164 | 288 xcidx(0) = 0; |
5275 | 289 for (octave_idx_type i = 0; i < old_nc; i++) |
290 for (octave_idx_type j = a.cidx(i); j < a.cidx(i+1); j++) | |
5164 | 291 { |
5275 | 292 octave_idx_type tmp = i * old_nr + a.ridx(j); |
293 octave_idx_type ii = tmp % new_nr; | |
294 octave_idx_type jj = (tmp - ii) / new_nr; | |
295 for (octave_idx_type k = kk; k < jj; k++) | |
5164 | 296 xcidx(k+1) = j; |
297 kk = jj; | |
298 xdata(j) = a.data(j); | |
299 xridx(j) = ii; | |
300 } | |
5275 | 301 for (octave_idx_type k = kk; k < new_nc; k++) |
5604 | 302 xcidx(k+1) = new_nzmx; |
5164 | 303 } |
304 } | |
305 | |
306 template <class T> | |
5275 | 307 Sparse<T>::Sparse (const Array<T>& a, const Array<octave_idx_type>& r, |
308 const Array<octave_idx_type>& c, octave_idx_type nr, | |
309 octave_idx_type nc, bool sum_terms) | |
5164 | 310 : dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) |
311 { | |
5275 | 312 octave_idx_type a_len = a.length (); |
313 octave_idx_type r_len = r.length (); | |
314 octave_idx_type c_len = c.length (); | |
5164 | 315 bool ri_scalar = (r_len == 1); |
316 bool ci_scalar = (c_len == 1); | |
317 bool cf_scalar = (a_len == 1); | |
318 | |
319 if ((a_len != r_len && !cf_scalar && !ri_scalar) || | |
320 (a_len != c_len && !cf_scalar && !ci_scalar) || | |
321 (r_len != c_len && !ri_scalar && !ci_scalar) || nr < 0 || nc < 0) | |
322 { | |
323 (*current_liboctave_error_handler) | |
5275 | 324 ("Sparse::Sparse (const Array<T>&, const Array<octave_idx_type>&, ...): dimension mismatch"); |
5164 | 325 rep = nil_rep (); |
326 dimensions = dim_vector (0, 0); | |
327 } | |
328 else | |
329 { | |
5604 | 330 octave_idx_type max_nzmx = (r_len > c_len ? r_len : c_len); |
331 | |
332 OCTAVE_LOCAL_BUFFER (octave_sparse_sort_idxl *, sidx, max_nzmx); | |
333 OCTAVE_LOCAL_BUFFER (octave_sparse_sort_idxl, sidxX, max_nzmx); | |
334 | |
335 for (octave_idx_type i = 0; i < max_nzmx; i++) | |
5164 | 336 sidx[i] = &sidxX[i]; |
337 | |
5604 | 338 octave_idx_type actual_nzmx = 0; |
5164 | 339 OCTAVE_QUIT; |
5604 | 340 for (octave_idx_type i = 0; i < max_nzmx; i++) |
5164 | 341 { |
5275 | 342 octave_idx_type rowidx = (ri_scalar ? r(0) : r(i)); |
343 octave_idx_type colidx = (ci_scalar ? c(0) : c(i)); | |
5164 | 344 if (rowidx < nr && rowidx >= 0 && |
345 colidx < nc && colidx >= 0 ) | |
346 { | |
347 if ( a (cf_scalar ? 0 : i ) != T ()) | |
348 { | |
5604 | 349 sidx[actual_nzmx]->r = rowidx; |
350 sidx[actual_nzmx]->c = colidx; | |
351 sidx[actual_nzmx]->idx = i; | |
352 actual_nzmx++; | |
5164 | 353 } |
354 } | |
355 else | |
356 { | |
357 (*current_liboctave_error_handler) | |
358 ("Sparse::Sparse : index (%d,%d) out of range", | |
359 rowidx + 1, colidx + 1); | |
360 rep = nil_rep (); | |
361 dimensions = dim_vector (0, 0); | |
362 return; | |
363 } | |
364 } | |
365 | |
5604 | 366 if (actual_nzmx == 0) |
5164 | 367 rep = new typename Sparse<T>::SparseRep (nr, nc); |
368 else | |
369 { | |
370 OCTAVE_QUIT; | |
371 octave_sort<octave_sparse_sort_idxl *> | |
7433 | 372 lsort (octave_sparse_sidxl_comp); |
373 | |
374 lsort.sort (sidx, actual_nzmx); | |
5164 | 375 OCTAVE_QUIT; |
376 | |
377 // Now count the unique non-zero values | |
5604 | 378 octave_idx_type real_nzmx = 1; |
379 for (octave_idx_type i = 1; i < actual_nzmx; i++) | |
5164 | 380 if (sidx[i-1]->r != sidx[i]->r || sidx[i-1]->c != sidx[i]->c) |
5604 | 381 real_nzmx++; |
382 | |
383 rep = new typename Sparse<T>::SparseRep (nr, nc, real_nzmx); | |
5164 | 384 |
5275 | 385 octave_idx_type cx = 0; |
386 octave_idx_type prev_rval = -1; | |
387 octave_idx_type prev_cval = -1; | |
388 octave_idx_type ii = -1; | |
5164 | 389 xcidx (0) = 0; |
5604 | 390 for (octave_idx_type i = 0; i < actual_nzmx; i++) |
5164 | 391 { |
392 OCTAVE_QUIT; | |
5275 | 393 octave_idx_type iidx = sidx[i]->idx; |
394 octave_idx_type rval = sidx[i]->r; | |
395 octave_idx_type cval = sidx[i]->c; | |
5164 | 396 |
397 if (prev_cval < cval || (prev_rval < rval && prev_cval == cval)) | |
398 { | |
5275 | 399 octave_idx_type ci = static_cast<octave_idx_type> (c (ci_scalar ? 0 : iidx)); |
5164 | 400 ii++; |
401 while (cx < ci) | |
402 xcidx (++cx) = ii; | |
403 xdata(ii) = a (cf_scalar ? 0 : iidx); | |
5275 | 404 xridx(ii) = static_cast<octave_idx_type> (r (ri_scalar ? 0 : iidx)); |
5164 | 405 } |
406 else | |
407 { | |
408 if (sum_terms) | |
409 xdata(ii) += a (cf_scalar ? 0 : iidx); | |
410 else | |
411 xdata(ii) = a (cf_scalar ? 0 : iidx); | |
412 } | |
413 prev_rval = rval; | |
414 prev_cval = cval; | |
415 } | |
416 | |
417 while (cx < nc) | |
418 xcidx (++cx) = ii + 1; | |
419 } | |
420 } | |
421 } | |
422 | |
423 template <class T> | |
424 Sparse<T>::Sparse (const Array<T>& a, const Array<double>& r, | |
5275 | 425 const Array<double>& c, octave_idx_type nr, |
426 octave_idx_type nc, bool sum_terms) | |
5164 | 427 : dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) |
428 { | |
5275 | 429 octave_idx_type a_len = a.length (); |
430 octave_idx_type r_len = r.length (); | |
431 octave_idx_type c_len = c.length (); | |
5164 | 432 bool ri_scalar = (r_len == 1); |
433 bool ci_scalar = (c_len == 1); | |
434 bool cf_scalar = (a_len == 1); | |
435 | |
436 if ((a_len != r_len && !cf_scalar && !ri_scalar) || | |
437 (a_len != c_len && !cf_scalar && !ci_scalar) || | |
438 (r_len != c_len && !ri_scalar && !ci_scalar) || nr < 0 || nc < 0) | |
439 { | |
440 (*current_liboctave_error_handler) | |
441 ("Sparse::Sparse (const Array<T>&, const Array<double>&, ...): dimension mismatch"); | |
442 rep = nil_rep (); | |
443 dimensions = dim_vector (0, 0); | |
444 } | |
445 else | |
446 { | |
5604 | 447 octave_idx_type max_nzmx = (r_len > c_len ? r_len : c_len); |
5164 | 448 |
5604 | 449 OCTAVE_LOCAL_BUFFER (octave_sparse_sort_idxl *, sidx, max_nzmx); |
450 OCTAVE_LOCAL_BUFFER (octave_sparse_sort_idxl, sidxX, max_nzmx); | |
451 | |
452 for (octave_idx_type i = 0; i < max_nzmx; i++) | |
5164 | 453 sidx[i] = &sidxX[i]; |
454 | |
5604 | 455 octave_idx_type actual_nzmx = 0; |
5164 | 456 OCTAVE_QUIT; |
457 | |
5604 | 458 for (octave_idx_type i = 0; i < max_nzmx; i++) |
5164 | 459 { |
5275 | 460 octave_idx_type rowidx = static_cast<octave_idx_type> (ri_scalar ? r(0) : r(i)); |
461 octave_idx_type colidx = static_cast<octave_idx_type> (ci_scalar ? c(0) : c(i)); | |
5164 | 462 if (rowidx < nr && rowidx >= 0 && |
463 colidx < nc && colidx >= 0 ) | |
464 { | |
465 if ( a (cf_scalar ? 0 : i ) != T ()) | |
466 { | |
5604 | 467 sidx[actual_nzmx]->r = rowidx; |
468 sidx[actual_nzmx]->c = colidx; | |
469 sidx[actual_nzmx]->idx = i; | |
470 actual_nzmx++; | |
5164 | 471 } |
472 } | |
473 else | |
474 { | |
475 (*current_liboctave_error_handler) | |
476 ("Sparse::Sparse : index (%d,%d) out of range", | |
477 rowidx + 1, colidx + 1); | |
478 rep = nil_rep (); | |
479 dimensions = dim_vector (0, 0); | |
480 return; | |
481 } | |
482 } | |
483 | |
5604 | 484 if (actual_nzmx == 0) |
5164 | 485 rep = new typename Sparse<T>::SparseRep (nr, nc); |
486 else | |
487 { | |
488 OCTAVE_QUIT; | |
489 octave_sort<octave_sparse_sort_idxl *> | |
7433 | 490 lsort (octave_sparse_sidxl_comp); |
491 | |
492 lsort.sort (sidx, actual_nzmx); | |
5164 | 493 OCTAVE_QUIT; |
494 | |
495 // Now count the unique non-zero values | |
5604 | 496 octave_idx_type real_nzmx = 1; |
497 for (octave_idx_type i = 1; i < actual_nzmx; i++) | |
5164 | 498 if (sidx[i-1]->r != sidx[i]->r || sidx[i-1]->c != sidx[i]->c) |
5604 | 499 real_nzmx++; |
500 | |
501 rep = new typename Sparse<T>::SparseRep (nr, nc, real_nzmx); | |
5164 | 502 |
5275 | 503 octave_idx_type cx = 0; |
504 octave_idx_type prev_rval = -1; | |
505 octave_idx_type prev_cval = -1; | |
506 octave_idx_type ii = -1; | |
5164 | 507 xcidx (0) = 0; |
5604 | 508 for (octave_idx_type i = 0; i < actual_nzmx; i++) |
5164 | 509 { |
510 OCTAVE_QUIT; | |
5275 | 511 octave_idx_type iidx = sidx[i]->idx; |
512 octave_idx_type rval = sidx[i]->r; | |
513 octave_idx_type cval = sidx[i]->c; | |
5164 | 514 |
515 if (prev_cval < cval || (prev_rval < rval && prev_cval == cval)) | |
516 { | |
5275 | 517 octave_idx_type ci = static_cast<octave_idx_type> (c (ci_scalar ? 0 : iidx)); |
5164 | 518 ii++; |
519 | |
520 while (cx < ci) | |
521 xcidx (++cx) = ii; | |
522 xdata(ii) = a (cf_scalar ? 0 : iidx); | |
5275 | 523 xridx(ii) = static_cast<octave_idx_type> (r (ri_scalar ? 0 : iidx)); |
5164 | 524 } |
525 else | |
526 { | |
527 if (sum_terms) | |
528 xdata(ii) += a (cf_scalar ? 0 : iidx); | |
529 else | |
530 xdata(ii) = a (cf_scalar ? 0 : iidx); | |
531 } | |
532 prev_rval = rval; | |
533 prev_cval = cval; | |
534 } | |
535 | |
536 while (cx < nc) | |
537 xcidx (++cx) = ii + 1; | |
538 } | |
539 } | |
540 } | |
541 | |
542 template <class T> | |
543 Sparse<T>::Sparse (const Array2<T>& a) | |
544 : dimensions (a.dims ()), idx (0), idx_count (0) | |
545 { | |
5275 | 546 octave_idx_type nr = rows (); |
547 octave_idx_type nc = cols (); | |
548 octave_idx_type len = a.length (); | |
5604 | 549 octave_idx_type new_nzmx = 0; |
5164 | 550 |
551 // First count the number of non-zero terms | |
5275 | 552 for (octave_idx_type i = 0; i < len; i++) |
5164 | 553 if (a(i) != T ()) |
5604 | 554 new_nzmx++; |
555 | |
556 rep = new typename Sparse<T>::SparseRep (nr, nc, new_nzmx); | |
5164 | 557 |
5275 | 558 octave_idx_type ii = 0; |
5164 | 559 xcidx(0) = 0; |
5275 | 560 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 561 { |
5275 | 562 for (octave_idx_type i = 0; i < nr; i++) |
5164 | 563 if (a.elem (i,j) != T ()) |
564 { | |
565 xdata(ii) = a.elem (i,j); | |
566 xridx(ii++) = i; | |
567 } | |
568 xcidx(j+1) = ii; | |
569 } | |
570 } | |
571 | |
572 template <class T> | |
573 Sparse<T>::Sparse (const Array<T>& a) | |
574 : dimensions (a.dims ()), idx (0), idx_count (0) | |
575 { | |
576 if (dimensions.length () > 2) | |
577 (*current_liboctave_error_handler) | |
578 ("Sparse::Sparse (const Array<T>&): dimension mismatch"); | |
579 else | |
580 { | |
5275 | 581 octave_idx_type nr = rows (); |
582 octave_idx_type nc = cols (); | |
583 octave_idx_type len = a.length (); | |
5604 | 584 octave_idx_type new_nzmx = 0; |
5164 | 585 |
586 // First count the number of non-zero terms | |
5275 | 587 for (octave_idx_type i = 0; i < len; i++) |
5164 | 588 if (a(i) != T ()) |
5604 | 589 new_nzmx++; |
590 | |
591 rep = new typename Sparse<T>::SparseRep (nr, nc, new_nzmx); | |
5164 | 592 |
5275 | 593 octave_idx_type ii = 0; |
5164 | 594 xcidx(0) = 0; |
5275 | 595 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 596 { |
5275 | 597 for (octave_idx_type i = 0; i < nr; i++) |
5164 | 598 if (a.elem (i,j) != T ()) |
599 { | |
600 xdata(ii) = a.elem (i,j); | |
601 xridx(ii++) = i; | |
602 } | |
603 xcidx(j+1) = ii; | |
604 } | |
605 } | |
606 } | |
607 | |
608 template <class T> | |
609 Sparse<T>::~Sparse (void) | |
610 { | |
611 if (--rep->count <= 0) | |
612 delete rep; | |
613 | |
614 delete [] idx; | |
615 } | |
616 | |
617 template <class T> | |
5275 | 618 octave_idx_type |
619 Sparse<T>::compute_index (const Array<octave_idx_type>& ra_idx) const | |
5164 | 620 { |
5275 | 621 octave_idx_type retval = -1; |
622 | |
623 octave_idx_type n = dimensions.length (); | |
5164 | 624 |
625 if (n > 0 && n == ra_idx.length ()) | |
626 { | |
627 retval = ra_idx(--n); | |
628 | |
629 while (--n >= 0) | |
630 { | |
631 retval *= dimensions(n); | |
632 retval += ra_idx(n); | |
633 } | |
634 } | |
635 else | |
636 (*current_liboctave_error_handler) | |
637 ("Sparse<T>::compute_index: invalid ra_idxing operation"); | |
638 | |
639 return retval; | |
640 } | |
641 | |
642 template <class T> | |
643 T | |
5275 | 644 Sparse<T>::range_error (const char *fcn, octave_idx_type n) const |
5164 | 645 { |
646 (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n); | |
647 return T (); | |
648 } | |
649 | |
650 template <class T> | |
651 T& | |
5275 | 652 Sparse<T>::range_error (const char *fcn, octave_idx_type n) |
5164 | 653 { |
654 (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n); | |
655 static T foo; | |
656 return foo; | |
657 } | |
658 | |
659 template <class T> | |
660 T | |
5275 | 661 Sparse<T>::range_error (const char *fcn, octave_idx_type i, octave_idx_type j) const |
5164 | 662 { |
663 (*current_liboctave_error_handler) | |
664 ("%s (%d, %d): range error", fcn, i, j); | |
665 return T (); | |
666 } | |
667 | |
668 template <class T> | |
669 T& | |
5275 | 670 Sparse<T>::range_error (const char *fcn, octave_idx_type i, octave_idx_type j) |
5164 | 671 { |
672 (*current_liboctave_error_handler) | |
673 ("%s (%d, %d): range error", fcn, i, j); | |
674 static T foo; | |
675 return foo; | |
676 } | |
677 | |
678 template <class T> | |
679 T | |
5275 | 680 Sparse<T>::range_error (const char *fcn, const Array<octave_idx_type>& ra_idx) const |
5164 | 681 { |
5765 | 682 std::ostringstream buf; |
5164 | 683 |
684 buf << fcn << " ("; | |
685 | |
5275 | 686 octave_idx_type n = ra_idx.length (); |
5164 | 687 |
688 if (n > 0) | |
689 buf << ra_idx(0); | |
690 | |
5275 | 691 for (octave_idx_type i = 1; i < n; i++) |
5164 | 692 buf << ", " << ra_idx(i); |
693 | |
694 buf << "): range error"; | |
5765 | 695 |
696 std::string buf_str = buf.str (); | |
697 | |
698 (*current_liboctave_error_handler) (buf_str.c_str ()); | |
5164 | 699 |
700 return T (); | |
701 } | |
702 | |
703 template <class T> | |
704 T& | |
5275 | 705 Sparse<T>::range_error (const char *fcn, const Array<octave_idx_type>& ra_idx) |
5164 | 706 { |
5765 | 707 std::ostringstream buf; |
5164 | 708 |
709 buf << fcn << " ("; | |
710 | |
5275 | 711 octave_idx_type n = ra_idx.length (); |
5164 | 712 |
713 if (n > 0) | |
714 buf << ra_idx(0); | |
715 | |
5275 | 716 for (octave_idx_type i = 1; i < n; i++) |
5164 | 717 buf << ", " << ra_idx(i); |
718 | |
719 buf << "): range error"; | |
720 | |
5765 | 721 std::string buf_str = buf.str (); |
722 | |
723 (*current_liboctave_error_handler) (buf_str.c_str ()); | |
5164 | 724 |
725 static T foo; | |
726 return foo; | |
727 } | |
728 | |
729 template <class T> | |
730 Sparse<T> | |
731 Sparse<T>::reshape (const dim_vector& new_dims) const | |
732 { | |
733 Sparse<T> retval; | |
6689 | 734 dim_vector dims2 = new_dims; |
735 | |
736 if (dims2.length () > 2) | |
5164 | 737 { |
6814 | 738 (*current_liboctave_warning_handler) |
739 ("reshape: sparse reshape to N-d array smashes dims"); | |
740 | |
6689 | 741 for (octave_idx_type i = 2; i < dims2.length(); i++) |
6814 | 742 dims2(1) *= dims2(i); |
743 | |
6689 | 744 dims2.resize (2); |
745 } | |
746 | |
747 if (dimensions != dims2) | |
748 { | |
749 if (dimensions.numel () == dims2.numel ()) | |
5164 | 750 { |
5681 | 751 octave_idx_type new_nnz = nnz (); |
6689 | 752 octave_idx_type new_nr = dims2 (0); |
753 octave_idx_type new_nc = dims2 (1); | |
5275 | 754 octave_idx_type old_nr = rows (); |
755 octave_idx_type old_nc = cols (); | |
5681 | 756 retval = Sparse<T> (new_nr, new_nc, new_nnz); |
5164 | 757 |
5275 | 758 octave_idx_type kk = 0; |
5164 | 759 retval.xcidx(0) = 0; |
5275 | 760 for (octave_idx_type i = 0; i < old_nc; i++) |
761 for (octave_idx_type j = cidx(i); j < cidx(i+1); j++) | |
5164 | 762 { |
5275 | 763 octave_idx_type tmp = i * old_nr + ridx(j); |
764 octave_idx_type ii = tmp % new_nr; | |
765 octave_idx_type jj = (tmp - ii) / new_nr; | |
766 for (octave_idx_type k = kk; k < jj; k++) | |
5164 | 767 retval.xcidx(k+1) = j; |
768 kk = jj; | |
769 retval.xdata(j) = data(j); | |
770 retval.xridx(j) = ii; | |
771 } | |
5275 | 772 for (octave_idx_type k = kk; k < new_nc; k++) |
5681 | 773 retval.xcidx(k+1) = new_nnz; |
5164 | 774 } |
775 else | |
776 (*current_liboctave_error_handler) ("reshape: size mismatch"); | |
777 } | |
778 else | |
779 retval = *this; | |
780 | |
781 return retval; | |
782 } | |
783 | |
784 template <class T> | |
785 Sparse<T> | |
5275 | 786 Sparse<T>::permute (const Array<octave_idx_type>& perm_vec, bool) const |
5164 | 787 { |
6813 | 788 // The only valid permutations of a sparse array are [1, 2] and [2, 1]. |
789 | |
790 bool fail = false; | |
6817 | 791 bool trans = false; |
6813 | 792 |
793 if (perm_vec.length () == 2) | |
5164 | 794 { |
6813 | 795 if (perm_vec(0) == 0 && perm_vec(1) == 1) |
796 /* do nothing */; | |
797 else if (perm_vec(0) == 1 && perm_vec(1) == 0) | |
6817 | 798 trans = true; |
5164 | 799 else |
6813 | 800 fail = true; |
5164 | 801 } |
802 else | |
6813 | 803 fail = true; |
804 | |
805 if (fail) | |
806 (*current_liboctave_error_handler) | |
807 ("permutation vector contains an invalid element"); | |
808 | |
6817 | 809 return trans ? this->transpose () : *this; |
5164 | 810 } |
811 | |
812 template <class T> | |
813 void | |
814 Sparse<T>::resize_no_fill (const dim_vector& dv) | |
815 { | |
5275 | 816 octave_idx_type n = dv.length (); |
5164 | 817 |
818 if (n != 2) | |
819 { | |
820 (*current_liboctave_error_handler) ("sparse array must be 2-D"); | |
821 return; | |
822 } | |
823 | |
824 resize_no_fill (dv(0), dv(1)); | |
825 } | |
826 | |
827 template <class T> | |
828 void | |
5275 | 829 Sparse<T>::resize_no_fill (octave_idx_type r, octave_idx_type c) |
5164 | 830 { |
831 if (r < 0 || c < 0) | |
832 { | |
833 (*current_liboctave_error_handler) | |
834 ("can't resize to negative dimension"); | |
835 return; | |
836 } | |
837 | |
838 if (ndims () == 0) | |
839 dimensions = dim_vector (0, 0); | |
840 | |
841 if (r == dim1 () && c == dim2 ()) | |
842 return; | |
843 | |
5731 | 844 typename Sparse<T>::SparseRep *old_rep = rep; |
845 | |
5275 | 846 octave_idx_type nc = cols (); |
847 octave_idx_type nr = rows (); | |
5164 | 848 |
5681 | 849 if (nnz () == 0 || r == 0 || c == 0) |
5164 | 850 // Special case of redimensioning to/from a sparse matrix with |
851 // no elements | |
852 rep = new typename Sparse<T>::SparseRep (r, c); | |
853 else | |
854 { | |
5275 | 855 octave_idx_type n = 0; |
5164 | 856 Sparse<T> tmpval; |
857 if (r >= nr) | |
858 { | |
859 if (c > nc) | |
5731 | 860 n = xcidx(nc); |
5164 | 861 else |
5731 | 862 n = xcidx(c); |
5164 | 863 |
864 tmpval = Sparse<T> (r, c, n); | |
865 | |
866 if (c > nc) | |
867 { | |
6101 | 868 for (octave_idx_type i = 0; i < nc + 1; i++) |
5731 | 869 tmpval.cidx(i) = xcidx(i); |
6101 | 870 for (octave_idx_type i = nc + 1; i < c + 1; i++) |
5164 | 871 tmpval.cidx(i) = tmpval.cidx(i-1); |
872 } | |
873 else if (c <= nc) | |
6101 | 874 for (octave_idx_type i = 0; i < c + 1; i++) |
5731 | 875 tmpval.cidx(i) = xcidx(i); |
5164 | 876 |
5275 | 877 for (octave_idx_type i = 0; i < n; i++) |
5164 | 878 { |
5731 | 879 tmpval.data(i) = xdata(i); |
880 tmpval.ridx(i) = xridx(i); | |
5164 | 881 } |
882 } | |
883 else | |
884 { | |
885 // Count how many non zero terms before we do anything | |
6101 | 886 octave_idx_type min_nc = (c < nc ? c : nc); |
887 for (octave_idx_type i = 0; i < min_nc; i++) | |
5731 | 888 for (octave_idx_type j = xcidx(i); j < xcidx(i+1); j++) |
889 if (xridx(j) < r) | |
5164 | 890 n++; |
891 | |
892 if (n) | |
893 { | |
894 // Now that we know the size we can do something | |
895 tmpval = Sparse<T> (r, c, n); | |
896 | |
897 tmpval.cidx(0); | |
6101 | 898 for (octave_idx_type i = 0, ii = 0; i < min_nc; i++) |
5164 | 899 { |
5731 | 900 for (octave_idx_type j = xcidx(i); j < xcidx(i+1); j++) |
901 if (xridx(j) < r) | |
5164 | 902 { |
5731 | 903 tmpval.data(ii) = xdata(j); |
904 tmpval.ridx(ii++) = xridx(j); | |
5164 | 905 } |
906 tmpval.cidx(i+1) = ii; | |
907 } | |
6101 | 908 if (c > min_nc) |
909 for (octave_idx_type i = nc; i < c; i++) | |
910 tmpval.cidx(i+1) = tmpval.cidx(i); | |
5164 | 911 } |
912 else | |
913 tmpval = Sparse<T> (r, c); | |
914 } | |
915 | |
916 rep = tmpval.rep; | |
917 rep->count++; | |
918 } | |
919 | |
920 dimensions = dim_vector (r, c); | |
921 | |
922 if (--old_rep->count <= 0) | |
923 delete old_rep; | |
924 } | |
925 | |
926 template <class T> | |
927 Sparse<T>& | |
5275 | 928 Sparse<T>::insert (const Sparse<T>& a, octave_idx_type r, octave_idx_type c) |
5164 | 929 { |
5275 | 930 octave_idx_type a_rows = a.rows (); |
931 octave_idx_type a_cols = a.cols (); | |
932 octave_idx_type nr = rows (); | |
933 octave_idx_type nc = cols (); | |
5164 | 934 |
935 if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ()) | |
936 { | |
937 (*current_liboctave_error_handler) ("range error for insert"); | |
938 return *this; | |
939 } | |
940 | |
941 // First count the number of elements in the final array | |
5681 | 942 octave_idx_type nel = cidx(c) + a.nnz (); |
5164 | 943 |
944 if (c + a_cols < nc) | |
945 nel += cidx(nc) - cidx(c + a_cols); | |
946 | |
5275 | 947 for (octave_idx_type i = c; i < c + a_cols; i++) |
948 for (octave_idx_type j = cidx(i); j < cidx(i+1); j++) | |
5164 | 949 if (ridx(j) < r || ridx(j) >= r + a_rows) |
950 nel++; | |
951 | |
952 Sparse<T> tmp (*this); | |
953 --rep->count; | |
954 rep = new typename Sparse<T>::SparseRep (nr, nc, nel); | |
955 | |
5275 | 956 for (octave_idx_type i = 0; i < tmp.cidx(c); i++) |
5164 | 957 { |
958 data(i) = tmp.data(i); | |
959 ridx(i) = tmp.ridx(i); | |
960 } | |
5275 | 961 for (octave_idx_type i = 0; i < c + 1; i++) |
5164 | 962 cidx(i) = tmp.cidx(i); |
963 | |
5275 | 964 octave_idx_type ii = cidx(c); |
965 | |
966 for (octave_idx_type i = c; i < c + a_cols; i++) | |
5164 | 967 { |
968 OCTAVE_QUIT; | |
969 | |
5275 | 970 for (octave_idx_type j = tmp.cidx(i); j < tmp.cidx(i+1); j++) |
5164 | 971 if (tmp.ridx(j) < r) |
972 { | |
973 data(ii) = tmp.data(j); | |
974 ridx(ii++) = tmp.ridx(j); | |
975 } | |
976 | |
977 OCTAVE_QUIT; | |
978 | |
5275 | 979 for (octave_idx_type j = a.cidx(i-c); j < a.cidx(i-c+1); j++) |
5164 | 980 { |
981 data(ii) = a.data(j); | |
982 ridx(ii++) = r + a.ridx(j); | |
983 } | |
984 | |
985 OCTAVE_QUIT; | |
986 | |
5275 | 987 for (octave_idx_type j = tmp.cidx(i); j < tmp.cidx(i+1); j++) |
5164 | 988 if (tmp.ridx(j) >= r + a_rows) |
989 { | |
990 data(ii) = tmp.data(j); | |
991 ridx(ii++) = tmp.ridx(j); | |
992 } | |
993 | |
994 cidx(i+1) = ii; | |
995 } | |
996 | |
5275 | 997 for (octave_idx_type i = c + a_cols; i < nc; i++) |
5164 | 998 { |
5275 | 999 for (octave_idx_type j = tmp.cidx(i); j < tmp.cidx(i+1); j++) |
5164 | 1000 { |
1001 data(ii) = tmp.data(j); | |
1002 ridx(ii++) = tmp.ridx(j); | |
1003 } | |
1004 cidx(i+1) = ii; | |
1005 } | |
1006 | |
1007 return *this; | |
1008 } | |
1009 | |
1010 template <class T> | |
1011 Sparse<T>& | |
5275 | 1012 Sparse<T>::insert (const Sparse<T>& a, const Array<octave_idx_type>& ra_idx) |
5164 | 1013 { |
1014 | |
1015 if (ra_idx.length () != 2) | |
1016 { | |
1017 (*current_liboctave_error_handler) ("range error for insert"); | |
1018 return *this; | |
1019 } | |
1020 | |
1021 return insert (a, ra_idx (0), ra_idx (1)); | |
1022 } | |
1023 | |
1024 template <class T> | |
1025 Sparse<T> | |
1026 Sparse<T>::transpose (void) const | |
1027 { | |
1028 assert (ndims () == 2); | |
1029 | |
5275 | 1030 octave_idx_type nr = rows (); |
1031 octave_idx_type nc = cols (); | |
5648 | 1032 octave_idx_type nz = nnz (); |
5164 | 1033 Sparse<T> retval (nc, nr, nz); |
1034 | |
5648 | 1035 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr + 1); |
1036 for (octave_idx_type i = 0; i < nr; i++) | |
1037 w[i] = 0; | |
1038 for (octave_idx_type i = 0; i < nz; i++) | |
1039 w[ridx(i)]++; | |
1040 nz = 0; | |
1041 for (octave_idx_type i = 0; i < nr; i++) | |
5164 | 1042 { |
5648 | 1043 retval.xcidx(i) = nz; |
1044 nz += w[i]; | |
1045 w[i] = retval.xcidx(i); | |
5164 | 1046 } |
5648 | 1047 retval.xcidx(nr) = nz; |
1048 w[nr] = nz; | |
1049 | |
1050 for (octave_idx_type j = 0; j < nc; j++) | |
1051 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) | |
1052 { | |
1053 octave_idx_type q = w [ridx(k)]++; | |
1054 retval.xridx (q) = j; | |
1055 retval.xdata (q) = data (k); | |
1056 } | |
5164 | 1057 |
1058 return retval; | |
1059 } | |
1060 | |
1061 template <class T> | |
1062 void | |
1063 Sparse<T>::clear_index (void) | |
1064 { | |
1065 delete [] idx; | |
1066 idx = 0; | |
1067 idx_count = 0; | |
1068 } | |
1069 | |
1070 template <class T> | |
1071 void | |
1072 Sparse<T>::set_index (const idx_vector& idx_arg) | |
1073 { | |
5275 | 1074 octave_idx_type nd = ndims (); |
5164 | 1075 |
1076 if (! idx && nd > 0) | |
1077 idx = new idx_vector [nd]; | |
1078 | |
1079 if (idx_count < nd) | |
1080 { | |
1081 idx[idx_count++] = idx_arg; | |
1082 } | |
1083 else | |
1084 { | |
1085 idx_vector *new_idx = new idx_vector [idx_count+1]; | |
1086 | |
5275 | 1087 for (octave_idx_type i = 0; i < idx_count; i++) |
5164 | 1088 new_idx[i] = idx[i]; |
1089 | |
1090 new_idx[idx_count++] = idx_arg; | |
1091 | |
1092 delete [] idx; | |
1093 | |
1094 idx = new_idx; | |
1095 } | |
1096 } | |
1097 | |
1098 template <class T> | |
1099 void | |
1100 Sparse<T>::maybe_delete_elements (idx_vector& idx_arg) | |
1101 { | |
5275 | 1102 octave_idx_type nr = dim1 (); |
1103 octave_idx_type nc = dim2 (); | |
5164 | 1104 |
1105 if (nr == 0 && nc == 0) | |
1106 return; | |
1107 | |
5275 | 1108 octave_idx_type n; |
5164 | 1109 if (nr == 1) |
1110 n = nc; | |
1111 else if (nc == 1) | |
1112 n = nr; | |
1113 else | |
1114 { | |
1115 // Reshape to row vector for Matlab compatibility. | |
1116 | |
1117 n = nr * nc; | |
1118 nr = 1; | |
1119 nc = n; | |
1120 } | |
1121 | |
1122 if (idx_arg.is_colon_equiv (n, 1)) | |
1123 { | |
1124 // Either A(:) = [] or A(idx) = [] with idx enumerating all | |
1125 // elements, so we delete all elements and return [](0x0). To | |
1126 // preserve the orientation of the vector, you have to use | |
1127 // A(idx,:) = [] (delete rows) or A(:,idx) (delete columns). | |
1128 | |
1129 resize_no_fill (0, 0); | |
1130 return; | |
1131 } | |
1132 | |
1133 idx_arg.sort (true); | |
1134 | |
5275 | 1135 octave_idx_type num_to_delete = idx_arg.length (n); |
5164 | 1136 |
1137 if (num_to_delete != 0) | |
1138 { | |
5275 | 1139 octave_idx_type new_n = n; |
5681 | 1140 octave_idx_type new_nnz = nnz (); |
5275 | 1141 |
1142 octave_idx_type iidx = 0; | |
5164 | 1143 |
1144 const Sparse<T> tmp (*this); | |
1145 | |
5275 | 1146 for (octave_idx_type i = 0; i < n; i++) |
5164 | 1147 { |
1148 OCTAVE_QUIT; | |
1149 | |
1150 if (i == idx_arg.elem (iidx)) | |
1151 { | |
1152 iidx++; | |
1153 new_n--; | |
1154 | |
1155 if (tmp.elem (i) != T ()) | |
5681 | 1156 new_nnz--; |
5164 | 1157 |
1158 if (iidx == num_to_delete) | |
1159 break; | |
1160 } | |
1161 } | |
1162 | |
1163 if (new_n > 0) | |
1164 { | |
1165 rep->count--; | |
1166 | |
1167 if (nr == 1) | |
5681 | 1168 rep = new typename Sparse<T>::SparseRep (1, new_n, new_nnz); |
5164 | 1169 else |
5681 | 1170 rep = new typename Sparse<T>::SparseRep (new_n, 1, new_nnz); |
5164 | 1171 |
5275 | 1172 octave_idx_type ii = 0; |
1173 octave_idx_type jj = 0; | |
5164 | 1174 iidx = 0; |
5275 | 1175 for (octave_idx_type i = 0; i < n; i++) |
5164 | 1176 { |
1177 OCTAVE_QUIT; | |
1178 | |
1179 if (iidx < num_to_delete && i == idx_arg.elem (iidx)) | |
1180 iidx++; | |
1181 else | |
1182 { | |
1183 T el = tmp.elem (i); | |
1184 if (el != T ()) | |
1185 { | |
1186 data(ii) = el; | |
1187 ridx(ii++) = jj; | |
1188 } | |
1189 jj++; | |
1190 } | |
1191 } | |
1192 | |
1193 dimensions.resize (2); | |
1194 | |
1195 if (nr == 1) | |
1196 { | |
1197 ii = 0; | |
1198 cidx(0) = 0; | |
5275 | 1199 for (octave_idx_type i = 0; i < new_n; i++) |
5164 | 1200 { |
1201 OCTAVE_QUIT; | |
1202 if (ridx(ii) == i) | |
1203 ridx(ii++) = 0; | |
1204 cidx(i+1) = ii; | |
1205 } | |
1206 | |
1207 dimensions(0) = 1; | |
1208 dimensions(1) = new_n; | |
1209 } | |
1210 else | |
1211 { | |
1212 cidx(0) = 0; | |
5681 | 1213 cidx(1) = new_nnz; |
5164 | 1214 dimensions(0) = new_n; |
1215 dimensions(1) = 1; | |
1216 } | |
1217 } | |
1218 else | |
1219 (*current_liboctave_error_handler) | |
1220 ("A(idx) = []: index out of range"); | |
1221 } | |
1222 } | |
1223 | |
1224 template <class T> | |
1225 void | |
1226 Sparse<T>::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j) | |
1227 { | |
1228 assert (ndims () == 2); | |
1229 | |
5275 | 1230 octave_idx_type nr = dim1 (); |
1231 octave_idx_type nc = dim2 (); | |
5164 | 1232 |
1233 if (nr == 0 && nc == 0) | |
1234 return; | |
1235 | |
1236 if (idx_i.is_colon ()) | |
1237 { | |
1238 if (idx_j.is_colon ()) | |
1239 { | |
1240 // A(:,:) -- We are deleting columns and rows, so the result | |
1241 // is [](0x0). | |
1242 | |
1243 resize_no_fill (0, 0); | |
1244 return; | |
1245 } | |
1246 | |
1247 if (idx_j.is_colon_equiv (nc, 1)) | |
1248 { | |
1249 // A(:,j) -- We are deleting columns by enumerating them, | |
1250 // If we enumerate all of them, we should have zero columns | |
1251 // with the same number of rows that we started with. | |
1252 | |
1253 resize_no_fill (nr, 0); | |
1254 return; | |
1255 } | |
1256 } | |
1257 | |
1258 if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1)) | |
1259 { | |
1260 // A(i,:) -- We are deleting rows by enumerating them. If we | |
1261 // enumerate all of them, we should have zero rows with the | |
1262 // same number of columns that we started with. | |
1263 | |
1264 resize_no_fill (0, nc); | |
1265 return; | |
1266 } | |
1267 | |
1268 if (idx_i.is_colon_equiv (nr, 1)) | |
1269 { | |
1270 if (idx_j.is_colon_equiv (nc, 1)) | |
1271 resize_no_fill (0, 0); | |
1272 else | |
1273 { | |
1274 idx_j.sort (true); | |
1275 | |
5275 | 1276 octave_idx_type num_to_delete = idx_j.length (nc); |
5164 | 1277 |
1278 if (num_to_delete != 0) | |
1279 { | |
1280 if (nr == 1 && num_to_delete == nc) | |
1281 resize_no_fill (0, 0); | |
1282 else | |
1283 { | |
5275 | 1284 octave_idx_type new_nc = nc; |
5681 | 1285 octave_idx_type new_nnz = nnz (); |
5275 | 1286 |
1287 octave_idx_type iidx = 0; | |
1288 | |
1289 for (octave_idx_type j = 0; j < nc; j++) | |
5164 | 1290 { |
1291 OCTAVE_QUIT; | |
1292 | |
1293 if (j == idx_j.elem (iidx)) | |
1294 { | |
1295 iidx++; | |
1296 new_nc--; | |
1297 | |
5681 | 1298 new_nnz -= cidx(j+1) - cidx(j); |
5164 | 1299 |
1300 if (iidx == num_to_delete) | |
1301 break; | |
1302 } | |
1303 } | |
1304 | |
1305 if (new_nc > 0) | |
1306 { | |
1307 const Sparse<T> tmp (*this); | |
1308 --rep->count; | |
1309 rep = new typename Sparse<T>::SparseRep (nr, new_nc, | |
5681 | 1310 new_nnz); |
5275 | 1311 octave_idx_type ii = 0; |
1312 octave_idx_type jj = 0; | |
5164 | 1313 iidx = 0; |
1314 cidx(0) = 0; | |
5275 | 1315 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 1316 { |
1317 OCTAVE_QUIT; | |
1318 | |
1319 if (iidx < num_to_delete && j == idx_j.elem (iidx)) | |
1320 iidx++; | |
1321 else | |
1322 { | |
5275 | 1323 for (octave_idx_type i = tmp.cidx(j); |
5164 | 1324 i < tmp.cidx(j+1); i++) |
1325 { | |
1326 data(jj) = tmp.data(i); | |
1327 ridx(jj++) = tmp.ridx(i); | |
1328 } | |
1329 cidx(++ii) = jj; | |
1330 } | |
1331 } | |
1332 | |
1333 dimensions.resize (2); | |
1334 dimensions(1) = new_nc; | |
1335 } | |
1336 else | |
1337 (*current_liboctave_error_handler) | |
1338 ("A(idx) = []: index out of range"); | |
1339 } | |
1340 } | |
1341 } | |
1342 } | |
1343 else if (idx_j.is_colon_equiv (nc, 1)) | |
1344 { | |
1345 if (idx_i.is_colon_equiv (nr, 1)) | |
1346 resize_no_fill (0, 0); | |
1347 else | |
1348 { | |
1349 idx_i.sort (true); | |
1350 | |
5275 | 1351 octave_idx_type num_to_delete = idx_i.length (nr); |
5164 | 1352 |
1353 if (num_to_delete != 0) | |
1354 { | |
1355 if (nc == 1 && num_to_delete == nr) | |
1356 resize_no_fill (0, 0); | |
1357 else | |
1358 { | |
5275 | 1359 octave_idx_type new_nr = nr; |
5681 | 1360 octave_idx_type new_nnz = nnz (); |
5275 | 1361 |
1362 octave_idx_type iidx = 0; | |
1363 | |
1364 for (octave_idx_type i = 0; i < nr; i++) | |
5164 | 1365 { |
1366 OCTAVE_QUIT; | |
1367 | |
1368 if (i == idx_i.elem (iidx)) | |
1369 { | |
1370 iidx++; | |
1371 new_nr--; | |
1372 | |
5681 | 1373 for (octave_idx_type j = 0; j < nnz (); j++) |
5164 | 1374 if (ridx(j) == i) |
5681 | 1375 new_nnz--; |
5164 | 1376 |
1377 if (iidx == num_to_delete) | |
1378 break; | |
1379 } | |
1380 } | |
1381 | |
1382 if (new_nr > 0) | |
1383 { | |
1384 const Sparse<T> tmp (*this); | |
1385 --rep->count; | |
1386 rep = new typename Sparse<T>::SparseRep (new_nr, nc, | |
5681 | 1387 new_nnz); |
5164 | 1388 |
5275 | 1389 octave_idx_type jj = 0; |
5164 | 1390 cidx(0) = 0; |
5275 | 1391 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 1392 { |
1393 iidx = 0; | |
5275 | 1394 for (octave_idx_type j = tmp.cidx(i); j < tmp.cidx(i+1); j++) |
5164 | 1395 { |
1396 OCTAVE_QUIT; | |
1397 | |
5275 | 1398 octave_idx_type ri = tmp.ridx(j); |
5164 | 1399 |
1400 while (iidx < num_to_delete && | |
1401 ri > idx_i.elem (iidx)) | |
1402 { | |
1403 iidx++; | |
1404 } | |
1405 | |
1406 if (iidx == num_to_delete || | |
1407 ri != idx_i.elem(iidx)) | |
1408 { | |
1409 data(jj) = tmp.data(j); | |
1410 ridx(jj++) = ri - iidx; | |
1411 } | |
1412 } | |
1413 cidx(i+1) = jj; | |
1414 } | |
1415 | |
1416 dimensions.resize (2); | |
1417 dimensions(0) = new_nr; | |
1418 } | |
1419 else | |
1420 (*current_liboctave_error_handler) | |
1421 ("A(idx) = []: index out of range"); | |
1422 } | |
1423 } | |
1424 } | |
1425 } | |
1426 } | |
1427 | |
1428 template <class T> | |
1429 void | |
1430 Sparse<T>::maybe_delete_elements (Array<idx_vector>& ra_idx) | |
1431 { | |
1432 if (ra_idx.length () == 1) | |
1433 maybe_delete_elements (ra_idx(0)); | |
1434 else if (ra_idx.length () == 2) | |
1435 maybe_delete_elements (ra_idx(0), ra_idx(1)); | |
1436 else | |
1437 (*current_liboctave_error_handler) | |
1438 ("range error for maybe_delete_elements"); | |
1439 } | |
1440 | |
1441 template <class T> | |
1442 Sparse<T> | |
1443 Sparse<T>::value (void) | |
1444 { | |
1445 Sparse<T> retval; | |
1446 | |
1447 int n_idx = index_count (); | |
1448 | |
1449 if (n_idx == 2) | |
1450 { | |
1451 idx_vector *tmp = get_idx (); | |
1452 | |
1453 idx_vector idx_i = tmp[0]; | |
1454 idx_vector idx_j = tmp[1]; | |
1455 | |
1456 retval = index (idx_i, idx_j); | |
1457 } | |
1458 else if (n_idx == 1) | |
1459 { | |
1460 retval = index (idx[0]); | |
1461 } | |
1462 else | |
1463 (*current_liboctave_error_handler) | |
1464 ("Sparse<T>::value: invalid number of indices specified"); | |
1465 | |
1466 clear_index (); | |
1467 | |
1468 return retval; | |
1469 } | |
1470 | |
1471 template <class T> | |
1472 Sparse<T> | |
1473 Sparse<T>::index (idx_vector& idx_arg, int resize_ok) const | |
1474 { | |
1475 Sparse<T> retval; | |
1476 | |
1477 assert (ndims () == 2); | |
1478 | |
5275 | 1479 octave_idx_type nr = dim1 (); |
1480 octave_idx_type nc = dim2 (); | |
5681 | 1481 octave_idx_type nz = nnz (); |
5275 | 1482 |
1483 octave_idx_type orig_len = nr * nc; | |
5164 | 1484 |
1485 dim_vector idx_orig_dims = idx_arg.orig_dimensions (); | |
1486 | |
5275 | 1487 octave_idx_type idx_orig_rows = idx_arg.orig_rows (); |
1488 octave_idx_type idx_orig_columns = idx_arg.orig_columns (); | |
5164 | 1489 |
1490 if (idx_orig_dims.length () > 2) | |
1491 (*current_liboctave_error_handler) | |
1492 ("Sparse<T>::index: Can not index Sparse<T> with an N-D Array"); | |
1493 else if (idx_arg.is_colon ()) | |
1494 { | |
1495 // Fast magic colon processing. | |
1496 retval = Sparse<T> (nr * nc, 1, nz); | |
1497 | |
5275 | 1498 for (octave_idx_type i = 0; i < nc; i++) |
1499 for (octave_idx_type j = cidx(i); j < cidx(i+1); j++) | |
5164 | 1500 { |
1501 OCTAVE_QUIT; | |
1502 retval.xdata(j) = data(j); | |
1503 retval.xridx(j) = ridx(j) + i * nr; | |
1504 } | |
1505 retval.xcidx(0) = 0; | |
1506 retval.xcidx(1) = nz; | |
1507 } | |
1508 else if (nr == 1 && nc == 1) | |
1509 { | |
1510 // You have to be pretty sick to get to this bit of code, | |
1511 // since you have a scalar stored as a sparse matrix, and | |
1512 // then want to make a dense matrix with sparse | |
1513 // representation. Ok, we'll do it, but you deserve what | |
1514 // you get!! | |
5275 | 1515 octave_idx_type n = idx_arg.freeze (length (), "sparse vector", resize_ok); |
5164 | 1516 if (n == 0) |
7573
755bf7ecc29b
eliminate one_zero stuff from idx_vector
John W. Eaton <jwe@octave.org>
parents:
7546
diff
changeset
|
1517 |
7299 | 1518 retval = Sparse<T> (idx_orig_dims); |
5164 | 1519 else if (nz < 1) |
1520 if (n >= idx_orig_dims.numel ()) | |
1521 retval = Sparse<T> (idx_orig_dims); | |
1522 else | |
1523 retval = Sparse<T> (dim_vector (n, 1)); | |
1524 else if (n >= idx_orig_dims.numel ()) | |
1525 { | |
1526 T el = elem (0); | |
5275 | 1527 octave_idx_type new_nr = idx_orig_rows; |
1528 octave_idx_type new_nc = idx_orig_columns; | |
1529 for (octave_idx_type i = 2; i < idx_orig_dims.length (); i++) | |
5164 | 1530 new_nc *= idx_orig_dims (i); |
1531 | |
1532 retval = Sparse<T> (new_nr, new_nc, idx_arg.ones_count ()); | |
1533 | |
5275 | 1534 octave_idx_type ic = 0; |
1535 for (octave_idx_type i = 0; i < n; i++) | |
5164 | 1536 { |
1537 if (i % new_nr == 0) | |
7322 | 1538 retval.xcidx(i / new_nr) = ic; |
5164 | 1539 |
5275 | 1540 octave_idx_type ii = idx_arg.elem (i); |
5164 | 1541 if (ii == 0) |
1542 { | |
1543 OCTAVE_QUIT; | |
1544 retval.xdata(ic) = el; | |
1545 retval.xridx(ic++) = i % new_nr; | |
1546 } | |
1547 } | |
1548 retval.xcidx (new_nc) = ic; | |
1549 } | |
1550 else | |
1551 { | |
1552 T el = elem (0); | |
1553 retval = Sparse<T> (n, 1, nz); | |
1554 | |
5275 | 1555 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 1556 { |
1557 OCTAVE_QUIT; | |
1558 retval.xdata(i) = el; | |
1559 retval.xridx(i) = i; | |
1560 } | |
1561 retval.xcidx(0) = 0; | |
1562 retval.xcidx(1) = n; | |
1563 } | |
1564 } | |
1565 else if (nr == 1 || nc == 1) | |
1566 { | |
1567 // If indexing a vector with a matrix, return value has same | |
1568 // shape as the index. Otherwise, it has same orientation as | |
1569 // indexed object. | |
5275 | 1570 octave_idx_type len = length (); |
1571 octave_idx_type n = idx_arg.freeze (len, "sparse vector", resize_ok); | |
5164 | 1572 |
1573 if (n == 0) | |
1574 if (nr == 1) | |
1575 retval = Sparse<T> (dim_vector (1, 0)); | |
1576 else | |
1577 retval = Sparse<T> (dim_vector (0, 1)); | |
1578 else if (nz < 1) | |
7573
755bf7ecc29b
eliminate one_zero stuff from idx_vector
John W. Eaton <jwe@octave.org>
parents:
7546
diff
changeset
|
1579 if (idx_orig_rows == 1 || idx_orig_columns == 1) |
5164 | 1580 retval = Sparse<T> ((nr == 1 ? 1 : n), (nr == 1 ? n : 1)); |
1581 else | |
1582 retval = Sparse<T> (idx_orig_dims); | |
1583 else | |
1584 { | |
1585 | |
5604 | 1586 octave_idx_type new_nzmx = 0; |
5164 | 1587 if (nr == 1) |
5275 | 1588 for (octave_idx_type i = 0; i < n; i++) |
5164 | 1589 { |
1590 OCTAVE_QUIT; | |
1591 | |
5275 | 1592 octave_idx_type ii = idx_arg.elem (i); |
5164 | 1593 if (ii < len) |
1594 if (cidx(ii) != cidx(ii+1)) | |
5604 | 1595 new_nzmx++; |
5164 | 1596 } |
1597 else | |
5275 | 1598 for (octave_idx_type i = 0; i < n; i++) |
5164 | 1599 { |
5275 | 1600 octave_idx_type ii = idx_arg.elem (i); |
5164 | 1601 if (ii < len) |
5275 | 1602 for (octave_idx_type j = 0; j < nz; j++) |
5164 | 1603 { |
1604 OCTAVE_QUIT; | |
1605 | |
1606 if (ridx(j) == ii) | |
5604 | 1607 new_nzmx++; |
5164 | 1608 if (ridx(j) >= ii) |
1609 break; | |
1610 } | |
1611 } | |
1612 | |
7573
755bf7ecc29b
eliminate one_zero stuff from idx_vector
John W. Eaton <jwe@octave.org>
parents:
7546
diff
changeset
|
1613 if (idx_orig_rows == 1 || idx_orig_columns == 1) |
5164 | 1614 { |
1615 if (nr == 1) | |
1616 { | |
5604 | 1617 retval = Sparse<T> (1, n, new_nzmx); |
5275 | 1618 octave_idx_type jj = 0; |
5164 | 1619 retval.xcidx(0) = 0; |
5275 | 1620 for (octave_idx_type i = 0; i < n; i++) |
5164 | 1621 { |
1622 OCTAVE_QUIT; | |
1623 | |
5275 | 1624 octave_idx_type ii = idx_arg.elem (i); |
5164 | 1625 if (ii < len) |
1626 if (cidx(ii) != cidx(ii+1)) | |
1627 { | |
1628 retval.xdata(jj) = data(cidx(ii)); | |
1629 retval.xridx(jj++) = 0; | |
1630 } | |
1631 retval.xcidx(i+1) = jj; | |
1632 } | |
1633 } | |
1634 else | |
1635 { | |
5604 | 1636 retval = Sparse<T> (n, 1, new_nzmx); |
5164 | 1637 retval.xcidx(0) = 0; |
5604 | 1638 retval.xcidx(1) = new_nzmx; |
5275 | 1639 octave_idx_type jj = 0; |
1640 for (octave_idx_type i = 0; i < n; i++) | |
5164 | 1641 { |
5275 | 1642 octave_idx_type ii = idx_arg.elem (i); |
5164 | 1643 if (ii < len) |
5275 | 1644 for (octave_idx_type j = 0; j < nz; j++) |
5164 | 1645 { |
1646 OCTAVE_QUIT; | |
1647 | |
1648 if (ridx(j) == ii) | |
1649 { | |
1650 retval.xdata(jj) = data(j); | |
1651 retval.xridx(jj++) = i; | |
1652 } | |
1653 if (ridx(j) >= ii) | |
1654 break; | |
1655 } | |
1656 } | |
1657 } | |
1658 } | |
1659 else | |
1660 { | |
5275 | 1661 octave_idx_type new_nr; |
1662 octave_idx_type new_nc; | |
5164 | 1663 if (n >= idx_orig_dims.numel ()) |
1664 { | |
1665 new_nr = idx_orig_rows; | |
1666 new_nc = idx_orig_columns; | |
1667 } | |
1668 else | |
1669 { | |
1670 new_nr = n; | |
1671 new_nc = 1; | |
1672 } | |
1673 | |
5604 | 1674 retval = Sparse<T> (new_nr, new_nc, new_nzmx); |
5164 | 1675 |
1676 if (nr == 1) | |
1677 { | |
5275 | 1678 octave_idx_type jj = 0; |
5164 | 1679 retval.xcidx(0) = 0; |
5275 | 1680 for (octave_idx_type i = 0; i < n; i++) |
5164 | 1681 { |
1682 OCTAVE_QUIT; | |
1683 | |
5275 | 1684 octave_idx_type ii = idx_arg.elem (i); |
5164 | 1685 if (ii < len) |
1686 if (cidx(ii) != cidx(ii+1)) | |
1687 { | |
1688 retval.xdata(jj) = data(cidx(ii)); | |
1689 retval.xridx(jj++) = 0; | |
1690 } | |
1691 retval.xcidx(i/new_nr+1) = jj; | |
1692 } | |
1693 } | |
1694 else | |
1695 { | |
5275 | 1696 octave_idx_type jj = 0; |
5164 | 1697 retval.xcidx(0) = 0; |
5275 | 1698 for (octave_idx_type i = 0; i < n; i++) |
5164 | 1699 { |
5275 | 1700 octave_idx_type ii = idx_arg.elem (i); |
5164 | 1701 if (ii < len) |
5275 | 1702 for (octave_idx_type j = 0; j < nz; j++) |
5164 | 1703 { |
1704 OCTAVE_QUIT; | |
1705 | |
1706 if (ridx(j) == ii) | |
1707 { | |
1708 retval.xdata(jj) = data(j); | |
1709 retval.xridx(jj++) = i; | |
1710 } | |
1711 if (ridx(j) >= ii) | |
1712 break; | |
1713 } | |
1714 retval.xcidx(i/new_nr+1) = jj; | |
1715 } | |
1716 } | |
1717 } | |
1718 } | |
1719 } | |
1720 else | |
1721 { | |
7573
755bf7ecc29b
eliminate one_zero stuff from idx_vector
John W. Eaton <jwe@octave.org>
parents:
7546
diff
changeset
|
1722 (*current_liboctave_warning_with_id_handler) |
755bf7ecc29b
eliminate one_zero stuff from idx_vector
John W. Eaton <jwe@octave.org>
parents:
7546
diff
changeset
|
1723 ("Octave:fortran-indexing", "single index used for sparse matrix"); |
5164 | 1724 |
1725 // This code is only for indexing matrices. The vector | |
1726 // cases are handled above. | |
1727 | |
1728 idx_arg.freeze (nr * nc, "matrix", resize_ok); | |
1729 | |
1730 if (idx_arg) | |
1731 { | |
5275 | 1732 octave_idx_type result_nr = idx_orig_rows; |
1733 octave_idx_type result_nc = idx_orig_columns; | |
5164 | 1734 |
1735 if (nz < 1) | |
7573
755bf7ecc29b
eliminate one_zero stuff from idx_vector
John W. Eaton <jwe@octave.org>
parents:
7546
diff
changeset
|
1736 retval = Sparse<T> (result_nr, result_nc); |
5164 | 1737 else |
1738 { | |
1739 // Count number of non-zero elements | |
5604 | 1740 octave_idx_type new_nzmx = 0; |
5275 | 1741 octave_idx_type kk = 0; |
1742 for (octave_idx_type j = 0; j < result_nc; j++) | |
5164 | 1743 { |
5275 | 1744 for (octave_idx_type i = 0; i < result_nr; i++) |
5164 | 1745 { |
1746 OCTAVE_QUIT; | |
1747 | |
5275 | 1748 octave_idx_type ii = idx_arg.elem (kk++); |
5164 | 1749 if (ii < orig_len) |
1750 { | |
5275 | 1751 octave_idx_type fr = ii % nr; |
1752 octave_idx_type fc = (ii - fr) / nr; | |
1753 for (octave_idx_type k = cidx(fc); k < cidx(fc+1); k++) | |
5164 | 1754 { |
1755 if (ridx(k) == fr) | |
5604 | 1756 new_nzmx++; |
5164 | 1757 if (ridx(k) >= fr) |
1758 break; | |
1759 } | |
1760 } | |
1761 } | |
1762 } | |
1763 | |
5604 | 1764 retval = Sparse<T> (result_nr, result_nc, new_nzmx); |
5164 | 1765 |
1766 kk = 0; | |
5275 | 1767 octave_idx_type jj = 0; |
5164 | 1768 retval.xcidx(0) = 0; |
5275 | 1769 for (octave_idx_type j = 0; j < result_nc; j++) |
5164 | 1770 { |
5275 | 1771 for (octave_idx_type i = 0; i < result_nr; i++) |
5164 | 1772 { |
1773 OCTAVE_QUIT; | |
1774 | |
5275 | 1775 octave_idx_type ii = idx_arg.elem (kk++); |
5164 | 1776 if (ii < orig_len) |
1777 { | |
5275 | 1778 octave_idx_type fr = ii % nr; |
1779 octave_idx_type fc = (ii - fr) / nr; | |
1780 for (octave_idx_type k = cidx(fc); k < cidx(fc+1); k++) | |
5164 | 1781 { |
1782 if (ridx(k) == fr) | |
1783 { | |
1784 retval.xdata(jj) = data(k); | |
1785 retval.xridx(jj++) = i; | |
1786 } | |
1787 if (ridx(k) >= fr) | |
1788 break; | |
1789 } | |
1790 } | |
1791 } | |
1792 retval.xcidx(j+1) = jj; | |
1793 } | |
1794 } | |
1795 // idx_vector::freeze() printed an error message for us. | |
1796 } | |
1797 } | |
1798 | |
1799 return retval; | |
1800 } | |
1801 | |
6988 | 1802 struct |
1803 idx_node | |
1804 { | |
1805 octave_idx_type i; | |
1806 struct idx_node *next; | |
1807 }; | |
1808 | |
5164 | 1809 template <class T> |
1810 Sparse<T> | |
1811 Sparse<T>::index (idx_vector& idx_i, idx_vector& idx_j, int resize_ok) const | |
1812 { | |
1813 Sparse<T> retval; | |
1814 | |
1815 assert (ndims () == 2); | |
1816 | |
5275 | 1817 octave_idx_type nr = dim1 (); |
1818 octave_idx_type nc = dim2 (); | |
1819 | |
1820 octave_idx_type n = idx_i.freeze (nr, "row", resize_ok); | |
1821 octave_idx_type m = idx_j.freeze (nc, "column", resize_ok); | |
5164 | 1822 |
1823 if (idx_i && idx_j) | |
1824 { | |
1825 if (idx_i.orig_empty () || idx_j.orig_empty () || n == 0 || m == 0) | |
1826 { | |
1827 retval.resize_no_fill (n, m); | |
1828 } | |
5681 | 1829 else |
5164 | 1830 { |
5681 | 1831 int idx_i_colon = idx_i.is_colon_equiv (nr); |
1832 int idx_j_colon = idx_j.is_colon_equiv (nc); | |
1833 | |
1834 if (idx_i_colon && idx_j_colon) | |
1835 { | |
1836 retval = *this; | |
1837 } | |
1838 else | |
5164 | 1839 { |
5681 | 1840 // Identify if the indices have any repeated values |
1841 bool permutation = true; | |
1842 | |
1843 OCTAVE_LOCAL_BUFFER (octave_idx_type, itmp, | |
1844 (nr > nc ? nr : nc)); | |
7433 | 1845 octave_sort<octave_idx_type> lsort; |
5681 | 1846 |
1847 if (n > nr || m > nc) | |
1848 permutation = false; | |
1849 | |
1850 if (permutation && ! idx_i_colon) | |
1851 { | |
1852 // Can't use something like | |
1853 // idx_vector tmp_idx = idx_i; | |
1854 // tmp_idx.sort (true); | |
1855 // if (tmp_idx.length(nr) != n) | |
1856 // permutation = false; | |
1857 // here as there is no make_unique function | |
1858 // for idx_vector type. | |
1859 for (octave_idx_type i = 0; i < n; i++) | |
1860 itmp [i] = idx_i.elem (i); | |
7433 | 1861 lsort.sort (itmp, n); |
5681 | 1862 for (octave_idx_type i = 1; i < n; i++) |
1863 if (itmp[i-1] == itmp[i]) | |
1864 { | |
1865 permutation = false; | |
1866 break; | |
1867 } | |
1868 } | |
1869 if (permutation && ! idx_j_colon) | |
1870 { | |
1871 for (octave_idx_type i = 0; i < m; i++) | |
1872 itmp [i] = idx_j.elem (i); | |
7433 | 1873 lsort.sort (itmp, m); |
5681 | 1874 for (octave_idx_type i = 1; i < m; i++) |
1875 if (itmp[i-1] == itmp[i]) | |
1876 { | |
1877 permutation = false; | |
1878 break; | |
1879 } | |
1880 } | |
1881 | |
1882 if (permutation) | |
5164 | 1883 { |
5681 | 1884 // Special case permutation like indexing for speed |
1885 retval = Sparse<T> (n, m, nnz ()); | |
1886 octave_idx_type *ri = retval.xridx (); | |
1887 | |
5766 | 1888 std::vector<T> X (n); |
5681 | 1889 for (octave_idx_type i = 0; i < nr; i++) |
1890 itmp [i] = -1; | |
1891 for (octave_idx_type i = 0; i < n; i++) | |
1892 itmp[idx_i.elem(i)] = i; | |
1893 | |
1894 octave_idx_type kk = 0; | |
1895 retval.xcidx(0) = 0; | |
1896 for (octave_idx_type j = 0; j < m; j++) | |
1897 { | |
1898 octave_idx_type jj = idx_j.elem (j); | |
1899 for (octave_idx_type i = cidx(jj); i < cidx(jj+1); i++) | |
1900 { | |
6988 | 1901 OCTAVE_QUIT; |
1902 | |
5681 | 1903 octave_idx_type ii = itmp [ridx(i)]; |
1904 if (ii >= 0) | |
1905 { | |
1906 X [ii] = data (i); | |
1907 retval.xridx (kk++) = ii; | |
1908 } | |
1909 } | |
7433 | 1910 lsort.sort (ri + retval.xcidx (j), kk - retval.xcidx (j)); |
5681 | 1911 for (octave_idx_type p = retval.xcidx (j); p < kk; p++) |
1912 retval.xdata (p) = X [retval.xridx (p)]; | |
1913 retval.xcidx(j+1) = kk; | |
1914 } | |
1915 retval.maybe_compress (); | |
1916 } | |
1917 else | |
1918 { | |
6988 | 1919 OCTAVE_LOCAL_BUFFER (struct idx_node, nodes, n); |
1920 OCTAVE_LOCAL_BUFFER (octave_idx_type, start_nodes, nr); | |
1921 | |
1922 for (octave_idx_type i = 0; i < nr; i++) | |
1923 start_nodes[i] = -1; | |
1924 | |
1925 for (octave_idx_type i = 0; i < n; i++) | |
1926 { | |
1927 octave_idx_type ii = idx_i.elem (i); | |
1928 nodes[i].i = i; | |
1929 nodes[i].next = 0; | |
1930 | |
1931 octave_idx_type node = start_nodes[ii]; | |
1932 if (node == -1) | |
1933 start_nodes[ii] = i; | |
1934 else | |
1935 { | |
7322 | 1936 while (nodes[node].next) |
1937 node = nodes[node].next->i; | |
1938 nodes[node].next = nodes + i; | |
6988 | 1939 } |
1940 } | |
1941 | |
5681 | 1942 // First count the number of non-zero elements |
1943 octave_idx_type new_nzmx = 0; | |
1944 for (octave_idx_type j = 0; j < m; j++) | |
5164 | 1945 { |
5681 | 1946 octave_idx_type jj = idx_j.elem (j); |
6988 | 1947 |
1948 if (jj < nc) | |
5164 | 1949 { |
6988 | 1950 for (octave_idx_type i = cidx(jj); |
1951 i < cidx(jj+1); i++) | |
5681 | 1952 { |
6988 | 1953 OCTAVE_QUIT; |
1954 | |
1955 octave_idx_type ii = start_nodes [ridx(i)]; | |
1956 | |
1957 if (ii >= 0) | |
5681 | 1958 { |
6988 | 1959 struct idx_node inode = nodes[ii]; |
1960 | |
1961 while (true) | |
1962 { | |
7326 | 1963 if (idx_i.elem (inode.i) < nr) |
6988 | 1964 new_nzmx ++; |
1965 if (inode.next == 0) | |
1966 break; | |
1967 else | |
1968 inode = *inode.next; | |
1969 } | |
5681 | 1970 } |
1971 } | |
5164 | 1972 } |
1973 } | |
5681 | 1974 |
6988 | 1975 std::vector<T> X (n); |
5681 | 1976 retval = Sparse<T> (n, m, new_nzmx); |
6988 | 1977 octave_idx_type *ri = retval.xridx (); |
5681 | 1978 |
1979 octave_idx_type kk = 0; | |
1980 retval.xcidx(0) = 0; | |
1981 for (octave_idx_type j = 0; j < m; j++) | |
1982 { | |
1983 octave_idx_type jj = idx_j.elem (j); | |
6988 | 1984 if (jj < nc) |
5681 | 1985 { |
6988 | 1986 for (octave_idx_type i = cidx(jj); |
1987 i < cidx(jj+1); i++) | |
5681 | 1988 { |
6988 | 1989 OCTAVE_QUIT; |
1990 | |
1991 octave_idx_type ii = start_nodes [ridx(i)]; | |
1992 | |
1993 if (ii >= 0) | |
5681 | 1994 { |
6988 | 1995 struct idx_node inode = nodes[ii]; |
1996 | |
1997 while (true) | |
5681 | 1998 { |
7326 | 1999 if (idx_i.elem (inode.i) < nr) |
6988 | 2000 { |
2001 X [inode.i] = data (i); | |
2002 retval.xridx (kk++) = inode.i; | |
2003 } | |
2004 | |
2005 if (inode.next == 0) | |
2006 break; | |
2007 else | |
2008 inode = *inode.next; | |
5681 | 2009 } |
2010 } | |
2011 } | |
7433 | 2012 lsort.sort (ri + retval.xcidx (j), |
6988 | 2013 kk - retval.xcidx (j)); |
2014 for (octave_idx_type p = retval.xcidx (j); | |
2015 p < kk; p++) | |
2016 retval.xdata (p) = X [retval.xridx (p)]; | |
2017 retval.xcidx(j+1) = kk; | |
5681 | 2018 } |
2019 } | |
5164 | 2020 } |
2021 } | |
2022 } | |
2023 } | |
2024 // idx_vector::freeze() printed an error message for us. | |
2025 | |
2026 return retval; | |
2027 } | |
2028 | |
2029 template <class T> | |
2030 Sparse<T> | |
2031 Sparse<T>::index (Array<idx_vector>& ra_idx, int resize_ok) const | |
2032 { | |
2033 | |
2034 if (ra_idx.length () != 2) | |
2035 { | |
2036 (*current_liboctave_error_handler) ("range error for index"); | |
2037 return *this; | |
2038 } | |
2039 | |
2040 return index (ra_idx (0), ra_idx (1), resize_ok); | |
2041 } | |
2042 | |
7433 | 2043 // Can't use versions of these in Array.cc due to duplication of the |
2044 // instantiations for Array<double and Sparse<double>, etc | |
2045 template <class T> | |
2046 bool | |
2047 sparse_ascending_compare (T a, T b) | |
2048 { | |
2049 return (a < b); | |
2050 } | |
2051 | |
2052 template <class T> | |
2053 bool | |
2054 sparse_descending_compare (T a, T b) | |
2055 { | |
2056 return (a > b); | |
2057 } | |
2058 | |
2059 template <class T> | |
2060 bool | |
2061 sparse_ascending_compare (vec_index<T> *a, vec_index<T> *b) | |
2062 { | |
2063 return (a->vec < b->vec); | |
2064 } | |
2065 | |
2066 template <class T> | |
2067 bool | |
2068 sparse_descending_compare (vec_index<T> *a, vec_index<T> *b) | |
2069 { | |
2070 return (a->vec > b->vec); | |
2071 } | |
2072 | |
2073 template <class T> | |
2074 Sparse<T> | |
2075 Sparse<T>::sort (octave_idx_type dim, sortmode mode) const | |
2076 { | |
2077 Sparse<T> m = *this; | |
2078 | |
2079 octave_idx_type nr = m.rows (); | |
2080 octave_idx_type nc = m.columns (); | |
2081 | |
2082 if (m.length () < 1) | |
2083 return m; | |
2084 | |
2085 if (dim > 0) | |
2086 { | |
2087 m = m.transpose (); | |
2088 nr = m.rows (); | |
2089 nc = m.columns (); | |
2090 } | |
2091 | |
2092 octave_sort<T> lsort; | |
2093 | |
2094 if (mode == ASCENDING) | |
2095 lsort.set_compare (sparse_ascending_compare); | |
2096 else if (mode == DESCENDING) | |
2097 lsort.set_compare (sparse_descending_compare); | |
7463
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
2098 else |
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
2099 abort (); |
7433 | 2100 |
2101 T *v = m.data (); | |
2102 octave_idx_type *mcidx = m.cidx (); | |
2103 octave_idx_type *mridx = m.ridx (); | |
2104 | |
2105 for (octave_idx_type j = 0; j < nc; j++) | |
2106 { | |
2107 octave_idx_type ns = mcidx [j + 1] - mcidx [j]; | |
2108 lsort.sort (v, ns); | |
2109 | |
2110 octave_idx_type i; | |
2111 if (mode == ASCENDING) | |
2112 { | |
2113 for (i = 0; i < ns; i++) | |
2114 if (sparse_ascending_compare (static_cast<T> (0), v [i])) | |
2115 break; | |
2116 } | |
2117 else | |
2118 { | |
2119 for (i = 0; i < ns; i++) | |
2120 if (sparse_descending_compare (static_cast<T> (0), v [i])) | |
2121 break; | |
2122 } | |
2123 for (octave_idx_type k = 0; k < i; k++) | |
2124 mridx [k] = k; | |
2125 for (octave_idx_type k = i; k < ns; k++) | |
2126 mridx [k] = k - ns + nr; | |
2127 | |
2128 v += ns; | |
2129 mridx += ns; | |
2130 } | |
2131 | |
2132 if (dim > 0) | |
2133 m = m.transpose (); | |
2134 | |
2135 return m; | |
2136 } | |
2137 | |
2138 template <class T> | |
2139 Sparse<T> | |
2140 Sparse<T>::sort (Array<octave_idx_type> &sidx, octave_idx_type dim, | |
2141 sortmode mode) const | |
2142 { | |
2143 Sparse<T> m = *this; | |
2144 | |
2145 octave_idx_type nr = m.rows (); | |
2146 octave_idx_type nc = m.columns (); | |
2147 | |
2148 if (m.length () < 1) | |
2149 { | |
2150 sidx = Array<octave_idx_type> (dim_vector (nr, nc)); | |
2151 return m; | |
2152 } | |
2153 | |
2154 if (dim > 0) | |
2155 { | |
2156 m = m.transpose (); | |
2157 nr = m.rows (); | |
2158 nc = m.columns (); | |
2159 } | |
2160 | |
2161 octave_sort<vec_index<T> *> indexed_sort; | |
2162 | |
2163 if (mode == ASCENDING) | |
2164 indexed_sort.set_compare (sparse_ascending_compare); | |
2165 else if (mode == DESCENDING) | |
2166 indexed_sort.set_compare (sparse_descending_compare); | |
7463
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
2167 else |
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
2168 abort (); |
7433 | 2169 |
2170 T *v = m.data (); | |
2171 octave_idx_type *mcidx = m.cidx (); | |
2172 octave_idx_type *mridx = m.ridx (); | |
2173 | |
2174 OCTAVE_LOCAL_BUFFER (vec_index<T> *, vi, nr); | |
2175 OCTAVE_LOCAL_BUFFER (vec_index<T>, vix, nr); | |
2176 | |
2177 for (octave_idx_type i = 0; i < nr; i++) | |
2178 vi[i] = &vix[i]; | |
2179 | |
2180 sidx = Array<octave_idx_type> (dim_vector (nr, nc)); | |
2181 | |
2182 for (octave_idx_type j = 0; j < nc; j++) | |
2183 { | |
2184 octave_idx_type ns = mcidx [j + 1] - mcidx [j]; | |
2185 octave_idx_type offset = j * nr; | |
2186 | |
2187 if (ns == 0) | |
2188 { | |
2189 for (octave_idx_type k = 0; k < nr; k++) | |
2190 sidx (offset + k) = k; | |
2191 } | |
2192 else | |
2193 { | |
2194 for (octave_idx_type i = 0; i < ns; i++) | |
2195 { | |
2196 vi[i]->vec = v[i]; | |
2197 vi[i]->indx = mridx[i]; | |
2198 } | |
2199 | |
2200 indexed_sort.sort (vi, ns); | |
2201 | |
2202 octave_idx_type i; | |
2203 if (mode == ASCENDING) | |
2204 { | |
2205 for (i = 0; i < ns; i++) | |
2206 if (sparse_ascending_compare (static_cast<T> (0), | |
2207 vi [i] -> vec)) | |
2208 break; | |
2209 } | |
2210 else | |
2211 { | |
2212 for (i = 0; i < ns; i++) | |
2213 if (sparse_descending_compare (static_cast<T> (0), | |
2214 vi [i] -> vec)) | |
2215 break; | |
2216 } | |
2217 | |
2218 octave_idx_type ii = 0; | |
2219 octave_idx_type jj = i; | |
2220 for (octave_idx_type k = 0; k < nr; k++) | |
2221 { | |
2222 if (ii < ns && mridx[ii] == k) | |
2223 ii++; | |
2224 else | |
2225 sidx (offset + jj++) = k; | |
2226 } | |
2227 | |
2228 for (octave_idx_type k = 0; k < i; k++) | |
2229 { | |
2230 v [k] = vi [k] -> vec; | |
2231 sidx (k + offset) = vi [k] -> indx; | |
2232 mridx [k] = k; | |
2233 } | |
2234 | |
2235 for (octave_idx_type k = i; k < ns; k++) | |
2236 { | |
2237 v [k] = vi [k] -> vec; | |
2238 sidx (k - ns + nr + offset) = vi [k] -> indx; | |
2239 mridx [k] = k - ns + nr; | |
2240 } | |
2241 | |
2242 v += ns; | |
2243 mridx += ns; | |
2244 } | |
2245 } | |
2246 | |
2247 if (dim > 0) | |
2248 { | |
2249 m = m.transpose (); | |
2250 sidx = sidx.transpose (); | |
2251 } | |
2252 | |
2253 return m; | |
2254 } | |
2255 | |
5775 | 2256 // FIXME |
5164 | 2257 // Unfortunately numel can overflow for very large but very sparse matrices. |
2258 // For now just flag an error when this happens. | |
2259 template <class LT, class RT> | |
2260 int | |
2261 assign1 (Sparse<LT>& lhs, const Sparse<RT>& rhs) | |
2262 { | |
2263 int retval = 1; | |
2264 | |
2265 idx_vector *idx_tmp = lhs.get_idx (); | |
2266 | |
2267 idx_vector lhs_idx = idx_tmp[0]; | |
2268 | |
5275 | 2269 octave_idx_type lhs_len = lhs.numel (); |
2270 octave_idx_type rhs_len = rhs.numel (); | |
5164 | 2271 |
5828 | 2272 uint64_t long_lhs_len = |
2273 static_cast<uint64_t> (lhs.rows ()) * | |
2274 static_cast<uint64_t> (lhs.cols ()); | |
2275 | |
2276 uint64_t long_rhs_len = | |
2277 static_cast<uint64_t> (rhs.rows ()) * | |
2278 static_cast<uint64_t> (rhs.cols ()); | |
2279 | |
2280 if (long_rhs_len != static_cast<uint64_t>(rhs_len) || | |
2281 long_lhs_len != static_cast<uint64_t>(lhs_len)) | |
5164 | 2282 { |
2283 (*current_liboctave_error_handler) | |
2284 ("A(I) = X: Matrix dimensions too large to ensure correct\n", | |
2285 "operation. This is an limitation that should be removed\n", | |
2286 "in the future."); | |
2287 | |
2288 lhs.clear_index (); | |
2289 return 0; | |
2290 } | |
2291 | |
5275 | 2292 octave_idx_type nr = lhs.rows (); |
2293 octave_idx_type nc = lhs.cols (); | |
5681 | 2294 octave_idx_type nz = lhs.nnz (); |
5275 | 2295 |
5781 | 2296 octave_idx_type n = lhs_idx.freeze (lhs_len, "vector", true); |
5164 | 2297 |
2298 if (n != 0) | |
2299 { | |
5275 | 2300 octave_idx_type max_idx = lhs_idx.max () + 1; |
5164 | 2301 max_idx = max_idx < lhs_len ? lhs_len : max_idx; |
2302 | |
2303 // Take a constant copy of lhs. This means that elem won't | |
2304 // create missing elements. | |
2305 const Sparse<LT> c_lhs (lhs); | |
2306 | |
2307 if (rhs_len == n) | |
2308 { | |
5681 | 2309 octave_idx_type new_nzmx = lhs.nnz (); |
5164 | 2310 |
5603 | 2311 OCTAVE_LOCAL_BUFFER (octave_idx_type, rhs_idx, n); |
2312 if (! lhs_idx.is_colon ()) | |
2313 { | |
2314 // Ok here we have to be careful with the indexing, | |
2315 // to treat cases like "a([3,2,1]) = b", and still | |
2316 // handle the need for strict sorting of the sparse | |
2317 // elements. | |
2318 OCTAVE_LOCAL_BUFFER (octave_idx_vector_sort *, sidx, n); | |
2319 OCTAVE_LOCAL_BUFFER (octave_idx_vector_sort, sidxX, n); | |
2320 | |
2321 for (octave_idx_type i = 0; i < n; i++) | |
2322 { | |
2323 sidx[i] = &sidxX[i]; | |
2324 sidx[i]->i = lhs_idx.elem(i); | |
2325 sidx[i]->idx = i; | |
2326 } | |
2327 | |
2328 OCTAVE_QUIT; | |
2329 octave_sort<octave_idx_vector_sort *> | |
2330 sort (octave_idx_vector_comp); | |
2331 | |
2332 sort.sort (sidx, n); | |
2333 | |
2334 intNDArray<octave_idx_type> new_idx (dim_vector (n,1)); | |
2335 | |
2336 for (octave_idx_type i = 0; i < n; i++) | |
2337 { | |
2338 new_idx.xelem(i) = sidx[i]->i + 1; | |
2339 rhs_idx[i] = sidx[i]->idx; | |
2340 } | |
2341 | |
2342 lhs_idx = idx_vector (new_idx); | |
2343 } | |
2344 else | |
2345 for (octave_idx_type i = 0; i < n; i++) | |
2346 rhs_idx[i] = i; | |
2347 | |
5164 | 2348 // First count the number of non-zero elements |
5275 | 2349 for (octave_idx_type i = 0; i < n; i++) |
5164 | 2350 { |
2351 OCTAVE_QUIT; | |
2352 | |
5275 | 2353 octave_idx_type ii = lhs_idx.elem (i); |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2354 if (i < n - 1 && lhs_idx.elem (i + 1) == ii) |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2355 continue; |
5164 | 2356 if (ii < lhs_len && c_lhs.elem(ii) != LT ()) |
5604 | 2357 new_nzmx--; |
5603 | 2358 if (rhs.elem(rhs_idx[i]) != RT ()) |
5604 | 2359 new_nzmx++; |
5164 | 2360 } |
2361 | |
2362 if (nr > 1) | |
2363 { | |
7246 | 2364 Sparse<LT> tmp ((max_idx > nr ? max_idx : nr), 1, new_nzmx); |
5164 | 2365 tmp.cidx(0) = 0; |
5681 | 2366 tmp.cidx(1) = new_nzmx; |
5164 | 2367 |
5275 | 2368 octave_idx_type i = 0; |
2369 octave_idx_type ii = 0; | |
5164 | 2370 if (i < nz) |
2371 ii = c_lhs.ridx(i); | |
2372 | |
5275 | 2373 octave_idx_type j = 0; |
2374 octave_idx_type jj = lhs_idx.elem(j); | |
2375 | |
2376 octave_idx_type kk = 0; | |
5164 | 2377 |
2378 while (j < n || i < nz) | |
2379 { | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2380 if (j < n - 1 && lhs_idx.elem (j + 1) == jj) |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2381 { |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2382 j++; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2383 jj = lhs_idx.elem (j); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2384 continue; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2385 } |
5164 | 2386 if (j == n || (i < nz && ii < jj)) |
2387 { | |
2388 tmp.xdata (kk) = c_lhs.data (i); | |
2389 tmp.xridx (kk++) = ii; | |
2390 if (++i < nz) | |
2391 ii = c_lhs.ridx(i); | |
2392 } | |
2393 else | |
2394 { | |
5603 | 2395 RT rtmp = rhs.elem (rhs_idx[j]); |
5164 | 2396 if (rtmp != RT ()) |
2397 { | |
2398 tmp.xdata (kk) = rtmp; | |
2399 tmp.xridx (kk++) = jj; | |
2400 } | |
2401 | |
2402 if (ii == jj && i < nz) | |
2403 if (++i < nz) | |
2404 ii = c_lhs.ridx(i); | |
2405 if (++j < n) | |
2406 jj = lhs_idx.elem(j); | |
2407 } | |
2408 } | |
2409 | |
2410 lhs = tmp; | |
2411 } | |
2412 else | |
2413 { | |
7246 | 2414 Sparse<LT> tmp (1, (max_idx > nc ? max_idx : nc), new_nzmx); |
5164 | 2415 |
5275 | 2416 octave_idx_type i = 0; |
2417 octave_idx_type ii = 0; | |
5164 | 2418 while (ii < nc && c_lhs.cidx(ii+1) <= i) |
2419 ii++; | |
2420 | |
5275 | 2421 octave_idx_type j = 0; |
2422 octave_idx_type jj = lhs_idx.elem(j); | |
2423 | |
2424 octave_idx_type kk = 0; | |
2425 octave_idx_type ic = 0; | |
5164 | 2426 |
2427 while (j < n || i < nz) | |
2428 { | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2429 if (j < n - 1 && lhs_idx.elem (j + 1) == jj) |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2430 { |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2431 j++; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2432 jj = lhs_idx.elem (j); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2433 continue; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2434 } |
5164 | 2435 if (j == n || (i < nz && ii < jj)) |
2436 { | |
2437 while (ic <= ii) | |
2438 tmp.xcidx (ic++) = kk; | |
2439 tmp.xdata (kk) = c_lhs.data (i); | |
5603 | 2440 tmp.xridx (kk++) = 0; |
5164 | 2441 i++; |
2442 while (ii < nc && c_lhs.cidx(ii+1) <= i) | |
2443 ii++; | |
2444 } | |
2445 else | |
2446 { | |
2447 while (ic <= jj) | |
2448 tmp.xcidx (ic++) = kk; | |
2449 | |
5603 | 2450 RT rtmp = rhs.elem (rhs_idx[j]); |
5164 | 2451 if (rtmp != RT ()) |
5603 | 2452 { |
2453 tmp.xdata (kk) = rtmp; | |
2454 tmp.xridx (kk++) = 0; | |
2455 } | |
5164 | 2456 if (ii == jj) |
2457 { | |
2458 i++; | |
2459 while (ii < nc && c_lhs.cidx(ii+1) <= i) | |
2460 ii++; | |
2461 } | |
2462 j++; | |
2463 if (j < n) | |
2464 jj = lhs_idx.elem(j); | |
2465 } | |
2466 } | |
2467 | |
5275 | 2468 for (octave_idx_type iidx = ic; iidx < max_idx+1; iidx++) |
5164 | 2469 tmp.xcidx(iidx) = kk; |
2470 | |
2471 lhs = tmp; | |
2472 } | |
2473 } | |
2474 else if (rhs_len == 1) | |
2475 { | |
5681 | 2476 octave_idx_type new_nzmx = lhs.nnz (); |
5164 | 2477 RT scalar = rhs.elem (0); |
2478 bool scalar_non_zero = (scalar != RT ()); | |
5603 | 2479 lhs_idx.sort (true); |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2480 n = lhs_idx.length (n); |
5164 | 2481 |
2482 // First count the number of non-zero elements | |
2483 if (scalar != RT ()) | |
5604 | 2484 new_nzmx += n; |
5275 | 2485 for (octave_idx_type i = 0; i < n; i++) |
5164 | 2486 { |
2487 OCTAVE_QUIT; | |
2488 | |
5275 | 2489 octave_idx_type ii = lhs_idx.elem (i); |
5164 | 2490 if (ii < lhs_len && c_lhs.elem(ii) != LT ()) |
5604 | 2491 new_nzmx--; |
5164 | 2492 } |
2493 | |
2494 if (nr > 1) | |
2495 { | |
7246 | 2496 Sparse<LT> tmp ((max_idx > nr ? max_idx : nr), 1, new_nzmx); |
5164 | 2497 tmp.cidx(0) = 0; |
5681 | 2498 tmp.cidx(1) = new_nzmx; |
5164 | 2499 |
5275 | 2500 octave_idx_type i = 0; |
2501 octave_idx_type ii = 0; | |
5164 | 2502 if (i < nz) |
2503 ii = c_lhs.ridx(i); | |
2504 | |
5275 | 2505 octave_idx_type j = 0; |
2506 octave_idx_type jj = lhs_idx.elem(j); | |
2507 | |
2508 octave_idx_type kk = 0; | |
5164 | 2509 |
2510 while (j < n || i < nz) | |
2511 { | |
2512 if (j == n || (i < nz && ii < jj)) | |
2513 { | |
2514 tmp.xdata (kk) = c_lhs.data (i); | |
2515 tmp.xridx (kk++) = ii; | |
2516 if (++i < nz) | |
2517 ii = c_lhs.ridx(i); | |
2518 } | |
2519 else | |
2520 { | |
2521 if (scalar_non_zero) | |
2522 { | |
2523 tmp.xdata (kk) = scalar; | |
2524 tmp.xridx (kk++) = jj; | |
2525 } | |
2526 | |
2527 if (ii == jj && i < nz) | |
2528 if (++i < nz) | |
2529 ii = c_lhs.ridx(i); | |
2530 if (++j < n) | |
2531 jj = lhs_idx.elem(j); | |
2532 } | |
2533 } | |
2534 | |
2535 lhs = tmp; | |
2536 } | |
2537 else | |
2538 { | |
7246 | 2539 Sparse<LT> tmp (1, (max_idx > nc ? max_idx : nc), new_nzmx); |
5164 | 2540 |
5275 | 2541 octave_idx_type i = 0; |
2542 octave_idx_type ii = 0; | |
5164 | 2543 while (ii < nc && c_lhs.cidx(ii+1) <= i) |
2544 ii++; | |
2545 | |
5275 | 2546 octave_idx_type j = 0; |
2547 octave_idx_type jj = lhs_idx.elem(j); | |
2548 | |
2549 octave_idx_type kk = 0; | |
2550 octave_idx_type ic = 0; | |
5164 | 2551 |
2552 while (j < n || i < nz) | |
2553 { | |
2554 if (j == n || (i < nz && ii < jj)) | |
2555 { | |
2556 while (ic <= ii) | |
2557 tmp.xcidx (ic++) = kk; | |
2558 tmp.xdata (kk) = c_lhs.data (i); | |
2559 i++; | |
2560 while (ii < nc && c_lhs.cidx(ii+1) <= i) | |
2561 ii++; | |
2562 } | |
2563 else | |
2564 { | |
2565 while (ic <= jj) | |
2566 tmp.xcidx (ic++) = kk; | |
2567 if (scalar_non_zero) | |
2568 tmp.xdata (kk) = scalar; | |
2569 if (ii == jj) | |
2570 { | |
2571 i++; | |
2572 while (ii < nc && c_lhs.cidx(ii+1) <= i) | |
2573 ii++; | |
2574 } | |
2575 j++; | |
2576 if (j < n) | |
2577 jj = lhs_idx.elem(j); | |
2578 } | |
2579 tmp.xridx (kk++) = 0; | |
2580 } | |
2581 | |
5275 | 2582 for (octave_idx_type iidx = ic; iidx < max_idx+1; iidx++) |
5164 | 2583 tmp.xcidx(iidx) = kk; |
2584 | |
2585 lhs = tmp; | |
2586 } | |
2587 } | |
2588 else | |
2589 { | |
2590 (*current_liboctave_error_handler) | |
2591 ("A(I) = X: X must be a scalar or a vector with same length as I"); | |
2592 | |
2593 retval = 0; | |
2594 } | |
2595 } | |
2596 else if (lhs_idx.is_colon ()) | |
2597 { | |
2598 if (lhs_len == 0) | |
2599 { | |
2600 | |
5681 | 2601 octave_idx_type new_nzmx = rhs.nnz (); |
5604 | 2602 Sparse<LT> tmp (1, rhs_len, new_nzmx); |
5164 | 2603 |
5275 | 2604 octave_idx_type ii = 0; |
2605 octave_idx_type jj = 0; | |
2606 for (octave_idx_type i = 0; i < rhs.cols(); i++) | |
2607 for (octave_idx_type j = rhs.cidx(i); j < rhs.cidx(i+1); j++) | |
5164 | 2608 { |
2609 OCTAVE_QUIT; | |
5275 | 2610 for (octave_idx_type k = jj; k <= i * rhs.rows() + rhs.ridx(j); k++) |
5164 | 2611 tmp.cidx(jj++) = ii; |
2612 | |
2613 tmp.data(ii) = rhs.data(j); | |
2614 tmp.ridx(ii++) = 0; | |
2615 } | |
2616 | |
5275 | 2617 for (octave_idx_type i = jj; i < rhs_len + 1; i++) |
5164 | 2618 tmp.cidx(i) = ii; |
2619 | |
2620 lhs = tmp; | |
2621 } | |
2622 else | |
2623 (*current_liboctave_error_handler) | |
2624 ("A(:) = X: A must be the same size as X"); | |
2625 } | |
2626 else if (! (rhs_len == 1 || rhs_len == 0)) | |
2627 { | |
2628 (*current_liboctave_error_handler) | |
2629 ("A([]) = X: X must also be an empty matrix or a scalar"); | |
2630 | |
2631 retval = 0; | |
2632 } | |
2633 | |
2634 lhs.clear_index (); | |
2635 | |
2636 return retval; | |
2637 } | |
2638 | |
2639 template <class LT, class RT> | |
2640 int | |
2641 assign (Sparse<LT>& lhs, const Sparse<RT>& rhs) | |
2642 { | |
2643 int retval = 1; | |
2644 | |
2645 int n_idx = lhs.index_count (); | |
2646 | |
5275 | 2647 octave_idx_type lhs_nr = lhs.rows (); |
2648 octave_idx_type lhs_nc = lhs.cols (); | |
5681 | 2649 octave_idx_type lhs_nz = lhs.nnz (); |
5275 | 2650 |
2651 octave_idx_type rhs_nr = rhs.rows (); | |
2652 octave_idx_type rhs_nc = rhs.cols (); | |
5164 | 2653 |
2654 idx_vector *tmp = lhs.get_idx (); | |
2655 | |
2656 idx_vector idx_i; | |
2657 idx_vector idx_j; | |
2658 | |
2659 if (n_idx > 2) | |
2660 { | |
2661 (*current_liboctave_error_handler) | |
2662 ("A(I, J) = X: can only have 1 or 2 indexes for sparse matrices"); | |
6092 | 2663 |
2664 lhs.clear_index (); | |
5164 | 2665 return 0; |
2666 } | |
2667 | |
2668 if (n_idx > 1) | |
2669 idx_j = tmp[1]; | |
2670 | |
2671 if (n_idx > 0) | |
2672 idx_i = tmp[0]; | |
2673 | |
6988 | 2674 // Take a constant copy of lhs. This means that ridx and family won't |
2675 // call make_unique. | |
2676 const Sparse<LT> c_lhs (lhs); | |
2677 | |
5164 | 2678 if (n_idx == 2) |
2679 { | |
5781 | 2680 octave_idx_type n = idx_i.freeze (lhs_nr, "row", true); |
2681 octave_idx_type m = idx_j.freeze (lhs_nc, "column", true); | |
5164 | 2682 |
2683 int idx_i_is_colon = idx_i.is_colon (); | |
2684 int idx_j_is_colon = idx_j.is_colon (); | |
2685 | |
7238 | 2686 if (lhs_nr == 0 && lhs_nc == 0) |
2687 { | |
2688 if (idx_i_is_colon) | |
2689 n = rhs_nr; | |
2690 | |
2691 if (idx_j_is_colon) | |
2692 m = rhs_nc; | |
2693 } | |
5164 | 2694 |
2695 if (idx_i && idx_j) | |
2696 { | |
2697 if (rhs_nr == 0 && rhs_nc == 0) | |
2698 { | |
2699 lhs.maybe_delete_elements (idx_i, idx_j); | |
2700 } | |
2701 else | |
2702 { | |
2703 if (rhs_nr == 1 && rhs_nc == 1 && n >= 0 && m >= 0) | |
2704 { | |
2705 if (n > 0 && m > 0) | |
2706 { | |
5603 | 2707 idx_i.sort (true); |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2708 n = idx_i.length (n); |
5603 | 2709 idx_j.sort (true); |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2710 m = idx_j.length (m); |
5603 | 2711 |
5275 | 2712 octave_idx_type max_row_idx = idx_i_is_colon ? rhs_nr : |
5164 | 2713 idx_i.max () + 1; |
5275 | 2714 octave_idx_type max_col_idx = idx_j_is_colon ? rhs_nc : |
5164 | 2715 idx_j.max () + 1; |
5603 | 2716 octave_idx_type new_nr = max_row_idx > lhs_nr ? |
2717 max_row_idx : lhs_nr; | |
2718 octave_idx_type new_nc = max_col_idx > lhs_nc ? | |
2719 max_col_idx : lhs_nc; | |
5164 | 2720 RT scalar = rhs.elem (0, 0); |
2721 | |
2722 // Count the number of non-zero terms | |
5681 | 2723 octave_idx_type new_nzmx = lhs.nnz (); |
5275 | 2724 for (octave_idx_type j = 0; j < m; j++) |
5164 | 2725 { |
5275 | 2726 octave_idx_type jj = idx_j.elem (j); |
5164 | 2727 if (jj < lhs_nc) |
2728 { | |
5275 | 2729 for (octave_idx_type i = 0; i < n; i++) |
5164 | 2730 { |
2731 OCTAVE_QUIT; | |
2732 | |
5275 | 2733 octave_idx_type ii = idx_i.elem (i); |
5164 | 2734 |
2735 if (ii < lhs_nr) | |
2736 { | |
6988 | 2737 for (octave_idx_type k = c_lhs.cidx(jj); |
2738 k < c_lhs.cidx(jj+1); k++) | |
5164 | 2739 { |
6988 | 2740 if (c_lhs.ridx(k) == ii) |
5604 | 2741 new_nzmx--; |
6988 | 2742 if (c_lhs.ridx(k) >= ii) |
5164 | 2743 break; |
2744 } | |
2745 } | |
2746 } | |
2747 } | |
2748 } | |
2749 | |
2750 if (scalar != RT()) | |
5604 | 2751 new_nzmx += m * n; |
2752 | |
2753 Sparse<LT> stmp (new_nr, new_nc, new_nzmx); | |
5164 | 2754 |
5275 | 2755 octave_idx_type jji = 0; |
2756 octave_idx_type jj = idx_j.elem (jji); | |
2757 octave_idx_type kk = 0; | |
5164 | 2758 stmp.cidx(0) = 0; |
5275 | 2759 for (octave_idx_type j = 0; j < new_nc; j++) |
5164 | 2760 { |
2761 if (jji < m && jj == j) | |
2762 { | |
5275 | 2763 octave_idx_type iii = 0; |
2764 octave_idx_type ii = idx_i.elem (iii); | |
5760 | 2765 octave_idx_type ppp = 0; |
6092 | 2766 octave_idx_type ppi = (j >= lhs_nc ? 0 : |
6988 | 2767 c_lhs.cidx(j+1) - |
2768 c_lhs.cidx(j)); | |
5760 | 2769 octave_idx_type pp = (ppp < ppi ? |
6988 | 2770 c_lhs.ridx(c_lhs.cidx(j)+ppp) : |
2771 new_nr); | |
5760 | 2772 while (ppp < ppi || iii < n) |
5164 | 2773 { |
5760 | 2774 if (iii < n && ii <= pp) |
5164 | 2775 { |
2776 if (scalar != RT ()) | |
2777 { | |
2778 stmp.data(kk) = scalar; | |
5760 | 2779 stmp.ridx(kk++) = ii; |
5164 | 2780 } |
5760 | 2781 if (ii == pp) |
6988 | 2782 pp = (++ppp < ppi ? c_lhs.ridx(c_lhs.cidx(j)+ppp) : new_nr); |
5164 | 2783 if (++iii < n) |
2784 ii = idx_i.elem(iii); | |
2785 } | |
5760 | 2786 else |
5164 | 2787 { |
5760 | 2788 stmp.data(kk) = |
6988 | 2789 c_lhs.data(c_lhs.cidx(j)+ppp); |
5760 | 2790 stmp.ridx(kk++) = pp; |
6988 | 2791 pp = (++ppp < ppi ? c_lhs.ridx(c_lhs.cidx(j)+ppp) : new_nr); |
5164 | 2792 } |
2793 } | |
2794 if (++jji < m) | |
2795 jj = idx_j.elem(jji); | |
2796 } | |
6988 | 2797 else if (j < lhs_nc) |
5164 | 2798 { |
6988 | 2799 for (octave_idx_type i = c_lhs.cidx(j); |
2800 i < c_lhs.cidx(j+1); i++) | |
5164 | 2801 { |
6988 | 2802 stmp.data(kk) = c_lhs.data(i); |
2803 stmp.ridx(kk++) = c_lhs.ridx(i); | |
5164 | 2804 } |
2805 } | |
2806 stmp.cidx(j+1) = kk; | |
2807 } | |
2808 | |
2809 lhs = stmp; | |
2810 } | |
7246 | 2811 else |
2812 { | |
7253 | 2813 #if 0 |
2814 // FIXME -- the following code will make this | |
2815 // function behave the same as the full matrix | |
2816 // case for things like | |
2817 // | |
2818 // x = sparse (ones (2)); | |
2819 // x([],3) = 2; | |
2820 // | |
2821 // x = | |
2822 // | |
2823 // Compressed Column Sparse (rows = 2, cols = 3, nnz = 4) | |
2824 // | |
2825 // (1, 1) -> 1 | |
2826 // (2, 1) -> 1 | |
2827 // (1, 2) -> 1 | |
2828 // (2, 2) -> 1 | |
2829 // | |
2830 // However, Matlab doesn't resize in this case | |
2831 // even though it does in the full matrix case. | |
2832 | |
7246 | 2833 if (n > 0) |
2834 { | |
2835 octave_idx_type max_row_idx = idx_i_is_colon ? | |
2836 rhs_nr : idx_i.max () + 1; | |
2837 octave_idx_type new_nr = max_row_idx > lhs_nr ? | |
2838 max_row_idx : lhs_nr; | |
2839 octave_idx_type new_nc = lhs_nc; | |
2840 | |
7253 | 2841 lhs.resize (new_nr, new_nc); |
7246 | 2842 } |
2843 else if (m > 0) | |
2844 { | |
2845 octave_idx_type max_col_idx = idx_j_is_colon ? | |
2846 rhs_nc : idx_j.max () + 1; | |
2847 octave_idx_type new_nr = lhs_nr; | |
2848 octave_idx_type new_nc = max_col_idx > lhs_nc ? | |
2849 max_col_idx : lhs_nc; | |
2850 | |
7253 | 2851 lhs.resize (new_nr, new_nc); |
7246 | 2852 } |
7253 | 2853 #endif |
7246 | 2854 } |
5164 | 2855 } |
2856 else if (n == rhs_nr && m == rhs_nc) | |
2857 { | |
2858 if (n > 0 && m > 0) | |
2859 { | |
5275 | 2860 octave_idx_type max_row_idx = idx_i_is_colon ? rhs_nr : |
5164 | 2861 idx_i.max () + 1; |
5275 | 2862 octave_idx_type max_col_idx = idx_j_is_colon ? rhs_nc : |
5164 | 2863 idx_j.max () + 1; |
5603 | 2864 octave_idx_type new_nr = max_row_idx > lhs_nr ? |
2865 max_row_idx : lhs_nr; | |
2866 octave_idx_type new_nc = max_col_idx > lhs_nc ? | |
2867 max_col_idx : lhs_nc; | |
2868 | |
2869 OCTAVE_LOCAL_BUFFER (octave_idx_type, rhs_idx_i, n); | |
2870 if (! idx_i.is_colon ()) | |
2871 { | |
2872 // Ok here we have to be careful with the indexing, | |
2873 // to treat cases like "a([3,2,1],:) = b", and still | |
2874 // handle the need for strict sorting of the sparse | |
2875 // elements. | |
2876 OCTAVE_LOCAL_BUFFER (octave_idx_vector_sort *, | |
2877 sidx, n); | |
2878 OCTAVE_LOCAL_BUFFER (octave_idx_vector_sort, | |
2879 sidxX, n); | |
2880 | |
2881 for (octave_idx_type i = 0; i < n; i++) | |
2882 { | |
2883 sidx[i] = &sidxX[i]; | |
2884 sidx[i]->i = idx_i.elem(i); | |
2885 sidx[i]->idx = i; | |
2886 } | |
2887 | |
2888 OCTAVE_QUIT; | |
2889 octave_sort<octave_idx_vector_sort *> | |
2890 sort (octave_idx_vector_comp); | |
2891 | |
2892 sort.sort (sidx, n); | |
2893 | |
2894 intNDArray<octave_idx_type> new_idx (dim_vector (n,1)); | |
2895 | |
2896 for (octave_idx_type i = 0; i < n; i++) | |
2897 { | |
2898 new_idx.xelem(i) = sidx[i]->i + 1; | |
2899 rhs_idx_i[i] = sidx[i]->idx; | |
2900 } | |
2901 | |
2902 idx_i = idx_vector (new_idx); | |
2903 } | |
2904 else | |
2905 for (octave_idx_type i = 0; i < n; i++) | |
2906 rhs_idx_i[i] = i; | |
2907 | |
2908 OCTAVE_LOCAL_BUFFER (octave_idx_type, rhs_idx_j, m); | |
2909 if (! idx_j.is_colon ()) | |
2910 { | |
2911 // Ok here we have to be careful with the indexing, | |
2912 // to treat cases like "a([3,2,1],:) = b", and still | |
2913 // handle the need for strict sorting of the sparse | |
2914 // elements. | |
2915 OCTAVE_LOCAL_BUFFER (octave_idx_vector_sort *, | |
2916 sidx, m); | |
2917 OCTAVE_LOCAL_BUFFER (octave_idx_vector_sort, | |
2918 sidxX, m); | |
2919 | |
2920 for (octave_idx_type i = 0; i < m; i++) | |
2921 { | |
2922 sidx[i] = &sidxX[i]; | |
2923 sidx[i]->i = idx_j.elem(i); | |
2924 sidx[i]->idx = i; | |
2925 } | |
2926 | |
2927 OCTAVE_QUIT; | |
2928 octave_sort<octave_idx_vector_sort *> | |
2929 sort (octave_idx_vector_comp); | |
2930 | |
2931 sort.sort (sidx, m); | |
2932 | |
2933 intNDArray<octave_idx_type> new_idx (dim_vector (m,1)); | |
2934 | |
2935 for (octave_idx_type i = 0; i < m; i++) | |
2936 { | |
2937 new_idx.xelem(i) = sidx[i]->i + 1; | |
2938 rhs_idx_j[i] = sidx[i]->idx; | |
2939 } | |
2940 | |
2941 idx_j = idx_vector (new_idx); | |
2942 } | |
2943 else | |
2944 for (octave_idx_type i = 0; i < m; i++) | |
2945 rhs_idx_j[i] = i; | |
5164 | 2946 |
5760 | 2947 // Maximum number of non-zero elements |
2948 octave_idx_type new_nzmx = lhs.nnz() + rhs.nnz(); | |
5164 | 2949 |
5604 | 2950 Sparse<LT> stmp (new_nr, new_nc, new_nzmx); |
5164 | 2951 |
5275 | 2952 octave_idx_type jji = 0; |
2953 octave_idx_type jj = idx_j.elem (jji); | |
2954 octave_idx_type kk = 0; | |
5164 | 2955 stmp.cidx(0) = 0; |
5275 | 2956 for (octave_idx_type j = 0; j < new_nc; j++) |
5164 | 2957 { |
2958 if (jji < m && jj == j) | |
2959 { | |
5275 | 2960 octave_idx_type iii = 0; |
2961 octave_idx_type ii = idx_i.elem (iii); | |
5760 | 2962 octave_idx_type ppp = 0; |
6092 | 2963 octave_idx_type ppi = (j >= lhs_nc ? 0 : |
6988 | 2964 c_lhs.cidx(j+1) - |
2965 c_lhs.cidx(j)); | |
5760 | 2966 octave_idx_type pp = (ppp < ppi ? |
6988 | 2967 c_lhs.ridx(c_lhs.cidx(j)+ppp) : |
2968 new_nr); | |
5760 | 2969 while (ppp < ppi || iii < n) |
5164 | 2970 { |
5760 | 2971 if (iii < n && ii <= pp) |
5164 | 2972 { |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2973 if (iii < n - 1 && |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2974 idx_i.elem (iii + 1) == ii) |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2975 { |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2976 iii++; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2977 ii = idx_i.elem(iii); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2978 continue; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2979 } |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
2980 |
5603 | 2981 RT rtmp = rhs.elem (rhs_idx_i[iii], |
2982 rhs_idx_j[jji]); | |
5164 | 2983 if (rtmp != RT ()) |
2984 { | |
2985 stmp.data(kk) = rtmp; | |
5760 | 2986 stmp.ridx(kk++) = ii; |
5164 | 2987 } |
5760 | 2988 if (ii == pp) |
6988 | 2989 pp = (++ppp < ppi ? c_lhs.ridx(c_lhs.cidx(j)+ppp) : new_nr); |
5164 | 2990 if (++iii < n) |
2991 ii = idx_i.elem(iii); | |
2992 } | |
5760 | 2993 else |
5164 | 2994 { |
5760 | 2995 stmp.data(kk) = |
6988 | 2996 c_lhs.data(c_lhs.cidx(j)+ppp); |
5760 | 2997 stmp.ridx(kk++) = pp; |
6988 | 2998 pp = (++ppp < ppi ? c_lhs.ridx(c_lhs.cidx(j)+ppp) : new_nr); |
5164 | 2999 } |
3000 } | |
3001 if (++jji < m) | |
3002 jj = idx_j.elem(jji); | |
3003 } | |
6988 | 3004 else if (j < lhs_nc) |
5164 | 3005 { |
6988 | 3006 for (octave_idx_type i = c_lhs.cidx(j); |
3007 i < c_lhs.cidx(j+1); i++) | |
5164 | 3008 { |
6988 | 3009 stmp.data(kk) = c_lhs.data(i); |
3010 stmp.ridx(kk++) = c_lhs.ridx(i); | |
5164 | 3011 } |
3012 } | |
3013 stmp.cidx(j+1) = kk; | |
3014 } | |
3015 | |
5760 | 3016 stmp.maybe_compress(); |
5164 | 3017 lhs = stmp; |
3018 } | |
3019 } | |
3020 else if (n == 0 && m == 0) | |
3021 { | |
3022 if (! ((rhs_nr == 1 && rhs_nc == 1) | |
3023 || (rhs_nr == 0 || rhs_nc == 0))) | |
3024 { | |
3025 (*current_liboctave_error_handler) | |
3026 ("A([], []) = X: X must be an empty matrix or a scalar"); | |
3027 | |
3028 retval = 0; | |
3029 } | |
3030 } | |
3031 else | |
3032 { | |
3033 (*current_liboctave_error_handler) | |
3034 ("A(I, J) = X: X must be a scalar or the number of elements in I must"); | |
3035 (*current_liboctave_error_handler) | |
3036 ("match the number of rows in X and the number of elements in J must"); | |
3037 (*current_liboctave_error_handler) | |
3038 ("match the number of columns in X"); | |
3039 | |
3040 retval = 0; | |
3041 } | |
3042 } | |
3043 } | |
3044 // idx_vector::freeze() printed an error message for us. | |
3045 } | |
3046 else if (n_idx == 1) | |
3047 { | |
3048 int lhs_is_empty = lhs_nr == 0 || lhs_nc == 0; | |
3049 | |
3050 if (lhs_is_empty || (lhs_nr == 1 && lhs_nc == 1)) | |
3051 { | |
5275 | 3052 octave_idx_type lhs_len = lhs.length (); |
3053 | |
5781 | 3054 octave_idx_type n = idx_i.freeze (lhs_len, 0, true); |
5164 | 3055 |
3056 if (idx_i) | |
3057 { | |
3058 if (rhs_nr == 0 && rhs_nc == 0) | |
3059 { | |
3060 if (n != 0 && (lhs_nr != 0 || lhs_nc != 0)) | |
3061 lhs.maybe_delete_elements (idx_i); | |
3062 } | |
3063 else | |
3064 { | |
5781 | 3065 if (lhs_is_empty |
3066 && idx_i.is_colon () | |
3067 && ! (rhs_nr == 1 || rhs_nc == 1)) | |
5164 | 3068 { |
5781 | 3069 (*current_liboctave_warning_with_id_handler) |
3070 ("Octave:fortran-indexing", | |
3071 "A(:) = X: X is not a vector or scalar"); | |
3072 } | |
3073 else | |
3074 { | |
3075 octave_idx_type idx_nr = idx_i.orig_rows (); | |
3076 octave_idx_type idx_nc = idx_i.orig_columns (); | |
3077 | |
3078 if (! (rhs_nr == idx_nr && rhs_nc == idx_nc)) | |
3079 (*current_liboctave_warning_with_id_handler) | |
3080 ("Octave:fortran-indexing", | |
3081 "A(I) = X: X does not have same shape as I"); | |
5164 | 3082 } |
3083 | |
5760 | 3084 if (! assign1 (lhs, rhs)) |
5164 | 3085 retval = 0; |
3086 } | |
3087 } | |
3088 // idx_vector::freeze() printed an error message for us. | |
3089 } | |
3090 else if (lhs_nr == 1) | |
3091 { | |
5781 | 3092 idx_i.freeze (lhs_nc, "vector", true); |
5164 | 3093 |
3094 if (idx_i) | |
3095 { | |
3096 if (rhs_nr == 0 && rhs_nc == 0) | |
3097 lhs.maybe_delete_elements (idx_i); | |
5760 | 3098 else if (! assign1 (lhs, rhs)) |
5164 | 3099 retval = 0; |
3100 } | |
3101 // idx_vector::freeze() printed an error message for us. | |
3102 } | |
3103 else if (lhs_nc == 1) | |
3104 { | |
5781 | 3105 idx_i.freeze (lhs_nr, "vector", true); |
5164 | 3106 |
3107 if (idx_i) | |
3108 { | |
3109 if (rhs_nr == 0 && rhs_nc == 0) | |
3110 lhs.maybe_delete_elements (idx_i); | |
5760 | 3111 else if (! assign1 (lhs, rhs)) |
5164 | 3112 retval = 0; |
3113 } | |
3114 // idx_vector::freeze() printed an error message for us. | |
3115 } | |
3116 else | |
3117 { | |
7573
755bf7ecc29b
eliminate one_zero stuff from idx_vector
John W. Eaton <jwe@octave.org>
parents:
7546
diff
changeset
|
3118 if (! idx_i.is_colon ()) |
5781 | 3119 (*current_liboctave_warning_with_id_handler) |
3120 ("Octave:fortran-indexing", "single index used for matrix"); | |
5164 | 3121 |
5275 | 3122 octave_idx_type lhs_len = lhs.length (); |
3123 | |
3124 octave_idx_type len = idx_i.freeze (lhs_nr * lhs_nc, "matrix"); | |
5164 | 3125 |
3126 if (idx_i) | |
3127 { | |
3128 if (rhs_nr == 0 && rhs_nc == 0) | |
3129 lhs.maybe_delete_elements (idx_i); | |
3130 else if (len == 0) | |
3131 { | |
3132 if (! ((rhs_nr == 1 && rhs_nc == 1) | |
3133 || (rhs_nr == 0 || rhs_nc == 0))) | |
3134 (*current_liboctave_error_handler) | |
3135 ("A([]) = X: X must be an empty matrix or scalar"); | |
3136 } | |
3137 else if (len == rhs_nr * rhs_nc) | |
3138 { | |
5604 | 3139 octave_idx_type new_nzmx = lhs_nz; |
5603 | 3140 OCTAVE_LOCAL_BUFFER (octave_idx_type, rhs_idx, len); |
3141 | |
3142 if (! idx_i.is_colon ()) | |
3143 { | |
3144 // Ok here we have to be careful with the indexing, to | |
3145 // treat cases like "a([3,2,1]) = b", and still handle | |
3146 // the need for strict sorting of the sparse elements. | |
3147 | |
3148 OCTAVE_LOCAL_BUFFER (octave_idx_vector_sort *, sidx, | |
3149 len); | |
3150 OCTAVE_LOCAL_BUFFER (octave_idx_vector_sort, sidxX, | |
3151 len); | |
3152 | |
3153 for (octave_idx_type i = 0; i < len; i++) | |
3154 { | |
3155 sidx[i] = &sidxX[i]; | |
3156 sidx[i]->i = idx_i.elem(i); | |
3157 sidx[i]->idx = i; | |
3158 } | |
3159 | |
3160 OCTAVE_QUIT; | |
3161 octave_sort<octave_idx_vector_sort *> | |
3162 sort (octave_idx_vector_comp); | |
3163 | |
3164 sort.sort (sidx, len); | |
3165 | |
3166 intNDArray<octave_idx_type> new_idx (dim_vector (len,1)); | |
3167 | |
3168 for (octave_idx_type i = 0; i < len; i++) | |
3169 { | |
3170 new_idx.xelem(i) = sidx[i]->i + 1; | |
3171 rhs_idx[i] = sidx[i]->idx; | |
3172 } | |
3173 | |
3174 idx_i = idx_vector (new_idx); | |
3175 } | |
3176 else | |
3177 for (octave_idx_type i = 0; i < len; i++) | |
3178 rhs_idx[i] = i; | |
5164 | 3179 |
3180 // First count the number of non-zero elements | |
5275 | 3181 for (octave_idx_type i = 0; i < len; i++) |
5164 | 3182 { |
3183 OCTAVE_QUIT; | |
3184 | |
5275 | 3185 octave_idx_type ii = idx_i.elem (i); |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3186 if (i < len - 1 && idx_i.elem (i + 1) == ii) |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3187 continue; |
5164 | 3188 if (ii < lhs_len && c_lhs.elem(ii) != LT ()) |
5604 | 3189 new_nzmx--; |
5603 | 3190 if (rhs.elem(rhs_idx[i]) != RT ()) |
5604 | 3191 new_nzmx++; |
5164 | 3192 } |
3193 | |
5604 | 3194 Sparse<LT> stmp (lhs_nr, lhs_nc, new_nzmx); |
5164 | 3195 |
5275 | 3196 octave_idx_type i = 0; |
3197 octave_idx_type ii = 0; | |
3198 octave_idx_type ic = 0; | |
5164 | 3199 if (i < lhs_nz) |
3200 { | |
3201 while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) | |
3202 ic++; | |
3203 ii = ic * lhs_nr + c_lhs.ridx(i); | |
3204 } | |
3205 | |
5275 | 3206 octave_idx_type j = 0; |
3207 octave_idx_type jj = idx_i.elem (j); | |
3208 octave_idx_type jr = jj % lhs_nr; | |
3209 octave_idx_type jc = (jj - jr) / lhs_nr; | |
3210 | |
3211 octave_idx_type kk = 0; | |
3212 octave_idx_type kc = 0; | |
5164 | 3213 |
3214 while (j < len || i < lhs_nz) | |
3215 { | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3216 if (j < len - 1 && idx_i.elem (j + 1) == jj) |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3217 { |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3218 j++; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3219 jj = idx_i.elem (j); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3220 jr = jj % lhs_nr; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3221 jc = (jj - jr) / lhs_nr; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3222 continue; |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3223 } |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3224 |
5164 | 3225 if (j == len || (i < lhs_nz && ii < jj)) |
3226 { | |
3227 while (kc <= ic) | |
3228 stmp.xcidx (kc++) = kk; | |
3229 stmp.xdata (kk) = c_lhs.data (i); | |
3230 stmp.xridx (kk++) = c_lhs.ridx (i); | |
3231 i++; | |
3232 while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) | |
3233 ic++; | |
3234 if (i < lhs_nz) | |
3235 ii = ic * lhs_nr + c_lhs.ridx(i); | |
3236 } | |
3237 else | |
3238 { | |
3239 while (kc <= jc) | |
3240 stmp.xcidx (kc++) = kk; | |
5603 | 3241 RT rtmp = rhs.elem (rhs_idx[j]); |
5164 | 3242 if (rtmp != RT ()) |
3243 { | |
3244 stmp.xdata (kk) = rtmp; | |
3245 stmp.xridx (kk++) = jr; | |
3246 } | |
3247 if (ii == jj) | |
3248 { | |
3249 i++; | |
3250 while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) | |
3251 ic++; | |
3252 if (i < lhs_nz) | |
3253 ii = ic * lhs_nr + c_lhs.ridx(i); | |
3254 } | |
3255 j++; | |
3256 if (j < len) | |
3257 { | |
3258 jj = idx_i.elem (j); | |
3259 jr = jj % lhs_nr; | |
3260 jc = (jj - jr) / lhs_nr; | |
3261 } | |
3262 } | |
3263 } | |
3264 | |
5275 | 3265 for (octave_idx_type iidx = kc; iidx < lhs_nc+1; iidx++) |
5603 | 3266 stmp.xcidx(iidx) = kk; |
5164 | 3267 |
3268 lhs = stmp; | |
3269 } | |
3270 else if (rhs_nr == 1 && rhs_nc == 1) | |
3271 { | |
3272 RT scalar = rhs.elem (0, 0); | |
5604 | 3273 octave_idx_type new_nzmx = lhs_nz; |
5603 | 3274 idx_i.sort (true); |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3275 len = idx_i.length (len); |
5164 | 3276 |
3277 // First count the number of non-zero elements | |
3278 if (scalar != RT ()) | |
5604 | 3279 new_nzmx += len; |
5275 | 3280 for (octave_idx_type i = 0; i < len; i++) |
5164 | 3281 { |
3282 OCTAVE_QUIT; | |
5275 | 3283 octave_idx_type ii = idx_i.elem (i); |
5164 | 3284 if (ii < lhs_len && c_lhs.elem(ii) != LT ()) |
5604 | 3285 new_nzmx--; |
5164 | 3286 } |
3287 | |
5604 | 3288 Sparse<LT> stmp (lhs_nr, lhs_nc, new_nzmx); |
5164 | 3289 |
5275 | 3290 octave_idx_type i = 0; |
3291 octave_idx_type ii = 0; | |
3292 octave_idx_type ic = 0; | |
5164 | 3293 if (i < lhs_nz) |
3294 { | |
3295 while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) | |
3296 ic++; | |
3297 ii = ic * lhs_nr + c_lhs.ridx(i); | |
3298 } | |
3299 | |
5275 | 3300 octave_idx_type j = 0; |
3301 octave_idx_type jj = idx_i.elem (j); | |
3302 octave_idx_type jr = jj % lhs_nr; | |
3303 octave_idx_type jc = (jj - jr) / lhs_nr; | |
3304 | |
3305 octave_idx_type kk = 0; | |
3306 octave_idx_type kc = 0; | |
5164 | 3307 |
3308 while (j < len || i < lhs_nz) | |
3309 { | |
3310 if (j == len || (i < lhs_nz && ii < jj)) | |
3311 { | |
3312 while (kc <= ic) | |
3313 stmp.xcidx (kc++) = kk; | |
3314 stmp.xdata (kk) = c_lhs.data (i); | |
3315 stmp.xridx (kk++) = c_lhs.ridx (i); | |
3316 i++; | |
3317 while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) | |
3318 ic++; | |
3319 if (i < lhs_nz) | |
3320 ii = ic * lhs_nr + c_lhs.ridx(i); | |
3321 } | |
3322 else | |
3323 { | |
3324 while (kc <= jc) | |
3325 stmp.xcidx (kc++) = kk; | |
3326 if (scalar != RT ()) | |
3327 { | |
3328 stmp.xdata (kk) = scalar; | |
3329 stmp.xridx (kk++) = jr; | |
3330 } | |
3331 if (ii == jj) | |
3332 { | |
3333 i++; | |
3334 while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) | |
3335 ic++; | |
3336 if (i < lhs_nz) | |
3337 ii = ic * lhs_nr + c_lhs.ridx(i); | |
3338 } | |
3339 j++; | |
3340 if (j < len) | |
3341 { | |
3342 jj = idx_i.elem (j); | |
3343 jr = jj % lhs_nr; | |
3344 jc = (jj - jr) / lhs_nr; | |
3345 } | |
3346 } | |
3347 } | |
3348 | |
5275 | 3349 for (octave_idx_type iidx = kc; iidx < lhs_nc+1; iidx++) |
5164 | 3350 stmp.xcidx(iidx) = kk; |
3351 | |
3352 lhs = stmp; | |
3353 } | |
3354 else | |
3355 { | |
3356 (*current_liboctave_error_handler) | |
3357 ("A(I) = X: X must be a scalar or a matrix with the same size as I"); | |
3358 | |
3359 retval = 0; | |
3360 } | |
3361 } | |
3362 // idx_vector::freeze() printed an error message for us. | |
3363 } | |
3364 } | |
3365 else | |
3366 { | |
3367 (*current_liboctave_error_handler) | |
3368 ("invalid number of indices for matrix expression"); | |
3369 | |
3370 retval = 0; | |
3371 } | |
3372 | |
3373 lhs.clear_index (); | |
3374 | |
3375 return retval; | |
3376 } | |
3377 | |
7356 | 3378 /* |
3379 * Tests | |
3380 * | |
3381 | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3382 %!function x = set_slice(x, dim, slice, arg) |
7356 | 3383 %! switch dim |
3384 %! case 11 | |
3385 %! x(slice) = 2; | |
3386 %! case 21 | |
3387 %! x(slice, :) = 2; | |
3388 %! case 22 | |
3389 %! x(:, slice) = 2; | |
3390 %! otherwise | |
3391 %! error("invalid dim, '%d'", dim); | |
3392 %! endswitch | |
3393 %! endfunction | |
3394 | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3395 %!function x = set_slice2(x, dim, slice) |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3396 %! switch dim |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3397 %! case 11 |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3398 %! x(slice) = 2 * ones (size(slice)); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3399 %! case 21 |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3400 %! x(slice, :) = 2 * ones (length(slice), columns (x)); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3401 %! case 22 |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3402 %! x(:, slice) = 2 * ones (rows (x), length(slice)); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3403 %! otherwise |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3404 %! error("invalid dim, '%d'", dim); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3405 %! endswitch |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3406 %! endfunction |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3407 |
7356 | 3408 %!function test_sparse_slice(size, dim, slice) |
3409 %! x = ones(size); | |
3410 %! s = set_slice(sparse(x), dim, slice); | |
3411 %! f = set_slice(x, dim, slice); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3412 %! assert (nnz(s), nnz(f)); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3413 %! assert(full(s), f); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3414 %! s = set_slice2(sparse(x), dim, slice); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3415 %! f = set_slice2(x, dim, slice); |
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3416 %! assert (nnz(s), nnz(f)); |
7356 | 3417 %! assert(full(s), f); |
3418 %! endfunction | |
3419 | |
3420 #### 1d indexing | |
3421 | |
3422 ## size = [2 0] | |
3423 %!test test_sparse_slice([2 0], 11, []); | |
3424 %!assert(set_slice(sparse(ones([2 0])), 11, 1), sparse([2 0]')); # sparse different from full | |
3425 %!assert(set_slice(sparse(ones([2 0])), 11, 2), sparse([0 2]')); # sparse different from full | |
3426 %!assert(set_slice(sparse(ones([2 0])), 11, 3), sparse([0 0 2]')); # sparse different from full | |
3427 %!assert(set_slice(sparse(ones([2 0])), 11, 4), sparse([0 0 0 2]')); # sparse different from full | |
3428 | |
3429 ## size = [0 2] | |
3430 %!test test_sparse_slice([0 2], 11, []); | |
3431 %!assert(set_slice(sparse(ones([0 2])), 11, 1), sparse(1,2)); # sparse different from full | |
3432 %!test test_sparse_slice([0 2], 11, 2); | |
3433 %!test test_sparse_slice([0 2], 11, 3); | |
3434 %!test test_sparse_slice([0 2], 11, 4); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3435 %!test test_sparse_slice([0 2], 11, [4, 4]); |
7356 | 3436 |
3437 ## size = [2 1] | |
3438 %!test test_sparse_slice([2 1], 11, []); | |
3439 %!test test_sparse_slice([2 1], 11, 1); | |
3440 %!test test_sparse_slice([2 1], 11, 2); | |
3441 %!test test_sparse_slice([2 1], 11, 3); | |
3442 %!test test_sparse_slice([2 1], 11, 4); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3443 %!test test_sparse_slice([2 1], 11, [4, 4]); |
7356 | 3444 |
3445 ## size = [1 2] | |
3446 %!test test_sparse_slice([1 2], 11, []); | |
3447 %!test test_sparse_slice([1 2], 11, 1); | |
3448 %!test test_sparse_slice([1 2], 11, 2); | |
3449 %!test test_sparse_slice([1 2], 11, 3); | |
3450 %!test test_sparse_slice([1 2], 11, 4); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3451 %!test test_sparse_slice([1 2], 11, [4, 4]); |
7356 | 3452 |
3453 ## size = [2 2] | |
3454 %!test test_sparse_slice([2 2], 11, []); | |
3455 %!test test_sparse_slice([2 2], 11, 1); | |
3456 %!test test_sparse_slice([2 2], 11, 2); | |
3457 %!test test_sparse_slice([2 2], 11, 3); | |
3458 %!test test_sparse_slice([2 2], 11, 4); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3459 %!test test_sparse_slice([2 2], 11, [4, 4]); |
7356 | 3460 # These 2 errors are the same as in the full case |
3461 %!error <invalid matrix index = 5> set_slice(sparse(ones([2 2])), 11, 5); | |
3462 %!error <invalid matrix index = 6> set_slice(sparse(ones([2 2])), 11, 6); | |
3463 | |
3464 | |
3465 #### 2d indexing | |
3466 | |
3467 ## size = [2 0] | |
3468 %!test test_sparse_slice([2 0], 21, []); | |
3469 %!test test_sparse_slice([2 0], 21, 1); | |
3470 %!test test_sparse_slice([2 0], 21, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3471 %!test test_sparse_slice([2 0], 21, [2,2]); |
7356 | 3472 %!assert(set_slice(sparse(ones([2 0])), 21, 3), sparse(2,0)); # sparse different from full |
3473 %!assert(set_slice(sparse(ones([2 0])), 21, 4), sparse(2,0)); # sparse different from full | |
3474 %!test test_sparse_slice([2 0], 22, []); | |
3475 %!test test_sparse_slice([2 0], 22, 1); | |
3476 %!test test_sparse_slice([2 0], 22, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3477 %!test test_sparse_slice([2 0], 22, [2,2]); |
7356 | 3478 %!assert(set_slice(sparse(ones([2 0])), 22, 3), sparse([0 0 2;0 0 2])); # sparse different from full |
3479 %!assert(set_slice(sparse(ones([2 0])), 22, 4), sparse([0 0 0 2;0 0 0 2])); # sparse different from full | |
3480 | |
3481 ## size = [0 2] | |
3482 %!test test_sparse_slice([0 2], 21, []); | |
3483 %!test test_sparse_slice([0 2], 21, 1); | |
3484 %!test test_sparse_slice([0 2], 21, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3485 %!test test_sparse_slice([0 2], 21, [2,2]); |
7356 | 3486 %!assert(set_slice(sparse(ones([0 2])), 21, 3), sparse([0 0;0 0;2 2])); # sparse different from full |
3487 %!assert(set_slice(sparse(ones([0 2])), 21, 4), sparse([0 0;0 0;0 0;2 2])); # sparse different from full | |
3488 %!test test_sparse_slice([0 2], 22, []); | |
3489 %!test test_sparse_slice([0 2], 22, 1); | |
3490 %!test test_sparse_slice([0 2], 22, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3491 %!test test_sparse_slice([0 2], 22, [2,2]); |
7356 | 3492 %!assert(set_slice(sparse(ones([0 2])), 22, 3), sparse(0,2)); # sparse different from full |
3493 %!assert(set_slice(sparse(ones([0 2])), 22, 4), sparse(0,2)); # sparse different from full | |
3494 | |
3495 ## size = [2 1] | |
3496 %!test test_sparse_slice([2 1], 21, []); | |
3497 %!test test_sparse_slice([2 1], 21, 1); | |
3498 %!test test_sparse_slice([2 1], 21, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3499 %!test test_sparse_slice([2 1], 21, [2,2]); |
7356 | 3500 %!test test_sparse_slice([2 1], 21, 3); |
3501 %!test test_sparse_slice([2 1], 21, 4); | |
3502 %!test test_sparse_slice([2 1], 22, []); | |
3503 %!test test_sparse_slice([2 1], 22, 1); | |
3504 %!test test_sparse_slice([2 1], 22, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3505 %!test test_sparse_slice([2 1], 22, [2,2]); |
7356 | 3506 %!test test_sparse_slice([2 1], 22, 3); |
3507 %!test test_sparse_slice([2 1], 22, 4); | |
3508 | |
3509 ## size = [1 2] | |
3510 %!test test_sparse_slice([1 2], 21, []); | |
3511 %!test test_sparse_slice([1 2], 21, 1); | |
3512 %!test test_sparse_slice([1 2], 21, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3513 %!test test_sparse_slice([1 2], 21, [2,2]); |
7356 | 3514 %!test test_sparse_slice([1 2], 21, 3); |
3515 %!test test_sparse_slice([1 2], 21, 4); | |
3516 %!test test_sparse_slice([1 2], 22, []); | |
3517 %!test test_sparse_slice([1 2], 22, 1); | |
3518 %!test test_sparse_slice([1 2], 22, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3519 %!test test_sparse_slice([1 2], 22, [2,2]); |
7356 | 3520 %!test test_sparse_slice([1 2], 22, 3); |
3521 %!test test_sparse_slice([1 2], 22, 4); | |
3522 | |
3523 ## size = [2 2] | |
3524 %!test test_sparse_slice([2 2], 21, []); | |
3525 %!test test_sparse_slice([2 2], 21, 1); | |
3526 %!test test_sparse_slice([2 2], 21, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3527 %!test test_sparse_slice([2 2], 21, [2,2]); |
7356 | 3528 %!test test_sparse_slice([2 2], 21, 3); |
3529 %!test test_sparse_slice([2 2], 21, 4); | |
3530 %!test test_sparse_slice([2 2], 22, []); | |
3531 %!test test_sparse_slice([2 2], 22, 1); | |
3532 %!test test_sparse_slice([2 2], 22, 2); | |
7546
4249c6fb6e09
Treat repeated indices in the sparse assignments
David Bateman <dbateman@free.fr>
parents:
7463
diff
changeset
|
3533 %!test test_sparse_slice([2 2], 22, [2,2]); |
7356 | 3534 %!test test_sparse_slice([2 2], 22, 3); |
3535 %!test test_sparse_slice([2 2], 22, 4); | |
3536 | |
3537 */ | |
3538 | |
5164 | 3539 template <class T> |
3540 void | |
3541 Sparse<T>::print_info (std::ostream& os, const std::string& prefix) const | |
3542 { | |
3543 os << prefix << "rep address: " << rep << "\n" | |
5604 | 3544 << prefix << "rep->nzmx: " << rep->nzmx << "\n" |
5164 | 3545 << prefix << "rep->nrows: " << rep->nrows << "\n" |
3546 << prefix << "rep->ncols: " << rep->ncols << "\n" | |
3547 << prefix << "rep->data: " << static_cast<void *> (rep->d) << "\n" | |
3548 << prefix << "rep->ridx: " << static_cast<void *> (rep->r) << "\n" | |
3549 << prefix << "rep->cidx: " << static_cast<void *> (rep->c) << "\n" | |
3550 << prefix << "rep->count: " << rep->count << "\n"; | |
3551 } | |
3552 | |
3553 /* | |
3554 ;;; Local Variables: *** | |
3555 ;;; mode: C++ *** | |
3556 ;;; End: *** | |
3557 */ |