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 |
|
521 Sparse<T> sort (octave_idx_type dim = 0, sortmode mode = UNDEFINED) const; |
|
522 Sparse<T> sort (Array<octave_idx_type> &sidx, octave_idx_type dim = 0, |
|
523 sortmode mode = UNDEFINED) 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 |
7433
|
549 #define INSTANTIATE_SPARSE_SORT(T) \ |
|
550 template class octave_sort<T>; \ |
|
551 template class vec_index<T>; \ |
|
552 template class octave_sort<vec_index<T> *>; |
|
553 |
5164
|
554 #endif |
|
555 |
|
556 /* |
|
557 ;;; Local Variables: *** |
|
558 ;;; mode: C++ *** |
|
559 ;;; End: *** |
|
560 */ |