237
|
1 // Template array classes -*- C++ -*- |
|
2 /* |
|
3 |
1011
|
4 Copyright (C) 1993, 1994, 1995 John W. Eaton |
237
|
5 |
|
6 This file is part of Octave. |
|
7 |
|
8 Octave is free software; you can redistribute it and/or modify it |
|
9 under the terms of the GNU General Public License as published by the |
|
10 Free Software Foundation; either version 2, or (at your option) any |
|
11 later version. |
|
12 |
|
13 Octave is distributed in the hope that it will be useful, but WITHOUT |
|
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
16 for more details. |
|
17 |
|
18 You should have received a copy of the GNU General Public License |
|
19 along with Octave; see the file COPYING. If not, write to the Free |
1315
|
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
237
|
21 |
|
22 */ |
|
23 |
1296
|
24 #if defined (__GNUG__) |
|
25 #pragma implementation |
|
26 #endif |
|
27 |
237
|
28 #ifdef HAVE_CONFIG_H |
1192
|
29 #include <config.h> |
237
|
30 #endif |
|
31 |
1367
|
32 #include <cassert> |
449
|
33 |
1560
|
34 #include <iostream.h> |
|
35 |
237
|
36 #include "Array.h" |
|
37 |
1560
|
38 #if defined (HEAVYWEIGHT_INDEXING) |
|
39 #include "idx-vector.h" |
|
40 #include "Array-idx.h" |
|
41 #endif |
|
42 |
|
43 #include "lo-error.h" |
|
44 |
1360
|
45 // The real representation of all arrays. |
237
|
46 |
|
47 template <class T> |
|
48 ArrayRep<T>::ArrayRep (int n) |
|
49 { |
|
50 len = n; |
1692
|
51 count = 1; |
237
|
52 data = new T [len]; |
|
53 } |
|
54 |
|
55 template <class T> |
|
56 ArrayRep<T>::ArrayRep (const ArrayRep<T>& a) |
|
57 { |
|
58 len = a.len; |
1692
|
59 count = 1; |
1560
|
60 |
237
|
61 data = new T [len]; |
|
62 for (int i = 0; i < len; i++) |
|
63 data[i] = a.data[i]; |
|
64 } |
|
65 |
|
66 template <class T> |
|
67 ArrayRep<T>::~ArrayRep (void) |
|
68 { |
|
69 delete [] data; |
|
70 } |
|
71 |
|
72 template <class T> |
|
73 T& |
|
74 ArrayRep<T>::elem (int n) |
|
75 { |
|
76 return data[n]; |
|
77 } |
|
78 |
|
79 template <class T> |
|
80 T |
|
81 ArrayRep<T>::elem (int n) const |
|
82 { |
|
83 return data[n]; |
|
84 } |
|
85 |
1360
|
86 // One dimensional array class. Handles the reference counting for |
|
87 // all the derived classes. |
237
|
88 |
|
89 template <class T> |
|
90 Array<T>::Array (int n, const T& val) |
|
91 { |
|
92 rep = new ArrayRep<T> (n); |
1619
|
93 |
237
|
94 for (int i = 0; i < n; i++) |
|
95 rep->data[i] = val; |
1619
|
96 |
|
97 #ifdef HEAVYWEIGHT_INDEXING |
|
98 max_indices = 1; |
|
99 idx_count = 0; |
|
100 idx = 0; |
|
101 #endif |
|
102 } |
|
103 |
|
104 template <class T> |
|
105 Array<T>::~Array (void) |
|
106 { |
|
107 if (--rep->count <= 0) |
|
108 delete rep; |
|
109 |
|
110 #ifdef HEAVYWEIGHT_INDEXING |
|
111 delete [] idx; |
|
112 #endif |
237
|
113 } |
|
114 |
|
115 template <class T> |
|
116 Array<T>& |
|
117 Array<T>::operator = (const Array<T>& a) |
|
118 { |
659
|
119 if (this != &a) |
|
120 { |
|
121 if (--rep->count <= 0) |
|
122 delete rep; |
237
|
123 |
659
|
124 rep = a.rep; |
|
125 rep->count++; |
|
126 } |
1619
|
127 |
|
128 #ifdef HEAVYWEIGHT_INDEXING |
|
129 max_indices = 1; |
|
130 idx_count = 0; |
|
131 idx = 0; |
|
132 #endif |
|
133 |
237
|
134 return *this; |
|
135 } |
|
136 |
|
137 template <class T> |
|
138 T& |
|
139 Array<T>::checkelem (int n) |
|
140 { |
|
141 if (n < 0 || n >= rep->length ()) |
|
142 { |
|
143 (*current_liboctave_error_handler) ("range error"); |
254
|
144 static T foo; |
237
|
145 return foo; |
|
146 } |
|
147 return elem (n); |
|
148 } |
|
149 |
|
150 template <class T> |
|
151 T |
|
152 Array<T>::elem (int n) const |
|
153 { |
|
154 return rep->elem (n); |
|
155 } |
|
156 |
|
157 template <class T> |
|
158 T |
|
159 Array<T>::checkelem (int n) const |
|
160 { |
|
161 if (n < 0 || n >= rep->length ()) |
|
162 { |
|
163 (*current_liboctave_error_handler) ("range error"); |
254
|
164 T foo; |
1470
|
165 static T *bar = &foo; |
254
|
166 return foo; |
237
|
167 } |
|
168 return elem (n); |
|
169 } |
|
170 |
|
171 template <class T> |
|
172 T |
|
173 Array<T>::operator () (int n) const |
|
174 { |
|
175 return checkelem (n); |
|
176 } |
|
177 |
|
178 template <class T> |
|
179 void |
|
180 Array<T>::resize (int n) |
|
181 { |
|
182 if (n < 0) |
|
183 { |
1560
|
184 (*current_liboctave_error_handler) ("can't resize to negative dimension"); |
237
|
185 return; |
|
186 } |
|
187 |
|
188 if (n == length ()) |
|
189 return; |
|
190 |
|
191 ArrayRep<T> *old_rep = rep; |
|
192 const T *old_data = data (); |
|
193 int old_len = length (); |
|
194 |
|
195 rep = new ArrayRep<T> (n); |
|
196 |
|
197 if (old_data && old_len > 0) |
|
198 { |
|
199 int min_len = old_len < n ? old_len : n; |
|
200 |
|
201 for (int i = 0; i < min_len; i++) |
|
202 xelem (i) = old_data[i]; |
|
203 } |
|
204 |
|
205 if (--old_rep->count <= 0) |
|
206 delete old_rep; |
|
207 } |
|
208 |
|
209 template <class T> |
|
210 void |
|
211 Array<T>::resize (int n, const T& val) |
|
212 { |
|
213 if (n < 0) |
|
214 { |
1560
|
215 (*current_liboctave_error_handler) ("can't resize to negative dimension"); |
237
|
216 return; |
|
217 } |
|
218 |
|
219 if (n == length ()) |
|
220 return; |
|
221 |
|
222 ArrayRep<T> *old_rep = rep; |
|
223 const T *old_data = data (); |
|
224 int old_len = length (); |
|
225 |
|
226 rep = new ArrayRep<T> (n); |
|
227 |
|
228 int min_len = old_len < n ? old_len : n; |
|
229 |
|
230 if (old_data && old_len > 0) |
|
231 { |
|
232 for (int i = 0; i < min_len; i++) |
|
233 xelem (i) = old_data[i]; |
|
234 } |
|
235 |
|
236 for (int i = old_len; i < n; i++) |
|
237 xelem (i) = val; |
|
238 |
|
239 if (--old_rep->count <= 0) |
|
240 delete old_rep; |
|
241 } |
|
242 |
|
243 template <class T> |
|
244 T * |
|
245 Array<T>::fortran_vec (void) |
|
246 { |
|
247 if (rep->count > 1) |
|
248 { |
|
249 --rep->count; |
|
250 rep = new ArrayRep<T> (*rep); |
|
251 } |
|
252 return rep->data; |
|
253 } |
|
254 |
1360
|
255 // Two dimensional array class. |
237
|
256 |
|
257 template <class T> |
|
258 T& |
|
259 Array2<T>::checkelem (int i, int j) |
|
260 { |
254
|
261 if (i < 0 || j < 0 || i >= d1 || j >= d2) |
|
262 { |
|
263 (*current_liboctave_error_handler) ("range error"); |
|
264 static T foo; |
|
265 return foo; |
|
266 } |
|
267 return Array<T>::elem (d1*j+i); |
237
|
268 } |
|
269 |
|
270 template <class T> |
|
271 T |
|
272 Array2<T>::elem (int i, int j) const |
|
273 { |
|
274 return Array<T>::elem (d1*j+i); |
|
275 } |
|
276 |
|
277 template <class T> |
|
278 T |
|
279 Array2<T>::checkelem (int i, int j) const |
|
280 { |
254
|
281 if (i < 0 || j < 0 || i >= d1 || j >= d2) |
|
282 { |
|
283 (*current_liboctave_error_handler) ("range error"); |
|
284 T foo; |
1470
|
285 static T *bar = &foo; |
254
|
286 return foo; |
|
287 } |
|
288 return Array<T>::elem (d1*j+i); |
237
|
289 } |
|
290 |
|
291 template <class T> |
|
292 T |
|
293 Array2<T>::operator () (int i, int j) const |
|
294 { |
254
|
295 if (i < 0 || j < 0 || i >= d1 || j >= d2) |
|
296 { |
|
297 (*current_liboctave_error_handler) ("range error"); |
|
298 T foo; |
1470
|
299 static T *bar = &foo; |
254
|
300 return foo; |
|
301 } |
|
302 return Array<T>::elem (d1*j+i); |
237
|
303 } |
|
304 |
|
305 template <class T> |
|
306 void |
|
307 Array2<T>::resize (int r, int c) |
|
308 { |
|
309 if (r < 0 || c < 0) |
|
310 { |
1560
|
311 (*current_liboctave_error_handler) ("can't resize to negative dimension"); |
237
|
312 return; |
|
313 } |
|
314 |
|
315 if (r == dim1 () && c == dim2 ()) |
|
316 return; |
|
317 |
|
318 ArrayRep<T> *old_rep = rep; |
|
319 const T *old_data = data (); |
1560
|
320 |
237
|
321 int old_d1 = dim1 (); |
|
322 int old_d2 = dim2 (); |
|
323 int old_len = length (); |
|
324 |
|
325 rep = new ArrayRep<T> (r*c); |
|
326 |
|
327 d1 = r; |
|
328 d2 = c; |
|
329 |
|
330 if (old_data && old_len > 0) |
|
331 { |
|
332 int min_r = old_d1 < r ? old_d1 : r; |
|
333 int min_c = old_d2 < c ? old_d2 : c; |
|
334 |
|
335 for (int j = 0; j < min_c; j++) |
|
336 for (int i = 0; i < min_r; i++) |
|
337 xelem (i, j) = old_data[old_d1*j+i]; |
|
338 } |
|
339 |
|
340 if (--old_rep->count <= 0) |
|
341 delete old_rep; |
|
342 } |
|
343 |
|
344 template <class T> |
|
345 void |
|
346 Array2<T>::resize (int r, int c, const T& val) |
|
347 { |
|
348 if (r < 0 || c < 0) |
|
349 { |
1560
|
350 (*current_liboctave_error_handler) ("can't resize to negative dimension"); |
237
|
351 return; |
|
352 } |
|
353 |
|
354 if (r == dim1 () && c == dim2 ()) |
|
355 return; |
|
356 |
|
357 ArrayRep<T> *old_rep = rep; |
|
358 const T *old_data = data (); |
|
359 int old_d1 = dim1 (); |
|
360 int old_d2 = dim2 (); |
|
361 int old_len = length (); |
|
362 |
|
363 rep = new ArrayRep<T> (r*c); |
|
364 |
|
365 d1 = r; |
|
366 d2 = c; |
|
367 |
|
368 int min_r = old_d1 < r ? old_d1 : r; |
|
369 int min_c = old_d2 < c ? old_d2 : c; |
|
370 |
|
371 if (old_data && old_len > 0) |
|
372 { |
1321
|
373 for (int j = 0; j < min_c; j++) |
|
374 for (int i = 0; i < min_r; i++) |
237
|
375 xelem (i, j) = old_data[old_d1*j+i]; |
|
376 } |
|
377 |
1321
|
378 for (int j = 0; j < min_c; j++) |
|
379 for (int i = min_r; i < r; i++) |
237
|
380 xelem (i, j) = val; |
|
381 |
1321
|
382 for (int j = min_c; j < c; j++) |
|
383 for (int i = 0; i < r; i++) |
237
|
384 xelem (i, j) = val; |
|
385 |
|
386 if (--old_rep->count <= 0) |
|
387 delete old_rep; |
|
388 } |
|
389 |
1561
|
390 template <class T> |
|
391 Array2<T>& |
|
392 Array2<T>::insert (const Array2<T>& a, int r, int c) |
|
393 { |
|
394 int a_rows = a.rows (); |
|
395 int a_cols = a.cols (); |
1698
|
396 |
|
397 if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ()) |
1561
|
398 { |
|
399 (*current_liboctave_error_handler) ("range error for insert"); |
|
400 return *this; |
|
401 } |
|
402 |
|
403 for (int j = 0; j < a_cols; j++) |
|
404 for (int i = 0; i < a_rows; i++) |
|
405 elem (r+i, c+j) = a.elem (i, j); |
|
406 |
|
407 return *this; |
|
408 } |
|
409 |
1360
|
410 // Three dimensional array class. |
237
|
411 |
|
412 template <class T> |
|
413 T& |
|
414 Array3<T>::checkelem (int i, int j, int k) |
|
415 { |
254
|
416 if (i < 0 || j < 0 || k < 0 || i >= d1 || j >= d2 || k >= d3) |
|
417 { |
|
418 (*current_liboctave_error_handler) ("range error"); |
|
419 static T foo; |
|
420 return foo; |
|
421 } |
|
422 return Array2<T>::elem (i, d1*k+j); |
237
|
423 } |
|
424 |
|
425 template <class T> |
|
426 T |
|
427 Array3<T>::elem (int i, int j, int k) const |
|
428 { |
|
429 return Array2<T>::elem (i, d2*k+j); |
|
430 } |
|
431 |
|
432 template <class T> |
|
433 T |
|
434 Array3<T>::checkelem (int i, int j, int k) const |
|
435 { |
254
|
436 if (i < 0 || j < 0 || k < 0 || i >= d1 || j >= d2 || k >= d3) |
|
437 { |
|
438 (*current_liboctave_error_handler) ("range error"); |
|
439 T foo; |
1470
|
440 static T *bar = &foo; |
254
|
441 return foo; |
|
442 } |
|
443 return Array2<T>::elem (i, d1*k+j); |
237
|
444 } |
|
445 |
|
446 template <class T> |
|
447 T |
|
448 Array3<T>::operator () (int i, int j, int k) const |
|
449 { |
254
|
450 if (i < 0 || j < 0 || k < 0 || i >= d1 || j >= d2 || k >= d3) |
|
451 { |
|
452 (*current_liboctave_error_handler) ("range error"); |
|
453 T foo; |
1470
|
454 static T *bar = &foo; |
254
|
455 return foo; |
|
456 } |
|
457 return Array2<T>::elem (i, d2*k+j); |
237
|
458 } |
|
459 |
|
460 template <class T> |
|
461 void |
|
462 Array3<T>::resize (int n, int m, int k) |
|
463 { |
1360
|
464 assert (0); // XXX FIXME XXX |
237
|
465 } |
|
466 |
|
467 template <class T> |
|
468 void |
|
469 Array3<T>::resize (int n, int m, int k, const T& val) |
|
470 { |
1360
|
471 assert (0); // XXX FIXME XXX |
237
|
472 } |
|
473 |
1360
|
474 // A two-dimensional array with diagonal elements only. |
237
|
475 |
1574
|
476 #ifndef NO_DIAG_ARRAY |
880
|
477 #if 1 |
344
|
478 template <class T> |
|
479 T& |
|
480 DiagArray<T>::elem (int r, int c) |
|
481 { |
|
482 static T foo (0); |
|
483 return (r == c) ? Array<T>::elem (r) : foo; |
|
484 } |
|
485 |
|
486 template <class T> |
|
487 T& |
|
488 DiagArray<T>::checkelem (int r, int c) |
|
489 { |
|
490 static T foo (0); |
|
491 if (r < 0 || c < 0 || r >= nr || c >= nc) |
|
492 { |
|
493 (*current_liboctave_error_handler) ("range error"); |
|
494 return foo; |
|
495 } |
|
496 return (r == c) ? Array<T>::elem (r) : foo; |
|
497 } |
|
498 |
|
499 template <class T> |
|
500 T& |
|
501 DiagArray<T>::operator () (int r, int c) |
|
502 { |
|
503 static T foo (0); |
|
504 if (r < 0 || c < 0 || r >= nr || c >= nc) |
|
505 { |
|
506 (*current_liboctave_error_handler) ("range error"); |
|
507 return foo; |
|
508 } |
|
509 return (r == c) ? Array<T>::elem (r) : foo; |
|
510 } |
347
|
511 #endif |
344
|
512 |
237
|
513 template <class T> |
|
514 T& |
|
515 DiagArray<T>::xelem (int r, int c) |
|
516 { |
|
517 static T foo (0); |
|
518 return (r == c) ? Array<T>::xelem (r) : foo; |
|
519 } |
|
520 |
|
521 template <class T> |
|
522 T |
|
523 DiagArray<T>::elem (int r, int c) const |
|
524 { |
|
525 return (r == c) ? Array<T>::elem (r) : T (0); |
|
526 } |
|
527 |
|
528 template <class T> |
|
529 T |
|
530 DiagArray<T>::checkelem (int r, int c) const |
|
531 { |
254
|
532 if (r < 0 || c < 0 || r >= nr || c >= nc) |
|
533 { |
|
534 (*current_liboctave_error_handler) ("range error"); |
|
535 T foo; |
1470
|
536 static T *bar = &foo; |
254
|
537 return foo; |
|
538 } |
|
539 return (r == c) ? Array<T>::elem (r) : T (0); |
237
|
540 } |
|
541 |
|
542 template <class T> |
|
543 T |
|
544 DiagArray<T>::operator () (int r, int c) const |
|
545 { |
254
|
546 if (r < 0 || c < 0 || r >= nr || c >= nc) |
|
547 { |
|
548 (*current_liboctave_error_handler) ("range error"); |
|
549 T foo; |
1470
|
550 static T *bar = &foo; |
254
|
551 return foo; |
|
552 } |
|
553 return (r == c) ? Array<T>::elem (r) : T (0); |
237
|
554 } |
|
555 |
|
556 template <class T> |
|
557 void |
|
558 DiagArray<T>::resize (int r, int c) |
|
559 { |
|
560 if (r < 0 || c < 0) |
|
561 { |
1560
|
562 (*current_liboctave_error_handler) ("can't resize to negative dimensions"); |
237
|
563 return; |
|
564 } |
|
565 |
|
566 if (r == dim1 () && c == dim2 ()) |
|
567 return; |
|
568 |
|
569 ArrayRep<T> *old_rep = rep; |
|
570 const T *old_data = data (); |
|
571 int old_len = length (); |
|
572 |
|
573 int new_len = r < c ? r : c; |
|
574 |
|
575 rep = new ArrayRep<T> (new_len); |
|
576 |
|
577 nr = r; |
|
578 nc = c; |
|
579 |
|
580 if (old_data && old_len > 0) |
|
581 { |
|
582 int min_len = old_len < new_len ? old_len : new_len; |
|
583 |
|
584 for (int i = 0; i < min_len; i++) |
|
585 xelem (i, i) = old_data[i]; |
|
586 } |
|
587 |
|
588 if (--old_rep->count <= 0) |
|
589 delete old_rep; |
|
590 } |
|
591 |
|
592 template <class T> |
|
593 void |
|
594 DiagArray<T>::resize (int r, int c, const T& val) |
|
595 { |
|
596 if (r < 0 || c < 0) |
|
597 { |
1560
|
598 (*current_liboctave_error_handler) ("can't resize to negative dimensions"); |
237
|
599 return; |
|
600 } |
|
601 |
|
602 if (r == dim1 () && c == dim2 ()) |
|
603 return; |
|
604 |
|
605 ArrayRep<T> *old_rep = rep; |
|
606 const T *old_data = data (); |
|
607 int old_len = length (); |
|
608 |
|
609 int new_len = r < c ? r : c; |
|
610 |
|
611 rep = new ArrayRep<T> (new_len); |
|
612 |
|
613 nr = r; |
|
614 nc = c; |
|
615 |
|
616 int min_len = old_len < new_len ? old_len : new_len; |
|
617 |
|
618 if (old_data && old_len > 0) |
|
619 { |
|
620 for (int i = 0; i < min_len; i++) |
|
621 xelem (i, i) = old_data[i]; |
|
622 } |
|
623 |
|
624 for (int i = min_len; i < new_len; i++) |
|
625 xelem (i, i) = val; |
|
626 |
|
627 if (--old_rep->count <= 0) |
|
628 delete old_rep; |
|
629 } |
1574
|
630 #endif |
237
|
631 |
|
632 /* |
|
633 ;;; Local Variables: *** |
|
634 ;;; mode: C++ *** |
|
635 ;;; page-delimiter: "^/\\*" *** |
|
636 ;;; End: *** |
|
637 */ |