comparison src/tc-rep.cc @ 492:d45bdf960233

[project @ 1994-07-06 14:54:58 by jwe] Initial revision
author jwe
date Wed, 06 Jul 1994 14:54:58 +0000
parents
children 5f91088cb98e
comparison
equal deleted inserted replaced
491:2d7f9d72170c 492:d45bdf960233
1 // The constants for the tree class. -*- C++ -*-
2 /*
3
4 Copyright (C) 1992, 1993, 1994 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 #if defined (__GNUG__)
29 #pragma implementation
30 #endif
31
32 #include <ctype.h>
33 #include <string.h>
34 #include <fstream.h>
35 #include <iostream.h>
36 #include <strstream.h>
37
38 #include "mx-base.h"
39 #include "Range.h"
40
41 #include "variables.h"
42 #include "error.h"
43 #include "gripes.h"
44 #include "user-prefs.h"
45 #include "utils.h"
46 #include "pager.h"
47 #include "pr-output.h"
48 #include "tree-const.h"
49 #include "idx-vector.h"
50
51 #include "tc-inlines.cc"
52
53 /*
54 * How about a few macros?
55 */
56
57 #ifndef MAX
58 #define MAX(a,b) ((a) > (b) ? (a) : (b))
59 #endif
60
61 #ifndef MIN
62 #define MIN(a,b) ((a) < (b) ? (a) : (b))
63 #endif
64
65 #ifndef ABS
66 #define ABS(x) (((x) < 0) ? (-x) : (x))
67 #endif
68
69 /*
70 * The following are used by some of the functions in the
71 * tree_constant_rep class that must deal with real and complex
72 * matrices. This was not done with overloaded or virtual functions
73 * from the Matrix class because there is no clean way to do that --
74 * the necessary functions (like elem) need to return values of
75 * different types...
76 */
77
78 // Given a tree_constant, and the names to be used for the real and
79 // complex matrix and their dimensions, declare a real or complex
80 // matrix, and initialize it from the tree_constant. Note that m, cm,
81 // nr, and nc must not be previously declared, and they must not be
82 // expressions. Since only one of the matrices will be defined after
83 // this macro is used, only one set of dimesions is declared.
84
85 // This macro only makes sense inside a friend or member function of
86 // the tree_constant_rep class
87
88 #define REP_RHS_MATRIX(tc,m,cm,nr,nc) \
89 int nr = 0; \
90 int nc = 0; \
91 Matrix m; \
92 ComplexMatrix cm; \
93 if ((tc).const_type () == tree_constant_rep::complex_matrix_constant) \
94 { \
95 cm = (tc).complex_matrix_value (); \
96 nr = (cm).rows (); \
97 nc = (cm).columns (); \
98 } \
99 else if ((tc).const_type () == tree_constant_rep::matrix_constant) \
100 { \
101 m = (tc).matrix_value (); \
102 nr = (m).rows (); \
103 nc = (m).columns (); \
104 } \
105 else \
106 abort ();
107
108 // Assign a real or complex value to a tree_constant.
109 //
110 // This macro only makes sense inside a friend or member function of
111 // the tree_constant_rep class.
112
113 #define REP_ELEM_ASSIGN(i,j,rval,cval,real_type) \
114 do \
115 { \
116 if (type_tag == tree_constant_rep::matrix_constant) \
117 { \
118 if (real_type) \
119 matrix->elem ((i), (j)) = (rval); \
120 else \
121 abort (); \
122 } \
123 else \
124 { \
125 if (real_type) \
126 complex_matrix->elem ((i), (j)) = (rval); \
127 else \
128 complex_matrix->elem ((i), (j)) = (cval); \
129 } \
130 } \
131 while (0)
132
133 // Given a real and complex matrix and row and column dimensions,
134 // declare both and size one of them. Only one of the matrices should
135 // be used after this macro has been used.
136
137 // This macro only makes sense inside a friend or member function of
138 // the tree_constant_rep class.
139
140 #define CRMATRIX(m,cm,nr,nc) \
141 Matrix m; \
142 ComplexMatrix cm; \
143 if (type_tag == tree_constant_rep::matrix_constant) \
144 (m).resize ((nr), (nc)); \
145 else if (type_tag == complex_matrix_constant) \
146 (cm).resize ((nr), (nc)); \
147 else \
148 abort (); \
149
150 // Assign a real or complex matrix to a tree constant.
151
152 // This macro only makes sense inside a friend or member function of
153 // the tree_constant_rep class.
154
155 #define ASSIGN_CRMATRIX_TO(tc,m,cm) \
156 do \
157 { \
158 if (type_tag == matrix_constant) \
159 tc = tree_constant (m); \
160 else \
161 tc = tree_constant (cm); \
162 } \
163 while (0)
164
165 // Assign an element of this tree_constant_rep's real or complex
166 // matrix to another real or complex matrix.
167
168 // This macro only makes sense inside a friend or member function of
169 // the tree_constant_rep class.
170
171 #define CRMATRIX_ASSIGN_REP_ELEM(m,cm,i1,j1,i2,j2) \
172 do \
173 { \
174 if (type_tag == matrix_constant) \
175 (m).elem ((i1), (j1)) = matrix->elem ((i2), (j2)); \
176 else \
177 (cm).elem ((i1), (j1)) = complex_matrix->elem ((i2), (j2)); \
178 } \
179 while (0)
180
181 // Assign a value to an element of a real or complex matrix. Assumes
182 // that the lhs and rhs are either both real or both complex types.
183
184 #define CRMATRIX_ASSIGN_ELEM(m,cm,i,j,rval,cval,real_type) \
185 do \
186 { \
187 if (real_type) \
188 (m).elem ((i), (j)) = (rval); \
189 else \
190 (cm).elem ((i), (j)) = (cval); \
191 } \
192 while (0)
193
194
195 // A couple of handy helper functions.
196
197 static int
198 any_element_less_than (const Matrix& a, double val)
199 {
200 int nr = a.rows ();
201 int nc = a.columns ();
202 for (int j = 0; j < nc; j++)
203 for (int i = 0; i < nr; i++)
204 if (a.elem (i, j) < val)
205 return 1;
206 return 0;
207 }
208
209 static int
210 any_element_greater_than (const Matrix& a, double val)
211 {
212 int nr = a.rows ();
213 int nc = a.columns ();
214 for (int j = 0; j < nc; j++)
215 for (int i = 0; i < nr; i++)
216 if (a.elem (i, j) > val)
217 return 1;
218 return 0;
219 }
220
221 static int
222 any_element_is_complex (const ComplexMatrix& a)
223 {
224 int nr = a.rows ();
225 int nc = a.columns ();
226 for (int j = 0; j < nc; j++)
227 for (int i = 0; i < nr; i++)
228 if (imag (a.elem (i, j)) != 0.0)
229 return 1;
230 return 0;
231 }
232
233 // Now, the classes.
234
235 /*
236 * The real representation of constants.
237 */
238 tree_constant_rep::tree_constant_rep (void)
239 {
240 type_tag = unknown_constant;
241 }
242
243 tree_constant_rep::tree_constant_rep (double d)
244 {
245 scalar = d;
246 type_tag = scalar_constant;
247 }
248
249 tree_constant_rep::tree_constant_rep (const Matrix& m)
250 {
251 if (m.rows () == 1 && m.columns () == 1)
252 {
253 scalar = m.elem (0, 0);
254 type_tag = scalar_constant;
255 }
256 else
257 {
258 matrix = new Matrix (m);
259 type_tag = matrix_constant;
260 }
261 }
262
263 tree_constant_rep::tree_constant_rep (const DiagMatrix& d)
264 {
265 if (d.rows () == 1 && d.columns () == 1)
266 {
267 scalar = d.elem (0, 0);
268 type_tag = scalar_constant;
269 }
270 else
271 {
272 matrix = new Matrix (d);
273 type_tag = matrix_constant;
274 }
275 }
276
277 tree_constant_rep::tree_constant_rep (const RowVector& v, int
278 prefer_column_vector)
279 {
280 int len = v.capacity ();
281 if (len == 1)
282 {
283 scalar = v.elem (0);
284 type_tag = scalar_constant;
285 }
286 else
287 {
288 int pcv = (prefer_column_vector < 0)
289 ? user_pref.prefer_column_vectors
290 : prefer_column_vector;
291
292 if (pcv)
293 {
294 Matrix m (len, 1);
295 for (int i = 0; i < len; i++)
296 m.elem (i, 0) = v.elem (i);
297 matrix = new Matrix (m);
298 type_tag = matrix_constant;
299 }
300 else
301 {
302 Matrix m (1, len);
303 for (int i = 0; i < len; i++)
304 m.elem (0, i) = v.elem (i);
305 matrix = new Matrix (m);
306 type_tag = matrix_constant;
307 }
308 }
309 }
310
311 tree_constant_rep::tree_constant_rep (const ColumnVector& v,
312 int prefer_column_vector)
313 {
314 int len = v.capacity ();
315 if (len == 1)
316 {
317 scalar = v.elem (0);
318 type_tag = scalar_constant;
319 }
320 else
321 {
322 int pcv = (prefer_column_vector < 0)
323 ? user_pref.prefer_column_vectors
324 : prefer_column_vector;
325
326 if (pcv)
327 {
328 Matrix m (len, 1);
329 for (int i = 0; i < len; i++)
330 m.elem (i, 0) = v.elem (i);
331 matrix = new Matrix (m);
332 type_tag = matrix_constant;
333 }
334 else
335 {
336 Matrix m (1, len);
337 for (int i = 0; i < len; i++)
338 m.elem (0, i) = v.elem (i);
339 matrix = new Matrix (m);
340 type_tag = matrix_constant;
341 }
342 }
343 }
344
345 tree_constant_rep::tree_constant_rep (const Complex& c)
346 {
347 complex_scalar = new Complex (c);
348 type_tag = complex_scalar_constant;
349 }
350
351 tree_constant_rep::tree_constant_rep (const ComplexMatrix& m)
352 {
353 if (m.rows () == 1 && m.columns () == 1)
354 {
355 complex_scalar = new Complex (m.elem (0, 0));
356 type_tag = complex_scalar_constant;
357 }
358 else
359 {
360 complex_matrix = new ComplexMatrix (m);
361 type_tag = complex_matrix_constant;
362 }
363 }
364
365 tree_constant_rep::tree_constant_rep (const ComplexDiagMatrix& d)
366 {
367 if (d.rows () == 1 && d.columns () == 1)
368 {
369 complex_scalar = new Complex (d.elem (0, 0));
370 type_tag = complex_scalar_constant;
371 }
372 else
373 {
374 complex_matrix = new ComplexMatrix (d);
375 type_tag = complex_matrix_constant;
376 }
377 }
378
379 tree_constant_rep::tree_constant_rep (const ComplexRowVector& v,
380 int prefer_column_vector)
381 {
382 int len = v.capacity ();
383 if (len == 1)
384 {
385 complex_scalar = new Complex (v.elem (0));
386 type_tag = complex_scalar_constant;
387 }
388 else
389 {
390 int pcv = (prefer_column_vector < 0)
391 ? user_pref.prefer_column_vectors
392 : prefer_column_vector;
393
394 if (pcv)
395 {
396 ComplexMatrix m (len, 1);
397 for (int i = 0; i < len; i++)
398 m.elem (i, 0) = v.elem (i);
399 complex_matrix = new ComplexMatrix (m);
400 type_tag = complex_matrix_constant;
401 }
402 else
403 {
404 ComplexMatrix m (1, len);
405 for (int i = 0; i < len; i++)
406 m.elem (0, i) = v.elem (i);
407 complex_matrix = new ComplexMatrix (m);
408 type_tag = complex_matrix_constant;
409 }
410 }
411 }
412
413 tree_constant_rep::tree_constant_rep (const ComplexColumnVector& v,
414 int prefer_column_vector)
415 {
416 int len = v.capacity ();
417 if (len == 1)
418 {
419 complex_scalar = new Complex (v.elem (0));
420 type_tag = complex_scalar_constant;
421 }
422 else
423 {
424 int pcv = (prefer_column_vector < 0)
425 ? user_pref.prefer_column_vectors
426 : prefer_column_vector;
427
428 if (pcv)
429 {
430 ComplexMatrix m (len, 1);
431 for (int i = 0; i < len; i++)
432 m.elem (i, 0) = v.elem (i);
433 complex_matrix = new ComplexMatrix (m);
434 type_tag = complex_matrix_constant;
435 }
436 else
437 {
438 ComplexMatrix m (1, len);
439 for (int i = 0; i < len; i++)
440 m.elem (0, i) = v.elem (i);
441 complex_matrix = new ComplexMatrix (m);
442 type_tag = complex_matrix_constant;
443 }
444 }
445 }
446
447 tree_constant_rep::tree_constant_rep (const char *s)
448 {
449 string = strsave (s);
450 type_tag = string_constant;
451 }
452
453 tree_constant_rep::tree_constant_rep (double b, double l, double i)
454 {
455 range = new Range (b, l, i);
456 int nel = range->nelem ();
457 if (nel < 0)
458 {
459 delete range;
460 type_tag = unknown_constant;
461 if (nel == -1)
462 ::error ("number of elements in range exceeds INT_MAX");
463 else
464 ::error ("invalid range");
465 }
466 else if (nel > 1)
467 type_tag = range_constant;
468 else
469 {
470 delete range;
471 if (nel == 1)
472 {
473 scalar = b;
474 type_tag = scalar_constant;
475 }
476 else if (nel == 0)
477 {
478 matrix = new Matrix ();
479 type_tag = matrix_constant;
480 }
481 else
482 panic_impossible ();
483 }
484 }
485
486 tree_constant_rep::tree_constant_rep (const Range& r)
487 {
488 if (r.nelem () > 1)
489 {
490 range = new Range (r);
491 type_tag = range_constant;
492 }
493 else if (r.nelem () == 1)
494 {
495 scalar = r.base ();
496 type_tag = scalar_constant;
497 }
498 else if (r.nelem () == 0)
499 {
500 matrix = new Matrix ();
501 type_tag = matrix_constant;
502 }
503 else
504 panic_impossible ();
505 }
506
507 tree_constant_rep::tree_constant_rep (tree_constant_rep::constant_type t)
508 {
509 assert (t == magic_colon);
510
511 type_tag = magic_colon;
512 }
513
514 tree_constant_rep::tree_constant_rep (const tree_constant_rep& t)
515 {
516 type_tag = t.type_tag;
517
518 switch (t.type_tag)
519 {
520 case unknown_constant:
521 break;
522 case scalar_constant:
523 scalar = t.scalar;
524 break;
525 case matrix_constant:
526 matrix = new Matrix (*(t.matrix));
527 break;
528 case string_constant:
529 string = strsave (t.string);
530 break;
531 case complex_matrix_constant:
532 complex_matrix = new ComplexMatrix (*(t.complex_matrix));
533 break;
534 case complex_scalar_constant:
535 complex_scalar = new Complex (*(t.complex_scalar));
536 break;
537 case range_constant:
538 range = new Range (*(t.range));
539 break;
540 case magic_colon:
541 break;
542 default:
543 panic_impossible ();
544 break;
545 }
546 }
547
548 tree_constant_rep::~tree_constant_rep (void)
549 {
550 switch (type_tag)
551 {
552 case unknown_constant:
553 break;
554 case scalar_constant:
555 break;
556 case matrix_constant:
557 delete matrix;
558 break;
559 case complex_scalar_constant:
560 delete complex_scalar;
561 break;
562 case complex_matrix_constant:
563 delete complex_matrix;
564 break;
565 case string_constant:
566 delete [] string;
567 break;
568 case range_constant:
569 delete range;
570 break;
571 case magic_colon:
572 break;
573 default:
574 panic_impossible ();
575 break;
576 }
577 }
578
579 #if defined (MDEBUG)
580 void *
581 tree_constant_rep::operator new (size_t size)
582 {
583 tree_constant_rep *p = ::new tree_constant_rep;
584 cerr << "tree_constant_rep::new(): " << p << "\n";
585 return p;
586 }
587
588 void
589 tree_constant_rep::operator delete (void *p, size_t size)
590 {
591 cerr << "tree_constant_rep::delete(): " << p << "\n";
592 ::delete p;
593 }
594 #endif
595
596 void
597 tree_constant_rep::resize (int i, int j)
598 {
599 switch (type_tag)
600 {
601 case matrix_constant:
602 matrix->resize (i, j);
603 break;
604 case complex_matrix_constant:
605 complex_matrix->resize (i, j);
606 break;
607 default:
608 panic_impossible ();
609 break;
610 }
611 }
612
613 void
614 tree_constant_rep::resize (int i, int j, double val)
615 {
616 switch (type_tag)
617 {
618 case matrix_constant:
619 matrix->resize (i, j, val);
620 break;
621 case complex_matrix_constant:
622 complex_matrix->resize (i, j, val);
623 break;
624 default:
625 panic_impossible ();
626 break;
627 }
628 }
629
630 void
631 tree_constant_rep::maybe_resize (int i, int j)
632 {
633 int nr = rows ();
634 int nc = columns ();
635
636 i++;
637 j++;
638
639 assert (i > 0 && j > 0);
640
641 if (i > nr || j > nc)
642 {
643 if (user_pref.resize_on_range_error)
644 resize (MAX (i, nr), MAX (j, nc), 0.0);
645 else
646 {
647 if (i > nr)
648 ::error ("row index = %d exceeds max row dimension = %d", i, nr);
649
650 if (j > nc)
651 ::error ("column index = %d exceeds max column dimension = %d",
652 j, nc);
653 }
654 }
655 }
656
657 void
658 tree_constant_rep::maybe_resize (int i, force_orient f_orient = no_orient)
659 {
660 int nr = rows ();
661 int nc = columns ();
662
663 i++;
664
665 assert (i >= 0 && (nr <= 1 || nc <= 1));
666
667 // This function never reduces the size of a vector, and all vectors
668 // have dimensions of at least 0x0. If i is 0, it is either because
669 // a vector has been indexed with a vector of all zeros (in which case
670 // the index vector is empty and nothing will happen) or a vector has
671 // been indexed with 0 (an error which will be caught elsewhere).
672 if (i == 0)
673 return;
674
675 if (nr <= 1 && nc <= 1 && i >= 1)
676 {
677 if (user_pref.resize_on_range_error)
678 {
679 if (f_orient == row_orient)
680 resize (1, i, 0.0);
681 else if (f_orient == column_orient)
682 resize (i, 1, 0.0);
683 else if (user_pref.prefer_column_vectors)
684 resize (i, 1, 0.0);
685 else
686 resize (1, i, 0.0);
687 }
688 else
689 ::error ("matrix index = %d exceeds max dimension = %d", i, nc);
690 }
691 else if (nr == 1 && i > nc)
692 {
693 if (user_pref.resize_on_range_error)
694 resize (1, i, 0.0);
695 else
696 ::error ("matrix index = %d exceeds max dimension = %d", i, nc);
697 }
698 else if (nc == 1 && i > nr)
699 {
700 if (user_pref.resize_on_range_error)
701 resize (i, 1, 0.0);
702 else
703 ::error ("matrix index = %d exceeds max dimension = ", i, nc);
704 }
705 }
706
707 double
708 tree_constant_rep::to_scalar (void) const
709 {
710 tree_constant tmp = make_numeric ();
711
712 double retval = 0.0;
713
714 switch (tmp.const_type ())
715 {
716 case tree_constant_rep::scalar_constant:
717 case tree_constant_rep::complex_scalar_constant:
718 retval = tmp.double_value ();
719 break;
720 case tree_constant_rep::matrix_constant:
721 if (user_pref.do_fortran_indexing)
722 {
723 Matrix m = tmp.matrix_value ();
724 retval = m (0, 0);
725 }
726 break;
727 case tree_constant_rep::complex_matrix_constant:
728 if (user_pref.do_fortran_indexing)
729 {
730 int flag = user_pref.ok_to_lose_imaginary_part;
731 if (flag == -1)
732 warning ("implicit conversion of complex value to real value");
733
734 if (flag != 0)
735 {
736 ComplexMatrix m = tmp.complex_matrix_value ();
737 return ::real (m (0, 0));
738 }
739 else
740 jump_to_top_level ();
741 }
742 else
743 {
744 ::error ("complex matrix used in invalid context");
745 jump_to_top_level ();
746 }
747 break;
748 default:
749 break;
750 }
751 return retval;
752 }
753
754 ColumnVector
755 tree_constant_rep::to_vector (void) const
756 {
757 tree_constant tmp = make_numeric ();
758
759 ColumnVector retval;
760
761 switch (tmp.const_type ())
762 {
763 case tree_constant_rep::scalar_constant:
764 case tree_constant_rep::complex_scalar_constant:
765 retval.resize (1);
766 retval.elem (0) = tmp.double_value ();
767 break;
768 case tree_constant_rep::complex_matrix_constant:
769 case tree_constant_rep::matrix_constant:
770 {
771 Matrix m = tmp.matrix_value ();
772 int nr = m.rows ();
773 int nc = m.columns ();
774 if (nr == 1)
775 {
776 retval.resize (nc);
777 for (int i = 0; i < nc; i++)
778 retval.elem (i) = m (0, i);
779 }
780 else if (nc == 1)
781 {
782 retval.resize (nr);
783 for (int i = 0; i < nr; i++)
784 retval.elem (i) = m.elem (i, 0);
785 }
786 }
787 break;
788 default:
789 panic_impossible ();
790 break;
791 }
792 return retval;
793 }
794
795 Matrix
796 tree_constant_rep::to_matrix (void) const
797 {
798 tree_constant tmp = make_numeric ();
799
800 Matrix retval;
801
802 switch (tmp.const_type ())
803 {
804 case tree_constant_rep::scalar_constant:
805 retval.resize (1, 1);
806 retval.elem (0, 0) = tmp.double_value ();
807 break;
808 case tree_constant_rep::matrix_constant:
809 retval = tmp.matrix_value ();
810 break;
811 default:
812 break;
813 }
814 return retval;
815 }
816
817 tree_constant_rep::constant_type
818 tree_constant_rep::force_numeric (int force_str_conv = 0)
819 {
820 switch (type_tag)
821 {
822 case scalar_constant:
823 case matrix_constant:
824 case complex_scalar_constant:
825 case complex_matrix_constant:
826 break;
827 case string_constant:
828 {
829 if (! force_str_conv && ! user_pref.implicit_str_to_num_ok)
830 {
831 ::error ("failed to convert `%s' to a numeric type --", string);
832 ::error ("default conversion turned off");
833 // Abort!
834 jump_to_top_level ();
835 }
836
837 int len = strlen (string);
838 if (len > 1)
839 {
840 type_tag = matrix_constant;
841 Matrix *tm = new Matrix (1, len);
842 for (int i = 0; i < len; i++)
843 tm->elem (0, i) = toascii ((int) string[i]);
844 matrix = tm;
845 }
846 else if (len == 1)
847 {
848 type_tag = scalar_constant;
849 scalar = toascii ((int) string[0]);
850 }
851 else if (len == 0)
852 {
853 type_tag = matrix_constant;
854 matrix = new Matrix (0, 0);
855 }
856 else
857 panic_impossible ();
858 }
859 break;
860 case range_constant:
861 {
862 int len = range->nelem ();
863 if (len > 1)
864 {
865 type_tag = matrix_constant;
866 Matrix *tm = new Matrix (1, len);
867 double b = range->base ();
868 double increment = range->inc ();
869 for (int i = 0; i < len; i++)
870 tm->elem (0, i) = b + i * increment;
871 matrix = tm;
872 }
873 else if (len == 1)
874 {
875 type_tag = scalar_constant;
876 scalar = range->base ();
877 }
878 }
879 break;
880 case magic_colon:
881 default:
882 panic_impossible ();
883 break;
884 }
885 return type_tag;
886 }
887
888 tree_constant
889 tree_constant_rep::make_numeric (int force_str_conv = 0) const
890 {
891 tree_constant retval;
892 switch (type_tag)
893 {
894 case scalar_constant:
895 retval = tree_constant (scalar);
896 break;
897 case matrix_constant:
898 retval = tree_constant (*matrix);
899 break;
900 case complex_scalar_constant:
901 retval = tree_constant (*complex_scalar);
902 break;
903 case complex_matrix_constant:
904 retval = tree_constant (*complex_matrix);
905 break;
906 case string_constant:
907 retval = tree_constant (string);
908 retval.force_numeric (force_str_conv);
909 break;
910 case range_constant:
911 retval = tree_constant (*range);
912 retval.force_numeric (force_str_conv);
913 break;
914 case magic_colon:
915 default:
916 panic_impossible ();
917 break;
918 }
919 return retval;
920 }
921
922 tree_constant
923 do_binary_op (tree_constant& a, tree_constant& b, tree::expression_type t)
924 {
925 tree_constant ans;
926
927 int first_empty = (a.rows () == 0 || a.columns () == 0);
928 int second_empty = (b.rows () == 0 || b.columns () == 0);
929
930 if (first_empty || second_empty)
931 {
932 int flag = user_pref.propagate_empty_matrices;
933 if (flag < 0)
934 warning ("binary operation on empty matrix");
935 else if (flag == 0)
936 {
937 ::error ("invalid binary operation on empty matrix");
938 return ans;
939 }
940 }
941
942 tree_constant tmp_a = a.make_numeric ();
943 tree_constant tmp_b = b.make_numeric ();
944
945 tree_constant_rep::constant_type a_type = tmp_a.const_type ();
946 tree_constant_rep::constant_type b_type = tmp_b.const_type ();
947
948 double d1, d2;
949 Matrix m1, m2;
950 Complex c1, c2;
951 ComplexMatrix cm1, cm2;
952
953 switch (a_type)
954 {
955 case tree_constant_rep::scalar_constant:
956 d1 = tmp_a.double_value ();
957 switch (b_type)
958 {
959 case tree_constant_rep::scalar_constant:
960 d2 = tmp_b.double_value ();
961 ans = do_binary_op (d1, d2, t);
962 break;
963 case tree_constant_rep::matrix_constant:
964 m2 = tmp_b.matrix_value ();
965 ans = do_binary_op (d1, m2, t);
966 break;
967 case tree_constant_rep::complex_scalar_constant:
968 c2 = tmp_b.complex_value ();
969 ans = do_binary_op (d1, c2, t);
970 break;
971 case tree_constant_rep::complex_matrix_constant:
972 cm2 = tmp_b.complex_matrix_value ();
973 ans = do_binary_op (d1, cm2, t);
974 break;
975 case tree_constant_rep::magic_colon:
976 default:
977 panic_impossible ();
978 break;
979 }
980 break;
981 case tree_constant_rep::matrix_constant:
982 m1 = tmp_a.matrix_value ();
983 switch (b_type)
984 {
985 case tree_constant_rep::scalar_constant:
986 d2 = tmp_b.double_value ();
987 ans = do_binary_op (m1, d2, t);
988 break;
989 case tree_constant_rep::matrix_constant:
990 m2 = tmp_b.matrix_value ();
991 ans = do_binary_op (m1, m2, t);
992 break;
993 case tree_constant_rep::complex_scalar_constant:
994 c2 = tmp_b.complex_value ();
995 ans = do_binary_op (m1, c2, t);
996 break;
997 case tree_constant_rep::complex_matrix_constant:
998 cm2 = tmp_b.complex_matrix_value ();
999 ans = do_binary_op (m1, cm2, t);
1000 break;
1001 case tree_constant_rep::magic_colon:
1002 default:
1003 panic_impossible ();
1004 break;
1005 }
1006 break;
1007 case tree_constant_rep::complex_scalar_constant:
1008 c1 = tmp_a.complex_value ();
1009 switch (b_type)
1010 {
1011 case tree_constant_rep::scalar_constant:
1012 d2 = tmp_b.double_value ();
1013 ans = do_binary_op (c1, d2, t);
1014 break;
1015 case tree_constant_rep::matrix_constant:
1016 m2 = tmp_b.matrix_value ();
1017 ans = do_binary_op (c1, m2, t);
1018 break;
1019 case tree_constant_rep::complex_scalar_constant:
1020 c2 = tmp_b.complex_value ();
1021 ans = do_binary_op (c1, c2, t);
1022 break;
1023 case tree_constant_rep::complex_matrix_constant:
1024 cm2 = tmp_b.complex_matrix_value ();
1025 ans = do_binary_op (c1, cm2, t);
1026 break;
1027 case tree_constant_rep::magic_colon:
1028 default:
1029 panic_impossible ();
1030 break;
1031 }
1032 break;
1033 case tree_constant_rep::complex_matrix_constant:
1034 cm1 = tmp_a.complex_matrix_value ();
1035 switch (b_type)
1036 {
1037 case tree_constant_rep::scalar_constant:
1038 d2 = tmp_b.double_value ();
1039 ans = do_binary_op (cm1, d2, t);
1040 break;
1041 case tree_constant_rep::matrix_constant:
1042 m2 = tmp_b.matrix_value ();
1043 ans = do_binary_op (cm1, m2, t);
1044 break;
1045 case tree_constant_rep::complex_scalar_constant:
1046 c2 = tmp_b.complex_value ();
1047 ans = do_binary_op (cm1, c2, t);
1048 break;
1049 case tree_constant_rep::complex_matrix_constant:
1050 cm2 = tmp_b.complex_matrix_value ();
1051 ans = do_binary_op (cm1, cm2, t);
1052 break;
1053 case tree_constant_rep::magic_colon:
1054 default:
1055 panic_impossible ();
1056 break;
1057 }
1058 break;
1059 case tree_constant_rep::magic_colon:
1060 default:
1061 panic_impossible ();
1062 break;
1063 }
1064 return ans;
1065 }
1066
1067 tree_constant
1068 do_unary_op (tree_constant& a, tree::expression_type t)
1069 {
1070 tree_constant ans;
1071
1072 if (a.rows () == 0 || a.columns () == 0)
1073 {
1074 int flag = user_pref.propagate_empty_matrices;
1075 if (flag < 0)
1076 warning ("unary operation on empty matrix");
1077 else if (flag == 0)
1078 {
1079 ::error ("invalid unary operation on empty matrix");
1080 return ans;
1081 }
1082 }
1083
1084 tree_constant tmp_a = a.make_numeric ();
1085
1086 switch (tmp_a.const_type ())
1087 {
1088 case tree_constant_rep::scalar_constant:
1089 ans = do_unary_op (tmp_a.double_value (), t);
1090 break;
1091 case tree_constant_rep::matrix_constant:
1092 {
1093 Matrix m = tmp_a.matrix_value ();
1094 ans = do_unary_op (m, t);
1095 }
1096 break;
1097 case tree_constant_rep::complex_scalar_constant:
1098 ans = do_unary_op (tmp_a.complex_value (), t);
1099 break;
1100 case tree_constant_rep::complex_matrix_constant:
1101 {
1102 ComplexMatrix m = tmp_a.complex_matrix_value ();
1103 ans = do_unary_op (m, t);
1104 }
1105 break;
1106 case tree_constant_rep::magic_colon:
1107 default:
1108 panic_impossible ();
1109 break;
1110 }
1111 return ans;
1112 }
1113
1114 void
1115 tree_constant_rep::bump_value (tree::expression_type etype)
1116 {
1117 switch (etype)
1118 {
1119 case tree::increment:
1120 switch (type_tag)
1121 {
1122 case scalar_constant:
1123 scalar++;
1124 break;
1125 case matrix_constant:
1126 *matrix = *matrix + 1.0;
1127 break;
1128 case complex_scalar_constant:
1129 *complex_scalar = *complex_scalar + 1.0;
1130 break;
1131 case complex_matrix_constant:
1132 *complex_matrix = *complex_matrix + 1.0;
1133 break;
1134 case string_constant:
1135 ::error ("string++ and ++string not implemented yet, ok?");
1136 break;
1137 case range_constant:
1138 range->set_base (range->base () + 1.0);
1139 range->set_limit (range->limit () + 1.0);
1140 break;
1141 case magic_colon:
1142 default:
1143 panic_impossible ();
1144 break;
1145 }
1146 break;
1147 case tree::decrement:
1148 switch (type_tag)
1149 {
1150 case scalar_constant:
1151 scalar--;
1152 break;
1153 case matrix_constant:
1154 *matrix = *matrix - 1.0;
1155 break;
1156 case string_constant:
1157 ::error ("string-- and -- string not implemented yet, ok?");
1158 break;
1159 case range_constant:
1160 range->set_base (range->base () - 1.0);
1161 range->set_limit (range->limit () - 1.0);
1162 break;
1163 case magic_colon:
1164 default:
1165 panic_impossible ();
1166 break;
1167 }
1168 break;
1169 default:
1170 panic_impossible ();
1171 break;
1172 }
1173 }
1174
1175 void
1176 tree_constant_rep::maybe_mutate (void)
1177 {
1178 if (error_state)
1179 return;
1180
1181 switch (type_tag)
1182 {
1183 case complex_scalar_constant:
1184 if (::imag (*complex_scalar) == 0.0)
1185 {
1186 double d = ::real (*complex_scalar);
1187 delete complex_scalar;
1188 scalar = d;
1189 type_tag = scalar_constant;
1190 }
1191 break;
1192 case complex_matrix_constant:
1193 if (! any_element_is_complex (*complex_matrix))
1194 {
1195 Matrix *m = new Matrix (::real (*complex_matrix));
1196 delete complex_matrix;
1197 matrix = m;
1198 type_tag = matrix_constant;
1199 }
1200 break;
1201 case scalar_constant:
1202 case matrix_constant:
1203 case string_constant:
1204 case range_constant:
1205 case magic_colon:
1206 break;
1207 default:
1208 panic_impossible ();
1209 break;
1210 }
1211
1212 // Avoid calling rows() and columns() for things like magic_colon.
1213
1214 int nr = 1;
1215 int nc = 1;
1216 if (type_tag == matrix_constant
1217 || type_tag == complex_matrix_constant
1218 || type_tag == range_constant)
1219 {
1220 nr = rows ();
1221 nc = columns ();
1222 }
1223
1224 switch (type_tag)
1225 {
1226 case matrix_constant:
1227 if (nr == 1 && nc == 1)
1228 {
1229 double d = matrix->elem (0, 0);
1230 delete matrix;
1231 scalar = d;
1232 type_tag = scalar_constant;
1233 }
1234 break;
1235 case complex_matrix_constant:
1236 if (nr == 1 && nc == 1)
1237 {
1238 Complex c = complex_matrix->elem (0, 0);
1239 delete complex_matrix;
1240 complex_scalar = new Complex (c);
1241 type_tag = complex_scalar_constant;
1242 }
1243 break;
1244 case range_constant:
1245 if (nr == 1 && nc == 1)
1246 {
1247 double d = range->base ();
1248 delete range;
1249 scalar = d;
1250 type_tag = scalar_constant;
1251 }
1252 break;
1253 default:
1254 break;
1255 }
1256 }
1257
1258 void
1259 tree_constant_rep::print (void)
1260 {
1261 if (error_state)
1262 return;
1263
1264 int nr = rows ();
1265 int nc = columns ();
1266
1267 if (print)
1268 {
1269 ostrstream output_buf;
1270 switch (type_tag)
1271 {
1272 case scalar_constant:
1273 octave_print_internal (output_buf, scalar);
1274 break;
1275 case matrix_constant:
1276 if (nr == 0 || nc == 0)
1277 {
1278 output_buf << "[]";
1279 if (user_pref.print_empty_dimensions)
1280 output_buf << "(" << nr << "x" << nc << ")";
1281 output_buf << "\n";
1282 }
1283 else
1284 octave_print_internal (output_buf, *matrix);
1285 break;
1286 case complex_scalar_constant:
1287 octave_print_internal (output_buf, *complex_scalar);
1288 break;
1289 case complex_matrix_constant:
1290 if (nr == 0 || nc == 0)
1291 {
1292 output_buf << "[]";
1293 if (user_pref.print_empty_dimensions)
1294 output_buf << "(" << nr << "x" << nc << ")";
1295 output_buf << "\n";
1296 }
1297 else
1298 octave_print_internal (output_buf, *complex_matrix);
1299 break;
1300 case string_constant:
1301 output_buf << string << "\n";
1302 break;
1303 case range_constant:
1304 octave_print_internal (output_buf, *range);
1305 break;
1306 case magic_colon:
1307 default:
1308 panic_impossible ();
1309 break;
1310 }
1311
1312 output_buf << ends;
1313 maybe_page_output (output_buf);
1314 }
1315 }
1316
1317 tree_constant
1318 tree_constant_rep::do_index (const tree_constant *args, int nargin)
1319 {
1320 tree_constant retval;
1321
1322 if (error_state)
1323 return retval;
1324
1325 if (rows () == 0 || columns () == 0)
1326 {
1327 ::error ("attempt to index empty matrix");
1328 return retval;
1329 }
1330
1331 switch (type_tag)
1332 {
1333 case complex_scalar_constant:
1334 case scalar_constant:
1335 retval = do_scalar_index (args, nargin);
1336 break;
1337 case complex_matrix_constant:
1338 case matrix_constant:
1339 retval = do_matrix_index (args, nargin);
1340 break;
1341 case string_constant:
1342 gripe_string_invalid ();
1343 // retval = do_string_index (args, nargin);
1344 break;
1345 case magic_colon:
1346 case range_constant:
1347 // This isn\'t great, but it\'s easier than implementing a lot of
1348 // range indexing functions.
1349 force_numeric ();
1350 assert (type_tag != magic_colon && type_tag != range_constant);
1351 retval = do_index (args, nargin);
1352 break;
1353 default:
1354 panic_impossible ();
1355 break;
1356 }
1357
1358 return retval;
1359 }
1360
1361 int
1362 tree_constant_rep::save (ostream& os, int mark_as_global, int precision)
1363 {
1364 switch (type_tag)
1365 {
1366 case scalar_constant:
1367 case matrix_constant:
1368 case complex_scalar_constant:
1369 case complex_matrix_constant:
1370 case string_constant:
1371 case range_constant:
1372 if (mark_as_global)
1373 os << "# type: global ";
1374 else
1375 os << "# type: ";
1376 break;
1377 case magic_colon:
1378 default:
1379 break;
1380 }
1381
1382 long old_precision = os.precision ();
1383 os.precision (precision);
1384
1385 switch (type_tag)
1386 {
1387 case scalar_constant:
1388 os << "scalar\n"
1389 << scalar << "\n";
1390 break;
1391 case matrix_constant:
1392 os << "matrix\n"
1393 << "# rows: " << rows () << "\n"
1394 << "# columns: " << columns () << "\n"
1395 << *matrix ;
1396 break;
1397 case complex_scalar_constant:
1398 os << "complex scalar\n"
1399 << *complex_scalar << "\n";
1400 break;
1401 case complex_matrix_constant:
1402 os << "complex matrix\n"
1403 << "# rows: " << rows () << "\n"
1404 << "# columns: " << columns () << "\n"
1405 << *complex_matrix ;
1406 break;
1407 case string_constant:
1408 os << "string\n"
1409 << "# length: " << strlen (string) << "\n"
1410 << string << "\n";
1411 break;
1412 case range_constant:
1413 {
1414 os << "range\n"
1415 << "# base, limit, increment\n"
1416 << range->base () << " "
1417 << range->limit () << " "
1418 << range->inc () << "\n";
1419 }
1420 break;
1421 case magic_colon:
1422 default:
1423 panic_impossible ();
1424 break;
1425 }
1426
1427 os.precision (old_precision);
1428
1429 // Really want to return 1 only if write is successful.
1430 return 1;
1431 }
1432
1433 int
1434 tree_constant_rep::save_three_d (ostream& os, int parametric)
1435 {
1436 int nr = rows ();
1437 int nc = columns ();
1438
1439 switch (type_tag)
1440 {
1441 case matrix_constant:
1442 os << "# 3D data...\n"
1443 << "# type: matrix\n"
1444 << "# total rows: " << nr << "\n"
1445 << "# total columns: " << nc << "\n";
1446
1447 if (parametric)
1448 {
1449 int extras = nc % 3;
1450 if (extras)
1451 warning ("ignoring last %d columns", extras);
1452
1453 for (int i = 0; i < nc-extras; i += 3)
1454 {
1455 os << matrix->extract (0, i, nr-1, i+2);
1456 if (i+3 < nc-extras)
1457 os << "\n";
1458 }
1459 }
1460 else
1461 {
1462 for (int i = 0; i < nc; i++)
1463 {
1464 os << matrix->extract (0, i, nr-1, i);
1465 if (i+1 < nc)
1466 os << "\n";
1467 }
1468 }
1469 break;
1470 default:
1471 ::error ("for now, I can only save real matrices in 3D format");
1472 return 0;
1473 break;
1474 }
1475 // Really want to return 1 only if write is successful.
1476 return 1;
1477 }
1478
1479 int
1480 tree_constant_rep::load (istream& is)
1481 {
1482 int is_global = 0;
1483
1484 type_tag = unknown_constant;
1485
1486 // Look for type keyword
1487
1488 char *tag = extract_keyword (is, "type");
1489
1490 if (tag != (char *) NULL && *tag != '\0')
1491 {
1492 char *ptr = strchr (tag, ' ');
1493 if (ptr != (char *) NULL)
1494 {
1495 *ptr = '\0';
1496 is_global = (strncmp (tag, "global", 6) == 0);
1497 *ptr = ' ';
1498 if (is_global)
1499 ptr++;
1500 else
1501 ptr = tag;
1502 }
1503 else
1504 ptr = tag;
1505
1506 if (strncmp (ptr, "scalar", 6) == 0)
1507 type_tag = load (is, scalar_constant);
1508 else if (strncmp (ptr, "matrix", 6) == 0)
1509 type_tag = load (is, matrix_constant);
1510 else if (strncmp (ptr, "complex scalar", 14) == 0)
1511 type_tag = load (is, complex_scalar_constant);
1512 else if (strncmp (ptr, "complex matrix", 14) == 0)
1513 type_tag = load (is, complex_matrix_constant);
1514 else if (strncmp (ptr, "string", 6) == 0)
1515 type_tag = load (is, string_constant);
1516 else if (strncmp (ptr, "range", 5) == 0)
1517 type_tag = load (is, range_constant);
1518 else
1519 ::error ("unknown constant type `%s'", tag);
1520 }
1521 else
1522 ::error ("failed to extract keyword specifying value type");
1523
1524 delete [] tag;
1525
1526 return is_global;
1527 }
1528
1529 tree_constant_rep::constant_type
1530 tree_constant_rep::load (istream& is, tree_constant_rep::constant_type t)
1531 {
1532 tree_constant_rep::constant_type status = unknown_constant;
1533
1534 switch (t)
1535 {
1536 case scalar_constant:
1537 is >> scalar;
1538 if (is)
1539 status = scalar_constant;
1540 else
1541 ::error ("failed to load scalar constant");
1542 break;
1543 case matrix_constant:
1544 {
1545 int nr = 0, nc = 0;
1546
1547 if (extract_keyword (is, "rows", nr) && nr > 0
1548 && extract_keyword (is, "columns", nc) && nc > 0)
1549 {
1550 matrix = new Matrix (nr, nc);
1551 is >> *matrix;
1552 if (is)
1553 status = matrix_constant;
1554 else
1555 ::error ("failed to load matrix constant");
1556 }
1557 else
1558 ::error ("failed to extract number of rows and columns");
1559 }
1560 break;
1561 case complex_scalar_constant:
1562 complex_scalar = new Complex;
1563 is >> *complex_scalar;
1564 if (is)
1565 status = complex_scalar_constant;
1566 else
1567 ::error ("failed to load complex scalar constant");
1568 break;
1569 case complex_matrix_constant:
1570 {
1571 int nr = 0, nc = 0;
1572
1573 if (extract_keyword (is, "rows", nr) && nr > 0
1574 && extract_keyword (is, "columns", nc) && nc > 0)
1575 {
1576 complex_matrix = new ComplexMatrix (nr, nc);
1577 is >> *complex_matrix;
1578 if (is)
1579 status = complex_matrix_constant;
1580 else
1581 ::error ("failed to load complex matrix constant");
1582 }
1583 else
1584 ::error ("failed to extract number of rows and columns");
1585 }
1586 break;
1587 case string_constant:
1588 {
1589 int len;
1590 if (extract_keyword (is, "length", len) && len > 0)
1591 {
1592 string = new char [len+1];
1593 is.get (string, len+1, EOF);
1594 if (is)
1595 status = string_constant;
1596 else
1597 ::error ("failed to load string constant");
1598 }
1599 else
1600 ::error ("failed to extract string length");
1601 }
1602 break;
1603 case range_constant:
1604 skip_comments (is);
1605 range = new Range ();
1606 is >> *range;
1607 if (is)
1608 status = range_constant;
1609 else
1610 ::error ("failed to load range constant");
1611 break;
1612 default:
1613 panic_impossible ();
1614 break;
1615 }
1616 return status;
1617 }
1618
1619 double
1620 tree_constant_rep::double_value (void) const
1621 {
1622 switch (type_tag)
1623 {
1624 case scalar_constant:
1625 return scalar;
1626 case complex_scalar_constant:
1627 {
1628 int flag = user_pref.ok_to_lose_imaginary_part;
1629 if (flag == -1)
1630 warning ("implicit conversion of complex value to real value");
1631
1632 if (flag != 0)
1633 return ::real (*complex_scalar);
1634
1635 ::error ("implicit conversion of complex value to real value");
1636 ::error ("not allowed");
1637 jump_to_top_level ();
1638 }
1639 default:
1640 panic_impossible ();
1641 break;
1642 }
1643 }
1644
1645 Matrix
1646 tree_constant_rep::matrix_value (void) const
1647 {
1648 switch (type_tag)
1649 {
1650 case scalar_constant:
1651 return Matrix (1, 1, scalar);
1652 case matrix_constant:
1653 return *matrix;
1654 case complex_scalar_constant:
1655 case complex_matrix_constant:
1656 {
1657 int flag = user_pref.ok_to_lose_imaginary_part;
1658 if (flag == -1)
1659 warning ("implicit conversion of complex matrix to real matrix");
1660
1661 if (flag != 0)
1662 {
1663 if (type_tag == complex_scalar_constant)
1664 return Matrix (1, 1, ::real (*complex_scalar));
1665 else if (type_tag == complex_matrix_constant)
1666 return ::real (*complex_matrix);
1667 else
1668 panic_impossible ();
1669 }
1670 else
1671 {
1672 ::error ("implicit conversion of complex matrix to real matrix");
1673 ::error ("not allowed");
1674 }
1675 jump_to_top_level ();
1676 }
1677 default:
1678 panic_impossible ();
1679 break;
1680 }
1681 }
1682
1683 Complex
1684 tree_constant_rep::complex_value (void) const
1685 {
1686 switch (type_tag)
1687 {
1688 case complex_scalar_constant:
1689 return *complex_scalar;
1690 case scalar_constant:
1691 return Complex (scalar);
1692 default:
1693 panic_impossible ();
1694 break;
1695 }
1696 }
1697
1698 ComplexMatrix
1699 tree_constant_rep::complex_matrix_value (void) const
1700 {
1701 switch (type_tag)
1702 {
1703 case scalar_constant:
1704 {
1705 return ComplexMatrix (1, 1, Complex (scalar));
1706 }
1707 case complex_scalar_constant:
1708 {
1709 return ComplexMatrix (1, 1, *complex_scalar);
1710 }
1711 case matrix_constant:
1712 {
1713 return ComplexMatrix (*matrix);
1714 }
1715 case complex_matrix_constant:
1716 return *complex_matrix;
1717 break;
1718 default:
1719 panic_impossible ();
1720 break;
1721 }
1722 }
1723
1724 char *
1725 tree_constant_rep::string_value (void) const
1726 {
1727 assert (type_tag == string_constant);
1728 return string;
1729 }
1730
1731 Range
1732 tree_constant_rep::range_value (void) const
1733 {
1734 assert (type_tag == range_constant);
1735 return *range;
1736 }
1737
1738 int
1739 tree_constant_rep::rows (void) const
1740 {
1741 int retval = -1;
1742 switch (type_tag)
1743 {
1744 case scalar_constant:
1745 case complex_scalar_constant:
1746 retval = 1;
1747 break;
1748 case string_constant:
1749 case range_constant:
1750 retval = (columns () > 0);
1751 break;
1752 case matrix_constant:
1753 retval = matrix->rows ();
1754 break;
1755 case complex_matrix_constant:
1756 retval = complex_matrix->rows ();
1757 break;
1758 case magic_colon:
1759 ::error ("invalid use of colon operator");
1760 break;
1761 case unknown_constant:
1762 retval = 0;
1763 break;
1764 default:
1765 panic_impossible ();
1766 break;
1767 }
1768 return retval;
1769 }
1770
1771 int
1772 tree_constant_rep::columns (void) const
1773 {
1774 int retval = -1;
1775 switch (type_tag)
1776 {
1777 case scalar_constant:
1778 case complex_scalar_constant:
1779 retval = 1;
1780 break;
1781 case matrix_constant:
1782 retval = matrix->columns ();
1783 break;
1784 case complex_matrix_constant:
1785 retval = complex_matrix->columns ();
1786 break;
1787 case string_constant:
1788 retval = strlen (string);
1789 break;
1790 case range_constant:
1791 retval = range->nelem ();
1792 break;
1793 case magic_colon:
1794 ::error ("invalid use of colon operator");
1795 break;
1796 case unknown_constant:
1797 retval = 0;
1798 break;
1799 default:
1800 panic_impossible ();
1801 break;
1802 }
1803 return retval;
1804 }
1805
1806 tree_constant
1807 tree_constant_rep::all (void) const
1808 {
1809 if (type_tag == string_constant || type_tag == range_constant)
1810 {
1811 tree_constant tmp = make_numeric ();
1812 return tmp.all ();
1813 }
1814
1815 tree_constant retval;
1816 switch (type_tag)
1817 {
1818 case scalar_constant:
1819 {
1820 double status = (scalar != 0.0);
1821 retval = tree_constant (status);
1822 }
1823 break;
1824 case matrix_constant:
1825 {
1826 Matrix m = matrix->all ();
1827 retval = tree_constant (m);
1828 }
1829 break;
1830 case complex_scalar_constant:
1831 {
1832 double status = (*complex_scalar != 0.0);
1833 retval = tree_constant (status);
1834 }
1835 break;
1836 case complex_matrix_constant:
1837 {
1838 Matrix m = complex_matrix->all ();
1839 retval = tree_constant (m);
1840 }
1841 break;
1842 case string_constant:
1843 case range_constant:
1844 case magic_colon:
1845 default:
1846 panic_impossible ();
1847 break;
1848 }
1849 return retval;
1850 }
1851
1852 tree_constant
1853 tree_constant_rep::any (void) const
1854 {
1855 if (type_tag == string_constant || type_tag == range_constant)
1856 {
1857 tree_constant tmp = make_numeric ();
1858 return tmp.any ();
1859 }
1860
1861 tree_constant retval;
1862 switch (type_tag)
1863 {
1864 case scalar_constant:
1865 {
1866 double status = (scalar != 0.0);
1867 retval = tree_constant (status);
1868 }
1869 break;
1870 case matrix_constant:
1871 {
1872 Matrix m = matrix->any ();
1873 retval = tree_constant (m);
1874 }
1875 break;
1876 case complex_scalar_constant:
1877 {
1878 double status = (*complex_scalar != 0.0);
1879 retval = tree_constant (status);
1880 }
1881 break;
1882 case complex_matrix_constant:
1883 {
1884 Matrix m = complex_matrix->any ();
1885 retval = tree_constant (m);
1886 }
1887 break;
1888 case string_constant:
1889 case range_constant:
1890 case magic_colon:
1891 default:
1892 panic_impossible ();
1893 break;
1894 }
1895 return retval;
1896 }
1897
1898 tree_constant
1899 tree_constant_rep::isstr (void) const
1900 {
1901 double status = 0.0;
1902 if (type_tag == string_constant)
1903 status = 1.0;
1904 tree_constant retval (status);
1905 return retval;
1906 }
1907
1908 tree_constant
1909 tree_constant_rep::convert_to_str (void)
1910 {
1911 tree_constant retval;
1912
1913 switch (type_tag)
1914 {
1915 case complex_scalar_constant:
1916 case scalar_constant:
1917 {
1918 double d = double_value ();
1919 int i = NINT (d);
1920 // Warn about out of range conversions?
1921 char s[2];
1922 s[0] = (char) i;
1923 s[1] = '\0';
1924 retval = tree_constant (s);
1925 }
1926 break;
1927 case complex_matrix_constant:
1928 case matrix_constant:
1929 {
1930 ColumnVector v = to_vector ();
1931 int len = v.length ();
1932 if (len == 0)
1933 ::error ("can only convert vectors and scalars to strings");
1934 else
1935 {
1936 char *s = new char [len+1];
1937 s[len] = '\0';
1938 for (int i = 0; i < len; i++)
1939 {
1940 double d = v.elem (i);
1941 int ival = NINT (d);
1942 // Warn about out of range conversions?
1943 s[i] = (char) ival;
1944 }
1945 retval = tree_constant (s);
1946 delete [] s;
1947 }
1948 }
1949 break;
1950 case range_constant:
1951 {
1952 Range r = range_value ();
1953 double b = r.base ();
1954 double incr = r.inc ();
1955 int nel = r.nelem ();
1956 char *s = new char [nel+1];
1957 s[nel] = '\0';
1958 for (int i = 0; i < nel; i++)
1959 {
1960 double d = b + i * incr;
1961 int ival = NINT (d);
1962 // Warn about out of range conversions?
1963 s[i] = (char) ival;
1964 }
1965 retval = tree_constant (s);
1966 delete [] s;
1967 }
1968 break;
1969 case string_constant:
1970 retval = tree_constant (*this);
1971 break;
1972 case magic_colon:
1973 default:
1974 panic_impossible ();
1975 break;
1976 }
1977 return retval;
1978 }
1979
1980 void
1981 tree_constant_rep::convert_to_row_or_column_vector (void)
1982 {
1983 assert (type_tag == matrix_constant || type_tag == complex_matrix_constant);
1984
1985 int nr = rows ();
1986 int nc = columns ();
1987
1988 int len = nr * nc;
1989
1990 assert (len > 0);
1991
1992 int new_nr = 1;
1993 int new_nc = 1;
1994
1995 if (user_pref.prefer_column_vectors)
1996 new_nr = len;
1997 else
1998 new_nc = len;
1999
2000 if (type_tag == matrix_constant)
2001 {
2002 Matrix *m = new Matrix (new_nr, new_nc);
2003
2004 double *cop_out = matrix->fortran_vec ();
2005
2006 for (int i = 0; i < len; i++)
2007 {
2008 if (new_nr == 1)
2009 m->elem (0, i) = *cop_out++;
2010 else
2011 m->elem (i, 0) = *cop_out++;
2012 }
2013
2014 delete matrix;
2015 matrix = m;
2016 }
2017 else
2018 {
2019 ComplexMatrix *cm = new ComplexMatrix (new_nr, new_nc);
2020
2021 Complex *cop_out = complex_matrix->fortran_vec ();
2022
2023 for (int i = 0; i < len; i++)
2024 {
2025 if (new_nr == 1)
2026 cm->elem (0, i) = *cop_out++;
2027 else
2028 cm->elem (i, 0) = *cop_out++;
2029 }
2030
2031 delete complex_matrix;
2032 complex_matrix = cm;
2033 }
2034 }
2035
2036 int
2037 tree_constant_rep::is_true (void) const
2038 {
2039 if (type_tag == string_constant || type_tag == range_constant)
2040 {
2041 tree_constant tmp = make_numeric ();
2042 return tmp.is_true ();
2043 }
2044
2045 int retval;
2046 switch (type_tag)
2047 {
2048 case scalar_constant:
2049 retval = (scalar != 0.0);
2050 break;
2051 case matrix_constant:
2052 {
2053 Matrix m = (matrix->all ()) . all ();
2054 retval = (m.rows () == 1
2055 && m.columns () == 1
2056 && m.elem (0, 0) != 0.0);
2057 }
2058 break;
2059 case complex_scalar_constant:
2060 retval = (*complex_scalar != 0.0);
2061 break;
2062 case complex_matrix_constant:
2063 {
2064 Matrix m = (complex_matrix->all ()) . all ();
2065 retval = (m.rows () == 1
2066 && m.columns () == 1
2067 && m.elem (0, 0) != 0.0);
2068 }
2069 break;
2070 case string_constant:
2071 case range_constant:
2072 case magic_colon:
2073 default:
2074 panic_impossible ();
2075 break;
2076 }
2077 return retval;
2078 }
2079
2080 tree_constant
2081 tree_constant_rep::cumprod (void) const
2082 {
2083 if (type_tag == string_constant || type_tag == range_constant)
2084 {
2085 tree_constant tmp = make_numeric ();
2086 return tmp.cumprod ();
2087 }
2088
2089 tree_constant retval;
2090 switch (type_tag)
2091 {
2092 case scalar_constant:
2093 retval = tree_constant (scalar);
2094 break;
2095 case matrix_constant:
2096 {
2097 Matrix m = matrix->cumprod ();
2098 retval = tree_constant (m);
2099 }
2100 break;
2101 case complex_scalar_constant:
2102 retval = tree_constant (*complex_scalar);
2103 break;
2104 case complex_matrix_constant:
2105 {
2106 ComplexMatrix m = complex_matrix->cumprod ();
2107 retval = tree_constant (m);
2108 }
2109 break;
2110 case string_constant:
2111 case range_constant:
2112 case magic_colon:
2113 default:
2114 panic_impossible ();
2115 break;
2116 }
2117 return retval;
2118 }
2119
2120 tree_constant
2121 tree_constant_rep::cumsum (void) const
2122 {
2123 if (type_tag == string_constant || type_tag == range_constant)
2124 {
2125 tree_constant tmp = make_numeric ();
2126 return tmp.cumsum ();
2127 }
2128
2129 tree_constant retval;
2130 switch (type_tag)
2131 {
2132 case scalar_constant:
2133 retval = tree_constant (scalar);
2134 break;
2135 case matrix_constant:
2136 {
2137 Matrix m = matrix->cumsum ();
2138 retval = tree_constant (m);
2139 }
2140 break;
2141 case complex_scalar_constant:
2142 retval = tree_constant (*complex_scalar);
2143 break;
2144 case complex_matrix_constant:
2145 {
2146 ComplexMatrix m = complex_matrix->cumsum ();
2147 retval = tree_constant (m);
2148 }
2149 break;
2150 case string_constant:
2151 case range_constant:
2152 case magic_colon:
2153 default:
2154 panic_impossible ();
2155 break;
2156 }
2157 return retval;
2158 }
2159
2160 tree_constant
2161 tree_constant_rep::prod (void) const
2162 {
2163 if (type_tag == string_constant || type_tag == range_constant)
2164 {
2165 tree_constant tmp = make_numeric ();
2166 return tmp.prod ();
2167 }
2168
2169 tree_constant retval;
2170 switch (type_tag)
2171 {
2172 case scalar_constant:
2173 retval = tree_constant (scalar);
2174 break;
2175 case matrix_constant:
2176 {
2177 Matrix m = matrix->prod ();
2178 retval = tree_constant (m);
2179 }
2180 break;
2181 case complex_scalar_constant:
2182 retval = tree_constant (*complex_scalar);
2183 break;
2184 case complex_matrix_constant:
2185 {
2186 ComplexMatrix m = complex_matrix->prod ();
2187 retval = tree_constant (m);
2188 }
2189 break;
2190 case string_constant:
2191 case range_constant:
2192 case magic_colon:
2193 default:
2194 panic_impossible ();
2195 break;
2196 }
2197 return retval;
2198 }
2199
2200 tree_constant
2201 tree_constant_rep::sum (void) const
2202 {
2203 if (type_tag == string_constant || type_tag == range_constant)
2204 {
2205 tree_constant tmp = make_numeric ();
2206 return tmp.sum ();
2207 }
2208
2209 tree_constant retval;
2210 switch (type_tag)
2211 {
2212 case scalar_constant:
2213 retval = tree_constant (scalar);
2214 break;
2215 case matrix_constant:
2216 {
2217 Matrix m = matrix->sum ();
2218 retval = tree_constant (m);
2219 }
2220 break;
2221 case complex_scalar_constant:
2222 retval = tree_constant (*complex_scalar);
2223 break;
2224 case complex_matrix_constant:
2225 {
2226 ComplexMatrix m = complex_matrix->sum ();
2227 retval = tree_constant (m);
2228 }
2229 break;
2230 case string_constant:
2231 case range_constant:
2232 case magic_colon:
2233 default:
2234 panic_impossible ();
2235 break;
2236 }
2237 return retval;
2238 }
2239
2240 tree_constant
2241 tree_constant_rep::sumsq (void) const
2242 {
2243 if (type_tag == string_constant || type_tag == range_constant)
2244 {
2245 tree_constant tmp = make_numeric ();
2246 return tmp.sumsq ();
2247 }
2248
2249 tree_constant retval;
2250 switch (type_tag)
2251 {
2252 case scalar_constant:
2253 retval = tree_constant (scalar * scalar);
2254 break;
2255 case matrix_constant:
2256 {
2257 Matrix m = matrix->sumsq ();
2258 retval = tree_constant (m);
2259 }
2260 break;
2261 case complex_scalar_constant:
2262 {
2263 Complex c (*complex_scalar);
2264 retval = tree_constant (c * c);
2265 }
2266 break;
2267 case complex_matrix_constant:
2268 {
2269 ComplexMatrix m = complex_matrix->sumsq ();
2270 retval = tree_constant (m);
2271 }
2272 break;
2273 case string_constant:
2274 case range_constant:
2275 case magic_colon:
2276 default:
2277 panic_impossible ();
2278 break;
2279 }
2280 return retval;
2281 }
2282
2283 static tree_constant
2284 make_diag (const Matrix& v, int k)
2285 {
2286 int nr = v.rows ();
2287 int nc = v.columns ();
2288 assert (nc == 1 || nr == 1);
2289
2290 tree_constant retval;
2291
2292 int roff = 0;
2293 int coff = 0;
2294 if (k > 0)
2295 {
2296 roff = 0;
2297 coff = k;
2298 }
2299 else if (k < 0)
2300 {
2301 roff = -k;
2302 coff = 0;
2303 }
2304
2305 if (nr == 1)
2306 {
2307 int n = nc + ABS (k);
2308 Matrix m (n, n, 0.0);
2309 for (int i = 0; i < nc; i++)
2310 m.elem (i+roff, i+coff) = v.elem (0, i);
2311 retval = tree_constant (m);
2312 }
2313 else
2314 {
2315 int n = nr + ABS (k);
2316 Matrix m (n, n, 0.0);
2317 for (int i = 0; i < nr; i++)
2318 m.elem (i+roff, i+coff) = v.elem (i, 0);
2319 retval = tree_constant (m);
2320 }
2321
2322 return retval;
2323 }
2324
2325 static tree_constant
2326 make_diag (const ComplexMatrix& v, int k)
2327 {
2328 int nr = v.rows ();
2329 int nc = v.columns ();
2330 assert (nc == 1 || nr == 1);
2331
2332 tree_constant retval;
2333
2334 int roff = 0;
2335 int coff = 0;
2336 if (k > 0)
2337 {
2338 roff = 0;
2339 coff = k;
2340 }
2341 else if (k < 0)
2342 {
2343 roff = -k;
2344 coff = 0;
2345 }
2346
2347 if (nr == 1)
2348 {
2349 int n = nc + ABS (k);
2350 ComplexMatrix m (n, n, 0.0);
2351 for (int i = 0; i < nc; i++)
2352 m.elem (i+roff, i+coff) = v.elem (0, i);
2353 retval = tree_constant (m);
2354 }
2355 else
2356 {
2357 int n = nr + ABS (k);
2358 ComplexMatrix m (n, n, 0.0);
2359 for (int i = 0; i < nr; i++)
2360 m.elem (i+roff, i+coff) = v.elem (i, 0);
2361 retval = tree_constant (m);
2362 }
2363
2364 return retval;
2365 }
2366
2367 tree_constant
2368 tree_constant_rep::diag (void) const
2369 {
2370 if (type_tag == string_constant || type_tag == range_constant)
2371 {
2372 tree_constant tmp = make_numeric ();
2373 return tmp.diag ();
2374 }
2375
2376 tree_constant retval;
2377 switch (type_tag)
2378 {
2379 case scalar_constant:
2380 retval = tree_constant (scalar);
2381 break;
2382 case matrix_constant:
2383 {
2384 int nr = rows ();
2385 int nc = columns ();
2386 if (nr == 0 || nc == 0)
2387 {
2388 Matrix mtmp;
2389 retval = tree_constant (mtmp);
2390 }
2391 else if (nr == 1 || nc == 1)
2392 retval = make_diag (matrix_value (), 0);
2393 else
2394 {
2395 ColumnVector v = matrix->diag ();
2396 if (v.capacity () > 0)
2397 retval = tree_constant (v);
2398 }
2399 }
2400 break;
2401 case complex_scalar_constant:
2402 retval = tree_constant (*complex_scalar);
2403 break;
2404 case complex_matrix_constant:
2405 {
2406 int nr = rows ();
2407 int nc = columns ();
2408 if (nr == 0 || nc == 0)
2409 {
2410 Matrix mtmp;
2411 retval = tree_constant (mtmp);
2412 }
2413 else if (nr == 1 || nc == 1)
2414 retval = make_diag (complex_matrix_value (), 0);
2415 else
2416 {
2417 ComplexColumnVector v = complex_matrix->diag ();
2418 if (v.capacity () > 0)
2419 retval = tree_constant (v);
2420 }
2421 }
2422 break;
2423 case string_constant:
2424 case range_constant:
2425 case magic_colon:
2426 default:
2427 panic_impossible ();
2428 break;
2429 }
2430 return retval;
2431 }
2432
2433 tree_constant
2434 tree_constant_rep::diag (const tree_constant& a) const
2435 {
2436 if (type_tag == string_constant || type_tag == range_constant)
2437 {
2438 tree_constant tmp = make_numeric ();
2439 return tmp.diag (a);
2440 }
2441
2442 tree_constant tmp_a = a.make_numeric ();
2443
2444 tree_constant_rep::constant_type a_type = tmp_a.const_type ();
2445
2446 tree_constant retval;
2447
2448 switch (type_tag)
2449 {
2450 case scalar_constant:
2451 if (a_type == scalar_constant)
2452 {
2453 int k = NINT (tmp_a.double_value ());
2454 int n = ABS (k) + 1;
2455 if (k == 0)
2456 retval = tree_constant (scalar);
2457 else if (k > 0)
2458 {
2459 Matrix m (n, n, 0.0);
2460 m.elem (0, k) = scalar;
2461 retval = tree_constant (m);
2462 }
2463 else if (k < 0)
2464 {
2465 Matrix m (n, n, 0.0);
2466 m.elem (-k, 0) = scalar;
2467 retval = tree_constant (m);
2468 }
2469 }
2470 break;
2471 case matrix_constant:
2472 if (a_type == scalar_constant)
2473 {
2474 int k = NINT (tmp_a.double_value ());
2475 int nr = rows ();
2476 int nc = columns ();
2477 if (nr == 0 || nc == 0)
2478 {
2479 Matrix mtmp;
2480 retval = tree_constant (mtmp);
2481 }
2482 else if (nr == 1 || nc == 1)
2483 retval = make_diag (matrix_value (), k);
2484 else
2485 {
2486 ColumnVector d = matrix->diag (k);
2487 retval = tree_constant (d);
2488 }
2489 }
2490 else
2491 ::error ("diag: invalid second argument");
2492
2493 break;
2494 case complex_scalar_constant:
2495 if (a_type == scalar_constant)
2496 {
2497 int k = NINT (tmp_a.double_value ());
2498 int n = ABS (k) + 1;
2499 if (k == 0)
2500 retval = tree_constant (*complex_scalar);
2501 else if (k > 0)
2502 {
2503 ComplexMatrix m (n, n, 0.0);
2504 m.elem (0, k) = *complex_scalar;
2505 retval = tree_constant (m);
2506 }
2507 else if (k < 0)
2508 {
2509 ComplexMatrix m (n, n, 0.0);
2510 m.elem (-k, 0) = *complex_scalar;
2511 retval = tree_constant (m);
2512 }
2513 }
2514 break;
2515 case complex_matrix_constant:
2516 if (a_type == scalar_constant)
2517 {
2518 int k = NINT (tmp_a.double_value ());
2519 int nr = rows ();
2520 int nc = columns ();
2521 if (nr == 0 || nc == 0)
2522 {
2523 Matrix mtmp;
2524 retval = tree_constant (mtmp);
2525 }
2526 else if (nr == 1 || nc == 1)
2527 retval = make_diag (complex_matrix_value (), k);
2528 else
2529 {
2530 ComplexColumnVector d = complex_matrix->diag (k);
2531 retval = tree_constant (d);
2532 }
2533 }
2534 else
2535 ::error ("diag: invalid second argument");
2536
2537 break;
2538 case string_constant:
2539 case range_constant:
2540 case magic_colon:
2541 default:
2542 panic_impossible ();
2543 break;
2544 }
2545 return retval;
2546 }
2547
2548 tree_constant
2549 tree_constant_rep::mapper (Mapper_fcn& m_fcn, int print) const
2550 {
2551 tree_constant retval;
2552
2553 if (type_tag == string_constant || type_tag == range_constant)
2554 {
2555 tree_constant tmp = make_numeric ();
2556 return tmp.mapper (m_fcn, print);
2557 }
2558
2559 switch (type_tag)
2560 {
2561 case scalar_constant:
2562 if (m_fcn.can_return_complex_for_real_arg
2563 && (scalar < m_fcn.lower_limit
2564 || scalar > m_fcn.upper_limit))
2565 {
2566 if (m_fcn.c_c_mapper != NULL)
2567 {
2568 Complex c = m_fcn.c_c_mapper (Complex (scalar));
2569 retval = tree_constant (c);
2570 }
2571 else
2572 panic_impossible ();
2573 }
2574 else
2575 {
2576 if (m_fcn.d_d_mapper != NULL)
2577 {
2578 double d = m_fcn.d_d_mapper (scalar);
2579 retval = tree_constant (d);
2580 }
2581 else
2582 panic_impossible ();
2583 }
2584 break;
2585 case matrix_constant:
2586 if (m_fcn.can_return_complex_for_real_arg
2587 && (any_element_less_than (*matrix, m_fcn.lower_limit)
2588 || any_element_greater_than (*matrix, m_fcn.upper_limit)))
2589 {
2590 if (m_fcn.c_c_mapper != NULL)
2591 {
2592 ComplexMatrix cm = map (m_fcn.c_c_mapper,
2593 ComplexMatrix (*matrix));
2594 retval = tree_constant (cm);
2595 }
2596 else
2597 panic_impossible ();
2598 }
2599 else
2600 {
2601 if (m_fcn.d_d_mapper != NULL)
2602 {
2603 Matrix m = map (m_fcn.d_d_mapper, *matrix);
2604 retval = tree_constant (m);
2605 }
2606 else
2607 panic_impossible ();
2608 }
2609 break;
2610 case complex_scalar_constant:
2611 if (m_fcn.d_c_mapper != NULL)
2612 {
2613 double d;
2614 d = m_fcn.d_c_mapper (*complex_scalar);
2615 retval = tree_constant (d);
2616 }
2617 else if (m_fcn.c_c_mapper != NULL)
2618 {
2619 Complex c;
2620 c = m_fcn.c_c_mapper (*complex_scalar);
2621 retval = tree_constant (c);
2622 }
2623 else
2624 panic_impossible ();
2625 break;
2626 case complex_matrix_constant:
2627 if (m_fcn.d_c_mapper != NULL)
2628 {
2629 Matrix m;
2630 m = map (m_fcn.d_c_mapper, *complex_matrix);
2631 retval = tree_constant (m);
2632 }
2633 else if (m_fcn.c_c_mapper != NULL)
2634 {
2635 ComplexMatrix cm;
2636 cm = map (m_fcn.c_c_mapper, *complex_matrix);
2637 retval = tree_constant (cm);
2638 }
2639 else
2640 panic_impossible ();
2641 break;
2642 case string_constant:
2643 case range_constant:
2644 case magic_colon:
2645 default:
2646 panic_impossible ();
2647 break;
2648 }
2649 return retval;
2650 }
2651
2652 /*
2653 * Top-level tree-constant function that handles assignments. Only
2654 * decide if the left-hand side is currently a scalar or a matrix and
2655 * hand off to other functions to do the real work.
2656 */
2657 void
2658 tree_constant_rep::assign (tree_constant& rhs, tree_constant *args, int nargs)
2659 {
2660 tree_constant rhs_tmp = rhs.make_numeric ();
2661
2662 // This is easier than actually handling assignments to strings.
2663 // An assignment to a range will normally require a conversion to a
2664 // vector since it will normally destroy the equally-spaced property
2665 // of the range elements.
2666
2667 if (type_tag == string_constant || type_tag == range_constant)
2668 force_numeric ();
2669
2670 switch (type_tag)
2671 {
2672 case complex_scalar_constant:
2673 case scalar_constant:
2674 case unknown_constant:
2675 do_scalar_assignment (rhs_tmp, args, nargs);
2676 break;
2677 case complex_matrix_constant:
2678 case matrix_constant:
2679 do_matrix_assignment (rhs_tmp, args, nargs);
2680 break;
2681 case string_constant:
2682 ::error ("invalid assignment to string type");
2683 break;
2684 case range_constant:
2685 case magic_colon:
2686 default:
2687 panic_impossible ();
2688 break;
2689 }
2690 }
2691
2692 /*
2693 * Assignments to scalars. If resize_on_range_error is true,
2694 * this can convert the left-hand side to a matrix.
2695 */
2696 void
2697 tree_constant_rep::do_scalar_assignment (tree_constant& rhs,
2698 tree_constant *args, int nargs)
2699 {
2700 assert (type_tag == unknown_constant
2701 || type_tag == scalar_constant
2702 || type_tag == complex_scalar_constant);
2703
2704 if ((rhs.is_scalar_type () || rhs.is_zero_by_zero ())
2705 && valid_scalar_indices (args, nargs))
2706 {
2707 if (rhs.is_zero_by_zero ())
2708 {
2709 if (type_tag == complex_scalar_constant)
2710 delete complex_scalar;
2711
2712 matrix = new Matrix (0, 0);
2713 type_tag = matrix_constant;
2714 }
2715 else if (type_tag == unknown_constant || type_tag == scalar_constant)
2716 {
2717 if (rhs.const_type () == scalar_constant)
2718 {
2719 scalar = rhs.double_value ();
2720 type_tag = scalar_constant;
2721 }
2722 else if (rhs.const_type () == complex_scalar_constant)
2723 {
2724 complex_scalar = new Complex (rhs.complex_value ());
2725 type_tag = complex_scalar_constant;
2726 }
2727 else
2728 {
2729 ::error ("invalid assignment to scalar");
2730 return;
2731 }
2732 }
2733 else
2734 {
2735 if (rhs.const_type () == scalar_constant)
2736 {
2737 delete complex_scalar;
2738 scalar = rhs.double_value ();
2739 type_tag = scalar_constant;
2740 }
2741 else if (rhs.const_type () == complex_scalar_constant)
2742 {
2743 *complex_scalar = rhs.complex_value ();
2744 type_tag = complex_scalar_constant;
2745 }
2746 else
2747 {
2748 ::error ("invalid assignment to scalar");
2749 return;
2750 }
2751 }
2752 }
2753 else if (user_pref.resize_on_range_error)
2754 {
2755 tree_constant_rep::constant_type old_type_tag = type_tag;
2756
2757 if (type_tag == complex_scalar_constant)
2758 {
2759 Complex *old_complex = complex_scalar;
2760 complex_matrix = new ComplexMatrix (1, 1, *complex_scalar);
2761 type_tag = complex_matrix_constant;
2762 delete old_complex;
2763 }
2764 else if (type_tag == scalar_constant)
2765 {
2766 matrix = new Matrix (1, 1, scalar);
2767 type_tag = matrix_constant;
2768 }
2769
2770 // If there is an error, the call to do_matrix_assignment should not
2771 // destroy the current value. tree_constant_rep::eval(int) will take
2772 // care of converting single element matrices back to scalars.
2773
2774 do_matrix_assignment (rhs, args, nargs);
2775
2776 // I don't think there's any other way to revert back to unknown
2777 // constant types, so here it is.
2778
2779 if (old_type_tag == unknown_constant && error_state)
2780 {
2781 if (type_tag == matrix_constant)
2782 delete matrix;
2783 else if (type_tag == complex_matrix_constant)
2784 delete complex_matrix;
2785
2786 type_tag = unknown_constant;
2787 }
2788 }
2789 else if (nargs > 3 || nargs < 2)
2790 ::error ("invalid index expression for scalar type");
2791 else
2792 ::error ("index invalid or out of range for scalar type");
2793 }
2794
2795 /*
2796 * Assignments to matrices (and vectors).
2797 *
2798 * For compatibility with Matlab, we allow assignment of an empty
2799 * matrix to an expression with empty indices to do nothing.
2800 */
2801 void
2802 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
2803 tree_constant *args, int nargs)
2804 {
2805 assert (type_tag == unknown_constant
2806 || type_tag == matrix_constant
2807 || type_tag == complex_matrix_constant);
2808
2809 if (type_tag == matrix_constant && rhs.is_complex_type ())
2810 {
2811 Matrix *old_matrix = matrix;
2812 complex_matrix = new ComplexMatrix (*matrix);
2813 type_tag = complex_matrix_constant;
2814 delete old_matrix;
2815 }
2816 else if (type_tag == unknown_constant)
2817 {
2818 if (rhs.is_complex_type ())
2819 {
2820 complex_matrix = new ComplexMatrix ();
2821 type_tag = complex_matrix_constant;
2822 }
2823 else
2824 {
2825 matrix = new Matrix ();
2826 type_tag = matrix_constant;
2827 }
2828 }
2829
2830 // The do_matrix_assignment functions can't handle empty matrices, so
2831 // don't let any pass through here.
2832 switch (nargs)
2833 {
2834 case 2:
2835 if (! args)
2836 ::error ("matrix index is null");
2837 else if (args[1].is_undefined ())
2838 ::error ("matrix index is undefined");
2839 else
2840 do_matrix_assignment (rhs, args[1]);
2841 break;
2842 case 3:
2843 if (! args)
2844 ::error ("matrix indices are null");
2845 else if (args[1].is_undefined ())
2846 ::error ("first matrix index is undefined");
2847 else if (args[2].is_undefined ())
2848 ::error ("second matrix index is undefined");
2849 else if (args[1].is_empty () || args[2].is_empty ())
2850 {
2851 if (! rhs.is_empty ())
2852 {
2853 ::error ("in assignment expression, a matrix index is empty");
2854 ::error ("but hte right hand side is not an empty matrix");
2855 }
2856 // XXX FIXME XXX -- to really be correct here, we should probably
2857 // check to see if the assignment conforms, but that seems like more
2858 // work than it's worth right now...
2859 }
2860 else
2861 do_matrix_assignment (rhs, args[1], args[2]);
2862 break;
2863 default:
2864 ::error ("too many indices for matrix expression");
2865 break;
2866 }
2867 }
2868
2869 /*
2870 * Matrix assignments indexed by a single value.
2871 */
2872 void
2873 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
2874 tree_constant& i_arg)
2875 {
2876 int nr = rows ();
2877 int nc = columns ();
2878
2879 if (user_pref.do_fortran_indexing || nr <= 1 || nc <= 1)
2880 {
2881 if (i_arg.is_empty ())
2882 {
2883 if (! rhs.is_empty ())
2884 {
2885 ::error ("in assignment expression, matrix index is empty but");
2886 ::error ("right hand side is not an empty matrix");
2887 }
2888 // XXX FIXME XXX -- to really be correct here, we should probably
2889 // check to see if the assignment conforms, but that seems like more
2890 // work than it's worth right now...
2891
2892 // The assignment functions can't handle empty matrices, so don't let
2893 // any pass through here.
2894 return;
2895 }
2896
2897 // We can't handle the case of assigning to a vector first, since even
2898 // then, the two operations are not equivalent. For example, the
2899 // expression V(:) = M is handled differently depending on whether the
2900 // user specified do_fortran_indexing = "true".
2901
2902 if (user_pref.do_fortran_indexing)
2903 fortran_style_matrix_assignment (rhs, i_arg);
2904 else if (nr <= 1 || nc <= 1)
2905 vector_assignment (rhs, i_arg);
2906 else
2907 panic_impossible ();
2908 }
2909 else
2910 ::error ("single index only valid for row or column vector");
2911 }
2912
2913 /*
2914 * Fortran-style assignments. Matrices are assumed to be stored in
2915 * column-major order and it is ok to use a single index for
2916 * multi-dimensional matrices.
2917 */
2918 void
2919 tree_constant_rep::fortran_style_matrix_assignment (tree_constant& rhs,
2920 tree_constant& i_arg)
2921 {
2922 tree_constant tmp_i = i_arg.make_numeric_or_magic ();
2923
2924 tree_constant_rep::constant_type itype = tmp_i.const_type ();
2925
2926 int nr = rows ();
2927 int nc = columns ();
2928
2929 int rhs_nr = rhs.rows ();
2930 int rhs_nc = rhs.columns ();
2931
2932 switch (itype)
2933 {
2934 case complex_scalar_constant:
2935 case scalar_constant:
2936 {
2937 int i = NINT (tmp_i.double_value ());
2938 int idx = i - 1;
2939
2940 if (rhs_nr == 0 && rhs_nc == 0)
2941 {
2942 if (idx < nr * nc)
2943 {
2944 convert_to_row_or_column_vector ();
2945
2946 nr = rows ();
2947 nc = columns ();
2948
2949 if (nr == 1)
2950 delete_column (idx);
2951 else if (nc == 1)
2952 delete_row (idx);
2953 else
2954 panic_impossible ();
2955 }
2956 return;
2957 }
2958
2959 if (index_check (idx, "") < 0)
2960 return;
2961
2962 if (nr <= 1 || nc <= 1)
2963 {
2964 maybe_resize (idx);
2965 if (error_state)
2966 return;
2967 }
2968 else if (range_max_check (idx, nr * nc) < 0)
2969 return;
2970
2971 nr = rows ();
2972 nc = columns ();
2973
2974 if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc))
2975 {
2976 ::error ("for A(int) = X: X must be a scalar");
2977 return;
2978 }
2979 int ii = fortran_row (i, nr) - 1;
2980 int jj = fortran_column (i, nr) - 1;
2981 do_matrix_assignment (rhs, ii, jj);
2982 }
2983 break;
2984 case complex_matrix_constant:
2985 case matrix_constant:
2986 {
2987 Matrix mi = tmp_i.matrix_value ();
2988 int len = nr * nc;
2989 idx_vector ii (mi, 1, "", len); // Always do fortran indexing here...
2990 if (! ii)
2991 return;
2992
2993 if (rhs_nr == 0 && rhs_nc == 0)
2994 {
2995 ii.sort_uniq ();
2996 int num_to_delete = 0;
2997 for (int i = 0; i < ii.length (); i++)
2998 {
2999 if (ii.elem (i) < len)
3000 num_to_delete++;
3001 else
3002 break;
3003 }
3004
3005 if (num_to_delete > 0)
3006 {
3007 if (num_to_delete != ii.length ())
3008 ii.shorten (num_to_delete);
3009
3010 convert_to_row_or_column_vector ();
3011
3012 nr = rows ();
3013 nc = columns ();
3014
3015 if (nr == 1)
3016 delete_columns (ii);
3017 else if (nc == 1)
3018 delete_rows (ii);
3019 else
3020 panic_impossible ();
3021 }
3022 return;
3023 }
3024
3025 if (nr <= 1 || nc <= 1)
3026 {
3027 maybe_resize (ii.max ());
3028 if (error_state)
3029 return;
3030 }
3031 else if (range_max_check (ii.max (), len) < 0)
3032 return;
3033
3034 int ilen = ii.capacity ();
3035
3036 if (ilen != rhs_nr * rhs_nc)
3037 {
3038 ::error ("A(matrix) = X: X and matrix must have the same number");
3039 ::error ("of elements");
3040 }
3041 else if (ilen == 1 && rhs.is_scalar_type ())
3042 {
3043 int nr = rows ();
3044 int idx = ii.elem (0);
3045 int ii = fortran_row (idx + 1, nr) - 1;
3046 int jj = fortran_column (idx + 1, nr) - 1;
3047
3048 if (rhs.const_type () == scalar_constant)
3049 matrix->elem (ii, jj) = rhs.double_value ();
3050 else if (rhs.const_type () == complex_scalar_constant)
3051 complex_matrix->elem (ii, jj) = rhs.complex_value ();
3052 else
3053 panic_impossible ();
3054 }
3055 else
3056 fortran_style_matrix_assignment (rhs, ii);
3057 }
3058 break;
3059 case string_constant:
3060 gripe_string_invalid ();
3061 break;
3062 case range_constant:
3063 gripe_range_invalid ();
3064 break;
3065 case magic_colon:
3066 // a(:) = [] is equivalent to a(:,:) = [].
3067 if (rhs_nr == 0 && rhs_nc == 0)
3068 do_matrix_assignment (rhs, magic_colon, magic_colon);
3069 else
3070 fortran_style_matrix_assignment (rhs, magic_colon);
3071 break;
3072 default:
3073 panic_impossible ();
3074 break;
3075 }
3076 }
3077
3078 /*
3079 * Fortran-style assignment for vector index.
3080 */
3081 void
3082 tree_constant_rep::fortran_style_matrix_assignment (tree_constant& rhs,
3083 idx_vector& i)
3084 {
3085 assert (rhs.is_matrix_type ());
3086
3087 int ilen = i.capacity ();
3088
3089 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
3090
3091 int len = rhs_nr * rhs_nc;
3092
3093 if (len == ilen)
3094 {
3095 int nr = rows ();
3096 if (rhs.const_type () == matrix_constant)
3097 {
3098 double *cop_out = rhs_m.fortran_vec ();
3099 for (int k = 0; k < len; k++)
3100 {
3101 int ii = fortran_row (i.elem (k) + 1, nr) - 1;
3102 int jj = fortran_column (i.elem (k) + 1, nr) - 1;
3103
3104 matrix->elem (ii, jj) = *cop_out++;
3105 }
3106 }
3107 else
3108 {
3109 Complex *cop_out = rhs_cm.fortran_vec ();
3110 for (int k = 0; k < len; k++)
3111 {
3112 int ii = fortran_row (i.elem (k) + 1, nr) - 1;
3113 int jj = fortran_column (i.elem (k) + 1, nr) - 1;
3114
3115 complex_matrix->elem (ii, jj) = *cop_out++;
3116 }
3117 }
3118 }
3119 else
3120 ::error ("number of rows and columns must match for indexed assignment");
3121 }
3122
3123 /*
3124 * Fortran-style assignment for colon index.
3125 */
3126 void
3127 tree_constant_rep::fortran_style_matrix_assignment
3128 (tree_constant& rhs, tree_constant_rep::constant_type mci)
3129 {
3130 assert (rhs.is_matrix_type () && mci == tree_constant_rep::magic_colon);
3131
3132 int nr = rows ();
3133 int nc = columns ();
3134
3135 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
3136
3137 int rhs_size = rhs_nr * rhs_nc;
3138 if (rhs_size == 0)
3139 {
3140 if (rhs.const_type () == matrix_constant)
3141 {
3142 delete matrix;
3143 matrix = new Matrix (0, 0);
3144 return;
3145 }
3146 else
3147 panic_impossible ();
3148 }
3149 else if (nr*nc != rhs_size)
3150 {
3151 ::error ("A(:) = X: X and A must have the same number of elements");
3152 return;
3153 }
3154
3155 if (rhs.const_type () == matrix_constant)
3156 {
3157 double *cop_out = rhs_m.fortran_vec ();
3158 for (int j = 0; j < nc; j++)
3159 for (int i = 0; i < nr; i++)
3160 matrix->elem (i, j) = *cop_out++;
3161 }
3162 else
3163 {
3164 Complex *cop_out = rhs_cm.fortran_vec ();
3165 for (int j = 0; j < nc; j++)
3166 for (int i = 0; i < nr; i++)
3167 complex_matrix->elem (i, j) = *cop_out++;
3168 }
3169 }
3170
3171 /*
3172 * Assignments to vectors. Hand off to other functions once we know
3173 * what kind of index we have. For a colon, it is the same as
3174 * assignment to a matrix indexed by two colons.
3175 */
3176 void
3177 tree_constant_rep::vector_assignment (tree_constant& rhs, tree_constant& i_arg)
3178 {
3179 int nr = rows ();
3180 int nc = columns ();
3181
3182 assert ((nr == 1 || nc == 1 || (nr == 0 && nc == 0))
3183 && ! user_pref.do_fortran_indexing);
3184
3185 tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic ();
3186
3187 tree_constant_rep::constant_type itype = tmp_i.const_type ();
3188
3189 switch (itype)
3190 {
3191 case complex_scalar_constant:
3192 case scalar_constant:
3193 {
3194 int i = tree_to_mat_idx (tmp_i.double_value ());
3195 if (index_check (i, "") < 0)
3196 return;
3197 do_vector_assign (rhs, i);
3198 }
3199 break;
3200 case complex_matrix_constant:
3201 case matrix_constant:
3202 {
3203 Matrix mi = tmp_i.matrix_value ();
3204 int len = nr * nc;
3205 idx_vector iv (mi, user_pref.do_fortran_indexing, "", len);
3206 if (! iv)
3207 return;
3208
3209 do_vector_assign (rhs, iv);
3210 }
3211 break;
3212 case string_constant:
3213 gripe_string_invalid ();
3214 break;
3215 case range_constant:
3216 {
3217 Range ri = tmp_i.range_value ();
3218 int len = nr * nc;
3219 if (len == 2 && is_zero_one (ri))
3220 {
3221 do_vector_assign (rhs, 1);
3222 }
3223 else if (len == 2 && is_one_zero (ri))
3224 {
3225 do_vector_assign (rhs, 0);
3226 }
3227 else
3228 {
3229 if (index_check (ri, "") < 0)
3230 return;
3231 do_vector_assign (rhs, ri);
3232 }
3233 }
3234 break;
3235 case magic_colon:
3236 {
3237 int rhs_nr = rhs.rows ();
3238 int rhs_nc = rhs.columns ();
3239
3240 if (! indexed_assign_conforms (nr, nc, rhs_nr, rhs_nc))
3241 {
3242 ::error ("A(:) = X: X and A must have the same dimensions");
3243 return;
3244 }
3245 do_matrix_assignment (rhs, magic_colon, magic_colon);
3246 }
3247 break;
3248 default:
3249 panic_impossible ();
3250 break;
3251 }
3252 }
3253
3254 /*
3255 * Check whether an indexed assignment to a vector is valid.
3256 */
3257 void
3258 tree_constant_rep::check_vector_assign (int rhs_nr, int rhs_nc,
3259 int ilen, const char *rm)
3260 {
3261 int nr = rows ();
3262 int nc = columns ();
3263
3264 if ((nr == 1 && nc == 1) || nr == 0 || nc == 0) // No orientation.
3265 {
3266 if (! (ilen == rhs_nr || ilen == rhs_nc))
3267 {
3268 ::error ("A(%s) = X: X and %s must have the same number of elements",
3269 rm, rm);
3270 }
3271 }
3272 else if (nr == 1) // Preserve current row orientation.
3273 {
3274 if (! (rhs_nr == 1 && rhs_nc == ilen))
3275 {
3276 ::error ("A(%s) = X: where A is a row vector, X must also be a", rm);
3277 ::error ("row vector with the same number of elements as %s", rm);
3278 }
3279 }
3280 else if (nc == 1) // Preserve current column orientation.
3281 {
3282 if (! (rhs_nc == 1 && rhs_nr == ilen))
3283 {
3284 ::error ("A(%s) = X: where A is a column vector, X must also be", rm);
3285 ::error ("a column vector with the same number of elements as %s", rm);
3286 }
3287 }
3288 else
3289 panic_impossible ();
3290 }
3291
3292 /*
3293 * Assignment to a vector with an integer index.
3294 */
3295 void
3296 tree_constant_rep::do_vector_assign (tree_constant& rhs, int i)
3297 {
3298 int rhs_nr = rhs.rows ();
3299 int rhs_nc = rhs.columns ();
3300
3301 if (indexed_assign_conforms (1, 1, rhs_nr, rhs_nc))
3302 {
3303 maybe_resize (i);
3304 if (error_state)
3305 return;
3306
3307 int nr = rows ();
3308 int nc = columns ();
3309
3310 if (nr == 1)
3311 {
3312 REP_ELEM_ASSIGN (0, i, rhs.double_value (), rhs.complex_value (),
3313 rhs.is_real_type ());
3314 }
3315 else if (nc == 1)
3316 {
3317 REP_ELEM_ASSIGN (i, 0, rhs.double_value (), rhs.complex_value (),
3318 rhs.is_real_type ());
3319 }
3320 else
3321 panic_impossible ();
3322 }
3323 else if (rhs_nr == 0 && rhs_nc == 0)
3324 {
3325 int nr = rows ();
3326 int nc = columns ();
3327
3328 int len = MAX (nr, nc);
3329
3330 if (i < 0 || i >= len)
3331 {
3332 ::error ("A(int) = []: index out of range");
3333 return;
3334 }
3335
3336 if (nr == 1)
3337 delete_column (i);
3338 else if (nc == 1)
3339 delete_row (i);
3340 else
3341 panic_impossible ();
3342 }
3343 else
3344 {
3345 ::error ("for A(int) = X: X must be a scalar");
3346 return;
3347 }
3348 }
3349
3350 /*
3351 * Assignment to a vector with a vector index.
3352 */
3353 void
3354 tree_constant_rep::do_vector_assign (tree_constant& rhs, idx_vector& iv)
3355 {
3356 if (rhs.is_zero_by_zero ())
3357 {
3358 int nr = rows ();
3359 int nc = columns ();
3360
3361 int len = MAX (nr, nc);
3362
3363 if (iv.max () >= len)
3364 {
3365 ::error ("A(matrix) = []: index out of range");
3366 return;
3367 }
3368
3369 if (nr == 1)
3370 delete_columns (iv);
3371 else if (nc == 1)
3372 delete_rows (iv);
3373 else
3374 panic_impossible ();
3375 }
3376 else if (rhs.is_scalar_type ())
3377 {
3378 int nr = rows ();
3379 int nc = columns ();
3380
3381 if (iv.capacity () == 1)
3382 {
3383 int idx = iv.elem (0);
3384
3385 if (nr == 1)
3386 {
3387 REP_ELEM_ASSIGN (0, idx, rhs.double_value (),
3388 rhs.complex_value (), rhs.is_real_type ());
3389 }
3390 else if (nc == 1)
3391 {
3392 REP_ELEM_ASSIGN (idx, 0, rhs.double_value (),
3393 rhs.complex_value (), rhs.is_real_type ());
3394 }
3395 else
3396 panic_impossible ();
3397 }
3398 else
3399 {
3400 if (nr == 1)
3401 {
3402 ::error ("A(matrix) = X: where A is a row vector, X must also be a");
3403 ::error ("row vector with the same number of elements as matrix");
3404 }
3405 else if (nc == 1)
3406 {
3407 ::error ("A(matrix) = X: where A is a column vector, X must also be a");
3408 ::error ("column vector with the same number of elements as matrix");
3409 }
3410 else
3411 panic_impossible ();
3412 }
3413 }
3414 else if (rhs.is_matrix_type ())
3415 {
3416 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
3417
3418 int ilen = iv.capacity ();
3419 check_vector_assign (rhs_nr, rhs_nc, ilen, "matrix");
3420 if (error_state)
3421 return;
3422
3423 force_orient f_orient = no_orient;
3424 if (rhs_nr == 1 && rhs_nc != 1)
3425 f_orient = row_orient;
3426 else if (rhs_nc == 1 && rhs_nr != 1)
3427 f_orient = column_orient;
3428
3429 maybe_resize (iv.max (), f_orient);
3430 if (error_state)
3431 return;
3432
3433 int nr = rows ();
3434 int nc = columns ();
3435
3436 if (nr == 1)
3437 {
3438 for (int i = 0; i < iv.capacity (); i++)
3439 REP_ELEM_ASSIGN (0, iv.elem (i), rhs_m.elem (0, i),
3440 rhs_cm.elem (0, i), rhs.is_real_type ());
3441 }
3442 else if (nc == 1)
3443 {
3444 for (int i = 0; i < iv.capacity (); i++)
3445 REP_ELEM_ASSIGN (iv.elem (i), 0, rhs_m.elem (i, 0),
3446 rhs_cm.elem (i, 0), rhs.is_real_type ());
3447 }
3448 else
3449 panic_impossible ();
3450 }
3451 else
3452 panic_impossible ();
3453 }
3454
3455 /*
3456 * Assignment to a vector with a range index.
3457 */
3458 void
3459 tree_constant_rep::do_vector_assign (tree_constant& rhs, Range& ri)
3460 {
3461 if (rhs.is_zero_by_zero ())
3462 {
3463 int nr = rows ();
3464 int nc = columns ();
3465
3466 int len = MAX (nr, nc);
3467
3468 int b = tree_to_mat_idx (ri.min ());
3469 int l = tree_to_mat_idx (ri.max ());
3470 if (b < 0 || l >= len)
3471 {
3472 ::error ("A(range) = []: index out of range");
3473 return;
3474 }
3475
3476 if (nr == 1)
3477 delete_columns (ri);
3478 else if (nc == 1)
3479 delete_rows (ri);
3480 else
3481 panic_impossible ();
3482 }
3483 else if (rhs.is_scalar_type ())
3484 {
3485 int nr = rows ();
3486 int nc = columns ();
3487
3488 if (nr == 1)
3489 {
3490 ::error ("A(range) = X: where A is a row vector, X must also be a");
3491 ::error ("row vector with the same number of elements as range");
3492 }
3493 else if (nc == 1)
3494 {
3495 ::error ("A(range) = X: where A is a column vector, X must also be a");
3496 ::error ("column vector with the same number of elements as range");
3497 }
3498 else
3499 panic_impossible ();
3500 }
3501 else if (rhs.is_matrix_type ())
3502 {
3503 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
3504
3505 int ilen = ri.nelem ();
3506 check_vector_assign (rhs_nr, rhs_nc, ilen, "range");
3507 if (error_state)
3508 return;
3509
3510 force_orient f_orient = no_orient;
3511 if (rhs_nr == 1 && rhs_nc != 1)
3512 f_orient = row_orient;
3513 else if (rhs_nc == 1 && rhs_nr != 1)
3514 f_orient = column_orient;
3515
3516 maybe_resize (tree_to_mat_idx (ri.max ()), f_orient);
3517 if (error_state)
3518 return;
3519
3520 int nr = rows ();
3521 int nc = columns ();
3522
3523 double b = ri.base ();
3524 double increment = ri.inc ();
3525
3526 if (nr == 1)
3527 {
3528 for (int i = 0; i < ri.nelem (); i++)
3529 {
3530 double tmp = b + i * increment;
3531 int col = tree_to_mat_idx (tmp);
3532 REP_ELEM_ASSIGN (0, col, rhs_m.elem (0, i), rhs_cm.elem (0, i),
3533 rhs.is_real_type ());
3534 }
3535 }
3536 else if (nc == 1)
3537 {
3538 for (int i = 0; i < ri.nelem (); i++)
3539 {
3540 double tmp = b + i * increment;
3541 int row = tree_to_mat_idx (tmp);
3542 REP_ELEM_ASSIGN (row, 0, rhs_m.elem (i, 0), rhs_cm.elem (i, 0),
3543 rhs.is_real_type ());
3544 }
3545 }
3546 else
3547 panic_impossible ();
3548 }
3549 else
3550 panic_impossible ();
3551 }
3552
3553 /*
3554 * Matrix assignment indexed by two values. This function determines
3555 * the type of the first arugment, checks as much as possible, and
3556 * then calls one of a set of functions to handle the specific cases:
3557 *
3558 * M (integer, arg2) = RHS (MA1)
3559 * M (vector, arg2) = RHS (MA2)
3560 * M (range, arg2) = RHS (MA3)
3561 * M (colon, arg2) = RHS (MA4)
3562 *
3563 * Each of those functions determines the type of the second argument
3564 * and calls another function to handle the real work of doing the
3565 * assignment.
3566 */
3567 void
3568 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
3569 tree_constant& i_arg,
3570 tree_constant& j_arg)
3571 {
3572 tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic ();
3573
3574 tree_constant_rep::constant_type itype = tmp_i.const_type ();
3575
3576 switch (itype)
3577 {
3578 case complex_scalar_constant:
3579 case scalar_constant:
3580 {
3581 int i = tree_to_mat_idx (tmp_i.double_value ());
3582 if (index_check (i, "row") < 0)
3583 return;
3584 do_matrix_assignment (rhs, i, j_arg);
3585 }
3586 break;
3587 case complex_matrix_constant:
3588 case matrix_constant:
3589 {
3590 Matrix mi = tmp_i.matrix_value ();
3591 idx_vector iv (mi, user_pref.do_fortran_indexing, "row", rows ());
3592 if (! iv)
3593 return;
3594
3595 do_matrix_assignment (rhs, iv, j_arg);
3596 }
3597 break;
3598 case string_constant:
3599 gripe_string_invalid ();
3600 break;
3601 case range_constant:
3602 {
3603 Range ri = tmp_i.range_value ();
3604 int nr = rows ();
3605 if (nr == 2 && is_zero_one (ri))
3606 {
3607 do_matrix_assignment (rhs, 1, j_arg);
3608 }
3609 else if (nr == 2 && is_one_zero (ri))
3610 {
3611 do_matrix_assignment (rhs, 0, j_arg);
3612 }
3613 else
3614 {
3615 if (index_check (ri, "row") < 0)
3616 return;
3617 do_matrix_assignment (rhs, ri, j_arg);
3618 }
3619 }
3620 break;
3621 case magic_colon:
3622 do_matrix_assignment (rhs, magic_colon, j_arg);
3623 break;
3624 default:
3625 panic_impossible ();
3626 break;
3627 }
3628 }
3629
3630 /* MA1 */
3631 void
3632 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i,
3633 tree_constant& j_arg)
3634 {
3635 tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
3636
3637 tree_constant_rep::constant_type jtype = tmp_j.const_type ();
3638
3639 int rhs_nr = rhs.rows ();
3640 int rhs_nc = rhs.columns ();
3641
3642 switch (jtype)
3643 {
3644 case complex_scalar_constant:
3645 case scalar_constant:
3646 {
3647 int j = tree_to_mat_idx (tmp_j.double_value ());
3648 if (index_check (j, "column") < 0)
3649 return;
3650 if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc))
3651 {
3652 ::error ("A(int,int) = X, X must be a scalar");
3653 return;
3654 }
3655 maybe_resize (i, j);
3656 if (error_state)
3657 return;
3658
3659 do_matrix_assignment (rhs, i, j);
3660 }
3661 break;
3662 case complex_matrix_constant:
3663 case matrix_constant:
3664 {
3665 Matrix mj = tmp_j.matrix_value ();
3666 idx_vector jv (mj, user_pref.do_fortran_indexing, "column",
3667 columns ());
3668 if (! jv)
3669 return;
3670
3671 if (! indexed_assign_conforms (1, jv.capacity (), rhs_nr, rhs_nc))
3672 {
3673 ::error ("A(int,matrix) = X: X must be a row vector with the same");
3674 ::error ("number of elements as matrix");
3675 return;
3676 }
3677 maybe_resize (i, jv.max ());
3678 if (error_state)
3679 return;
3680
3681 do_matrix_assignment (rhs, i, jv);
3682 }
3683 break;
3684 case string_constant:
3685 gripe_string_invalid ();
3686 break;
3687 case range_constant:
3688 {
3689 Range rj = tmp_j.range_value ();
3690 if (! indexed_assign_conforms (1, rj.nelem (), rhs_nr, rhs_nc))
3691 {
3692 ::error ("A(int,range) = X: X must be a row vector with the same");
3693 ::error ("number of elements as range");
3694 return;
3695 }
3696
3697 int nc = columns ();
3698 if (nc == 2 && is_zero_one (rj) && rhs_nc == 1)
3699 {
3700 do_matrix_assignment (rhs, i, 1);
3701 }
3702 else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1)
3703 {
3704 do_matrix_assignment (rhs, i, 0);
3705 }
3706 else
3707 {
3708 if (index_check (rj, "column") < 0)
3709 return;
3710 maybe_resize (i, tree_to_mat_idx (rj.max ()));
3711 if (error_state)
3712 return;
3713
3714 do_matrix_assignment (rhs, i, rj);
3715 }
3716 }
3717 break;
3718 case magic_colon:
3719 {
3720 int nc = columns ();
3721 int nr = rows ();
3722 if (nc == 0 && nr == 0 && rhs_nr == 1)
3723 {
3724 if (rhs.is_complex_type ())
3725 {
3726 complex_matrix = new ComplexMatrix ();
3727 type_tag = complex_matrix_constant;
3728 }
3729 else
3730 {
3731 matrix = new Matrix ();
3732 type_tag = matrix_constant;
3733 }
3734 maybe_resize (i, rhs_nc-1);
3735 if (error_state)
3736 return;
3737 }
3738 else if (indexed_assign_conforms (1, nc, rhs_nr, rhs_nc))
3739 {
3740 maybe_resize (i, nc-1);
3741 if (error_state)
3742 return;
3743 }
3744 else if (rhs_nr == 0 && rhs_nc == 0)
3745 {
3746 if (i < 0 || i >= nr)
3747 {
3748 ::error ("A(int,:) = []: row index out of range");
3749 return;
3750 }
3751 }
3752 else
3753 {
3754 ::error ("A(int,:) = X: X must be a row vector with the same");
3755 ::error ("number of columns as A");
3756 return;
3757 }
3758
3759 do_matrix_assignment (rhs, i, magic_colon);
3760 }
3761 break;
3762 default:
3763 panic_impossible ();
3764 break;
3765 }
3766 }
3767
3768 /* MA2 */
3769 void
3770 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, idx_vector& iv,
3771 tree_constant& j_arg)
3772 {
3773 tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
3774
3775 tree_constant_rep::constant_type jtype = tmp_j.const_type ();
3776
3777 int rhs_nr = rhs.rows ();
3778 int rhs_nc = rhs.columns ();
3779
3780 switch (jtype)
3781 {
3782 case complex_scalar_constant:
3783 case scalar_constant:
3784 {
3785 int j = tree_to_mat_idx (tmp_j.double_value ());
3786 if (index_check (j, "column") < 0)
3787 return;
3788 if (! indexed_assign_conforms (iv.capacity (), 1, rhs_nr, rhs_nc))
3789 {
3790 ::error ("A(matrix,int) = X: X must be a column vector with the");
3791 ::error ("same number of elements as matrix");
3792 return;
3793 }
3794 maybe_resize (iv.max (), j);
3795 if (error_state)
3796 return;
3797
3798 do_matrix_assignment (rhs, iv, j);
3799 }
3800 break;
3801 case complex_matrix_constant:
3802 case matrix_constant:
3803 {
3804 Matrix mj = tmp_j.matrix_value ();
3805 idx_vector jv (mj, user_pref.do_fortran_indexing, "column",
3806 columns ());
3807 if (! jv)
3808 return;
3809
3810 if (! indexed_assign_conforms (iv.capacity (), jv.capacity (),
3811 rhs_nr, rhs_nc))
3812 {
3813 ::error ("A(r_mat,c_mat) = X: the number of rows in X must match");
3814 ::error ("the number of elements in r_mat and the number of");
3815 ::error ("columns in X must match the number of elements in c_mat");
3816 return;
3817 }
3818 maybe_resize (iv.max (), jv.max ());
3819 if (error_state)
3820 return;
3821
3822 do_matrix_assignment (rhs, iv, jv);
3823 }
3824 break;
3825 case string_constant:
3826 gripe_string_invalid ();
3827 break;
3828 case range_constant:
3829 {
3830 Range rj = tmp_j.range_value ();
3831 if (! indexed_assign_conforms (iv.capacity (), rj.nelem (),
3832 rhs_nr, rhs_nc))
3833 {
3834 ::error ("A(matrix,range) = X: the number of rows in X must match");
3835 ::error ("the number of elements in matrix and the number of");
3836 ::error ("columns in X must match the number of elements in range");
3837 return;
3838 }
3839
3840 int nc = columns ();
3841 if (nc == 2 && is_zero_one (rj) && rhs_nc == 1)
3842 {
3843 do_matrix_assignment (rhs, iv, 1);
3844 }
3845 else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1)
3846 {
3847 do_matrix_assignment (rhs, iv, 0);
3848 }
3849 else
3850 {
3851 if (index_check (rj, "column") < 0)
3852 return;
3853 maybe_resize (iv.max (), tree_to_mat_idx (rj.max ()));
3854 if (error_state)
3855 return;
3856
3857 do_matrix_assignment (rhs, iv, rj);
3858 }
3859 }
3860 break;
3861 case magic_colon:
3862 {
3863 int nc = columns ();
3864 int new_nc = nc;
3865 if (nc == 0)
3866 new_nc = rhs_nc;
3867
3868 if (indexed_assign_conforms (iv.capacity (), new_nc,
3869 rhs_nr, rhs_nc))
3870 {
3871 maybe_resize (iv.max (), new_nc-1);
3872 if (error_state)
3873 return;
3874 }
3875 else if (rhs_nr == 0 && rhs_nc == 0)
3876 {
3877 if (iv.max () >= rows ())
3878 {
3879 ::error ("A(matrix,:) = []: row index out of range");
3880 return;
3881 }
3882 }
3883 else
3884 {
3885 ::error ("A(matrix,:) = X: the number of rows in X must match the");
3886 ::error ("number of elements in matrix, and the number of columns");
3887 ::error ("in X must match the number of columns in A");
3888 return;
3889 }
3890
3891 do_matrix_assignment (rhs, iv, magic_colon);
3892 }
3893 break;
3894 default:
3895 panic_impossible ();
3896 break;
3897 }
3898 }
3899
3900 /* MA3 */
3901 void
3902 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
3903 Range& ri, tree_constant& j_arg)
3904 {
3905 tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
3906
3907 tree_constant_rep::constant_type jtype = tmp_j.const_type ();
3908
3909 int rhs_nr = rhs.rows ();
3910 int rhs_nc = rhs.columns ();
3911
3912 switch (jtype)
3913 {
3914 case complex_scalar_constant:
3915 case scalar_constant:
3916 {
3917 int j = tree_to_mat_idx (tmp_j.double_value ());
3918 if (index_check (j, "column") < 0)
3919 return;
3920 if (! indexed_assign_conforms (ri.nelem (), 1, rhs_nr, rhs_nc))
3921 {
3922 ::error ("A(range,int) = X: X must be a column vector with the");
3923 ::error ("same number of elements as range");
3924 return;
3925 }
3926 maybe_resize (tree_to_mat_idx (ri.max ()), j);
3927 if (error_state)
3928 return;
3929
3930 do_matrix_assignment (rhs, ri, j);
3931 }
3932 break;
3933 case complex_matrix_constant:
3934 case matrix_constant:
3935 {
3936 Matrix mj = tmp_j.matrix_value ();
3937 idx_vector jv (mj, user_pref.do_fortran_indexing, "column",
3938 columns ());
3939 if (! jv)
3940 return;
3941
3942 if (! indexed_assign_conforms (ri.nelem (), jv.capacity (),
3943 rhs_nr, rhs_nc))
3944 {
3945 ::error ("A(range,matrix) = X: the number of rows in X must match");
3946 ::error ("the number of elements in range and the number of");
3947 ::error ("columns in X must match the number of elements in matrix");
3948 return;
3949 }
3950 maybe_resize (tree_to_mat_idx (ri.max ()), jv.max ());
3951 if (error_state)
3952 return;
3953
3954 do_matrix_assignment (rhs, ri, jv);
3955 }
3956 break;
3957 case string_constant:
3958 gripe_string_invalid ();
3959 break;
3960 case range_constant:
3961 {
3962 Range rj = tmp_j.range_value ();
3963 if (! indexed_assign_conforms (ri.nelem (), rj.nelem (),
3964 rhs_nr, rhs_nc))
3965 {
3966 ::error ("A(r_range,c_range) = X: the number of rows in X must");
3967 ::error ("match the number of elements in r_range and the number");
3968 ::error ("of columns in X must match the number of elements in");
3969 ::error ("c_range");
3970 return;
3971 }
3972
3973 int nc = columns ();
3974 if (nc == 2 && is_zero_one (rj) && rhs_nc == 1)
3975 {
3976 do_matrix_assignment (rhs, ri, 1);
3977 }
3978 else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1)
3979 {
3980 do_matrix_assignment (rhs, ri, 0);
3981 }
3982 else
3983 {
3984 if (index_check (rj, "column") < 0)
3985 return;
3986
3987 maybe_resize (tree_to_mat_idx (ri.max ()),
3988 tree_to_mat_idx (rj.max ()));
3989
3990 if (error_state)
3991 return;
3992
3993 do_matrix_assignment (rhs, ri, rj);
3994 }
3995 }
3996 break;
3997 case magic_colon:
3998 {
3999 int nc = columns ();
4000 int new_nc = nc;
4001 if (nc == 0)
4002 new_nc = rhs_nc;
4003
4004 if (indexed_assign_conforms (ri.nelem (), new_nc, rhs_nr, rhs_nc))
4005 {
4006 maybe_resize (tree_to_mat_idx (ri.max ()), new_nc-1);
4007 if (error_state)
4008 return;
4009 }
4010 else if (rhs_nr == 0 && rhs_nc == 0)
4011 {
4012 int b = tree_to_mat_idx (ri.min ());
4013 int l = tree_to_mat_idx (ri.max ());
4014 if (b < 0 || l >= rows ())
4015 {
4016 ::error ("A(range,:) = []: row index out of range");
4017 return;
4018 }
4019 }
4020 else
4021 {
4022 ::error ("A(range,:) = X: the number of rows in X must match the");
4023 ::error ("number of elements in range, and the number of columns");
4024 ::error ("in X must match the number of columns in A");
4025 return;
4026 }
4027
4028 do_matrix_assignment (rhs, ri, magic_colon);
4029 }
4030 break;
4031 default:
4032 panic_impossible ();
4033 break;
4034 }
4035 }
4036
4037 /* MA4 */
4038 void
4039 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
4040 tree_constant_rep::constant_type i,
4041 tree_constant& j_arg)
4042 {
4043 tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
4044
4045 tree_constant_rep::constant_type jtype = tmp_j.const_type ();
4046
4047 int rhs_nr = rhs.rows ();
4048 int rhs_nc = rhs.columns ();
4049
4050 switch (jtype)
4051 {
4052 case complex_scalar_constant:
4053 case scalar_constant:
4054 {
4055 int j = tree_to_mat_idx (tmp_j.double_value ());
4056 if (index_check (j, "column") < 0)
4057 return;
4058 int nr = rows ();
4059 int nc = columns ();
4060 if (nr == 0 && nc == 0 && rhs_nc == 1)
4061 {
4062 if (rhs.is_complex_type ())
4063 {
4064 complex_matrix = new ComplexMatrix ();
4065 type_tag = complex_matrix_constant;
4066 }
4067 else
4068 {
4069 matrix = new Matrix ();
4070 type_tag = matrix_constant;
4071 }
4072 maybe_resize (rhs_nr-1, j);
4073 if (error_state)
4074 return;
4075 }
4076 else if (indexed_assign_conforms (nr, 1, rhs_nr, rhs_nc))
4077 {
4078 maybe_resize (nr-1, j);
4079 if (error_state)
4080 return;
4081 }
4082 else if (rhs_nr == 0 && rhs_nc == 0)
4083 {
4084 if (j < 0 || j >= nc)
4085 {
4086 ::error ("A(:,int) = []: column index out of range");
4087 return;
4088 }
4089 }
4090 else
4091 {
4092 ::error ("A(:,int) = X: X must be a column vector with the same");
4093 ::error ("number of rows as A");
4094 return;
4095 }
4096
4097 do_matrix_assignment (rhs, magic_colon, j);
4098 }
4099 break;
4100 case complex_matrix_constant:
4101 case matrix_constant:
4102 {
4103 Matrix mj = tmp_j.matrix_value ();
4104 idx_vector jv (mj, user_pref.do_fortran_indexing, "column",
4105 columns ());
4106 if (! jv)
4107 return;
4108
4109 int nr = rows ();
4110 int new_nr = nr;
4111 if (nr == 0)
4112 new_nr = rhs_nr;
4113
4114 if (indexed_assign_conforms (new_nr, jv.capacity (),
4115 rhs_nr, rhs_nc))
4116 {
4117 maybe_resize (new_nr-1, jv.max ());
4118 if (error_state)
4119 return;
4120 }
4121 else if (rhs_nr == 0 && rhs_nc == 0)
4122 {
4123 if (jv.max () >= columns ())
4124 {
4125 ::error ("A(:,matrix) = []: column index out of range");
4126 return;
4127 }
4128 }
4129 else
4130 {
4131 ::error ("A(:,matrix) = X: the number of rows in X must match the");
4132 ::error ("number of rows in A, and the number of columns in X must");
4133 ::error ("match the number of elements in matrix");
4134 return;
4135 }
4136
4137 do_matrix_assignment (rhs, magic_colon, jv);
4138 }
4139 break;
4140 case string_constant:
4141 gripe_string_invalid ();
4142 break;
4143 case range_constant:
4144 {
4145 Range rj = tmp_j.range_value ();
4146 int nr = rows ();
4147 int new_nr = nr;
4148 if (nr == 0)
4149 new_nr = rhs_nr;
4150
4151 if (indexed_assign_conforms (new_nr, rj.nelem (), rhs_nr, rhs_nc))
4152 {
4153 int nc = columns ();
4154 if (nc == 2 && is_zero_one (rj) && rhs_nc == 1)
4155 {
4156 do_matrix_assignment (rhs, magic_colon, 1);
4157 }
4158 else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1)
4159 {
4160 do_matrix_assignment (rhs, magic_colon, 0);
4161 }
4162 else
4163 {
4164 if (index_check (rj, "column") < 0)
4165 return;
4166 maybe_resize (new_nr-1, tree_to_mat_idx (rj.max ()));
4167 if (error_state)
4168 return;
4169 }
4170 }
4171 else if (rhs_nr == 0 && rhs_nc == 0)
4172 {
4173 int b = tree_to_mat_idx (rj.min ());
4174 int l = tree_to_mat_idx (rj.max ());
4175 if (b < 0 || l >= columns ())
4176 {
4177 ::error ("A(:,range) = []: column index out of range");
4178 return;
4179 }
4180 }
4181 else
4182 {
4183 ::error ("A(:,range) = X: the number of rows in X must match the");
4184 ::error ("number of rows in A, and the number of columns in X");
4185 ::error ("must match the number of elements in range");
4186 return;
4187 }
4188
4189 do_matrix_assignment (rhs, magic_colon, rj);
4190 }
4191 break;
4192 case magic_colon:
4193 // a(:,:) = foo is equivalent to a = foo.
4194 do_matrix_assignment (rhs, magic_colon, magic_colon);
4195 break;
4196 default:
4197 panic_impossible ();
4198 break;
4199 }
4200 }
4201
4202 /*
4203 * Functions that actually handle assignment to a matrix using two
4204 * index values.
4205 *
4206 * idx2
4207 * +---+---+----+----+
4208 * idx1 | i | v | r | c |
4209 * ---------+---+---+----+----+
4210 * integer | 1 | 5 | 9 | 13 |
4211 * ---------+---+---+----+----+
4212 * vector | 2 | 6 | 10 | 14 |
4213 * ---------+---+---+----+----+
4214 * range | 3 | 7 | 11 | 15 |
4215 * ---------+---+---+----+----+
4216 * colon | 4 | 8 | 12 | 16 |
4217 * ---------+---+---+----+----+
4218 */
4219
4220 /* 1 */
4221 void
4222 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, int j)
4223 {
4224 REP_ELEM_ASSIGN (i, j, rhs.double_value (), rhs.complex_value (),
4225 rhs.is_real_type ());
4226 }
4227
4228 /* 2 */
4229 void
4230 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i,
4231 idx_vector& jv)
4232 {
4233 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4234
4235 for (int j = 0; j < jv.capacity (); j++)
4236 REP_ELEM_ASSIGN (i, jv.elem (j), rhs_m.elem (0, j),
4237 rhs_cm.elem (0, j), rhs.is_real_type ());
4238 }
4239
4240 /* 3 */
4241 void
4242 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i, Range& rj)
4243 {
4244 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4245
4246 double b = rj.base ();
4247 double increment = rj.inc ();
4248
4249 for (int j = 0; j < rj.nelem (); j++)
4250 {
4251 double tmp = b + j * increment;
4252 int col = tree_to_mat_idx (tmp);
4253 REP_ELEM_ASSIGN (i, col, rhs_m.elem (0, j), rhs_cm.elem (0, j),
4254 rhs.is_real_type ());
4255 }
4256 }
4257
4258 /* 4 */
4259 void
4260 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, int i,
4261 tree_constant_rep::constant_type mcj)
4262 {
4263 assert (mcj == magic_colon);
4264
4265 int nc = columns ();
4266
4267 if (rhs.is_zero_by_zero ())
4268 {
4269 delete_row (i);
4270 }
4271 else if (rhs.is_matrix_type ())
4272 {
4273 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4274
4275 for (int j = 0; j < nc; j++)
4276 REP_ELEM_ASSIGN (i, j, rhs_m.elem (0, j), rhs_cm.elem (0, j),
4277 rhs.is_real_type ());
4278 }
4279 else if (rhs.is_scalar_type () && nc == 1)
4280 {
4281 REP_ELEM_ASSIGN (i, 0, rhs.double_value (),
4282 rhs.complex_value (), rhs.is_real_type ());
4283 }
4284 else
4285 panic_impossible ();
4286 }
4287
4288 /* 5 */
4289 void
4290 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
4291 idx_vector& iv, int j)
4292 {
4293 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4294
4295 for (int i = 0; i < iv.capacity (); i++)
4296 {
4297 int row = iv.elem (i);
4298 REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, 0),
4299 rhs_cm.elem (i, 0), rhs.is_real_type ());
4300 }
4301 }
4302
4303 /* 6 */
4304 void
4305 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
4306 idx_vector& iv, idx_vector& jv)
4307 {
4308 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4309
4310 for (int i = 0; i < iv.capacity (); i++)
4311 {
4312 int row = iv.elem (i);
4313 for (int j = 0; j < jv.capacity (); j++)
4314 {
4315 int col = jv.elem (j);
4316 REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j),
4317 rhs_cm.elem (i, j), rhs.is_real_type ());
4318 }
4319 }
4320 }
4321
4322 /* 7 */
4323 void
4324 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
4325 idx_vector& iv, Range& rj)
4326 {
4327 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4328
4329 double b = rj.base ();
4330 double increment = rj.inc ();
4331
4332 for (int i = 0; i < iv.capacity (); i++)
4333 {
4334 int row = iv.elem (i);
4335 for (int j = 0; j < rj.nelem (); j++)
4336 {
4337 double tmp = b + j * increment;
4338 int col = tree_to_mat_idx (tmp);
4339 REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j),
4340 rhs_cm.elem (i, j), rhs.is_real_type ());
4341 }
4342 }
4343 }
4344
4345 /* 8 */
4346 void
4347 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, idx_vector& iv,
4348 tree_constant_rep::constant_type mcj)
4349 {
4350 assert (mcj == magic_colon);
4351
4352 if (rhs.is_zero_by_zero ())
4353 {
4354 delete_rows (iv);
4355 }
4356 else
4357 {
4358 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4359
4360 int nc = columns ();
4361
4362 for (int j = 0; j < nc; j++)
4363 {
4364 for (int i = 0; i < iv.capacity (); i++)
4365 {
4366 int row = iv.elem (i);
4367 REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, j),
4368 rhs_cm.elem (i, j), rhs.is_real_type ());
4369 }
4370 }
4371 }
4372 }
4373
4374 /* 9 */
4375 void
4376 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri, int j)
4377 {
4378 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4379
4380 double b = ri.base ();
4381 double increment = ri.inc ();
4382
4383 for (int i = 0; i < ri.nelem (); i++)
4384 {
4385 double tmp = b + i * increment;
4386 int row = tree_to_mat_idx (tmp);
4387 REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, 0),
4388 rhs_cm.elem (i, 0), rhs.is_real_type ());
4389 }
4390 }
4391
4392 /* 10 */
4393 void
4394 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri,
4395 idx_vector& jv)
4396 {
4397 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4398
4399 double b = ri.base ();
4400 double increment = ri.inc ();
4401
4402 for (int j = 0; j < jv.capacity (); j++)
4403 {
4404 int col = jv.elem (j);
4405 for (int i = 0; i < ri.nelem (); i++)
4406 {
4407 double tmp = b + i * increment;
4408 int row = tree_to_mat_idx (tmp);
4409 REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j),
4410 rhs_m.elem (i, j), rhs.is_real_type ());
4411 }
4412 }
4413 }
4414
4415 /* 11 */
4416 void
4417 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri,
4418 Range& rj)
4419 {
4420 double ib = ri.base ();
4421 double iinc = ri.inc ();
4422 double jb = rj.base ();
4423 double jinc = rj.inc ();
4424
4425 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4426
4427 for (int i = 0; i < ri.nelem (); i++)
4428 {
4429 double itmp = ib + i * iinc;
4430 int row = tree_to_mat_idx (itmp);
4431 for (int j = 0; j < rj.nelem (); j++)
4432 {
4433 double jtmp = jb + j * jinc;
4434 int col = tree_to_mat_idx (jtmp);
4435 REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j),
4436 rhs_cm.elem (i, j), rhs.is_real_type ());
4437 }
4438 }
4439 }
4440
4441 /* 12 */
4442 void
4443 tree_constant_rep::do_matrix_assignment (tree_constant& rhs, Range& ri,
4444 tree_constant_rep::constant_type mcj)
4445 {
4446 assert (mcj == magic_colon);
4447
4448 if (rhs.is_zero_by_zero ())
4449 {
4450 delete_rows (ri);
4451 }
4452 else
4453 {
4454 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4455
4456 double ib = ri.base ();
4457 double iinc = ri.inc ();
4458
4459 int nc = columns ();
4460
4461 for (int i = 0; i < ri.nelem (); i++)
4462 {
4463 double itmp = ib + i * iinc;
4464 int row = tree_to_mat_idx (itmp);
4465 for (int j = 0; j < nc; j++)
4466 REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, j),
4467 rhs_cm.elem (i, j), rhs.is_real_type ());
4468 }
4469 }
4470 }
4471
4472 /* 13 */
4473 void
4474 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
4475 tree_constant_rep::constant_type mci,
4476 int j)
4477 {
4478 assert (mci == magic_colon);
4479
4480 int nr = rows ();
4481
4482 if (rhs.is_zero_by_zero ())
4483 {
4484 delete_column (j);
4485 }
4486 else if (rhs.is_matrix_type ())
4487 {
4488 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4489
4490 for (int i = 0; i < nr; i++)
4491 REP_ELEM_ASSIGN (i, j, rhs_m.elem (i, 0),
4492 rhs_cm.elem (i, 0), rhs.is_real_type ());
4493 }
4494 else if (rhs.is_scalar_type () && nr == 1)
4495 {
4496 REP_ELEM_ASSIGN (0, j, rhs.double_value (),
4497 rhs.complex_value (), rhs.is_real_type ());
4498 }
4499 else
4500 panic_impossible ();
4501 }
4502
4503 /* 14 */
4504 void
4505 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
4506 tree_constant_rep::constant_type mci,
4507 idx_vector& jv)
4508 {
4509 assert (mci == magic_colon);
4510
4511 if (rhs.is_zero_by_zero ())
4512 {
4513 delete_columns (jv);
4514 }
4515 else
4516 {
4517 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4518
4519 int nr = rows ();
4520
4521 for (int i = 0; i < nr; i++)
4522 {
4523 for (int j = 0; j < jv.capacity (); j++)
4524 {
4525 int col = jv.elem (j);
4526 REP_ELEM_ASSIGN (i, col, rhs_m.elem (i, j),
4527 rhs_cm.elem (i, j), rhs.is_real_type ());
4528 }
4529 }
4530 }
4531 }
4532
4533 /* 15 */
4534 void
4535 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
4536 tree_constant_rep::constant_type mci,
4537 Range& rj)
4538 {
4539 assert (mci == magic_colon);
4540
4541 if (rhs.is_zero_by_zero ())
4542 {
4543 delete_columns (rj);
4544 }
4545 else
4546 {
4547 REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
4548
4549 int nr = rows ();
4550
4551 double jb = rj.base ();
4552 double jinc = rj.inc ();
4553
4554 for (int j = 0; j < rj.nelem (); j++)
4555 {
4556 double jtmp = jb + j * jinc;
4557 int col = tree_to_mat_idx (jtmp);
4558 for (int i = 0; i < nr; i++)
4559 {
4560 REP_ELEM_ASSIGN (i, col, rhs_m.elem (i, j),
4561 rhs_cm.elem (i, j), rhs.is_real_type ());
4562 }
4563 }
4564 }
4565 }
4566
4567 /* 16 */
4568 void
4569 tree_constant_rep::do_matrix_assignment (tree_constant& rhs,
4570 tree_constant_rep::constant_type mci,
4571 tree_constant_rep::constant_type mcj)
4572 {
4573 assert (mci == magic_colon && mcj == magic_colon);
4574
4575 switch (type_tag)
4576 {
4577 case scalar_constant:
4578 break;
4579 case matrix_constant:
4580 delete matrix;
4581 break;
4582 case complex_scalar_constant:
4583 delete complex_scalar;
4584 break;
4585 case complex_matrix_constant:
4586 delete complex_matrix;
4587 break;
4588 case string_constant:
4589 delete [] string;
4590 break;
4591 case range_constant:
4592 delete range;
4593 break;
4594 case magic_colon:
4595 default:
4596 panic_impossible ();
4597 break;
4598 }
4599
4600 type_tag = rhs.const_type ();
4601
4602 switch (type_tag)
4603 {
4604 case scalar_constant:
4605 scalar = rhs.double_value ();
4606 break;
4607 case matrix_constant:
4608 matrix = new Matrix (rhs.matrix_value ());
4609 break;
4610 case string_constant:
4611 string = strsave (rhs.string_value ());
4612 break;
4613 case complex_matrix_constant:
4614 complex_matrix = new ComplexMatrix (rhs.complex_matrix_value ());
4615 break;
4616 case complex_scalar_constant:
4617 complex_scalar = new Complex (rhs.complex_value ());
4618 break;
4619 case range_constant:
4620 range = new Range (rhs.range_value ());
4621 break;
4622 case magic_colon:
4623 default:
4624 panic_impossible ();
4625 break;
4626 }
4627 }
4628
4629 /*
4630 * Functions for deleting rows or columns of a matrix. These are used
4631 * to handle statements like
4632 *
4633 * M (i, j) = []
4634 */
4635 void
4636 tree_constant_rep::delete_row (int idx)
4637 {
4638 if (type_tag == matrix_constant)
4639 {
4640 int nr = matrix->rows ();
4641 int nc = matrix->columns ();
4642 Matrix *new_matrix = new Matrix (nr-1, nc);
4643 int ii = 0;
4644 for (int i = 0; i < nr; i++)
4645 {
4646 if (i != idx)
4647 {
4648 for (int j = 0; j < nc; j++)
4649 new_matrix->elem (ii, j) = matrix->elem (i, j);
4650 ii++;
4651 }
4652 }
4653 delete matrix;
4654 matrix = new_matrix;
4655 }
4656 else if (type_tag == complex_matrix_constant)
4657 {
4658 int nr = complex_matrix->rows ();
4659 int nc = complex_matrix->columns ();
4660 ComplexMatrix *new_matrix = new ComplexMatrix (nr-1, nc);
4661 int ii = 0;
4662 for (int i = 0; i < nr; i++)
4663 {
4664 if (i != idx)
4665 {
4666 for (int j = 0; j < nc; j++)
4667 new_matrix->elem (ii, j) = complex_matrix->elem (i, j);
4668 ii++;
4669 }
4670 }
4671 delete complex_matrix;
4672 complex_matrix = new_matrix;
4673 }
4674 else
4675 panic_impossible ();
4676 }
4677
4678 void
4679 tree_constant_rep::delete_rows (idx_vector& iv)
4680 {
4681 iv.sort_uniq ();
4682 int num_to_delete = iv.length ();
4683
4684 int nr = rows ();
4685 int nc = columns ();
4686
4687 // If deleting all rows of a column vector, make result 0x0.
4688 if (nc == 1 && num_to_delete == nr)
4689 nc = 0;
4690
4691 if (type_tag == matrix_constant)
4692 {
4693 Matrix *new_matrix = new Matrix (nr-num_to_delete, nc);
4694 if (nr > num_to_delete)
4695 {
4696 int ii = 0;
4697 int idx = 0;
4698 for (int i = 0; i < nr; i++)
4699 {
4700 if (i == iv.elem (idx))
4701 idx++;
4702 else
4703 {
4704 for (int j = 0; j < nc; j++)
4705 new_matrix->elem (ii, j) = matrix->elem (i, j);
4706 ii++;
4707 }
4708 }
4709 }
4710 delete matrix;
4711 matrix = new_matrix;
4712 }
4713 else if (type_tag == complex_matrix_constant)
4714 {
4715 ComplexMatrix *new_matrix = new ComplexMatrix (nr-num_to_delete, nc);
4716 if (nr > num_to_delete)
4717 {
4718 int ii = 0;
4719 int idx = 0;
4720 for (int i = 0; i < nr; i++)
4721 {
4722 if (i == iv.elem (idx))
4723 idx++;
4724 else
4725 {
4726 for (int j = 0; j < nc; j++)
4727 new_matrix->elem (ii, j) = complex_matrix->elem (i, j);
4728 ii++;
4729 }
4730 }
4731 }
4732 delete complex_matrix;
4733 complex_matrix = new_matrix;
4734 }
4735 else
4736 panic_impossible ();
4737 }
4738
4739 void
4740 tree_constant_rep::delete_rows (Range& ri)
4741 {
4742 ri.sort ();
4743 int num_to_delete = ri.nelem ();
4744
4745 int nr = rows ();
4746 int nc = columns ();
4747
4748 // If deleting all rows of a column vector, make result 0x0.
4749 if (nc == 1 && num_to_delete == nr)
4750 nc = 0;
4751
4752 double ib = ri.base ();
4753 double iinc = ri.inc ();
4754
4755 int max_idx = tree_to_mat_idx (ri.max ());
4756
4757 if (type_tag == matrix_constant)
4758 {
4759 Matrix *new_matrix = new Matrix (nr-num_to_delete, nc);
4760 if (nr > num_to_delete)
4761 {
4762 int ii = 0;
4763 int idx = 0;
4764 for (int i = 0; i < nr; i++)
4765 {
4766 double itmp = ib + idx * iinc;
4767 int row = tree_to_mat_idx (itmp);
4768
4769 if (i == row && row <= max_idx)
4770 idx++;
4771 else
4772 {
4773 for (int j = 0; j < nc; j++)
4774 new_matrix->elem (ii, j) = matrix->elem (i, j);
4775 ii++;
4776 }
4777 }
4778 }
4779 delete matrix;
4780 matrix = new_matrix;
4781 }
4782 else if (type_tag == complex_matrix_constant)
4783 {
4784 ComplexMatrix *new_matrix = new ComplexMatrix (nr-num_to_delete, nc);
4785 if (nr > num_to_delete)
4786 {
4787 int ii = 0;
4788 int idx = 0;
4789 for (int i = 0; i < nr; i++)
4790 {
4791 double itmp = ib + idx * iinc;
4792 int row = tree_to_mat_idx (itmp);
4793
4794 if (i == row && row <= max_idx)
4795 idx++;
4796 else
4797 {
4798 for (int j = 0; j < nc; j++)
4799 new_matrix->elem (ii, j) = complex_matrix->elem (i, j);
4800 ii++;
4801 }
4802 }
4803 }
4804 delete complex_matrix;
4805 complex_matrix = new_matrix;
4806 }
4807 else
4808 panic_impossible ();
4809 }
4810
4811 void
4812 tree_constant_rep::delete_column (int idx)
4813 {
4814 if (type_tag == matrix_constant)
4815 {
4816 int nr = matrix->rows ();
4817 int nc = matrix->columns ();
4818 Matrix *new_matrix = new Matrix (nr, nc-1);
4819 int jj = 0;
4820 for (int j = 0; j < nc; j++)
4821 {
4822 if (j != idx)
4823 {
4824 for (int i = 0; i < nr; i++)
4825 new_matrix->elem (i, jj) = matrix->elem (i, j);
4826 jj++;
4827 }
4828 }
4829 delete matrix;
4830 matrix = new_matrix;
4831 }
4832 else if (type_tag == complex_matrix_constant)
4833 {
4834 int nr = complex_matrix->rows ();
4835 int nc = complex_matrix->columns ();
4836 ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-1);
4837 int jj = 0;
4838 for (int j = 0; j < nc; j++)
4839 {
4840 if (j != idx)
4841 {
4842 for (int i = 0; i < nr; i++)
4843 new_matrix->elem (i, jj) = complex_matrix->elem (i, j);
4844 jj++;
4845 }
4846 }
4847 delete complex_matrix;
4848 complex_matrix = new_matrix;
4849 }
4850 else
4851 panic_impossible ();
4852 }
4853
4854 void
4855 tree_constant_rep::delete_columns (idx_vector& jv)
4856 {
4857 jv.sort_uniq ();
4858 int num_to_delete = jv.length ();
4859
4860 int nr = rows ();
4861 int nc = columns ();
4862
4863 // If deleting all columns of a row vector, make result 0x0.
4864 if (nr == 1 && num_to_delete == nc)
4865 nr = 0;
4866
4867 if (type_tag == matrix_constant)
4868 {
4869 Matrix *new_matrix = new Matrix (nr, nc-num_to_delete);
4870 if (nc > num_to_delete)
4871 {
4872 int jj = 0;
4873 int idx = 0;
4874 for (int j = 0; j < nc; j++)
4875 {
4876 if (j == jv.elem (idx))
4877 idx++;
4878 else
4879 {
4880 for (int i = 0; i < nr; i++)
4881 new_matrix->elem (i, jj) = matrix->elem (i, j);
4882 jj++;
4883 }
4884 }
4885 }
4886 delete matrix;
4887 matrix = new_matrix;
4888 }
4889 else if (type_tag == complex_matrix_constant)
4890 {
4891 ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-num_to_delete);
4892 if (nc > num_to_delete)
4893 {
4894 int jj = 0;
4895 int idx = 0;
4896 for (int j = 0; j < nc; j++)
4897 {
4898 if (j == jv.elem (idx))
4899 idx++;
4900 else
4901 {
4902 for (int i = 0; i < nr; i++)
4903 new_matrix->elem (i, jj) = complex_matrix->elem (i, j);
4904 jj++;
4905 }
4906 }
4907 }
4908 delete complex_matrix;
4909 complex_matrix = new_matrix;
4910 }
4911 else
4912 panic_impossible ();
4913 }
4914
4915 void
4916 tree_constant_rep::delete_columns (Range& rj)
4917 {
4918 rj.sort ();
4919 int num_to_delete = rj.nelem ();
4920
4921 int nr = rows ();
4922 int nc = columns ();
4923
4924 // If deleting all columns of a row vector, make result 0x0.
4925 if (nr == 1 && num_to_delete == nc)
4926 nr = 0;
4927
4928 double jb = rj.base ();
4929 double jinc = rj.inc ();
4930
4931 int max_idx = tree_to_mat_idx (rj.max ());
4932
4933 if (type_tag == matrix_constant)
4934 {
4935 Matrix *new_matrix = new Matrix (nr, nc-num_to_delete);
4936 if (nc > num_to_delete)
4937 {
4938 int jj = 0;
4939 int idx = 0;
4940 for (int j = 0; j < nc; j++)
4941 {
4942 double jtmp = jb + idx * jinc;
4943 int col = tree_to_mat_idx (jtmp);
4944
4945 if (j == col && col <= max_idx)
4946 idx++;
4947 else
4948 {
4949 for (int i = 0; i < nr; i++)
4950 new_matrix->elem (i, jj) = matrix->elem (i, j);
4951 jj++;
4952 }
4953 }
4954 }
4955 delete matrix;
4956 matrix = new_matrix;
4957 }
4958 else if (type_tag == complex_matrix_constant)
4959 {
4960 ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-num_to_delete);
4961 if (nc > num_to_delete)
4962 {
4963 int jj = 0;
4964 int idx = 0;
4965 for (int j = 0; j < nc; j++)
4966 {
4967 double jtmp = jb + idx * jinc;
4968 int col = tree_to_mat_idx (jtmp);
4969
4970 if (j == col && col <= max_idx)
4971 idx++;
4972 else
4973 {
4974 for (int i = 0; i < nr; i++)
4975 new_matrix->elem (i, jj) = complex_matrix->elem (i, j);
4976 jj++;
4977 }
4978 }
4979 }
4980 delete complex_matrix;
4981 complex_matrix = new_matrix;
4982 }
4983 else
4984 panic_impossible ();
4985 }
4986
4987 /*
4988 * Indexing functions.
4989 */
4990 int
4991 tree_constant_rep::valid_as_scalar_index (void) const
4992 {
4993 int valid = type_tag == magic_colon
4994 || (type_tag == scalar_constant && NINT (scalar) == 1)
4995 || (type_tag == range_constant
4996 && range->nelem () == 1 && NINT (range->base ()) == 1);
4997
4998 return valid;
4999 }
5000
5001 tree_constant
5002 tree_constant_rep::do_scalar_index (const tree_constant *args,
5003 int nargs) const
5004 {
5005 if (valid_scalar_indices (args, nargs))
5006 {
5007 if (type_tag == scalar_constant)
5008 return tree_constant (scalar);
5009 else if (type_tag == complex_scalar_constant)
5010 return tree_constant (*complex_scalar);
5011 else
5012 panic_impossible ();
5013 }
5014 else
5015 {
5016 int rows = 0;
5017 int cols = 0;
5018
5019 switch (nargs)
5020 {
5021 case 3:
5022 {
5023 if (args[2].is_matrix_type ())
5024 {
5025 Matrix mj = args[2].matrix_value ();
5026
5027 idx_vector j (mj, user_pref.do_fortran_indexing, "");
5028 if (! j)
5029 return tree_constant ();
5030
5031 int len = j.length ();
5032 if (len == j.ones_count ())
5033 cols = len;
5034 }
5035 else if (args[2].const_type () == magic_colon
5036 || (args[2].is_scalar_type ()
5037 && NINT (args[2].double_value ()) == 1))
5038 {
5039 cols = 1;
5040 }
5041 else
5042 break;
5043 }
5044 // Fall through...
5045 case 2:
5046 {
5047 if (args[1].is_matrix_type ())
5048 {
5049 Matrix mi = args[1].matrix_value ();
5050
5051 idx_vector i (mi, user_pref.do_fortran_indexing, "");
5052 if (! i)
5053 return tree_constant ();
5054
5055 int len = i.length ();
5056 if (len == i.ones_count ())
5057 rows = len;
5058 }
5059 else if (args[1].const_type () == magic_colon
5060 || (args[1].is_scalar_type ()
5061 && NINT (args[1].double_value ()) == 1))
5062 {
5063 rows = 1;
5064 }
5065 else if (args[1].is_scalar_type ()
5066 && NINT (args[1].double_value ()) == 0)
5067 {
5068 Matrix m (0, 0);
5069 return tree_constant (m);
5070 }
5071 else
5072 break;
5073
5074 if (cols == 0)
5075 {
5076 if (user_pref.prefer_column_vectors)
5077 cols = 1;
5078 else
5079 {
5080 cols = rows;
5081 rows = 1;
5082 }
5083 }
5084
5085 if (type_tag == scalar_constant)
5086 {
5087 Matrix m (rows, cols, scalar);
5088 return tree_constant (m);
5089 }
5090 else if (type_tag == complex_scalar_constant)
5091 {
5092 ComplexMatrix cm (rows, cols, *complex_scalar);
5093 return tree_constant (cm);
5094 }
5095 else
5096 panic_impossible ();
5097 }
5098 break;
5099 default:
5100 ::error ("illegal number of arguments for scalar type");
5101 return tree_constant ();
5102 break;
5103 }
5104 }
5105
5106 ::error ("index invalid or out of range for scalar type");
5107 return tree_constant ();
5108 }
5109
5110 tree_constant
5111 tree_constant_rep::do_matrix_index (const tree_constant *args,
5112 int nargin) const
5113 {
5114 tree_constant retval;
5115
5116 switch (nargin)
5117 {
5118 case 2:
5119 if (! args)
5120 ::error ("matrix index is null");
5121 else if (args[1].is_undefined ())
5122 ::error ("matrix index is a null expression");
5123 else
5124 retval = do_matrix_index (args[1]);
5125 break;
5126 case 3:
5127 if (! args)
5128 ::error ("matrix indices are null");
5129 else if (args[1].is_undefined ())
5130 ::error ("first matrix index is a null expression");
5131 else if (args[2].is_undefined ())
5132 ::error ("second matrix index is a null expression");
5133 else
5134 retval = do_matrix_index (args[1], args[2]);
5135 break;
5136 default:
5137 ::error ("too many indices for matrix expression");
5138 break;
5139 }
5140
5141 return retval;
5142 }
5143
5144 tree_constant
5145 tree_constant_rep::do_matrix_index (const tree_constant& i_arg) const
5146 {
5147 tree_constant retval;
5148
5149 int nr = rows ();
5150 int nc = columns ();
5151
5152 if (user_pref.do_fortran_indexing)
5153 retval = fortran_style_matrix_index (i_arg);
5154 else if (nr <= 1 || nc <= 1)
5155 retval = do_vector_index (i_arg);
5156 else
5157 ::error ("single index only valid for row or column vector");
5158
5159 return retval;
5160 }
5161
5162 tree_constant
5163 tree_constant_rep::fortran_style_matrix_index
5164 (const tree_constant& i_arg) const
5165 {
5166 tree_constant retval;
5167
5168 tree_constant tmp_i = i_arg.make_numeric_or_magic ();
5169
5170 tree_constant_rep::constant_type itype = tmp_i.const_type ();
5171
5172 int nr = rows ();
5173 int nc = columns ();
5174
5175 switch (itype)
5176 {
5177 case complex_scalar_constant:
5178 case scalar_constant:
5179 {
5180 int i = NINT (tmp_i.double_value ());
5181 int ii = fortran_row (i, nr) - 1;
5182 int jj = fortran_column (i, nr) - 1;
5183 if (index_check (i-1, "") < 0)
5184 return tree_constant ();
5185 if (range_max_check (i-1, nr * nc) < 0)
5186 return tree_constant ();
5187 retval = do_matrix_index (ii, jj);
5188 }
5189 break;
5190 case complex_matrix_constant:
5191 case matrix_constant:
5192 {
5193 Matrix mi = tmp_i.matrix_value ();
5194 if (mi.rows () == 0 || mi.columns () == 0)
5195 {
5196 Matrix mtmp;
5197 retval = tree_constant (mtmp);
5198 }
5199 else
5200 {
5201 // Yes, we really do want to call this with mi.
5202 retval = fortran_style_matrix_index (mi);
5203 }
5204 }
5205 break;
5206 case string_constant:
5207 gripe_string_invalid ();
5208 break;
5209 case range_constant:
5210 gripe_range_invalid ();
5211 break;
5212 case magic_colon:
5213 retval = do_matrix_index (magic_colon);
5214 break;
5215 default:
5216 panic_impossible ();
5217 break;
5218 }
5219
5220 return retval;
5221 }
5222
5223 tree_constant
5224 tree_constant_rep::fortran_style_matrix_index (const Matrix& mi) const
5225 {
5226 assert (is_matrix_type ());
5227
5228 tree_constant retval;
5229
5230 int nr = rows ();
5231 int nc = columns ();
5232
5233 int len = nr * nc;
5234
5235 int index_nr = mi.rows ();
5236 int index_nc = mi.columns ();
5237
5238 if (index_nr >= 1 && index_nc >= 1)
5239 {
5240 const double *cop_out = (const double *) NULL;
5241 const Complex *c_cop_out = (const Complex *) NULL;
5242 int real_type = type_tag == matrix_constant;
5243 if (real_type)
5244 cop_out = matrix->data ();
5245 else
5246 c_cop_out = complex_matrix->data ();
5247
5248 const double *cop_out_index = mi.data ();
5249
5250 idx_vector iv (mi, 1, "", len);
5251 if (! iv)
5252 return tree_constant ();
5253
5254 int result_size = iv.length ();
5255
5256 if (nc == 1 || (nr != 1 && iv.one_zero_only ()))
5257 {
5258 CRMATRIX (m, cm, result_size, 1);
5259
5260 for (int i = 0; i < result_size; i++)
5261 {
5262 int idx = iv.elem (i);
5263 CRMATRIX_ASSIGN_ELEM (m, cm, i, 0, cop_out [idx],
5264 c_cop_out [idx], real_type);
5265 }
5266
5267 ASSIGN_CRMATRIX_TO (retval, m, cm);
5268 }
5269 else if (nr == 1)
5270 {
5271 CRMATRIX (m, cm, 1, result_size);
5272
5273 for (int i = 0; i < result_size; i++)
5274 {
5275 int idx = iv.elem (i);
5276 CRMATRIX_ASSIGN_ELEM (m, cm, 0, i, cop_out [idx],
5277 c_cop_out [idx], real_type);
5278 }
5279
5280 ASSIGN_CRMATRIX_TO (retval, m, cm);
5281 }
5282 else
5283 {
5284 CRMATRIX (m, cm, index_nr, index_nc);
5285
5286 for (int j = 0; j < index_nc; j++)
5287 for (int i = 0; i < index_nr; i++)
5288 {
5289 double tmp = *cop_out_index++;
5290 int idx = tree_to_mat_idx (tmp);
5291 CRMATRIX_ASSIGN_ELEM (m, cm, i, j, cop_out [idx],
5292 c_cop_out [idx], real_type);
5293 }
5294
5295 ASSIGN_CRMATRIX_TO (retval, m, cm);
5296 }
5297 }
5298 else
5299 {
5300 if (index_nr == 0 || index_nc == 0)
5301 ::error ("empty matrix invalid as index");
5302 else
5303 ::error ("invalid matrix index");
5304 return tree_constant ();
5305 }
5306
5307 return retval;
5308 }
5309
5310 tree_constant
5311 tree_constant_rep::do_vector_index (const tree_constant& i_arg) const
5312 {
5313 tree_constant retval;
5314
5315 tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic ();
5316
5317 tree_constant_rep::constant_type itype = tmp_i.const_type ();
5318
5319 int nr = rows ();
5320 int nc = columns ();
5321
5322 int len = MAX (nr, nc);
5323
5324 assert ((nr == 1 || nc == 1) && ! user_pref.do_fortran_indexing);
5325
5326 int swap_indices = (nr == 1);
5327
5328 switch (itype)
5329 {
5330 case complex_scalar_constant:
5331 case scalar_constant:
5332 {
5333 int i = tree_to_mat_idx (tmp_i.double_value ());
5334 if (index_check (i, "") < 0)
5335 return tree_constant ();
5336 if (swap_indices)
5337 {
5338 if (range_max_check (i, nc) < 0)
5339 return tree_constant ();
5340 retval = do_matrix_index (0, i);
5341 }
5342 else
5343 {
5344 if (range_max_check (i, nr) < 0)
5345 return tree_constant ();
5346 retval = do_matrix_index (i, 0);
5347 }
5348 }
5349 break;
5350 case complex_matrix_constant:
5351 case matrix_constant:
5352 {
5353 Matrix mi = tmp_i.matrix_value ();
5354 if (mi.rows () == 0 || mi.columns () == 0)
5355 {
5356 Matrix mtmp;
5357 retval = tree_constant (mtmp);
5358 }
5359 else
5360 {
5361 idx_vector iv (mi, user_pref.do_fortran_indexing, "", len);
5362 if (! iv)
5363 return tree_constant ();
5364
5365 if (swap_indices)
5366 {
5367 if (range_max_check (iv.max (), nc) < 0)
5368 return tree_constant ();
5369 retval = do_matrix_index (0, iv);
5370 }
5371 else
5372 {
5373 if (range_max_check (iv.max (), nr) < 0)
5374 return tree_constant ();
5375 retval = do_matrix_index (iv, 0);
5376 }
5377 }
5378 }
5379 break;
5380 case string_constant:
5381 gripe_string_invalid ();
5382 break;
5383 case range_constant:
5384 {
5385 Range ri = tmp_i.range_value ();
5386 if (len == 2 && is_zero_one (ri))
5387 {
5388 if (swap_indices)
5389 retval = do_matrix_index (0, 1);
5390 else
5391 retval = do_matrix_index (1, 0);
5392 }
5393 else if (len == 2 && is_one_zero (ri))
5394 {
5395 retval = do_matrix_index (0, 0);
5396 }
5397 else
5398 {
5399 if (index_check (ri, "") < 0)
5400 return tree_constant ();
5401 if (swap_indices)
5402 {
5403 if (range_max_check (tree_to_mat_idx (ri.max ()), nc) < 0)
5404 return tree_constant ();
5405 retval = do_matrix_index (0, ri);
5406 }
5407 else
5408 {
5409 if (range_max_check (tree_to_mat_idx (ri.max ()), nr) < 0)
5410 return tree_constant ();
5411 retval = do_matrix_index (ri, 0);
5412 }
5413 }
5414 }
5415 break;
5416 case magic_colon:
5417 if (swap_indices)
5418 retval = do_matrix_index (0, magic_colon);
5419 else
5420 retval = do_matrix_index (magic_colon, 0);
5421 break;
5422 default:
5423 panic_impossible ();
5424 break;
5425 }
5426
5427 return retval;
5428 }
5429
5430 tree_constant
5431 tree_constant_rep::do_matrix_index (const tree_constant& i_arg,
5432 const tree_constant& j_arg) const
5433 {
5434 tree_constant retval;
5435
5436 tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic ();
5437
5438 tree_constant_rep::constant_type itype = tmp_i.const_type ();
5439
5440 switch (itype)
5441 {
5442 case complex_scalar_constant:
5443 case scalar_constant:
5444 {
5445 int i = tree_to_mat_idx (tmp_i.double_value ());
5446 if (index_check (i, "row") < 0)
5447 return tree_constant ();
5448 retval = do_matrix_index (i, j_arg);
5449 }
5450 break;
5451 case complex_matrix_constant:
5452 case matrix_constant:
5453 {
5454 Matrix mi = tmp_i.matrix_value ();
5455 idx_vector iv (mi, user_pref.do_fortran_indexing, "row", rows ());
5456 if (! iv)
5457 return tree_constant ();
5458
5459 if (iv.length () == 0)
5460 {
5461 Matrix mtmp;
5462 retval = tree_constant (mtmp);
5463 }
5464 else
5465 retval = do_matrix_index (iv, j_arg);
5466 }
5467 break;
5468 case string_constant:
5469 gripe_string_invalid ();
5470 break;
5471 case range_constant:
5472 {
5473 Range ri = tmp_i.range_value ();
5474 int nr = rows ();
5475 if (nr == 2 && is_zero_one (ri))
5476 {
5477 retval = do_matrix_index (1, j_arg);
5478 }
5479 else if (nr == 2 && is_one_zero (ri))
5480 {
5481 retval = do_matrix_index (0, j_arg);
5482 }
5483 else
5484 {
5485 if (index_check (ri, "row") < 0)
5486 return tree_constant ();
5487 retval = do_matrix_index (ri, j_arg);
5488 }
5489 }
5490 break;
5491 case magic_colon:
5492 retval = do_matrix_index (magic_colon, j_arg);
5493 break;
5494 default:
5495 panic_impossible ();
5496 break;
5497 }
5498
5499 return retval;
5500 }
5501
5502 tree_constant
5503 tree_constant_rep::do_matrix_index (int i, const tree_constant& j_arg) const
5504 {
5505 tree_constant retval;
5506
5507 tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
5508
5509 tree_constant_rep::constant_type jtype = tmp_j.const_type ();
5510
5511 int nr = rows ();
5512 int nc = columns ();
5513
5514 switch (jtype)
5515 {
5516 case complex_scalar_constant:
5517 case scalar_constant:
5518 {
5519 int j = tree_to_mat_idx (tmp_j.double_value ());
5520 if (index_check (j, "column") < 0)
5521 return tree_constant ();
5522 if (range_max_check (i, j, nr, nc) < 0)
5523 return tree_constant ();
5524 retval = do_matrix_index (i, j);
5525 }
5526 break;
5527 case complex_matrix_constant:
5528 case matrix_constant:
5529 {
5530 Matrix mj = tmp_j.matrix_value ();
5531 idx_vector jv (mj, user_pref.do_fortran_indexing, "column", nc);
5532 if (! jv)
5533 return tree_constant ();
5534
5535 if (jv.length () == 0)
5536 {
5537 Matrix mtmp;
5538 retval = tree_constant (mtmp);
5539 }
5540 else
5541 {
5542 if (range_max_check (i, jv.max (), nr, nc) < 0)
5543 return tree_constant ();
5544 retval = do_matrix_index (i, jv);
5545 }
5546 }
5547 break;
5548 case string_constant:
5549 gripe_string_invalid ();
5550 break;
5551 case range_constant:
5552 {
5553 Range rj = tmp_j.range_value ();
5554 if (nc == 2 && is_zero_one (rj))
5555 {
5556 retval = do_matrix_index (i, 1);
5557 }
5558 else if (nc == 2 && is_one_zero (rj))
5559 {
5560 retval = do_matrix_index (i, 0);
5561 }
5562 else
5563 {
5564 if (index_check (rj, "column") < 0)
5565 return tree_constant ();
5566 if (range_max_check (i, tree_to_mat_idx (rj.max ()), nr, nc) < 0)
5567 return tree_constant ();
5568 retval = do_matrix_index (i, rj);
5569 }
5570 }
5571 break;
5572 case magic_colon:
5573 if (range_max_check (i, 0, nr, nc) < 0)
5574 return tree_constant ();
5575 retval = do_matrix_index (i, magic_colon);
5576 break;
5577 default:
5578 panic_impossible ();
5579 break;
5580 }
5581
5582 return retval;
5583 }
5584
5585 tree_constant
5586 tree_constant_rep::do_matrix_index (const idx_vector& iv,
5587 const tree_constant& j_arg) const
5588 {
5589 tree_constant retval;
5590
5591 tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
5592
5593 tree_constant_rep::constant_type jtype = tmp_j.const_type ();
5594
5595 int nr = rows ();
5596 int nc = columns ();
5597
5598 switch (jtype)
5599 {
5600 case complex_scalar_constant:
5601 case scalar_constant:
5602 {
5603 int j = tree_to_mat_idx (tmp_j.double_value ());
5604 if (index_check (j, "column") < 0)
5605 return tree_constant ();
5606 if (range_max_check (iv.max (), j, nr, nc) < 0)
5607 return tree_constant ();
5608 retval = do_matrix_index (iv, j);
5609 }
5610 break;
5611 case complex_matrix_constant:
5612 case matrix_constant:
5613 {
5614 Matrix mj = tmp_j.matrix_value ();
5615 idx_vector jv (mj, user_pref.do_fortran_indexing, "column", nc);
5616 if (! jv)
5617 return tree_constant ();
5618
5619 if (jv.length () == 0)
5620 {
5621 Matrix mtmp;
5622 retval = tree_constant (mtmp);
5623 }
5624 else
5625 {
5626 if (range_max_check (iv.max (), jv.max (), nr, nc) < 0)
5627 return tree_constant ();
5628 retval = do_matrix_index (iv, jv);
5629 }
5630 }
5631 break;
5632 case string_constant:
5633 gripe_string_invalid ();
5634 break;
5635 case range_constant:
5636 {
5637 Range rj = tmp_j.range_value ();
5638 if (nc == 2 && is_zero_one (rj))
5639 {
5640 retval = do_matrix_index (iv, 1);
5641 }
5642 else if (nc == 2 && is_one_zero (rj))
5643 {
5644 retval = do_matrix_index (iv, 0);
5645 }
5646 else
5647 {
5648 if (index_check (rj, "column") < 0)
5649 return tree_constant ();
5650 if (range_max_check (iv.max (), tree_to_mat_idx (rj.max ()),
5651 nr, nc) < 0)
5652 return tree_constant ();
5653 retval = do_matrix_index (iv, rj);
5654 }
5655 }
5656 break;
5657 case magic_colon:
5658 if (range_max_check (iv.max (), 0, nr, nc) < 0)
5659 return tree_constant ();
5660 retval = do_matrix_index (iv, magic_colon);
5661 break;
5662 default:
5663 panic_impossible ();
5664 break;
5665 }
5666
5667 return retval;
5668 }
5669
5670 tree_constant
5671 tree_constant_rep::do_matrix_index (const Range& ri,
5672 const tree_constant& j_arg) const
5673 {
5674 tree_constant retval;
5675
5676 tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
5677
5678 tree_constant_rep::constant_type jtype = tmp_j.const_type ();
5679
5680 int nr = rows ();
5681 int nc = columns ();
5682
5683 switch (jtype)
5684 {
5685 case complex_scalar_constant:
5686 case scalar_constant:
5687 {
5688 int j = tree_to_mat_idx (tmp_j.double_value ());
5689 if (index_check (j, "column") < 0)
5690 return tree_constant ();
5691 if (range_max_check (tree_to_mat_idx (ri.max ()), j, nr, nc) < 0)
5692 return tree_constant ();
5693 retval = do_matrix_index (ri, j);
5694 }
5695 break;
5696 case complex_matrix_constant:
5697 case matrix_constant:
5698 {
5699 Matrix mj = tmp_j.matrix_value ();
5700 idx_vector jv (mj, user_pref.do_fortran_indexing, "column", nc);
5701 if (! jv)
5702 return tree_constant ();
5703
5704 if (jv.length () == 0)
5705 {
5706 Matrix mtmp;
5707 retval = tree_constant (mtmp);
5708 }
5709 else
5710 {
5711 if (range_max_check (tree_to_mat_idx (ri.max ()),
5712 jv.max (), nr, nc) < 0)
5713 return tree_constant ();
5714 retval = do_matrix_index (ri, jv);
5715 }
5716 }
5717 break;
5718 case string_constant:
5719 gripe_string_invalid ();
5720 break;
5721 case range_constant:
5722 {
5723 Range rj = tmp_j.range_value ();
5724 if (nc == 2 && is_zero_one (rj))
5725 {
5726 retval = do_matrix_index (ri, 1);
5727 }
5728 else if (nc == 2 && is_one_zero (rj))
5729 {
5730 retval = do_matrix_index (ri, 0);
5731 }
5732 else
5733 {
5734 if (index_check (rj, "column") < 0)
5735 return tree_constant ();
5736 if (range_max_check (tree_to_mat_idx (ri.max ()),
5737 tree_to_mat_idx (rj.max ()), nr, nc) < 0)
5738 return tree_constant ();
5739 retval = do_matrix_index (ri, rj);
5740 }
5741 }
5742 break;
5743 case magic_colon:
5744 retval = do_matrix_index (ri, magic_colon);
5745 break;
5746 default:
5747 panic_impossible ();
5748 break;
5749 }
5750
5751 return retval;
5752 }
5753
5754 tree_constant
5755 tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci,
5756 const tree_constant& j_arg) const
5757 {
5758 tree_constant retval;
5759
5760 tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
5761
5762 tree_constant_rep::constant_type jtype = tmp_j.const_type ();
5763
5764 int nr = rows ();
5765 int nc = columns ();
5766
5767 switch (jtype)
5768 {
5769 case complex_scalar_constant:
5770 case scalar_constant:
5771 {
5772 int j = tree_to_mat_idx (tmp_j.double_value ());
5773 if (index_check (j, "column") < 0)
5774 return tree_constant ();
5775 if (range_max_check (0, j, nr, nc) < 0)
5776 return tree_constant ();
5777 retval = do_matrix_index (magic_colon, j);
5778 }
5779 break;
5780 case complex_matrix_constant:
5781 case matrix_constant:
5782 {
5783 Matrix mj = tmp_j.matrix_value ();
5784 idx_vector jv (mj, user_pref.do_fortran_indexing, "column", nc);
5785 if (! jv)
5786 return tree_constant ();
5787
5788 if (jv.length () == 0)
5789 {
5790 Matrix mtmp;
5791 retval = tree_constant (mtmp);
5792 }
5793 else
5794 {
5795 if (range_max_check (0, jv.max (), nr, nc) < 0)
5796 return tree_constant ();
5797 retval = do_matrix_index (magic_colon, jv);
5798 }
5799 }
5800 break;
5801 case string_constant:
5802 gripe_string_invalid ();
5803 break;
5804 case range_constant:
5805 {
5806 Range rj = tmp_j.range_value ();
5807 if (nc == 2 && is_zero_one (rj))
5808 {
5809 retval = do_matrix_index (magic_colon, 1);
5810 }
5811 else if (nc == 2 && is_one_zero (rj))
5812 {
5813 retval = do_matrix_index (magic_colon, 0);
5814 }
5815 else
5816 {
5817 if (index_check (rj, "column") < 0)
5818 return tree_constant ();
5819 if (range_max_check (0, tree_to_mat_idx (rj.max ()), nr, nc) < 0)
5820 return tree_constant ();
5821 retval = do_matrix_index (magic_colon, rj);
5822 }
5823 }
5824 break;
5825 case magic_colon:
5826 retval = do_matrix_index (magic_colon, magic_colon);
5827 break;
5828 default:
5829 panic_impossible ();
5830 break;
5831 }
5832
5833 return retval;
5834 }
5835
5836 tree_constant
5837 tree_constant_rep::do_matrix_index (int i, int j) const
5838 {
5839 tree_constant retval;
5840
5841 if (type_tag == matrix_constant)
5842 retval = tree_constant (matrix->elem (i, j));
5843 else
5844 retval = tree_constant (complex_matrix->elem (i, j));
5845
5846 return retval;
5847 }
5848
5849 tree_constant
5850 tree_constant_rep::do_matrix_index (int i, const idx_vector& jv) const
5851 {
5852 tree_constant retval;
5853
5854 int jlen = jv.capacity ();
5855
5856 CRMATRIX (m, cm, 1, jlen);
5857
5858 for (int j = 0; j < jlen; j++)
5859 {
5860 int col = jv.elem (j);
5861 CRMATRIX_ASSIGN_REP_ELEM (m, cm, 0, j, i, col);
5862 }
5863 ASSIGN_CRMATRIX_TO (retval, m, cm);
5864
5865 return retval;
5866 }
5867
5868 tree_constant
5869 tree_constant_rep::do_matrix_index (int i, const Range& rj) const
5870 {
5871 tree_constant retval;
5872
5873 int jlen = rj.nelem ();
5874
5875 CRMATRIX (m, cm, 1, jlen);
5876
5877 double b = rj.base ();
5878 double increment = rj.inc ();
5879 for (int j = 0; j < jlen; j++)
5880 {
5881 double tmp = b + j * increment;
5882 int col = tree_to_mat_idx (tmp);
5883 CRMATRIX_ASSIGN_REP_ELEM (m, cm, 0, j, i, col);
5884 }
5885
5886 ASSIGN_CRMATRIX_TO (retval, m, cm);
5887
5888 return retval;
5889 }
5890
5891 tree_constant
5892 tree_constant_rep::do_matrix_index
5893 (int i, tree_constant_rep::constant_type mcj) const
5894 {
5895 assert (mcj == magic_colon);
5896
5897 tree_constant retval;
5898
5899 int nc = columns ();
5900
5901 CRMATRIX (m, cm, 1, nc);
5902
5903 for (int j = 0; j < nc; j++)
5904 {
5905 CRMATRIX_ASSIGN_REP_ELEM (m, cm, 0, j, i, j);
5906 }
5907
5908 ASSIGN_CRMATRIX_TO (retval, m, cm);
5909
5910 return retval;
5911 }
5912
5913 tree_constant
5914 tree_constant_rep::do_matrix_index (const idx_vector& iv, int j) const
5915 {
5916 tree_constant retval;
5917
5918 int ilen = iv.capacity ();
5919
5920 CRMATRIX (m, cm, ilen, 1);
5921
5922 for (int i = 0; i < ilen; i++)
5923 {
5924 int row = iv.elem (i);
5925 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, 0, row, j);
5926 }
5927
5928 ASSIGN_CRMATRIX_TO (retval, m, cm);
5929
5930 return retval;
5931 }
5932
5933 tree_constant
5934 tree_constant_rep::do_matrix_index (const idx_vector& iv,
5935 const idx_vector& jv) const
5936 {
5937 tree_constant retval;
5938
5939 int ilen = iv.capacity ();
5940 int jlen = jv.capacity ();
5941
5942 CRMATRIX (m, cm, ilen, jlen);
5943
5944 for (int i = 0; i < ilen; i++)
5945 {
5946 int row = iv.elem (i);
5947 for (int j = 0; j < jlen; j++)
5948 {
5949 int col = jv.elem (j);
5950 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col);
5951 }
5952 }
5953
5954 ASSIGN_CRMATRIX_TO (retval, m, cm);
5955
5956 return retval;
5957 }
5958
5959 tree_constant
5960 tree_constant_rep::do_matrix_index (const idx_vector& iv,
5961 const Range& rj) const
5962 {
5963 tree_constant retval;
5964
5965 int ilen = iv.capacity ();
5966 int jlen = rj.nelem ();
5967
5968 CRMATRIX (m, cm, ilen, jlen);
5969
5970 double b = rj.base ();
5971 double increment = rj.inc ();
5972
5973 for (int i = 0; i < ilen; i++)
5974 {
5975 int row = iv.elem (i);
5976 for (int j = 0; j < jlen; j++)
5977 {
5978 double tmp = b + j * increment;
5979 int col = tree_to_mat_idx (tmp);
5980 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col);
5981 }
5982 }
5983
5984 ASSIGN_CRMATRIX_TO (retval, m, cm);
5985
5986 return retval;
5987 }
5988
5989 tree_constant
5990 tree_constant_rep::do_matrix_index
5991 (const idx_vector& iv, tree_constant_rep::constant_type mcj) const
5992 {
5993 assert (mcj == magic_colon);
5994
5995 tree_constant retval;
5996
5997 int nc = columns ();
5998 int ilen = iv.capacity ();
5999
6000 CRMATRIX (m, cm, ilen, nc);
6001
6002 for (int j = 0; j < nc; j++)
6003 {
6004 for (int i = 0; i < ilen; i++)
6005 {
6006 int row = iv.elem (i);
6007 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, j);
6008 }
6009 }
6010
6011 ASSIGN_CRMATRIX_TO (retval, m, cm);
6012
6013 return retval;
6014 }
6015
6016 tree_constant
6017 tree_constant_rep::do_matrix_index (const Range& ri, int j) const
6018 {
6019 tree_constant retval;
6020
6021 int ilen = ri.nelem ();
6022
6023 CRMATRIX (m, cm, ilen, 1);
6024
6025 double b = ri.base ();
6026 double increment = ri.inc ();
6027 for (int i = 0; i < ilen; i++)
6028 {
6029 double tmp = b + i * increment;
6030 int row = tree_to_mat_idx (tmp);
6031 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, 0, row, j);
6032 }
6033
6034 ASSIGN_CRMATRIX_TO (retval, m, cm);
6035
6036 return retval;
6037 }
6038
6039 tree_constant
6040 tree_constant_rep::do_matrix_index (const Range& ri,
6041 const idx_vector& jv) const
6042 {
6043 tree_constant retval;
6044
6045 int ilen = ri.nelem ();
6046 int jlen = jv.capacity ();
6047
6048 CRMATRIX (m, cm, ilen, jlen);
6049
6050 double b = ri.base ();
6051 double increment = ri.inc ();
6052 for (int i = 0; i < ilen; i++)
6053 {
6054 double tmp = b + i * increment;
6055 int row = tree_to_mat_idx (tmp);
6056 for (int j = 0; j < jlen; j++)
6057 {
6058 int col = jv.elem (j);
6059 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col);
6060 }
6061 }
6062
6063 ASSIGN_CRMATRIX_TO (retval, m, cm);
6064
6065 return retval;
6066 }
6067
6068 tree_constant
6069 tree_constant_rep::do_matrix_index (const Range& ri, const Range& rj) const
6070 {
6071 tree_constant retval;
6072
6073 int ilen = ri.nelem ();
6074 int jlen = rj.nelem ();
6075
6076 CRMATRIX (m, cm, ilen, jlen);
6077
6078 double ib = ri.base ();
6079 double iinc = ri.inc ();
6080 double jb = rj.base ();
6081 double jinc = rj.inc ();
6082
6083 for (int i = 0; i < ilen; i++)
6084 {
6085 double itmp = ib + i * iinc;
6086 int row = tree_to_mat_idx (itmp);
6087 for (int j = 0; j < jlen; j++)
6088 {
6089 double jtmp = jb + j * jinc;
6090 int col = tree_to_mat_idx (jtmp);
6091
6092 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, col);
6093 }
6094 }
6095
6096 ASSIGN_CRMATRIX_TO (retval, m, cm);
6097
6098 return retval;
6099 }
6100
6101 tree_constant
6102 tree_constant_rep::do_matrix_index
6103 (const Range& ri, tree_constant_rep::constant_type mcj) const
6104 {
6105 assert (mcj == magic_colon);
6106
6107 tree_constant retval;
6108
6109 int nc = columns ();
6110
6111 int ilen = ri.nelem ();
6112
6113 CRMATRIX (m, cm, ilen, nc);
6114
6115 double ib = ri.base ();
6116 double iinc = ri.inc ();
6117
6118 for (int i = 0; i < ilen; i++)
6119 {
6120 double itmp = ib + i * iinc;
6121 int row = tree_to_mat_idx (itmp);
6122 for (int j = 0; j < nc; j++)
6123 {
6124 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, row, j);
6125 }
6126 }
6127
6128 ASSIGN_CRMATRIX_TO (retval, m, cm);
6129
6130 return retval;
6131 }
6132
6133 tree_constant
6134 tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci,
6135 int j) const
6136 {
6137 assert (mci == magic_colon);
6138
6139 tree_constant retval;
6140
6141 int nr = rows ();
6142
6143 CRMATRIX (m, cm, nr, 1);
6144
6145 for (int i = 0; i < nr; i++)
6146 {
6147 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, 0, i, j);
6148 }
6149
6150 ASSIGN_CRMATRIX_TO (retval, m, cm);
6151
6152 return retval;
6153 }
6154
6155 tree_constant
6156 tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci,
6157 const idx_vector& jv) const
6158 {
6159 assert (mci == magic_colon);
6160
6161 tree_constant retval;
6162
6163 int nr = rows ();
6164 int jlen = jv.capacity ();
6165
6166 CRMATRIX (m, cm, nr, jlen);
6167
6168 for (int i = 0; i < nr; i++)
6169 {
6170 for (int j = 0; j < jlen; j++)
6171 {
6172 int col = jv.elem (j);
6173 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, i, col);
6174 }
6175 }
6176
6177 ASSIGN_CRMATRIX_TO (retval, m, cm);
6178
6179 return retval;
6180 }
6181
6182 tree_constant
6183 tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci,
6184 const Range& rj) const
6185 {
6186 assert (mci == magic_colon);
6187
6188 tree_constant retval;
6189
6190 int nr = rows ();
6191 int jlen = rj.nelem ();
6192
6193 CRMATRIX (m, cm, nr, jlen);
6194
6195 double jb = rj.base ();
6196 double jinc = rj.inc ();
6197
6198 for (int j = 0; j < jlen; j++)
6199 {
6200 double jtmp = jb + j * jinc;
6201 int col = tree_to_mat_idx (jtmp);
6202 for (int i = 0; i < nr; i++)
6203 {
6204 CRMATRIX_ASSIGN_REP_ELEM (m, cm, i, j, i, col);
6205 }
6206 }
6207
6208 ASSIGN_CRMATRIX_TO (retval, m, cm);
6209
6210 return retval;
6211 }
6212
6213 tree_constant
6214 tree_constant_rep::do_matrix_index (tree_constant_rep::constant_type mci,
6215 tree_constant_rep::constant_type mcj) const
6216 {
6217 assert (mci == magic_colon && mcj == magic_colon);
6218
6219 return tree_constant (*this);
6220 }
6221
6222 tree_constant
6223 tree_constant_rep::do_matrix_index
6224 (tree_constant_rep::constant_type mci) const
6225 {
6226 assert (mci == magic_colon);
6227
6228 tree_constant retval;
6229 int nr = rows ();
6230 int nc = columns ();
6231 int size = nr * nc;
6232 if (size > 0)
6233 {
6234 CRMATRIX (m, cm, size, 1);
6235 int idx = 0;
6236 for (int j = 0; j < nc; j++)
6237 for (int i = 0; i < nr; i++)
6238 {
6239 CRMATRIX_ASSIGN_REP_ELEM (m, cm, idx, 0, i, j);
6240 idx++;
6241 }
6242 ASSIGN_CRMATRIX_TO (retval, m, cm);
6243 }
6244 return retval;
6245 }
6246
6247 /*
6248 ;;; Local Variables: ***
6249 ;;; mode: C++ ***
6250 ;;; page-delimiter: "^/\\*" ***
6251 ;;; End: ***
6252 */