Mercurial > hg > octave-nkf
annotate liboctave/Sparse.h @ 7470:ada435261879
eliminate unnecessary explicit template instantiations
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 12 Feb 2008 15:44:42 -0500 |
parents | 2467639bd8c0 |
children | 7bfaa9611558 |
rev | line source |
---|---|
5164 | 1 // Template sparse classes |
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 #if !defined (octave_Sparse_h) | |
26 #define octave_Sparse_h 1 | |
27 | |
28 #include <cassert> | |
29 #include <cstddef> | |
30 | |
31 #include <iostream> | |
32 | |
33 #include "Array.h" | |
34 #include "Array2.h" | |
35 #include "dim-vector.h" | |
36 #include "lo-utils.h" | |
37 | |
7433 | 38 #include "oct-sort.h" |
39 | |
5164 | 40 class idx_vector; |
41 | |
42 // Two dimensional sparse class. Handles the reference counting for | |
43 // all the derived classes. | |
44 | |
45 template <class T> | |
46 class | |
47 Sparse | |
48 { | |
49 protected: | |
50 //-------------------------------------------------------------------- | |
51 // The real representation of all Sparse arrays. | |
52 //-------------------------------------------------------------------- | |
53 | |
6108 | 54 class OCTAVE_API SparseRep |
5164 | 55 { |
56 public: | |
57 | |
58 T *d; | |
5275 | 59 octave_idx_type *r; |
60 octave_idx_type *c; | |
5604 | 61 octave_idx_type nzmx; |
5275 | 62 octave_idx_type nrows; |
63 octave_idx_type ncols; | |
5164 | 64 int count; |
65 | |
5604 | 66 SparseRep (void) : d (0), r (0), c (new octave_idx_type [1]), nzmx (0), nrows (0), |
5164 | 67 ncols (0), count (1) { c[0] = 0; } |
68 | |
5604 | 69 SparseRep (octave_idx_type n) : d (0), r (0), c (new octave_idx_type [n+1]), nzmx (0), nrows (n), |
5164 | 70 ncols (n), count (1) |
71 { | |
5275 | 72 for (octave_idx_type i = 0; i < n + 1; i++) |
5164 | 73 c[i] = 0; |
74 } | |
75 | |
5604 | 76 SparseRep (octave_idx_type nr, octave_idx_type nc) : d (0), r (0), c (new octave_idx_type [nc+1]), nzmx (0), |
5164 | 77 nrows (nr), ncols (nc), count (1) |
78 { | |
5275 | 79 for (octave_idx_type i = 0; i < nc + 1; i++) |
5164 | 80 c[i] = 0; |
81 } | |
82 | |
5275 | 83 SparseRep (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz) : d (new T [nz]), |
5604 | 84 r (new octave_idx_type [nz]), c (new octave_idx_type [nc+1]), nzmx (nz), nrows (nr), |
5164 | 85 ncols (nc), count (1) |
86 { | |
5275 | 87 for (octave_idx_type i = 0; i < nc + 1; i++) |
5164 | 88 c[i] = 0; |
89 } | |
90 | |
91 SparseRep (const SparseRep& a) | |
5604 | 92 : d (new T [a.nzmx]), r (new octave_idx_type [a.nzmx]), c (new octave_idx_type [a.ncols + 1]), |
93 nzmx (a.nzmx), nrows (a.nrows), ncols (a.ncols), count (1) | |
5164 | 94 { |
5604 | 95 for (octave_idx_type i = 0; i < nzmx; i++) |
5164 | 96 { |
97 d[i] = a.d[i]; | |
98 r[i] = a.r[i]; | |
99 } | |
5275 | 100 for (octave_idx_type i = 0; i < ncols + 1; i++) |
5164 | 101 c[i] = a.c[i]; |
102 } | |
103 | |
104 ~SparseRep (void) { delete [] d; delete [] r; delete [] c; } | |
105 | |
5604 | 106 octave_idx_type length (void) const { return nzmx; } |
5164 | 107 |
5604 | 108 octave_idx_type nnz (void) const { return c [ncols]; } |
5164 | 109 |
5275 | 110 T& elem (octave_idx_type _r, octave_idx_type _c); |
5164 | 111 |
5275 | 112 T celem (octave_idx_type _r, octave_idx_type _c) const; |
5164 | 113 |
5275 | 114 T& data (octave_idx_type i) { return d[i]; } |
5164 | 115 |
5275 | 116 T cdata (octave_idx_type i) const { return d[i]; } |
5164 | 117 |
5275 | 118 octave_idx_type& ridx (octave_idx_type i) { return r[i]; } |
5164 | 119 |
5275 | 120 octave_idx_type cridx (octave_idx_type i) const { return r[i]; } |
5164 | 121 |
5275 | 122 octave_idx_type& cidx (octave_idx_type i) { return c[i]; } |
5164 | 123 |
5275 | 124 octave_idx_type ccidx (octave_idx_type i) const { return c[i]; } |
5164 | 125 |
126 void maybe_compress (bool remove_zeros); | |
127 | |
5275 | 128 void change_length (octave_idx_type nz); |
5164 | 129 |
130 private: | |
131 | |
132 // No assignment! | |
133 | |
134 SparseRep& operator = (const SparseRep& a); | |
135 }; | |
136 | |
137 //-------------------------------------------------------------------- | |
138 | |
139 void make_unique (void) | |
140 { | |
141 if (rep->count > 1) | |
142 { | |
143 --rep->count; | |
144 rep = new SparseRep (*rep); | |
145 } | |
146 } | |
147 | |
148 public: | |
149 | |
150 // !!! WARNING !!! -- these should be protected, not public. You | |
151 // should not access these data members directly! | |
152 | |
153 typename Sparse<T>::SparseRep *rep; | |
154 | |
155 dim_vector dimensions; | |
156 | |
157 protected: | |
158 idx_vector *idx; | |
5275 | 159 octave_idx_type idx_count; |
5164 | 160 |
161 private: | |
162 | |
163 typename Sparse<T>::SparseRep *nil_rep (void) const | |
164 { | |
165 static typename Sparse<T>::SparseRep *nr | |
166 = new typename Sparse<T>::SparseRep (); | |
167 | |
168 nr->count++; | |
169 | |
170 return nr; | |
171 } | |
172 | |
173 public: | |
174 | |
175 Sparse (void) | |
176 : rep (nil_rep ()), dimensions (dim_vector(0,0)), | |
177 idx (0), idx_count (0) { } | |
178 | |
5275 | 179 explicit Sparse (octave_idx_type n) |
5164 | 180 : rep (new typename Sparse<T>::SparseRep (n)), |
181 dimensions (dim_vector (n, n)), idx (0), idx_count (0) { } | |
182 | |
5275 | 183 explicit Sparse (octave_idx_type nr, octave_idx_type nc) |
5164 | 184 : rep (new typename Sparse<T>::SparseRep (nr, nc)), |
185 dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) { } | |
186 | |
5275 | 187 explicit Sparse (octave_idx_type nr, octave_idx_type nc, T val); |
5164 | 188 |
5275 | 189 Sparse (const dim_vector& dv, octave_idx_type nz) |
5164 | 190 : rep (new typename Sparse<T>::SparseRep (dv(0), dv(1), nz)), |
191 dimensions (dv), idx (0), idx_count (0) { } | |
192 | |
5275 | 193 Sparse (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz) |
5164 | 194 : rep (new typename Sparse<T>::SparseRep (nr, nc, nz)), |
195 dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) { } | |
196 | |
197 // Type conversion case. | |
198 template <class U> Sparse (const Sparse<U>& a); | |
199 | |
200 // No type conversion case. | |
201 Sparse (const Sparse<T>& a) | |
202 : rep (a.rep), dimensions (a.dimensions), idx (0), idx_count (0) | |
203 { | |
204 rep->count++; | |
205 } | |
206 | |
207 public: | |
208 | |
209 Sparse (const dim_vector& dv); | |
210 | |
211 Sparse (const Sparse<T>& a, const dim_vector& dv); | |
212 | |
5275 | 213 Sparse (const Array<T>& a, const Array<octave_idx_type>& r, const Array<octave_idx_type>& c, |
214 octave_idx_type nr, octave_idx_type nc, bool sum_terms); | |
5164 | 215 |
216 Sparse (const Array<T>& a, const Array<double>& r, const Array<double>& c, | |
5275 | 217 octave_idx_type nr, octave_idx_type nc, bool sum_terms); |
5164 | 218 |
219 // Sparsify a normal matrix | |
220 Sparse (const Array2<T>& a); | |
221 Sparse (const Array<T>& a); | |
222 | |
223 virtual ~Sparse (void); | |
224 | |
225 Sparse<T>& operator = (const Sparse<T>& a) | |
226 { | |
227 if (this != &a) | |
228 { | |
229 if (--rep->count <= 0) | |
230 delete rep; | |
231 | |
232 rep = a.rep; | |
233 rep->count++; | |
234 | |
235 dimensions = a.dimensions; | |
236 } | |
237 | |
238 idx_count = 0; | |
239 idx = 0; | |
240 | |
241 return *this; | |
242 } | |
243 | |
5604 | 244 // Note that nzmax and capacity are the amount of storage for |
245 // non-zero elements, while nnz is the actual number of non-zero | |
246 // terms. | |
247 octave_idx_type nzmax (void) const { return rep->length (); } | |
248 octave_idx_type capacity (void) const { return nzmax (); } | |
249 octave_idx_type nnz (void) const { return rep->nnz (); } | |
5164 | 250 |
251 // Paranoid number of elements test for case of dims = (-1,-1) | |
5275 | 252 octave_idx_type numel (void) const |
5164 | 253 { |
254 if (dim1() < 0 || dim2() < 0) | |
255 return 0; | |
256 else | |
257 return dimensions.numel (); | |
258 } | |
259 | |
5275 | 260 octave_idx_type nelem (void) const { return capacity (); } |
261 octave_idx_type length (void) const { return numel (); } | |
5164 | 262 |
5275 | 263 octave_idx_type dim1 (void) const { return dimensions(0); } |
264 octave_idx_type dim2 (void) const { return dimensions(1); } | |
5164 | 265 |
5275 | 266 octave_idx_type rows (void) const { return dim1 (); } |
267 octave_idx_type cols (void) const { return dim2 (); } | |
268 octave_idx_type columns (void) const { return dim2 (); } | |
5164 | 269 |
5275 | 270 octave_idx_type get_row_index (octave_idx_type k) { return ridx (k); } |
271 octave_idx_type get_col_index (octave_idx_type k) | |
5164 | 272 { |
5275 | 273 octave_idx_type ret = 0; |
5164 | 274 while (cidx(ret+1) < k) |
275 ret++; | |
276 return ret; | |
277 } | |
5275 | 278 size_t byte_size (void) const { return (cols () + 1) * sizeof (octave_idx_type) + |
279 capacity () * (sizeof (T) + sizeof (octave_idx_type)); } | |
5164 | 280 |
281 dim_vector dims (void) const { return dimensions; } | |
282 | |
283 Sparse<T> squeeze (void) const { return *this; } | |
284 | |
5275 | 285 octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx) const; |
5164 | 286 |
5275 | 287 T range_error (const char *fcn, octave_idx_type n) const; |
288 T& range_error (const char *fcn, octave_idx_type n); | |
5164 | 289 |
5275 | 290 T range_error (const char *fcn, octave_idx_type i, octave_idx_type j) const; |
291 T& range_error (const char *fcn, octave_idx_type i, octave_idx_type j); | |
5164 | 292 |
5275 | 293 T range_error (const char *fcn, const Array<octave_idx_type>& ra_idx) const; |
294 T& range_error (const char *fcn, const Array<octave_idx_type>& ra_idx); | |
5164 | 295 |
296 // No checking, even for multiple references, ever. | |
297 | |
5275 | 298 T& xelem (octave_idx_type n) |
5164 | 299 { |
5275 | 300 octave_idx_type i = n % rows (), j = n / rows(); |
5164 | 301 return xelem (i, j); |
302 } | |
303 | |
5275 | 304 T xelem (octave_idx_type n) const |
5164 | 305 { |
5275 | 306 octave_idx_type i = n % rows (), j = n / rows(); |
5164 | 307 return xelem (i, j); |
308 } | |
309 | |
5275 | 310 T& xelem (octave_idx_type i, octave_idx_type j) { return rep->elem (i, j); } |
311 T xelem (octave_idx_type i, octave_idx_type j) const { return rep->celem (i, j); } | |
5164 | 312 |
5275 | 313 T& xelem (const Array<octave_idx_type>& ra_idx) |
5164 | 314 { return xelem (compute_index (ra_idx)); } |
315 | |
5275 | 316 T xelem (const Array<octave_idx_type>& ra_idx) const |
5164 | 317 { return xelem (compute_index (ra_idx)); } |
318 | |
5775 | 319 // FIXME -- would be nice to fix this so that we don't |
5164 | 320 // unnecessarily force a copy, but that is not so easy, and I see no |
321 // clean way to do it. | |
322 | |
5275 | 323 T& checkelem (octave_idx_type n) |
5164 | 324 { |
325 if (n < 0 || n >= numel ()) | |
326 return range_error ("T& Sparse<T>::checkelem", n); | |
327 else | |
328 { | |
329 make_unique (); | |
330 return xelem (n); | |
331 } | |
332 } | |
333 | |
5275 | 334 T& checkelem (octave_idx_type i, octave_idx_type j) |
5164 | 335 { |
336 if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ()) | |
337 return range_error ("T& Sparse<T>::checkelem", i, j); | |
338 else | |
339 { | |
340 make_unique (); | |
341 return xelem (i, j); | |
342 } | |
343 } | |
344 | |
5275 | 345 T& checkelem (const Array<octave_idx_type>& ra_idx) |
5164 | 346 { |
5275 | 347 octave_idx_type i = compute_index (ra_idx); |
5164 | 348 |
349 if (i < 0) | |
350 return range_error ("T& Sparse<T>::checkelem", ra_idx); | |
351 else | |
352 return elem (i); | |
353 } | |
354 | |
5275 | 355 T& elem (octave_idx_type n) |
5164 | 356 { |
357 make_unique (); | |
358 return xelem (n); | |
359 } | |
360 | |
5275 | 361 T& elem (octave_idx_type i, octave_idx_type j) |
5164 | 362 { |
363 make_unique (); | |
364 return xelem (i, j); | |
365 } | |
366 | |
5275 | 367 T& elem (const Array<octave_idx_type>& ra_idx) |
5164 | 368 { return Sparse<T>::elem (compute_index (ra_idx)); } |
369 | |
370 #if defined (BOUNDS_CHECKING) | |
5275 | 371 T& operator () (octave_idx_type n) { return checkelem (n); } |
372 T& operator () (octave_idx_type i, octave_idx_type j) { return checkelem (i, j); } | |
373 T& operator () (const Array<octave_idx_type>& ra_idx) { return checkelem (ra_idx); } | |
5164 | 374 #else |
5275 | 375 T& operator () (octave_idx_type n) { return elem (n); } |
376 T& operator () (octave_idx_type i, octave_idx_type j) { return elem (i, j); } | |
377 T& operator () (const Array<octave_idx_type>& ra_idx) { return elem (ra_idx); } | |
5164 | 378 #endif |
379 | |
5275 | 380 T checkelem (octave_idx_type n) const |
5164 | 381 { |
382 if (n < 0 || n >= numel ()) | |
383 return range_error ("T Sparse<T>::checkelem", n); | |
384 else | |
385 return xelem (n); | |
386 } | |
387 | |
5275 | 388 T checkelem (octave_idx_type i, octave_idx_type j) const |
5164 | 389 { |
390 if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ()) | |
391 return range_error ("T Sparse<T>::checkelem", i, j); | |
392 else | |
393 return xelem (i, j); | |
394 } | |
395 | |
5275 | 396 T checkelem (const Array<octave_idx_type>& ra_idx) const |
5164 | 397 { |
5275 | 398 octave_idx_type i = compute_index (ra_idx); |
5164 | 399 |
400 if (i < 0) | |
401 return range_error ("T Sparse<T>::checkelem", ra_idx); | |
402 else | |
403 return Sparse<T>::elem (i); | |
404 } | |
405 | |
5275 | 406 T elem (octave_idx_type n) const { return xelem (n); } |
5164 | 407 |
5275 | 408 T elem (octave_idx_type i, octave_idx_type j) const { return xelem (i, j); } |
5164 | 409 |
5275 | 410 T elem (const Array<octave_idx_type>& ra_idx) const |
5164 | 411 { return Sparse<T>::elem (compute_index (ra_idx)); } |
412 | |
413 #if defined (BOUNDS_CHECKING) | |
5275 | 414 T operator () (octave_idx_type n) const { return checkelem (n); } |
415 T operator () (octave_idx_type i, octave_idx_type j) const { return checkelem (i, j); } | |
416 T operator () (const Array<octave_idx_type>& ra_idx) const { return checkelem (ra_idx); } | |
5164 | 417 #else |
5275 | 418 T operator () (octave_idx_type n) const { return elem (n); } |
419 T operator () (octave_idx_type i, octave_idx_type j) const { return elem (i, j); } | |
420 T operator () (const Array<octave_idx_type>& ra_idx) const { return elem (ra_idx); } | |
5164 | 421 #endif |
422 | |
423 Sparse<T> maybe_compress (bool remove_zeros = false) | |
424 { rep->maybe_compress (remove_zeros); return (*this); } | |
425 | |
426 Sparse<T> reshape (const dim_vector& new_dims) const; | |
427 | |
428 // !!! WARNING !!! -- the following resize_no_fill functions are | |
429 // public because template friends don't work properly with versions | |
430 // of gcc earlier than 3.3. You should use these functions only in | |
431 // classes that are derived from Sparse<T>. | |
432 | |
433 // protected: | |
434 | |
5275 | 435 void resize_no_fill (octave_idx_type r, octave_idx_type c); |
5164 | 436 |
437 void resize_no_fill (const dim_vector& dv); | |
438 | |
439 public: | |
5275 | 440 Sparse<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const; |
5164 | 441 |
5275 | 442 Sparse<T> ipermute (const Array<octave_idx_type>& vec) const |
5164 | 443 { return permute (vec, true); } |
444 | |
5275 | 445 void resize (octave_idx_type r, octave_idx_type c) { resize_no_fill (r, c); } |
5164 | 446 |
447 void resize (const dim_vector& dv) { resize_no_fill (dv); } | |
448 | |
5275 | 449 void change_capacity (octave_idx_type nz) { rep->change_length (nz); } |
5164 | 450 |
5275 | 451 Sparse<T>& insert (const Sparse<T>& a, octave_idx_type r, octave_idx_type c); |
452 Sparse<T>& insert (const Sparse<T>& a, const Array<octave_idx_type>& idx); | |
5164 | 453 |
454 bool is_square (void) const { return (dim1 () == dim2 ()); } | |
455 | |
456 bool is_empty (void) const { return (rows () < 1 && cols () < 1); } | |
457 | |
458 Sparse<T> transpose (void) const; | |
459 | |
460 T* data (void) { make_unique (); return rep->d; } | |
5275 | 461 T& data (octave_idx_type i) { make_unique (); return rep->data (i); } |
5164 | 462 T* xdata (void) { return rep->d; } |
5275 | 463 T& xdata (octave_idx_type i) { return rep->data (i); } |
5164 | 464 |
5275 | 465 T data (octave_idx_type i) const { return rep->data (i); } |
5900 | 466 // FIXME -- shouldn't this be returning const T*? |
5164 | 467 T* data (void) const { return rep->d; } |
468 | |
5275 | 469 octave_idx_type* ridx (void) { make_unique (); return rep->r; } |
470 octave_idx_type& ridx (octave_idx_type i) { make_unique (); return rep->ridx (i); } | |
471 octave_idx_type* xridx (void) { return rep->r; } | |
472 octave_idx_type& xridx (octave_idx_type i) { return rep->ridx (i); } | |
5164 | 473 |
5275 | 474 octave_idx_type ridx (octave_idx_type i) const { return rep->cridx (i); } |
5900 | 475 // FIXME -- shouldn't this be returning const octave_idx_type*? |
5275 | 476 octave_idx_type* ridx (void) const { return rep->r; } |
5164 | 477 |
5275 | 478 octave_idx_type* cidx (void) { make_unique (); return rep->c; } |
479 octave_idx_type& cidx (octave_idx_type i) { make_unique (); return rep->cidx (i); } | |
480 octave_idx_type* xcidx (void) { return rep->c; } | |
481 octave_idx_type& xcidx (octave_idx_type i) { return rep->cidx (i); } | |
5164 | 482 |
5275 | 483 octave_idx_type cidx (octave_idx_type i) const { return rep->ccidx (i); } |
5900 | 484 // FIXME -- shouldn't this be returning const octave_idx_type*? |
5275 | 485 octave_idx_type* cidx (void) const { return rep->c; } |
5164 | 486 |
5275 | 487 octave_idx_type ndims (void) const { return dimensions.length (); } |
5164 | 488 |
489 void clear_index (void); | |
490 | |
491 void set_index (const idx_vector& i); | |
492 | |
5275 | 493 octave_idx_type index_count (void) const { return idx_count; } |
5164 | 494 |
495 idx_vector *get_idx (void) const { return idx; } | |
496 | |
497 void maybe_delete_elements (idx_vector& i); | |
498 | |
499 void maybe_delete_elements (idx_vector& i, idx_vector& j); | |
500 | |
501 void maybe_delete_elements (Array<idx_vector>& ra_idx); | |
502 | |
503 Sparse<T> value (void); | |
504 | |
505 Sparse<T> index (idx_vector& i, int resize_ok = 0) const; | |
506 | |
507 Sparse<T> index (idx_vector& i, idx_vector& j, int resize_ok = 0) const; | |
508 | |
509 Sparse<T> index (Array<idx_vector>& ra_idx, int resize_ok = 0) const; | |
510 | |
511 void print_info (std::ostream& os, const std::string& prefix) const; | |
512 | |
5900 | 513 // Unsafe. These functions exist to support the MEX interface. |
514 // You should not use them anywhere else. | |
515 void *mex_get_data (void) const { return const_cast<T *> (data ()); } | |
516 | |
517 octave_idx_type *mex_get_ir (void) const { return const_cast<octave_idx_type *> (ridx ()); } | |
518 | |
519 octave_idx_type *mex_get_jc (void) const { return const_cast<octave_idx_type *> (cidx ()); } | |
7433 | 520 |
7463
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
521 Sparse<T> sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const; |
7433 | 522 Sparse<T> sort (Array<octave_idx_type> &sidx, octave_idx_type dim = 0, |
7463
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
523 sortmode mode = ASCENDING) const; |
5164 | 524 }; |
525 | |
526 // NOTE: these functions should be friends of the Sparse<T> class and | |
527 // Sparse<T>::dimensions should be protected, not public, but we can't | |
528 // do that because of bugs in gcc prior to 3.3. | |
529 | |
530 template <class LT, class RT> | |
531 /* friend */ int | |
532 assign (Sparse<LT>& lhs, const Sparse<RT>& rhs); | |
533 | |
534 template <class LT, class RT> | |
535 /* friend */ int | |
536 assign1 (Sparse<LT>& lhs, const Sparse<RT>& rhs); | |
537 | |
6708 | 538 #define INSTANTIATE_SPARSE_ASSIGN(LT, RT, API) \ |
539 template API int assign (Sparse<LT>&, const Sparse<RT>&); \ | |
540 template API int assign1 (Sparse<LT>&, const Sparse<RT>&); | |
5164 | 541 |
6708 | 542 #define INSTANTIATE_SPARSE(T, API) \ |
543 template class API Sparse<T>; | |
5164 | 544 |
6708 | 545 #define INSTANTIATE_SPARSE_AND_ASSIGN(T, API) \ |
546 INSTANTIATE_SPARSE (T, API); \ | |
547 INSTANTIATE_SPARSE_ASSIGN (T, T, API) | |
5164 | 548 |
549 #endif | |
550 | |
551 /* | |
552 ;;; Local Variables: *** | |
553 ;;; mode: C++ *** | |
554 ;;; End: *** | |
555 */ |