Mercurial > hg > octave-nkf
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 */ |