comparison liboctave/Array.cc @ 237:5a9e23307fb0

[project @ 1993-11-30 20:23:04 by jwe] Initial revision
author jwe
date Tue, 30 Nov 1993 20:23:04 +0000
parents
children 5ba769d183b9
comparison
equal deleted inserted replaced
236:93bbd907de34 237:5a9e23307fb0
1 // Template array classes -*- C++ -*-
2 /*
3
4 Copyright (C) 1993 John W. Eaton
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
20 Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <assert.h>
29
30 #if defined (__GNUG__) && defined (USE_EXTERNAL_TEMPLATES)
31 #pragma implementation
32 #endif
33
34 #include "Array.h"
35 #include "lo-error.h"
36
37 /*
38 * The real representation of all arrays.
39 */
40
41 template <class T>
42 ArrayRep<T>::ArrayRep (T *d, int l)
43 {
44 data = d;
45 len = l;
46 }
47
48 template <class T>
49 ArrayRep<T>::ArrayRep (void)
50 {
51 len = 0;
52 data = (T *) 0;
53 }
54
55 template <class T>
56 ArrayRep<T>::ArrayRep (int n)
57 {
58 len = n;
59 data = new T [len];
60 }
61
62 template <class T>
63 ArrayRep<T>::ArrayRep (const ArrayRep<T>& a)
64 {
65 len = a.len;
66 count = a.count;
67 data = new T [len];
68 for (int i = 0; i < len; i++)
69 data[i] = a.data[i];
70 }
71
72 template <class T>
73 ArrayRep<T>::~ArrayRep (void)
74 {
75 delete [] data;
76 data = (T *) 0;
77 }
78
79 template <class T>
80 int
81 ArrayRep<T>::length (void) const
82 {
83 return len;
84 }
85
86 template <class T>
87 T&
88 ArrayRep<T>::elem (int n)
89 {
90 return data[n];
91 }
92
93 template <class T>
94 T
95 ArrayRep<T>::elem (int n) const
96 {
97 return data[n];
98 }
99
100 /*
101 * One dimensional array class. Handles the reference counting for
102 * all the derived classes.
103 */
104
105 template <class T>
106 Array<T>::Array (T *d, int l)
107 {
108 rep = new ArrayRep<T> (d, l);
109 rep->count = 1;
110 }
111
112 template <class T>
113 Array<T>::Array (void)
114 {
115 rep = new ArrayRep<T>;
116 rep->count = 1;
117 }
118
119 template <class T>
120 Array<T>::Array (int n)
121 {
122 rep = new ArrayRep<T> (n);
123 rep->count = 1;
124 }
125
126 template <class T>
127 Array<T>::Array (int n, const T& val)
128 {
129 rep = new ArrayRep<T> (n);
130 rep->count = 1;
131 for (int i = 0; i < n; i++)
132 rep->data[i] = val;
133 }
134
135 template <class T>
136 Array<T>::Array (const Array<T>& a)
137 {
138 rep = a.rep;
139 rep->count++;
140 }
141
142 template <class T>
143 Array<T>::~Array (void)
144 {
145 if (--rep->count <= 0)
146 delete rep;
147 }
148
149 template <class T>
150 Array<T>&
151 Array<T>::operator = (const Array<T>& a)
152 {
153 if (--rep->count <= 0)
154 delete rep;
155
156 rep = a.rep;
157 rep->count++;
158 return *this;
159 }
160
161 template <class T>
162 int
163 Array<T>::capacity (void) const
164 {
165 return rep->length ();
166 }
167
168 template <class T>
169 int
170 Array<T>::length (void) const
171 {
172 return rep->length ();
173 }
174
175 template <class T>
176 T&
177 Array<T>::elem (int n)
178 {
179 if (rep->count > 1)
180 {
181 --rep->count;
182 rep = new ArrayRep<T> (*rep);
183 rep->count = 1;
184 }
185 return rep->elem (n);
186 }
187
188 template <class T>
189 T&
190 Array<T>::checkelem (int n)
191 {
192 if (n < 0 || n >= rep->length ())
193 {
194 (*current_liboctave_error_handler) ("range error");
195 static T foo (0);
196 return foo;
197 }
198 return elem (n);
199 }
200
201 template <class T>
202 T&
203 Array<T>::operator () (int n)
204 {
205 return checkelem (n);
206 }
207
208 template <class T>
209 T&
210 Array<T>::xelem (int n)
211 {
212 return rep->elem (n);
213 }
214
215 template <class T>
216 T
217 Array<T>::elem (int n) const
218 {
219 return rep->elem (n);
220 }
221
222 template <class T>
223 T
224 Array<T>::checkelem (int n) const
225 {
226 if (n < 0 || n >= rep->length ())
227 {
228 (*current_liboctave_error_handler) ("range error");
229 return T (0);
230 }
231 return elem (n);
232 }
233
234 template <class T>
235 T
236 Array<T>::operator () (int n) const
237 {
238 return checkelem (n);
239 }
240
241 template <class T>
242 void
243 Array<T>::resize (int n)
244 {
245 if (n < 0)
246 {
247 (*current_liboctave_error_handler)
248 ("can't resize to negative dimension");
249 return;
250 }
251
252 if (n == length ())
253 return;
254
255 ArrayRep<T> *old_rep = rep;
256 const T *old_data = data ();
257 int old_len = length ();
258
259 rep = new ArrayRep<T> (n);
260 rep->count = 1;
261
262 if (old_data && old_len > 0)
263 {
264 int min_len = old_len < n ? old_len : n;
265
266 for (int i = 0; i < min_len; i++)
267 xelem (i) = old_data[i];
268 }
269
270 if (--old_rep->count <= 0)
271 delete old_rep;
272 }
273
274 template <class T>
275 void
276 Array<T>::resize (int n, const T& val)
277 {
278 if (n < 0)
279 {
280 (*current_liboctave_error_handler)
281 ("can't resize to negative dimension");
282 return;
283 }
284
285 if (n == length ())
286 return;
287
288 ArrayRep<T> *old_rep = rep;
289 const T *old_data = data ();
290 int old_len = length ();
291
292 rep = new ArrayRep<T> (n);
293 rep->count = 1;
294
295 int min_len = old_len < n ? old_len : n;
296
297 if (old_data && old_len > 0)
298 {
299 for (int i = 0; i < min_len; i++)
300 xelem (i) = old_data[i];
301 }
302
303 for (int i = old_len; i < n; i++)
304 xelem (i) = val;
305
306 if (--old_rep->count <= 0)
307 delete old_rep;
308 }
309
310 template <class T>
311 const T *
312 Array<T>::data (void) const
313 {
314 return rep->data;
315 }
316
317 template <class T>
318 T *
319 Array<T>::fortran_vec (void)
320 {
321 if (rep->count > 1)
322 {
323 --rep->count;
324 rep = new ArrayRep<T> (*rep);
325 rep->count = 1;
326 }
327 return rep->data;
328 }
329
330 /*
331 * Two dimensional array class.
332 */
333
334 template <class T>
335 Array2<T>::Array2 (T *d, int n, int m) : Array<T> (d, n*m)
336 {
337 d1 = n;
338 d2 = m;
339 }
340
341 template <class T>
342 Array2<T>::Array2 (void) : Array<T> ()
343 {
344 d1 = 0;
345 d2 = 0;
346 }
347
348 template <class T>
349 Array2<T>::Array2 (int n, int m) : Array<T> (n*m)
350 {
351 d1 = n;
352 d2 = m;
353 }
354
355 template <class T>
356 Array2<T>::Array2 (int n, int m, const T& val) : Array<T> (n*m, val)
357 {
358 d1 = n;
359 d2 = m;
360 }
361
362 template <class T>
363 Array2<T>::Array2 (const Array2<T>& a) : Array<T> (a)
364 {
365 d1 = a.d1;
366 d2 = a.d2;
367 }
368
369 template <class T>
370 Array2<T>::Array2 (const DiagArray<T>& a)
371 : Array<T> (a.rows () * a.cols (), T (0))
372 {
373 for (int i = 0; i < a.length (); i++)
374 elem (i, i) = a.elem (i, i);
375 }
376
377 template <class T>
378 Array2<T>&
379 Array2<T>::operator = (const Array2<T>& a)
380 {
381 Array<T>::operator = (a);
382 d1 = a.d1;
383 d2 = a.d2;
384 return *this;
385 }
386
387 template <class T>
388 int
389 Array2<T>::dim1 (void) const
390 {
391 return d1;
392 }
393
394 template <class T>
395 int
396 Array2<T>::dim2 (void) const
397 {
398 return d2;
399 }
400
401 template <class T>
402 int
403 Array2<T>::rows (void) const
404 {
405 return d1;
406 }
407
408 template <class T>
409 int
410 Array2<T>::cols (void) const
411 {
412 return d2;
413 }
414
415 template <class T>
416 int
417 Array2<T>::columns (void) const
418 {
419 return d2;
420 }
421
422 template <class T>
423 T&
424 Array2<T>::elem (int i, int j)
425 {
426 return Array<T>::elem (d1*j+i);
427 }
428
429 template <class T>
430 T&
431 Array2<T>::checkelem (int i, int j)
432 {
433 return Array<T>::checkelem (d1*j+i);
434 }
435
436 template <class T>
437 T&
438 Array2<T>::operator () (int i, int j)
439 {
440 return Array<T>::checkelem (d1*j+i);
441 }
442
443 template <class T>
444 T&
445 Array2<T>::xelem (int i, int j)
446 {
447 return Array<T>::xelem (d1*j+i);
448 }
449
450 template <class T>
451 T
452 Array2<T>::elem (int i, int j) const
453 {
454 return Array<T>::elem (d1*j+i);
455 }
456
457 template <class T>
458 T
459 Array2<T>::checkelem (int i, int j) const
460 {
461 return Array<T>::checkelem (d1*j+i);
462 }
463
464 template <class T>
465 T
466 Array2<T>::operator () (int i, int j) const
467 {
468 return Array<T>::checkelem (d1*j+i);
469 }
470
471 template <class T>
472 void
473 Array2<T>::resize (int r, int c)
474 {
475 if (r < 0 || c < 0)
476 {
477 (*current_liboctave_error_handler)
478 ("can't resize to negative dimension");
479 return;
480 }
481
482 if (r == dim1 () && c == dim2 ())
483 return;
484
485 ArrayRep<T> *old_rep = rep;
486 const T *old_data = data ();
487 int old_d1 = dim1 ();
488 int old_d2 = dim2 ();
489 int old_len = length ();
490
491 rep = new ArrayRep<T> (r*c);
492 rep->count = 1;
493
494 d1 = r;
495 d2 = c;
496
497 if (old_data && old_len > 0)
498 {
499 int min_r = old_d1 < r ? old_d1 : r;
500 int min_c = old_d2 < c ? old_d2 : c;
501
502 for (int j = 0; j < min_c; j++)
503 for (int i = 0; i < min_r; i++)
504 xelem (i, j) = old_data[old_d1*j+i];
505 }
506
507 if (--old_rep->count <= 0)
508 delete old_rep;
509 }
510
511 template <class T>
512 void
513 Array2<T>::resize (int r, int c, const T& val)
514 {
515 if (r < 0 || c < 0)
516 {
517 (*current_liboctave_error_handler)
518 ("can't resize to negative dimension");
519 return;
520 }
521
522 if (r == dim1 () && c == dim2 ())
523 return;
524
525 ArrayRep<T> *old_rep = rep;
526 const T *old_data = data ();
527 int old_d1 = dim1 ();
528 int old_d2 = dim2 ();
529 int old_len = length ();
530
531 rep = new ArrayRep<T> (r*c);
532 rep->count = 1;
533
534 d1 = r;
535 d2 = c;
536
537 int min_r = old_d1 < r ? old_d1 : r;
538 int min_c = old_d2 < c ? old_d2 : c;
539
540 int i, j;
541
542 if (old_data && old_len > 0)
543 {
544 for (j = 0; j < min_c; j++)
545 for (i = 0; i < min_r; i++)
546 xelem (i, j) = old_data[old_d1*j+i];
547 }
548
549 for (j = 0; j < min_c; j++)
550 for (i = min_r; i < r; i++)
551 xelem (i, j) = val;
552
553 for (j = min_c; j < c; j++)
554 for (i = 0; i < r; i++)
555 xelem (i, j) = val;
556
557 if (--old_rep->count <= 0)
558 delete old_rep;
559 }
560
561 /*
562 * Three dimensional array class.
563 */
564
565 template <class T>
566 Array3<T>::Array3 (T *d, int n, int m, int k) : Array2<T> (d, n, m*k)
567 {
568 d2 = m;
569 d3 = k;
570 }
571
572 template <class T>
573 Array3<T>::Array3 (void) : Array2<T> ()
574 {
575 d2 = 0;
576 d3 = 0;
577 }
578
579 template <class T>
580 Array3<T>::Array3 (int n, int m, int k) : Array2<T> (n, m*k)
581 {
582 d2 = m;
583 d3 = k;
584 }
585
586 template <class T>
587 Array3<T>::Array3 (int n, int m, int k, const T& val) : Array2<T> (n, m*k, val)
588 {
589 d2 = m;
590 d3 = k;
591 }
592
593 template <class T>
594 Array3<T>::Array3 (const Array3<T>& a) : Array2<T> (a)
595 {
596 d2 = a.d2;
597 d3 = a.d3;
598 }
599
600 template <class T>
601 Array3<T>&
602 Array3<T>::operator = (const Array3<T>& a)
603 {
604 Array<T>::operator = (a);
605 d1 = a.d1;
606 d2 = a.d2;
607 d3 = a.d3;
608 return *this;
609 }
610
611 template <class T>
612 int
613 Array3<T>::dim3 (void) const
614 {
615 return d3;
616 }
617
618 template <class T>
619 T&
620 Array3<T>::elem (int i, int j, int k)
621 {
622 return Array2<T>::elem (i, d2*k+j);
623 }
624
625 template <class T>
626 T&
627 Array3<T>::checkelem (int i, int j, int k)
628 {
629 return Array2<T>::checkelem (i, d1*k+j);
630 }
631
632 template <class T>
633 T&
634 Array3<T>::operator () (int i, int j, int k)
635 {
636 return Array2<T>::checkelem (i, d2*k+j);
637 }
638
639 template <class T>
640 T&
641 Array3<T>::xelem (int i, int j, int k)
642 {
643 return Array2<T>::xelem (i, d2*k+j);
644 }
645
646 template <class T>
647 T
648 Array3<T>::elem (int i, int j, int k) const
649 {
650 return Array2<T>::elem (i, d2*k+j);
651 }
652
653 template <class T>
654 T
655 Array3<T>::checkelem (int i, int j, int k) const
656 {
657 return Array2<T>::checkelem (i, d1*k+j);
658 }
659
660 template <class T>
661 T
662 Array3<T>::operator () (int i, int j, int k) const
663 {
664 return Array2<T>::checkelem (i, d2*k+j);
665 }
666
667 template <class T>
668 void
669 Array3<T>::resize (int n, int m, int k)
670 {
671 assert (0); /* XXX FIXME XXX */
672 }
673
674 template <class T>
675 void
676 Array3<T>::resize (int n, int m, int k, const T& val)
677 {
678 assert (0); /* XXX FIXME XXX */
679 }
680
681 /*
682 * A two-dimensional array with diagonal elements only.
683 */
684
685 template <class T>
686 DiagArray<T>::DiagArray (T *d, int r, int c) : Array<T> (d, r < c ? r : c)
687 {
688 nr = r;
689 nc = c;
690 }
691
692 template <class T>
693 DiagArray<T>::DiagArray (void) : Array<T> ()
694 {
695 nr = 0;
696 nc = 0;
697 }
698
699 template <class T>
700 DiagArray<T>::DiagArray (int n) : Array<T> (n)
701 {
702 nr = n;
703 nc = n;
704 }
705
706 template <class T>
707 DiagArray<T>::DiagArray (int n, const T& val) : Array<T> (n, val)
708 {
709 nr = 0;
710 nc = 0;
711 }
712
713 template <class T>
714 DiagArray<T>::DiagArray (int r, int c) : Array<T> (r < c ? r : c)
715 {
716 nr = r;
717 nc = c;
718 }
719
720 template <class T>
721 DiagArray<T>::DiagArray (int r, int c, const T& val)
722 : Array<T> (r < c ? r : c, val)
723 {
724 nr = r;
725 nc = c;
726 }
727
728 template <class T>
729 DiagArray<T>::DiagArray (const Array<T>& a) : Array<T> (a)
730 {
731 nr = nc = a.length ();
732 }
733
734 template <class T>
735 DiagArray<T>::DiagArray (const DiagArray<T>& a) : Array<T> (a)
736 {
737 nr = a.nr;
738 nc = a.nc;
739 }
740
741 template <class T>
742 DiagArray<T>&
743 DiagArray<T>::operator = (const DiagArray<T>& a)
744 {
745 Array<T>::operator = (a);
746 nr = a.nr;
747 nc = a.nc;
748 return *this;
749 }
750
751 template <class T>
752 int
753 DiagArray<T>::dim1 (void) const
754 {
755 return nr;
756 }
757
758 template <class T>
759 int
760 DiagArray<T>::dim2 (void) const
761 {
762 return nc;
763 }
764
765 template <class T>
766 int
767 DiagArray<T>::rows (void) const
768 {
769 return nr;
770 }
771
772 template <class T>
773 int
774 DiagArray<T>::cols (void) const
775 {
776 return nc;
777 }
778
779 template <class T>
780 int
781 DiagArray<T>::columns (void) const
782 {
783 return nc;
784 }
785
786 template <class T>
787 T&
788 DiagArray<T>::elem (int r, int c)
789 {
790 static T foo (0);
791 return (r == c) ? Array<T>::elem (r) : foo;
792 }
793
794 template <class T>
795 T&
796 DiagArray<T>::checkelem (int r, int c)
797 {
798 static T foo (0);
799 return (r == c) ? Array<T>::checkelem (r) : foo;
800 }
801
802 template <class T>
803 T&
804 DiagArray<T>::operator () (int r, int c)
805 {
806 static T foo (0);
807 return (r == c) ? Array<T>::operator () (r) : foo;
808 }
809
810 template <class T>
811 T&
812 DiagArray<T>::xelem (int r, int c)
813 {
814 static T foo (0);
815 return (r == c) ? Array<T>::xelem (r) : foo;
816 }
817
818 template <class T>
819 T
820 DiagArray<T>::elem (int r, int c) const
821 {
822 return (r == c) ? Array<T>::elem (r) : T (0);
823 }
824
825 template <class T>
826 T
827 DiagArray<T>::checkelem (int r, int c) const
828 {
829 return (r == c) ? Array<T>::checkelem (r) : T (0);
830 }
831
832 template <class T>
833 T
834 DiagArray<T>::operator () (int r, int c) const
835 {
836 return (r == c) ? Array<T>::operator () (r) : T (0);
837 }
838
839 template <class T>
840 void
841 DiagArray<T>::resize (int r, int c)
842 {
843 if (r < 0 || c < 0)
844 {
845 (*current_liboctave_error_handler)
846 ("can't resize to negative dimensions");
847 return;
848 }
849
850 if (r == dim1 () && c == dim2 ())
851 return;
852
853 ArrayRep<T> *old_rep = rep;
854 const T *old_data = data ();
855 int old_len = length ();
856
857 int new_len = r < c ? r : c;
858
859 rep = new ArrayRep<T> (new_len);
860 rep->count = 1;
861
862 nr = r;
863 nc = c;
864
865 if (old_data && old_len > 0)
866 {
867 int min_len = old_len < new_len ? old_len : new_len;
868
869 for (int i = 0; i < min_len; i++)
870 xelem (i, i) = old_data[i];
871 }
872
873 if (--old_rep->count <= 0)
874 delete old_rep;
875 }
876
877 template <class T>
878 void
879 DiagArray<T>::resize (int r, int c, const T& val)
880 {
881 if (r < 0 || c < 0)
882 {
883 (*current_liboctave_error_handler)
884 ("can't resize to negative dimensions");
885 return;
886 }
887
888 if (r == dim1 () && c == dim2 ())
889 return;
890
891 ArrayRep<T> *old_rep = rep;
892 const T *old_data = data ();
893 int old_len = length ();
894
895 int new_len = r < c ? r : c;
896
897 rep = new ArrayRep<T> (new_len);
898 rep->count = 1;
899
900 nr = r;
901 nc = c;
902
903 int min_len = old_len < new_len ? old_len : new_len;
904
905 if (old_data && old_len > 0)
906 {
907 for (int i = 0; i < min_len; i++)
908 xelem (i, i) = old_data[i];
909 }
910
911 for (int i = min_len; i < new_len; i++)
912 xelem (i, i) = val;
913
914 if (--old_rep->count <= 0)
915 delete old_rep;
916 }
917
918 #ifdef __GNUG__
919 #if defined (OCTAVE_SOURCE) && defined (USE_EXTERNAL_TEMPLATES)
920
921 typedef Array<double> array_type_double;
922 typedef Array2<double> array2_type_double;
923 typedef DiagArray<double> diag_array_type_double;
924
925 #include <Complex.h>
926 typedef Array<Complex> array_type_complex;
927 typedef Array2<Complex> array2_type_complex;
928 typedef DiagArray<Complex> diag_array_type_complex;
929
930 #endif
931 #endif
932
933 /*
934 ;;; Local Variables: ***
935 ;;; mode: C++ ***
936 ;;; page-delimiter: "^/\\*" ***
937 ;;; End: ***
938 */