00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #if !defined (octave_Sparse_h)
00026 #define octave_Sparse_h 1
00027
00028 #include <cassert>
00029 #include <cstddef>
00030
00031 #include <iosfwd>
00032
00033 #include "Array.h"
00034 #include "Array2.h"
00035 #include "dim-vector.h"
00036 #include "lo-error.h"
00037 #include "lo-utils.h"
00038
00039 #include "oct-sort.h"
00040
00041 class idx_vector;
00042
00043
00044
00045
00046 template <class T>
00047 class
00048 Sparse
00049 {
00050 public:
00051
00052 typedef T element_type;
00053
00054 protected:
00055
00056
00057
00058
00059 class OCTAVE_API SparseRep
00060 {
00061 public:
00062
00063 T *d;
00064 octave_idx_type *r;
00065 octave_idx_type *c;
00066 octave_idx_type nzmx;
00067 octave_idx_type nrows;
00068 octave_idx_type ncols;
00069 int count;
00070
00071 SparseRep (void) : d (0), r (0), c (new octave_idx_type [1]), nzmx (0), nrows (0),
00072 ncols (0), count (1) { c[0] = 0; }
00073
00074 SparseRep (octave_idx_type n) : d (0), r (0), c (new octave_idx_type [n+1]), nzmx (0), nrows (n),
00075 ncols (n), count (1)
00076 {
00077 for (octave_idx_type i = 0; i < n + 1; i++)
00078 c[i] = 0;
00079 }
00080
00081 SparseRep (octave_idx_type nr, octave_idx_type nc) : d (0), r (0), c (new octave_idx_type [nc+1]), nzmx (0),
00082 nrows (nr), ncols (nc), count (1)
00083 {
00084 for (octave_idx_type i = 0; i < nc + 1; i++)
00085 c[i] = 0;
00086 }
00087
00088 SparseRep (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz) : d (new T [nz]),
00089 r (new octave_idx_type [nz]), c (new octave_idx_type [nc+1]), nzmx (nz), nrows (nr),
00090 ncols (nc), count (1)
00091 {
00092 for (octave_idx_type i = 0; i < nc + 1; i++)
00093 c[i] = 0;
00094 }
00095
00096 SparseRep (const SparseRep& a)
00097 : d (new T [a.nzmx]), r (new octave_idx_type [a.nzmx]), c (new octave_idx_type [a.ncols + 1]),
00098 nzmx (a.nzmx), nrows (a.nrows), ncols (a.ncols), count (1)
00099 {
00100 for (octave_idx_type i = 0; i < nzmx; i++)
00101 {
00102 d[i] = a.d[i];
00103 r[i] = a.r[i];
00104 }
00105 for (octave_idx_type i = 0; i < ncols + 1; i++)
00106 c[i] = a.c[i];
00107 }
00108
00109 ~SparseRep (void) { delete [] d; delete [] r; delete [] c; }
00110
00111 octave_idx_type length (void) const { return nzmx; }
00112
00113 octave_idx_type nnz (void) const { return c [ncols]; }
00114
00115 T& elem (octave_idx_type _r, octave_idx_type _c);
00116
00117 T celem (octave_idx_type _r, octave_idx_type _c) const;
00118
00119 T& data (octave_idx_type i) { return d[i]; }
00120
00121 T cdata (octave_idx_type i) const { return d[i]; }
00122
00123 octave_idx_type& ridx (octave_idx_type i) { return r[i]; }
00124
00125 octave_idx_type cridx (octave_idx_type i) const { return r[i]; }
00126
00127 octave_idx_type& cidx (octave_idx_type i) { return c[i]; }
00128
00129 octave_idx_type ccidx (octave_idx_type i) const { return c[i]; }
00130
00131 void maybe_compress (bool remove_zeros);
00132
00133 void change_length (octave_idx_type nz);
00134
00135 bool indices_ok (void) const;
00136
00137 private:
00138
00139
00140
00141 SparseRep& operator = (const SparseRep& a);
00142 };
00143
00144
00145
00146 void make_unique (void)
00147 {
00148 if (rep->count > 1)
00149 {
00150 --rep->count;
00151 rep = new SparseRep (*rep);
00152 }
00153 }
00154
00155 public:
00156
00157
00158
00159
00160 typename Sparse<T>::SparseRep *rep;
00161
00162 dim_vector dimensions;
00163
00164 protected:
00165 idx_vector *idx;
00166 octave_idx_type idx_count;
00167
00168 private:
00169
00170 typename Sparse<T>::SparseRep *nil_rep (void) const
00171 {
00172 static typename Sparse<T>::SparseRep *nr
00173 = new typename Sparse<T>::SparseRep ();
00174
00175 nr->count++;
00176
00177 return nr;
00178 }
00179
00180 public:
00181
00182 Sparse (void)
00183 : rep (nil_rep ()), dimensions (dim_vector(0,0)),
00184 idx (0), idx_count (0) { }
00185
00186 explicit Sparse (octave_idx_type n)
00187 : rep (new typename Sparse<T>::SparseRep (n)),
00188 dimensions (dim_vector (n, n)), idx (0), idx_count (0) { }
00189
00190 explicit Sparse (octave_idx_type nr, octave_idx_type nc)
00191 : rep (new typename Sparse<T>::SparseRep (nr, nc)),
00192 dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) { }
00193
00194 explicit Sparse (octave_idx_type nr, octave_idx_type nc, T val);
00195
00196 Sparse (const dim_vector& dv, octave_idx_type nz)
00197 : rep (new typename Sparse<T>::SparseRep (dv(0), dv(1), nz)),
00198 dimensions (dv), idx (0), idx_count (0) { }
00199
00200 Sparse (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz)
00201 : rep (new typename Sparse<T>::SparseRep (nr, nc, nz)),
00202 dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) { }
00203
00204
00205 template <class U> Sparse (const Sparse<U>& a);
00206
00207
00208 Sparse (const Sparse<T>& a)
00209 : rep (a.rep), dimensions (a.dimensions), idx (0), idx_count (0)
00210 {
00211 rep->count++;
00212 }
00213
00214 public:
00215
00216 Sparse (const dim_vector& dv);
00217
00218 Sparse (const Sparse<T>& a, const dim_vector& dv);
00219
00220 Sparse (const Array<T>& a, const Array<octave_idx_type>& r, const Array<octave_idx_type>& c,
00221 octave_idx_type nr, octave_idx_type nc, bool sum_terms);
00222
00223 Sparse (const Array<T>& a, const Array<double>& r, const Array<double>& c,
00224 octave_idx_type nr, octave_idx_type nc, bool sum_terms);
00225
00226
00227 Sparse (const Array2<T>& a);
00228 Sparse (const Array<T>& a);
00229
00230 virtual ~Sparse (void);
00231
00232 Sparse<T>& operator = (const Sparse<T>& a);
00233
00234
00235
00236
00237 octave_idx_type nzmax (void) const { return rep->length (); }
00238 octave_idx_type capacity (void) const { return nzmax (); }
00239 octave_idx_type nnz (void) const { return rep->nnz (); }
00240
00241
00242 octave_idx_type numel (void) const
00243 {
00244 if (dim1() < 0 || dim2() < 0)
00245 return 0;
00246 else
00247 return dimensions.numel ();
00248 }
00249
00250 octave_idx_type nelem (void) const { return capacity (); }
00251 octave_idx_type length (void) const { return numel (); }
00252
00253 octave_idx_type dim1 (void) const { return dimensions(0); }
00254 octave_idx_type dim2 (void) const { return dimensions(1); }
00255
00256 octave_idx_type rows (void) const { return dim1 (); }
00257 octave_idx_type cols (void) const { return dim2 (); }
00258 octave_idx_type columns (void) const { return dim2 (); }
00259
00260 octave_idx_type get_row_index (octave_idx_type k) { return ridx (k); }
00261 octave_idx_type get_col_index (octave_idx_type k)
00262 {
00263 octave_idx_type ret = 0;
00264 while (cidx(ret+1) < k)
00265 ret++;
00266 return ret;
00267 }
00268 size_t byte_size (void) const { return (cols () + 1) * sizeof (octave_idx_type) +
00269 capacity () * (sizeof (T) + sizeof (octave_idx_type)); }
00270
00271 dim_vector dims (void) const { return dimensions; }
00272
00273 Sparse<T> squeeze (void) const { return *this; }
00274
00275 octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx) const;
00276
00277 T range_error (const char *fcn, octave_idx_type n) const;
00278 T& range_error (const char *fcn, octave_idx_type n);
00279
00280 T range_error (const char *fcn, octave_idx_type i, octave_idx_type j) const;
00281 T& range_error (const char *fcn, octave_idx_type i, octave_idx_type j);
00282
00283 T range_error (const char *fcn, const Array<octave_idx_type>& ra_idx) const;
00284 T& range_error (const char *fcn, const Array<octave_idx_type>& ra_idx);
00285
00286
00287
00288 T& xelem (octave_idx_type n)
00289 {
00290 octave_idx_type i = n % rows (), j = n / rows();
00291 return xelem (i, j);
00292 }
00293
00294 T xelem (octave_idx_type n) const
00295 {
00296 octave_idx_type i = n % rows (), j = n / rows();
00297 return xelem (i, j);
00298 }
00299
00300 T& xelem (octave_idx_type i, octave_idx_type j) { return rep->elem (i, j); }
00301 T xelem (octave_idx_type i, octave_idx_type j) const { return rep->celem (i, j); }
00302
00303 T& xelem (const Array<octave_idx_type>& ra_idx)
00304 { return xelem (compute_index (ra_idx)); }
00305
00306 T xelem (const Array<octave_idx_type>& ra_idx) const
00307 { return xelem (compute_index (ra_idx)); }
00308
00309
00310
00311
00312
00313 T& checkelem (octave_idx_type n)
00314 {
00315 if (n < 0 || n >= numel ())
00316 return range_error ("T& Sparse<T>::checkelem", n);
00317 else
00318 {
00319 make_unique ();
00320 return xelem (n);
00321 }
00322 }
00323
00324 T& checkelem (octave_idx_type i, octave_idx_type j)
00325 {
00326 if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ())
00327 return range_error ("T& Sparse<T>::checkelem", i, j);
00328 else
00329 {
00330 make_unique ();
00331 return xelem (i, j);
00332 }
00333 }
00334
00335 T& checkelem (const Array<octave_idx_type>& ra_idx)
00336 {
00337 octave_idx_type i = compute_index (ra_idx);
00338
00339 if (i < 0)
00340 return range_error ("T& Sparse<T>::checkelem", ra_idx);
00341 else
00342 return elem (i);
00343 }
00344
00345 T& elem (octave_idx_type n)
00346 {
00347 make_unique ();
00348 return xelem (n);
00349 }
00350
00351 T& elem (octave_idx_type i, octave_idx_type j)
00352 {
00353 make_unique ();
00354 return xelem (i, j);
00355 }
00356
00357 T& elem (const Array<octave_idx_type>& ra_idx)
00358 { return Sparse<T>::elem (compute_index (ra_idx)); }
00359
00360 #if defined (BOUNDS_CHECKING)
00361 T& operator () (octave_idx_type n) { return checkelem (n); }
00362 T& operator () (octave_idx_type i, octave_idx_type j) { return checkelem (i, j); }
00363 T& operator () (const Array<octave_idx_type>& ra_idx) { return checkelem (ra_idx); }
00364 #else
00365 T& operator () (octave_idx_type n) { return elem (n); }
00366 T& operator () (octave_idx_type i, octave_idx_type j) { return elem (i, j); }
00367 T& operator () (const Array<octave_idx_type>& ra_idx) { return elem (ra_idx); }
00368 #endif
00369
00370 T checkelem (octave_idx_type n) const
00371 {
00372 if (n < 0 || n >= numel ())
00373 return range_error ("T Sparse<T>::checkelem", n);
00374 else
00375 return xelem (n);
00376 }
00377
00378 T checkelem (octave_idx_type i, octave_idx_type j) const
00379 {
00380 if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ())
00381 return range_error ("T Sparse<T>::checkelem", i, j);
00382 else
00383 return xelem (i, j);
00384 }
00385
00386 T checkelem (const Array<octave_idx_type>& ra_idx) const
00387 {
00388 octave_idx_type i = compute_index (ra_idx);
00389
00390 if (i < 0)
00391 return range_error ("T Sparse<T>::checkelem", ra_idx);
00392 else
00393 return Sparse<T>::elem (i);
00394 }
00395
00396 T elem (octave_idx_type n) const { return xelem (n); }
00397
00398 T elem (octave_idx_type i, octave_idx_type j) const { return xelem (i, j); }
00399
00400 T elem (const Array<octave_idx_type>& ra_idx) const
00401 { return Sparse<T>::elem (compute_index (ra_idx)); }
00402
00403 #if defined (BOUNDS_CHECKING)
00404 T operator () (octave_idx_type n) const { return checkelem (n); }
00405 T operator () (octave_idx_type i, octave_idx_type j) const { return checkelem (i, j); }
00406 T operator () (const Array<octave_idx_type>& ra_idx) const { return checkelem (ra_idx); }
00407 #else
00408 T operator () (octave_idx_type n) const { return elem (n); }
00409 T operator () (octave_idx_type i, octave_idx_type j) const { return elem (i, j); }
00410 T operator () (const Array<octave_idx_type>& ra_idx) const { return elem (ra_idx); }
00411 #endif
00412
00413 Sparse<T> maybe_compress (bool remove_zeros = false)
00414 { rep->maybe_compress (remove_zeros); return (*this); }
00415
00416 Sparse<T> reshape (const dim_vector& new_dims) const;
00417
00418
00419
00420
00421
00422
00423
00424
00425 void resize_no_fill (octave_idx_type r, octave_idx_type c);
00426
00427 void resize_no_fill (const dim_vector& dv);
00428
00429 public:
00430 Sparse<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const;
00431
00432 Sparse<T> ipermute (const Array<octave_idx_type>& vec) const
00433 { return permute (vec, true); }
00434
00435 void resize (octave_idx_type r, octave_idx_type c) { resize_no_fill (r, c); }
00436
00437 void resize (const dim_vector& dv) { resize_no_fill (dv); }
00438
00439 void change_capacity (octave_idx_type nz) { rep->change_length (nz); }
00440
00441 Sparse<T>& insert (const Sparse<T>& a, octave_idx_type r, octave_idx_type c);
00442 Sparse<T>& insert (const Sparse<T>& a, const Array<octave_idx_type>& idx);
00443
00444 bool is_square (void) const { return (dim1 () == dim2 ()); }
00445
00446 bool is_empty (void) const { return (rows () < 1 && cols () < 1); }
00447
00448 Sparse<T> transpose (void) const;
00449
00450 T* data (void) { make_unique (); return rep->d; }
00451 T& data (octave_idx_type i) { make_unique (); return rep->data (i); }
00452 T* xdata (void) { return rep->d; }
00453 T& xdata (octave_idx_type i) { return rep->data (i); }
00454
00455 T data (octave_idx_type i) const { return rep->data (i); }
00456
00457 T* data (void) const { return rep->d; }
00458
00459 octave_idx_type* ridx (void) { make_unique (); return rep->r; }
00460 octave_idx_type& ridx (octave_idx_type i) { make_unique (); return rep->ridx (i); }
00461 octave_idx_type* xridx (void) { return rep->r; }
00462 octave_idx_type& xridx (octave_idx_type i) { return rep->ridx (i); }
00463
00464 octave_idx_type ridx (octave_idx_type i) const { return rep->cridx (i); }
00465
00466 octave_idx_type* ridx (void) const { return rep->r; }
00467
00468 octave_idx_type* cidx (void) { make_unique (); return rep->c; }
00469 octave_idx_type& cidx (octave_idx_type i) { make_unique (); return rep->cidx (i); }
00470 octave_idx_type* xcidx (void) { return rep->c; }
00471 octave_idx_type& xcidx (octave_idx_type i) { return rep->cidx (i); }
00472
00473 octave_idx_type cidx (octave_idx_type i) const { return rep->ccidx (i); }
00474
00475 octave_idx_type* cidx (void) const { return rep->c; }
00476
00477 octave_idx_type ndims (void) const { return dimensions.length (); }
00478
00479 void clear_index (void);
00480
00481 void set_index (const idx_vector& i);
00482
00483 octave_idx_type index_count (void) const { return idx_count; }
00484
00485 idx_vector *get_idx (void) const { return idx; }
00486
00487 void maybe_delete_elements (idx_vector& i);
00488
00489 void maybe_delete_elements (idx_vector& i, idx_vector& j);
00490
00491 void maybe_delete_elements (Array<idx_vector>& ra_idx);
00492
00493 Sparse<T> value (void);
00494
00495 Sparse<T> index (idx_vector& i, int resize_ok = 0) const;
00496
00497 Sparse<T> index (idx_vector& i, idx_vector& j, int resize_ok = 0) const;
00498
00499 Sparse<T> index (Array<idx_vector>& ra_idx, int resize_ok = 0) const;
00500
00501 void print_info (std::ostream& os, const std::string& prefix) const;
00502
00503
00504
00505 void *mex_get_data (void) const { return const_cast<T *> (data ()); }
00506
00507 octave_idx_type *mex_get_ir (void) const { return const_cast<octave_idx_type *> (ridx ()); }
00508
00509 octave_idx_type *mex_get_jc (void) const { return const_cast<octave_idx_type *> (cidx ()); }
00510
00511 Sparse<T> sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;
00512 Sparse<T> sort (Array<octave_idx_type> &sidx, octave_idx_type dim = 0,
00513 sortmode mode = ASCENDING) const;
00514
00515 Sparse<T> diag (octave_idx_type k = 0) const;
00516
00517 template <class U, class F>
00518 Sparse<U>
00519 map (F fcn) const
00520 {
00521 Sparse<U> result;
00522 U f_zero = fcn (0.);
00523
00524 if (f_zero != 0.)
00525 {
00526 octave_idx_type nr = rows ();
00527 octave_idx_type nc = cols ();
00528
00529 result = Sparse<U> (nr, nc, f_zero);
00530
00531 for (octave_idx_type j = 0; j < nc; j++)
00532 for (octave_idx_type i = cidx(j); i < cidx (j+1); i++)
00533 {
00534 OCTAVE_QUIT;
00535
00536 result.data (ridx (i) + j * nr) = fcn (data(i));
00537 }
00538
00539 result.maybe_compress (true);
00540 }
00541 else
00542 {
00543 octave_idx_type nz = nnz ();
00544 octave_idx_type nr = rows ();
00545 octave_idx_type nc = cols ();
00546
00547 result = Sparse<U> (nr, nc, nz);
00548 octave_idx_type ii = 0;
00549 result.cidx (ii) = 0;
00550
00551 for (octave_idx_type j = 0; j < nc; j++)
00552 {
00553 for (octave_idx_type i = cidx(j); i < cidx (j+1); i++)
00554 {
00555 U val = fcn (data (i));
00556 if (val != 0.0)
00557 {
00558 result.data (ii) = val;
00559 result.ridx (ii++) = ridx (i);
00560 }
00561 OCTAVE_QUIT;
00562 }
00563 result.cidx (j+1) = ii;
00564 }
00565
00566 result.maybe_compress (false);
00567 }
00568
00569 return result;
00570 }
00571
00572 bool indices_ok (void) const { return rep->indices_ok (); }
00573 };
00574
00575
00576
00577
00578
00579 template <class LT, class RT>
00580 int
00581 assign (Sparse<LT>& lhs, const Sparse<RT>& rhs);
00582
00583 template <class LT, class RT>
00584 int
00585 assign1 (Sparse<LT>& lhs, const Sparse<RT>& rhs);
00586
00587 template<typename T>
00588 std::istream&
00589 read_sparse_matrix (std::istream& is, Sparse<T>& a,
00590 T (*read_fcn) (std::istream&))
00591 {
00592 octave_idx_type nr = a.rows ();
00593 octave_idx_type nc = a.cols ();
00594 octave_idx_type nz = a.nzmax ();
00595
00596 if (nr > 0 && nc > 0)
00597 {
00598 octave_idx_type itmp;
00599 octave_idx_type jtmp;
00600 octave_idx_type iold = 0;
00601 octave_idx_type jold = 0;
00602 octave_idx_type ii = 0;
00603 T tmp;
00604
00605 a.cidx (0) = 0;
00606 for (octave_idx_type i = 0; i < nz; i++)
00607 {
00608 is >> itmp;
00609 itmp--;
00610
00611 if (itmp < iold)
00612 {
00613 (*current_liboctave_error_handler)
00614 ("invalid sparse matrix: row indices must appear in ascending order in each column");
00615 is.setstate (std::ios::failbit);
00616 goto done;
00617 }
00618
00619 if (itmp < 0 || itmp >= nr)
00620 {
00621 (*current_liboctave_error_handler)
00622 ("invalid sparse matrix: row index = %d out of range",
00623 itmp + 1);
00624 is.setstate (std::ios::failbit);
00625 goto done;
00626 }
00627
00628
00629 iold = itmp;
00630
00631 is >> jtmp;
00632 jtmp--;
00633
00634 if (jtmp < jold)
00635 {
00636 (*current_liboctave_error_handler)
00637 ("invalid sparse matrix: column indices must appear in ascending order");
00638 is.setstate (std::ios::failbit);
00639 goto done;
00640 }
00641
00642 if (jtmp < 0 || jtmp >= nc)
00643 {
00644 (*current_liboctave_error_handler)
00645 ("invalid sparse matrix: column index = %d out of range",
00646 jtmp + 1);
00647 is.setstate (std::ios::failbit);
00648 goto done;
00649 }
00650
00651 tmp = read_fcn (is);
00652
00653 if (is)
00654 {
00655 if (jold != jtmp)
00656 {
00657 for (octave_idx_type j = jold; j < jtmp; j++)
00658 a.cidx(j+1) = ii;
00659
00660 jold = jtmp;
00661 iold = 0;
00662 }
00663 a.data (ii) = tmp;
00664 a.ridx (ii++) = itmp;
00665 }
00666 else
00667 goto done;
00668 }
00669
00670 for (octave_idx_type j = jold; j < nc; j++)
00671 a.cidx(j+1) = ii;
00672 }
00673
00674 done:
00675
00676 return is;
00677 }
00678
00679 #define INSTANTIATE_SPARSE_ASSIGN(LT, RT, API) \
00680 template API int assign (Sparse<LT>&, const Sparse<RT>&); \
00681 template API int assign1 (Sparse<LT>&, const Sparse<RT>&);
00682
00683 #define INSTANTIATE_SPARSE(T, API) \
00684 template class API Sparse<T>;
00685
00686 #define INSTANTIATE_SPARSE_AND_ASSIGN(T, API) \
00687 INSTANTIATE_SPARSE (T, API); \
00688 INSTANTIATE_SPARSE_ASSIGN (T, T, API)
00689
00690 #endif
00691
00692
00693
00694
00695
00696