1
|
1 /* |
|
2 |
1827
|
3 Copyright (C) 1996 John W. Eaton |
1
|
4 |
|
5 This file is part of Octave. |
|
6 |
|
7 Octave is free software; you can redistribute it and/or modify it |
|
8 under the terms of the GNU General Public License as published by the |
|
9 Free Software Foundation; either version 2, or (at your option) any |
|
10 later version. |
|
11 |
|
12 Octave is distributed in the hope that it will be useful, but WITHOUT |
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
15 for more details. |
|
16 |
|
17 You should have received a copy of the GNU General Public License |
|
18 along with Octave; see the file COPYING. If not, write to the Free |
1315
|
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
1
|
20 |
|
21 */ |
|
22 |
1299
|
23 #if defined (__GNUG__) |
|
24 #pragma implementation |
|
25 #endif |
|
26 |
240
|
27 #ifdef HAVE_CONFIG_H |
1192
|
28 #include <config.h> |
1
|
29 #endif |
|
30 |
1558
|
31 #include <cctype> |
1355
|
32 #include <cstring> |
|
33 |
1728
|
34 #include <string> |
|
35 |
1558
|
36 #include <fstream.h> |
581
|
37 #include <iostream.h> |
|
38 |
1742
|
39 #include <SLList.h> |
|
40 |
1558
|
41 #include "mx-base.h" |
|
42 #include "Range.h" |
1755
|
43 #include "str-vec.h" |
1558
|
44 |
|
45 #include "arith-ops.h" |
1
|
46 #include "error.h" |
|
47 #include "gripes.h" |
1558
|
48 #include "idx-vector.h" |
1742
|
49 #include "mappers.h" |
747
|
50 #include "oct-map.h" |
1742
|
51 #include "oct-obj.h" |
1355
|
52 #include "pager.h" |
1558
|
53 #include "pr-output.h" |
|
54 #include "sysdep.h" |
1742
|
55 #include "pt-const.h" |
1558
|
56 #include "unwind-prot.h" |
1355
|
57 #include "user-prefs.h" |
1430
|
58 #include "utils.h" |
1558
|
59 #include "variables.h" |
|
60 |
2086
|
61 #ifndef OCT_VAL_REP |
|
62 #define OCT_VAL_REP octave_value::octave_value_rep |
1558
|
63 #endif |
|
64 |
|
65 #ifndef MAX |
|
66 #define MAX(a,b) ((a) > (b) ? (a) : (b)) |
|
67 #endif |
|
68 |
2086
|
69 #ifndef OCT_VAL_REP |
|
70 #define OCT_VAL_REP octave_value::octave_value_rep |
1558
|
71 #endif |
|
72 |
|
73 #ifndef MAX |
|
74 #define MAX(a,b) ((a) > (b) ? (a) : (b)) |
|
75 #endif |
|
76 |
|
77 // The following three variables could be made static members of the |
2086
|
78 // OCT_VAL_REP class. |
1558
|
79 |
|
80 // Pointer to the blocks of memory we manage. |
2086
|
81 static OCT_VAL_REP *tc_rep_newlist = 0; |
1558
|
82 |
|
83 // Multiplier for allocating new blocks. |
|
84 static const int tc_rep_newlist_grow_size = 128; |
|
85 |
|
86 // Indentation level for structures. |
1973
|
87 static int struct_indent = 0; |
1558
|
88 |
|
89 static void |
1973
|
90 increment_struct_indent (void) |
1558
|
91 { |
1973
|
92 struct_indent += 2; |
1558
|
93 } |
|
94 |
|
95 static void |
1973
|
96 decrement_struct_indent (void) |
1558
|
97 { |
1973
|
98 struct_indent -= 2; |
1558
|
99 } |
|
100 |
1827
|
101 static bool |
1558
|
102 any_element_is_complex (const ComplexMatrix& a) |
|
103 { |
|
104 int nr = a.rows (); |
|
105 int nc = a.columns (); |
1827
|
106 |
1558
|
107 for (int j = 0; j < nc; j++) |
|
108 for (int i = 0; i < nr; i++) |
|
109 if (imag (a.elem (i, j)) != 0.0) |
1827
|
110 return true; |
|
111 |
|
112 return false; |
1558
|
113 } |
747
|
114 |
1168
|
115 // The following three variables could be made static members of the |
2086
|
116 // octave_value class. |
1168
|
117 |
|
118 // Pointer to the blocks of memory we manage. |
2086
|
119 static octave_value *tc_newlist = 0; |
1168
|
120 |
|
121 // Multiplier for allocating new blocks. |
1299
|
122 static const int tc_newlist_grow_size = 128; |
1168
|
123 |
747
|
124 Octave_map |
2086
|
125 octave_value::map_value (void) const |
747
|
126 { |
|
127 return rep->map_value (); |
|
128 } |
1
|
129 |
2086
|
130 octave_value::~octave_value (void) |
1
|
131 { |
|
132 #if defined (MDEBUG) |
2086
|
133 cerr << "~octave_value: rep: " << rep |
1
|
134 << " rep->count: " << rep->count << "\n"; |
|
135 #endif |
|
136 |
|
137 if (--rep->count <= 0) |
|
138 { |
|
139 delete rep; |
531
|
140 rep = 0; |
1
|
141 } |
|
142 } |
|
143 |
|
144 void * |
2086
|
145 octave_value::operator new (size_t size) |
1
|
146 { |
2086
|
147 assert (size == sizeof (octave_value)); |
1168
|
148 |
1299
|
149 if (! tc_newlist) |
|
150 { |
2086
|
151 int block_size = tc_newlist_grow_size * sizeof (octave_value); |
|
152 tc_newlist = (octave_value *) new char [block_size]; |
1299
|
153 |
1321
|
154 int i = 0; |
|
155 |
|
156 for (i = 0; i < tc_newlist_grow_size - 1; i++) |
1299
|
157 tc_newlist[i].freeptr = &tc_newlist[i+1]; |
|
158 |
|
159 tc_newlist[i].freeptr = 0; |
|
160 } |
|
161 |
2086
|
162 octave_value *tmp = tc_newlist; |
1299
|
163 tc_newlist = tc_newlist->freeptr; |
1168
|
164 return tmp; |
1
|
165 } |
|
166 |
|
167 void |
2086
|
168 octave_value::operator delete (void *p, size_t /* size */) |
1
|
169 { |
2086
|
170 octave_value *tmp = (octave_value *) p; |
1299
|
171 tmp->freeptr = tc_newlist; |
|
172 tc_newlist = tmp; |
1
|
173 } |
|
174 |
747
|
175 // Simple assignment. |
|
176 |
2086
|
177 octave_value |
|
178 octave_value::operator = (const octave_value& a) |
747
|
179 { |
|
180 if (rep != a.rep) |
|
181 { |
|
182 if (--rep->count <= 0) |
|
183 delete rep; |
|
184 rep = a.rep; |
|
185 rep->count++; |
|
186 } |
|
187 return *this; |
|
188 } |
|
189 |
2086
|
190 octave_value |
|
191 octave_value::lookup_map_element (const string& ref, bool insert, |
1827
|
192 bool silent) |
1277
|
193 { |
2086
|
194 octave_value retval; |
1277
|
195 |
1755
|
196 if (! ref.empty ()) |
1277
|
197 { |
1755
|
198 SLList<string> list; |
|
199 |
|
200 size_t beg = 0; |
|
201 size_t end; |
|
202 |
1277
|
203 do |
|
204 { |
1755
|
205 end = ref.find ('.', beg); |
|
206 |
|
207 string tmp = (end == NPOS) |
|
208 ? ref.substr (beg) : ref.substr (beg, end - 1); |
|
209 |
|
210 list.append (tmp); |
1277
|
211 } |
1755
|
212 while (end != NPOS && (beg = end + 1)); |
1277
|
213 |
|
214 retval = lookup_map_element (list, insert, silent); |
|
215 } |
|
216 |
|
217 return retval; |
|
218 } |
|
219 |
2086
|
220 octave_value |
|
221 octave_value::lookup_map_element (SLList<string>& list, bool insert, |
1827
|
222 bool silent) |
747
|
223 { |
2086
|
224 octave_value retval; |
|
225 |
|
226 octave_value_rep *tmp_rep = rep; |
747
|
227 |
|
228 Pix p = list.first (); |
|
229 while (p) |
|
230 { |
1755
|
231 string elt = list (p); |
747
|
232 |
|
233 list.next (p); |
|
234 |
2086
|
235 octave_value tmp; |
1277
|
236 |
|
237 tmp = tmp_rep->lookup_map_element (elt, insert, silent); |
747
|
238 |
|
239 if (error_state) |
|
240 break; |
|
241 |
|
242 tmp_rep = tmp.rep; |
|
243 |
|
244 if (! p) |
|
245 retval = tmp; |
|
246 } |
|
247 |
|
248 return retval; |
|
249 } |
|
250 |
1199
|
251 void |
2086
|
252 octave_value::print (void) |
1199
|
253 { |
2095
|
254 print (octave_stdout); |
1199
|
255 } |
|
256 |
1755
|
257 void |
2086
|
258 octave_value::print_with_name (const string& name, bool print_padding) |
1755
|
259 { |
2095
|
260 print_with_name (octave_stdout, name, print_padding); |
1755
|
261 } |
|
262 |
|
263 void |
2086
|
264 octave_value::print_with_name (ostream& output_buf, const string& name, |
2095
|
265 bool print_padding) |
1755
|
266 { |
1827
|
267 bool pad_after = false; |
1755
|
268 |
|
269 if (user_pref.print_answer_id_name) |
|
270 { |
1973
|
271 if (print_as_scalar ()) |
1755
|
272 output_buf << name << " = "; |
1973
|
273 else if (print_as_structure ()) |
|
274 { |
|
275 pad_after = true; |
|
276 output_buf << name << " ="; |
|
277 } |
1755
|
278 else |
|
279 { |
1827
|
280 pad_after = true; |
1755
|
281 output_buf << name << " =\n\n"; |
|
282 } |
|
283 } |
|
284 |
|
285 print (output_buf); |
|
286 |
|
287 if (print_padding && pad_after) |
|
288 output_buf << "\n"; |
|
289 } |
|
290 |
747
|
291 // Simple structure assignment. |
|
292 |
|
293 void |
2086
|
294 octave_value::make_unique (void) |
747
|
295 { |
|
296 if (rep->count > 1) |
|
297 { |
|
298 --rep->count; |
2086
|
299 rep = new octave_value_rep (*rep); |
747
|
300 rep->count = 1; |
|
301 } |
|
302 |
|
303 if (rep->is_map ()) |
|
304 { |
|
305 for (Pix p = rep->a_map->first (); p != 0; rep->a_map->next (p)) |
|
306 { |
|
307 rep->a_map->contents (p) . make_unique (); |
|
308 } |
|
309 } |
|
310 } |
|
311 |
2086
|
312 octave_value::octave_value_rep * |
|
313 octave_value::make_unique_map (void) |
747
|
314 { |
|
315 if (! rep->is_map ()) |
|
316 { |
|
317 if (--rep->count <= 0) |
|
318 delete rep; |
|
319 |
|
320 Octave_map m; |
2086
|
321 rep = new octave_value_rep (m); |
747
|
322 rep->count = 1; |
|
323 } |
|
324 |
|
325 make_unique (); |
|
326 |
|
327 return rep; |
|
328 } |
|
329 |
2086
|
330 octave_value |
|
331 octave_value::assign_map_element (SLList<string>& list, |
|
332 octave_value& rhs) |
747
|
333 { |
2086
|
334 octave_value_rep *tmp_rep = make_unique_map (); |
747
|
335 |
|
336 if (rhs.is_map ()) |
|
337 rhs.make_unique (); |
|
338 |
|
339 Pix p = list.first (); |
|
340 while (p) |
|
341 { |
1755
|
342 string elt = list (p); |
747
|
343 |
|
344 list.next (p); |
|
345 |
2086
|
346 octave_value& tmp = tmp_rep->lookup_map_element (elt, 1); |
747
|
347 |
|
348 if (! p) |
|
349 { |
|
350 tmp = rhs; |
|
351 return tmp; |
|
352 } |
|
353 |
|
354 tmp_rep = tmp.make_unique_map (); |
|
355 } |
|
356 |
2086
|
357 return octave_value (); |
747
|
358 } |
|
359 |
|
360 // Indexed structure assignment. |
|
361 |
2086
|
362 octave_value |
|
363 octave_value::assign_map_element (SLList<string>& list, |
|
364 octave_value& rhs, |
|
365 const octave_value_list& args) |
747
|
366 { |
2086
|
367 octave_value_rep *tmp_rep = make_unique_map (); |
747
|
368 |
|
369 if (rhs.is_map ()) |
|
370 rhs.make_unique (); |
|
371 |
|
372 Pix p = list.first (); |
|
373 while (p) |
|
374 { |
1755
|
375 string elt = list (p); |
747
|
376 |
|
377 list.next (p); |
|
378 |
2086
|
379 octave_value& tmp = tmp_rep->lookup_map_element (elt, 1); |
747
|
380 |
|
381 if (! p) |
|
382 { |
|
383 tmp.assign (rhs, args); |
|
384 return tmp; |
|
385 } |
|
386 |
|
387 tmp_rep = tmp.make_unique_map (); |
|
388 } |
|
389 |
2086
|
390 return octave_value (); |
747
|
391 } |
|
392 |
2086
|
393 octave_value_list |
|
394 octave_value::eval (bool print, int, const octave_value_list& args) |
1742
|
395 { |
2086
|
396 octave_value_list retval; |
1742
|
397 |
|
398 if (args.length () > 0) |
|
399 retval(0) = rep->do_index (args); |
|
400 else |
|
401 retval(0) = *this; |
|
402 |
|
403 if (retval(0).is_defined ()) |
|
404 retval(0).eval (print); |
|
405 |
|
406 return retval; |
|
407 } |
|
408 |
747
|
409 void |
2086
|
410 octave_value::print_code (ostream& os) |
747
|
411 { |
|
412 print_code_indent (os); |
|
413 |
|
414 if (in_parens) |
|
415 os << "("; |
|
416 |
|
417 if (rep) |
|
418 rep->print_code (os); |
|
419 |
|
420 if (in_parens) |
|
421 os << ")"; |
|
422 } |
|
423 |
1299
|
424 // The real representation of constants. |
|
425 |
2086
|
426 OCT_VAL_REP::octave_value_rep (void) |
1299
|
427 { |
|
428 type_tag = unknown_constant; |
|
429 } |
|
430 |
2086
|
431 OCT_VAL_REP::octave_value_rep (double d) |
1299
|
432 { |
|
433 scalar = d; |
|
434 type_tag = scalar_constant; |
|
435 } |
|
436 |
2086
|
437 OCT_VAL_REP::octave_value_rep (const Matrix& m) |
1299
|
438 { |
|
439 if (m.rows () == 1 && m.columns () == 1) |
|
440 { |
|
441 scalar = m.elem (0, 0); |
|
442 type_tag = scalar_constant; |
|
443 } |
|
444 else |
|
445 { |
|
446 matrix = new Matrix (m); |
|
447 type_tag = matrix_constant; |
|
448 } |
|
449 } |
|
450 |
2086
|
451 OCT_VAL_REP::octave_value_rep (const DiagMatrix& d) |
1299
|
452 { |
|
453 if (d.rows () == 1 && d.columns () == 1) |
|
454 { |
|
455 scalar = d.elem (0, 0); |
|
456 type_tag = scalar_constant; |
|
457 } |
|
458 else |
|
459 { |
|
460 matrix = new Matrix (d); |
|
461 type_tag = matrix_constant; |
|
462 } |
|
463 } |
|
464 |
2086
|
465 OCT_VAL_REP::octave_value_rep (const RowVector& v, int prefer_column_vector) |
1299
|
466 { |
|
467 int len = v.capacity (); |
|
468 if (len == 1) |
|
469 { |
|
470 scalar = v.elem (0); |
|
471 type_tag = scalar_constant; |
|
472 } |
|
473 else |
|
474 { |
|
475 int pcv = (prefer_column_vector < 0) |
|
476 ? user_pref.prefer_column_vectors |
|
477 : prefer_column_vector; |
|
478 |
|
479 if (pcv) |
|
480 { |
|
481 Matrix m (len, 1); |
|
482 for (int i = 0; i < len; i++) |
|
483 m.elem (i, 0) = v.elem (i); |
|
484 matrix = new Matrix (m); |
|
485 type_tag = matrix_constant; |
|
486 } |
|
487 else |
|
488 { |
|
489 Matrix m (1, len); |
|
490 for (int i = 0; i < len; i++) |
|
491 m.elem (0, i) = v.elem (i); |
|
492 matrix = new Matrix (m); |
|
493 type_tag = matrix_constant; |
|
494 } |
|
495 } |
|
496 } |
|
497 |
2086
|
498 OCT_VAL_REP::octave_value_rep (const ColumnVector& v, int prefer_column_vector) |
1299
|
499 { |
|
500 int len = v.capacity (); |
|
501 if (len == 1) |
|
502 { |
|
503 scalar = v.elem (0); |
|
504 type_tag = scalar_constant; |
|
505 } |
|
506 else |
|
507 { |
|
508 int pcv = (prefer_column_vector < 0) |
|
509 ? user_pref.prefer_column_vectors |
|
510 : prefer_column_vector; |
|
511 |
|
512 if (pcv) |
|
513 { |
|
514 Matrix m (len, 1); |
|
515 for (int i = 0; i < len; i++) |
|
516 m.elem (i, 0) = v.elem (i); |
|
517 matrix = new Matrix (m); |
|
518 type_tag = matrix_constant; |
|
519 } |
|
520 else |
|
521 { |
|
522 Matrix m (1, len); |
|
523 for (int i = 0; i < len; i++) |
|
524 m.elem (0, i) = v.elem (i); |
|
525 matrix = new Matrix (m); |
|
526 type_tag = matrix_constant; |
|
527 } |
|
528 } |
|
529 } |
|
530 |
2086
|
531 OCT_VAL_REP::octave_value_rep (const Complex& c) |
1299
|
532 { |
1615
|
533 if (::imag (c) == 0.0) |
|
534 { |
|
535 scalar = ::real (c); |
|
536 type_tag = scalar_constant; |
|
537 } |
|
538 else |
|
539 { |
|
540 complex_scalar = new Complex (c); |
|
541 type_tag = complex_scalar_constant; |
|
542 } |
1299
|
543 } |
|
544 |
2086
|
545 OCT_VAL_REP::octave_value_rep (const ComplexMatrix& m) |
1299
|
546 { |
|
547 if (m.rows () == 1 && m.columns () == 1) |
|
548 { |
1615
|
549 Complex c = m.elem (0, 0); |
|
550 |
|
551 if (::imag (c) == 0.0) |
|
552 { |
|
553 scalar = ::real (c); |
|
554 type_tag = scalar_constant; |
|
555 } |
|
556 else |
|
557 { |
|
558 complex_scalar = new Complex (c); |
|
559 type_tag = complex_scalar_constant; |
|
560 } |
1299
|
561 } |
|
562 else |
|
563 { |
|
564 complex_matrix = new ComplexMatrix (m); |
|
565 type_tag = complex_matrix_constant; |
|
566 } |
|
567 } |
|
568 |
2086
|
569 OCT_VAL_REP::octave_value_rep (const ComplexDiagMatrix& d) |
1299
|
570 { |
|
571 if (d.rows () == 1 && d.columns () == 1) |
|
572 { |
1615
|
573 Complex c = d.elem (0, 0); |
|
574 |
|
575 if (::imag (c) == 0.0) |
|
576 { |
|
577 scalar = ::real (c); |
|
578 type_tag = scalar_constant; |
|
579 } |
|
580 else |
|
581 { |
|
582 complex_scalar = new Complex (c); |
|
583 type_tag = complex_scalar_constant; |
|
584 } |
1299
|
585 } |
|
586 else |
|
587 { |
|
588 complex_matrix = new ComplexMatrix (d); |
|
589 type_tag = complex_matrix_constant; |
|
590 } |
|
591 } |
|
592 |
2086
|
593 OCT_VAL_REP::octave_value_rep (const ComplexRowVector& v, |
1299
|
594 int prefer_column_vector) |
|
595 { |
|
596 int len = v.capacity (); |
|
597 if (len == 1) |
|
598 { |
1615
|
599 Complex c = v.elem (0); |
|
600 |
|
601 if (::imag (c) == 0.0) |
|
602 { |
|
603 scalar = ::real (c); |
|
604 type_tag = scalar_constant; |
|
605 } |
|
606 else |
|
607 { |
|
608 complex_scalar = new Complex (c); |
|
609 type_tag = complex_scalar_constant; |
|
610 } |
1299
|
611 } |
|
612 else |
|
613 { |
|
614 int pcv = (prefer_column_vector < 0) |
|
615 ? user_pref.prefer_column_vectors |
|
616 : prefer_column_vector; |
|
617 |
|
618 if (pcv) |
|
619 { |
|
620 ComplexMatrix m (len, 1); |
|
621 for (int i = 0; i < len; i++) |
|
622 m.elem (i, 0) = v.elem (i); |
|
623 complex_matrix = new ComplexMatrix (m); |
|
624 type_tag = complex_matrix_constant; |
|
625 } |
|
626 else |
|
627 { |
|
628 ComplexMatrix m (1, len); |
|
629 for (int i = 0; i < len; i++) |
|
630 m.elem (0, i) = v.elem (i); |
|
631 complex_matrix = new ComplexMatrix (m); |
|
632 type_tag = complex_matrix_constant; |
|
633 } |
|
634 } |
|
635 } |
|
636 |
2086
|
637 OCT_VAL_REP::octave_value_rep (const ComplexColumnVector& v, int |
1299
|
638 prefer_column_vector) |
|
639 { |
|
640 int len = v.capacity (); |
|
641 if (len == 1) |
|
642 { |
1615
|
643 Complex c = v.elem (0); |
|
644 |
|
645 if (::imag (c) == 0.0) |
|
646 { |
|
647 scalar = ::real (c); |
|
648 type_tag = scalar_constant; |
|
649 } |
|
650 else |
|
651 { |
|
652 complex_scalar = new Complex (c); |
|
653 type_tag = complex_scalar_constant; |
|
654 } |
1299
|
655 } |
|
656 else |
|
657 { |
|
658 int pcv = (prefer_column_vector < 0) |
|
659 ? user_pref.prefer_column_vectors |
|
660 : prefer_column_vector; |
|
661 |
|
662 if (pcv) |
|
663 { |
|
664 ComplexMatrix m (len, 1); |
|
665 for (int i = 0; i < len; i++) |
|
666 m.elem (i, 0) = v.elem (i); |
|
667 complex_matrix = new ComplexMatrix (m); |
|
668 type_tag = complex_matrix_constant; |
|
669 } |
|
670 else |
|
671 { |
|
672 ComplexMatrix m (1, len); |
|
673 for (int i = 0; i < len; i++) |
|
674 m.elem (0, i) = v.elem (i); |
|
675 complex_matrix = new ComplexMatrix (m); |
|
676 type_tag = complex_matrix_constant; |
|
677 } |
|
678 } |
|
679 } |
|
680 |
2086
|
681 OCT_VAL_REP::octave_value_rep (const char *s) |
1299
|
682 { |
1572
|
683 char_matrix = new charMatrix (s); |
|
684 type_tag = char_matrix_constant_str; |
1355
|
685 } |
|
686 |
2086
|
687 OCT_VAL_REP::octave_value_rep (const string& s) |
1731
|
688 { |
|
689 char_matrix = new charMatrix (s); |
|
690 type_tag = char_matrix_constant_str; |
1755
|
691 } |
|
692 |
2086
|
693 OCT_VAL_REP::octave_value_rep (const string_vector& s) |
1755
|
694 { |
|
695 int nr = s.length (); |
|
696 int nc = s.max_length (); |
|
697 char_matrix = new charMatrix (nr, nc, 0); |
|
698 for (int i = 0; i < nr; i++) |
|
699 { |
|
700 nc = s[i].length (); |
|
701 for (int j = 0; j < nc; j++) |
|
702 char_matrix->elem (i, j) = s[i][j]; |
|
703 } |
|
704 type_tag = char_matrix_constant_str; |
1731
|
705 } |
|
706 |
2086
|
707 OCT_VAL_REP::octave_value_rep (const charMatrix& chm, bool is_str) |
1355
|
708 { |
1572
|
709 char_matrix = new charMatrix (chm); |
|
710 type_tag = is_str ? char_matrix_constant_str : char_matrix_constant; |
1299
|
711 } |
|
712 |
2086
|
713 OCT_VAL_REP::octave_value_rep (double b, double l, double i) |
1299
|
714 { |
|
715 range = new Range (b, l, i); |
|
716 int nel = range->nelem (); |
|
717 if (nel > 1) |
|
718 type_tag = range_constant; |
|
719 else |
|
720 { |
|
721 delete range; |
|
722 if (nel == 1) |
|
723 { |
|
724 scalar = b; |
|
725 type_tag = scalar_constant; |
|
726 } |
|
727 else if (nel == 0) |
|
728 { |
|
729 matrix = new Matrix (); |
|
730 type_tag = matrix_constant; |
|
731 } |
|
732 else |
|
733 { |
|
734 type_tag = unknown_constant; |
|
735 if (nel == -1) |
|
736 ::error ("number of elements in range exceeds INT_MAX"); |
|
737 else |
|
738 ::error ("invalid range"); |
|
739 } |
|
740 } |
|
741 } |
|
742 |
2086
|
743 OCT_VAL_REP::octave_value_rep (const Range& r) |
1299
|
744 { |
|
745 int nel = r.nelem (); |
|
746 if (nel > 1) |
|
747 { |
|
748 range = new Range (r); |
|
749 type_tag = range_constant; |
|
750 } |
|
751 else if (nel == 1) |
|
752 { |
|
753 scalar = r.base (); |
|
754 type_tag = scalar_constant; |
|
755 } |
|
756 else if (nel == 0) |
|
757 { |
|
758 matrix = new Matrix (); |
|
759 type_tag = matrix_constant; |
|
760 } |
|
761 else |
|
762 { |
|
763 type_tag = unknown_constant; |
|
764 if (nel == -1) |
|
765 ::error ("number of elements in range exceeds INT_MAX"); |
|
766 else |
|
767 ::error ("invalid range"); |
|
768 } |
|
769 } |
|
770 |
2086
|
771 OCT_VAL_REP::octave_value_rep (const Octave_map& m) |
1299
|
772 { |
|
773 a_map = new Octave_map (m); |
|
774 type_tag = map_constant; |
|
775 } |
|
776 |
2086
|
777 OCT_VAL_REP::octave_value_rep (OCT_VAL_REP::constant_type t) |
1299
|
778 { |
|
779 assert (t == magic_colon || t == all_va_args); |
|
780 type_tag = t; |
|
781 } |
|
782 |
2086
|
783 OCT_VAL_REP::octave_value_rep (const octave_value_rep& t) |
1299
|
784 { |
|
785 type_tag = t.type_tag; |
|
786 |
|
787 switch (t.type_tag) |
|
788 { |
|
789 case unknown_constant: |
|
790 break; |
|
791 |
|
792 case scalar_constant: |
|
793 scalar = t.scalar; |
|
794 break; |
|
795 |
|
796 case matrix_constant: |
|
797 matrix = new Matrix (*(t.matrix)); |
|
798 break; |
|
799 |
1572
|
800 case char_matrix_constant: |
|
801 char_matrix = new charMatrix (*(t.char_matrix)); |
|
802 break; |
|
803 |
|
804 case char_matrix_constant_str: |
|
805 char_matrix = new charMatrix (*(t.char_matrix)); |
1299
|
806 break; |
|
807 |
|
808 case complex_matrix_constant: |
|
809 complex_matrix = new ComplexMatrix (*(t.complex_matrix)); |
|
810 break; |
|
811 |
|
812 case complex_scalar_constant: |
|
813 complex_scalar = new Complex (*(t.complex_scalar)); |
|
814 break; |
|
815 |
|
816 case range_constant: |
|
817 range = new Range (*(t.range)); |
|
818 break; |
|
819 |
|
820 case map_constant: |
|
821 a_map = new Octave_map (*(t.a_map)); |
|
822 break; |
|
823 |
|
824 case magic_colon: |
|
825 case all_va_args: |
|
826 break; |
|
827 } |
|
828 |
1755
|
829 orig_text = t.orig_text; |
1299
|
830 } |
|
831 |
2086
|
832 OCT_VAL_REP::~octave_value_rep (void) |
1299
|
833 { |
|
834 switch (type_tag) |
|
835 { |
|
836 case matrix_constant: |
|
837 delete matrix; |
|
838 break; |
|
839 |
|
840 case complex_scalar_constant: |
|
841 delete complex_scalar; |
|
842 break; |
|
843 |
|
844 case complex_matrix_constant: |
|
845 delete complex_matrix; |
|
846 break; |
|
847 |
1572
|
848 case char_matrix_constant: |
|
849 case char_matrix_constant_str: |
|
850 delete char_matrix; |
1299
|
851 break; |
|
852 |
|
853 case range_constant: |
|
854 delete range; |
|
855 break; |
|
856 |
|
857 case map_constant: |
|
858 delete a_map; |
|
859 break; |
|
860 |
|
861 case unknown_constant: |
|
862 case scalar_constant: |
|
863 case magic_colon: |
|
864 case all_va_args: |
|
865 break; |
|
866 } |
|
867 } |
|
868 |
|
869 void * |
2086
|
870 OCT_VAL_REP::operator new (size_t size) |
1299
|
871 { |
2086
|
872 assert (size == sizeof (OCT_VAL_REP)); |
1299
|
873 |
|
874 if (! tc_rep_newlist) |
|
875 { |
2086
|
876 int block_size = tc_rep_newlist_grow_size * sizeof (OCT_VAL_REP); |
|
877 tc_rep_newlist = (OCT_VAL_REP *) new char [block_size]; |
1299
|
878 |
1321
|
879 int i = 0; |
|
880 |
|
881 for (i = 0; i < tc_rep_newlist_grow_size - 1; i++) |
1299
|
882 tc_rep_newlist[i].freeptr = &tc_rep_newlist[i+1]; |
|
883 |
|
884 tc_rep_newlist[i].freeptr = 0; |
|
885 } |
|
886 |
2086
|
887 OCT_VAL_REP *tmp = tc_rep_newlist; |
1299
|
888 tc_rep_newlist = tc_rep_newlist->freeptr; |
|
889 return tmp; |
|
890 } |
|
891 |
|
892 void |
2086
|
893 OCT_VAL_REP::operator delete (void *p, size_t /* size */) |
1299
|
894 { |
2086
|
895 OCT_VAL_REP *tmp = (OCT_VAL_REP *) p; |
1299
|
896 tmp->freeptr = tc_rep_newlist; |
|
897 tc_rep_newlist = tmp; |
|
898 } |
|
899 |
|
900 int |
2086
|
901 OCT_VAL_REP::rows (void) const |
1299
|
902 { |
|
903 int retval = -1; |
|
904 |
|
905 switch (type_tag) |
|
906 { |
|
907 case scalar_constant: |
|
908 case complex_scalar_constant: |
|
909 retval = 1; |
|
910 break; |
|
911 |
1572
|
912 case char_matrix_constant: |
|
913 case char_matrix_constant_str: |
|
914 retval = char_matrix->rows (); |
1355
|
915 break; |
|
916 |
1299
|
917 case range_constant: |
|
918 retval = (columns () > 0); |
|
919 break; |
|
920 |
|
921 case matrix_constant: |
|
922 retval = matrix->rows (); |
|
923 break; |
|
924 |
|
925 case complex_matrix_constant: |
|
926 retval = complex_matrix->rows (); |
|
927 break; |
|
928 |
|
929 default: |
|
930 break; |
|
931 } |
|
932 |
|
933 return retval; |
|
934 } |
|
935 |
|
936 int |
2086
|
937 OCT_VAL_REP::columns (void) const |
1299
|
938 { |
|
939 int retval = -1; |
|
940 |
|
941 switch (type_tag) |
|
942 { |
|
943 case scalar_constant: |
|
944 case complex_scalar_constant: |
|
945 retval = 1; |
|
946 break; |
|
947 |
|
948 case matrix_constant: |
|
949 retval = matrix->columns (); |
|
950 break; |
|
951 |
|
952 case complex_matrix_constant: |
|
953 retval = complex_matrix->columns (); |
|
954 break; |
|
955 |
1572
|
956 case char_matrix_constant: |
|
957 case char_matrix_constant_str: |
|
958 retval = char_matrix->columns (); |
1299
|
959 break; |
|
960 |
|
961 case range_constant: |
|
962 retval = range->nelem (); |
|
963 break; |
|
964 |
|
965 default: |
|
966 break; |
|
967 } |
|
968 |
|
969 return retval; |
|
970 } |
|
971 |
2086
|
972 octave_value |
|
973 OCT_VAL_REP::all (void) const |
1299
|
974 { |
2086
|
975 octave_value retval; |
1299
|
976 |
|
977 if (error_state) |
|
978 return retval; |
|
979 |
|
980 if (! is_numeric_type ()) |
|
981 { |
2086
|
982 octave_value tmp = make_numeric (); |
1299
|
983 |
|
984 if (error_state) |
|
985 return retval; |
|
986 |
|
987 return tmp.all (); |
|
988 } |
|
989 |
|
990 switch (type_tag) |
|
991 { |
|
992 case scalar_constant: |
1355
|
993 retval = (double) (scalar != 0.0); |
1299
|
994 break; |
|
995 |
|
996 case matrix_constant: |
1355
|
997 retval = matrix->all (); |
1299
|
998 break; |
|
999 |
|
1000 case complex_scalar_constant: |
1355
|
1001 retval = (double) (*complex_scalar != 0.0); |
1299
|
1002 break; |
|
1003 |
|
1004 case complex_matrix_constant: |
1355
|
1005 retval = complex_matrix->all (); |
1299
|
1006 break; |
|
1007 |
|
1008 default: |
|
1009 gripe_wrong_type_arg ("all", *this); |
|
1010 break; |
|
1011 } |
|
1012 |
|
1013 return retval; |
|
1014 } |
|
1015 |
2086
|
1016 octave_value |
|
1017 OCT_VAL_REP::any (void) const |
1299
|
1018 { |
2086
|
1019 octave_value retval; |
1299
|
1020 |
|
1021 if (error_state) |
|
1022 return retval; |
|
1023 |
|
1024 if (! is_numeric_type ()) |
|
1025 { |
2086
|
1026 octave_value tmp = make_numeric (); |
1299
|
1027 |
|
1028 if (error_state) |
|
1029 return retval; |
|
1030 |
|
1031 return tmp.any (); |
|
1032 } |
|
1033 |
|
1034 switch (type_tag) |
|
1035 { |
|
1036 case scalar_constant: |
1355
|
1037 retval = (double) (scalar != 0.0); |
1299
|
1038 break; |
|
1039 |
|
1040 case matrix_constant: |
1355
|
1041 retval = matrix->any (); |
1299
|
1042 break; |
|
1043 |
|
1044 case complex_scalar_constant: |
1355
|
1045 retval = (double) (*complex_scalar != 0.0); |
1299
|
1046 break; |
|
1047 |
|
1048 case complex_matrix_constant: |
1355
|
1049 retval = complex_matrix->any (); |
1299
|
1050 break; |
|
1051 |
|
1052 default: |
|
1053 gripe_wrong_type_arg ("any", *this); |
|
1054 break; |
|
1055 } |
|
1056 |
|
1057 return retval; |
|
1058 } |
|
1059 |
1827
|
1060 bool |
2086
|
1061 OCT_VAL_REP::valid_as_scalar_index (void) const |
1299
|
1062 { |
|
1063 return (type_tag == magic_colon |
|
1064 || (type_tag == scalar_constant |
|
1065 && ! xisnan (scalar) |
|
1066 && NINT (scalar) == 1) |
|
1067 || (type_tag == range_constant |
|
1068 && range->nelem () == 1 |
|
1069 && ! xisnan (range->base ()) |
|
1070 && NINT (range->base ()) == 1)); |
|
1071 } |
|
1072 |
1827
|
1073 bool |
2086
|
1074 OCT_VAL_REP::valid_as_zero_index (void) const |
1299
|
1075 { |
|
1076 return ((type_tag == scalar_constant |
|
1077 && ! xisnan (scalar) |
|
1078 && NINT (scalar) == 0) |
|
1079 || (type_tag == matrix_constant |
|
1080 && matrix->rows () == 0 |
|
1081 && matrix->columns () == 0) |
|
1082 || (type_tag == range_constant |
|
1083 && range->nelem () == 1 |
|
1084 && ! xisnan (range->base ()) |
|
1085 && NINT (range->base ()) == 0)); |
|
1086 } |
|
1087 |
1827
|
1088 bool |
2086
|
1089 OCT_VAL_REP::is_true (void) const |
1299
|
1090 { |
1827
|
1091 int retval = false; |
1299
|
1092 |
|
1093 if (error_state) |
|
1094 return retval; |
|
1095 |
|
1096 if (! is_numeric_type ()) |
|
1097 { |
2086
|
1098 octave_value tmp = make_numeric (); |
1299
|
1099 |
|
1100 if (error_state) |
|
1101 return retval; |
|
1102 |
|
1103 return tmp.is_true (); |
|
1104 } |
|
1105 |
|
1106 switch (type_tag) |
|
1107 { |
|
1108 case scalar_constant: |
|
1109 retval = (scalar != 0.0); |
|
1110 break; |
|
1111 |
|
1112 case matrix_constant: |
|
1113 { |
|
1114 Matrix m = (matrix->all ()) . all (); |
|
1115 retval = (m.rows () == 1 |
|
1116 && m.columns () == 1 |
|
1117 && m.elem (0, 0) != 0.0); |
|
1118 } |
|
1119 break; |
|
1120 |
|
1121 case complex_scalar_constant: |
|
1122 retval = (*complex_scalar != 0.0); |
|
1123 break; |
|
1124 |
|
1125 case complex_matrix_constant: |
|
1126 { |
|
1127 Matrix m = (complex_matrix->all ()) . all (); |
|
1128 retval = (m.rows () == 1 |
|
1129 && m.columns () == 1 |
|
1130 && m.elem (0, 0) != 0.0); |
|
1131 } |
|
1132 break; |
|
1133 |
|
1134 default: |
|
1135 gripe_wrong_type_arg (0, *this); |
|
1136 break; |
|
1137 } |
|
1138 |
|
1139 return retval; |
|
1140 } |
|
1141 |
|
1142 static void |
|
1143 warn_implicit_conversion (const char *from, const char *to) |
|
1144 { |
|
1145 warning ("implicit conversion from %s to %s", from, to); |
|
1146 } |
|
1147 |
2067
|
1148 // XXX FIXME XXX -- we need a better way of handling conversions. |
|
1149 |
1299
|
1150 double |
2086
|
1151 OCT_VAL_REP::double_value (bool force_string_conv) const |
1299
|
1152 { |
|
1153 double retval = octave_NaN; |
|
1154 |
|
1155 switch (type_tag) |
|
1156 { |
|
1157 case scalar_constant: |
|
1158 retval = scalar; |
|
1159 break; |
|
1160 |
|
1161 case matrix_constant: |
|
1162 { |
|
1163 if (user_pref.do_fortran_indexing && rows () > 0 && columns () > 0) |
|
1164 retval = matrix->elem (0, 0); |
|
1165 else |
|
1166 gripe_invalid_conversion ("real matrix", "real scalar"); |
|
1167 } |
|
1168 break; |
|
1169 |
|
1170 case complex_matrix_constant: |
|
1171 case complex_scalar_constant: |
|
1172 { |
|
1173 int flag = user_pref.ok_to_lose_imaginary_part; |
|
1174 |
|
1175 if (flag < 0) |
|
1176 warn_implicit_conversion ("complex scalar", "real scalar"); |
|
1177 |
|
1178 if (flag) |
|
1179 { |
|
1180 if (type_tag == complex_scalar_constant) |
|
1181 retval = ::real (*complex_scalar); |
|
1182 else if (type_tag == complex_matrix_constant) |
|
1183 { |
|
1184 if (user_pref.do_fortran_indexing |
|
1185 && rows () > 0 && columns () > 0) |
|
1186 retval = ::real (complex_matrix->elem (0, 0)); |
|
1187 else |
|
1188 gripe_invalid_conversion ("complex matrix", "real scalar"); |
|
1189 } |
|
1190 else |
|
1191 panic_impossible (); |
|
1192 } |
|
1193 else |
|
1194 gripe_invalid_conversion ("complex scalar", "real scalar"); |
|
1195 } |
|
1196 break; |
|
1197 |
1572
|
1198 case char_matrix_constant: |
1299
|
1199 { |
1572
|
1200 int len = char_matrix->rows (); |
|
1201 if ((char_matrix->rows () == 1 && len == 1) |
|
1202 || (len > 1 && user_pref.do_fortran_indexing)) |
|
1203 retval = toascii ((int) char_matrix->elem (0, 0)); |
|
1204 else |
|
1205 gripe_invalid_conversion ("char matrix", "real scalar"); |
|
1206 } |
|
1207 break; |
|
1208 |
|
1209 case char_matrix_constant_str: |
|
1210 { |
1827
|
1211 int flag = force_string_conv; |
1299
|
1212 if (! flag) |
|
1213 flag = user_pref.implicit_str_to_num_ok; |
|
1214 |
|
1215 if (flag < 0) |
|
1216 warn_implicit_conversion ("string", "real scalar"); |
|
1217 |
1572
|
1218 int len = char_matrix->rows (); |
1355
|
1219 if (flag |
1572
|
1220 && ((char_matrix->rows () == 1 && len == 1) |
1355
|
1221 || (len > 1 && user_pref.do_fortran_indexing))) |
1572
|
1222 retval = toascii ((int) char_matrix->elem (0, 0)); |
1299
|
1223 else |
|
1224 gripe_invalid_conversion ("string", "real scalar"); |
|
1225 } |
|
1226 break; |
|
1227 |
|
1228 case range_constant: |
|
1229 { |
|
1230 int nel = range->nelem (); |
|
1231 if (nel == 1 || (nel > 1 && user_pref.do_fortran_indexing)) |
|
1232 retval = range->base (); |
|
1233 else |
|
1234 gripe_invalid_conversion ("range", "real scalar"); |
|
1235 } |
|
1236 break; |
|
1237 |
|
1238 default: |
|
1239 gripe_invalid_conversion (type_as_string (), "real scalar"); |
|
1240 break; |
|
1241 } |
|
1242 |
|
1243 return retval; |
|
1244 } |
|
1245 |
|
1246 Matrix |
2086
|
1247 OCT_VAL_REP::matrix_value (bool force_string_conv) const |
1299
|
1248 { |
|
1249 Matrix retval; |
|
1250 |
|
1251 switch (type_tag) |
|
1252 { |
|
1253 case scalar_constant: |
|
1254 retval = Matrix (1, 1, scalar); |
|
1255 break; |
|
1256 |
|
1257 case matrix_constant: |
|
1258 retval = *matrix; |
|
1259 break; |
|
1260 |
|
1261 case complex_scalar_constant: |
|
1262 case complex_matrix_constant: |
|
1263 { |
|
1264 int flag = user_pref.ok_to_lose_imaginary_part; |
|
1265 if (flag < 0) |
|
1266 warn_implicit_conversion ("complex matrix", "real matrix"); |
|
1267 |
|
1268 if (flag) |
|
1269 { |
|
1270 if (type_tag == complex_scalar_constant) |
|
1271 retval = Matrix (1, 1, ::real (*complex_scalar)); |
|
1272 else if (type_tag == complex_matrix_constant) |
|
1273 retval = ::real (*complex_matrix); |
|
1274 else |
|
1275 panic_impossible (); |
|
1276 } |
|
1277 else |
|
1278 gripe_invalid_conversion ("complex matrix", "real matrix"); |
|
1279 } |
|
1280 break; |
|
1281 |
1572
|
1282 case char_matrix_constant: |
|
1283 retval = Matrix (*char_matrix); |
|
1284 break; |
|
1285 |
|
1286 case char_matrix_constant_str: |
1299
|
1287 { |
1827
|
1288 int flag = force_string_conv; |
1299
|
1289 if (! flag) |
|
1290 flag = user_pref.implicit_str_to_num_ok; |
|
1291 |
|
1292 if (flag < 0) |
|
1293 warn_implicit_conversion ("string", "real matrix"); |
|
1294 |
|
1295 if (flag) |
1572
|
1296 retval = Matrix (*char_matrix); |
1299
|
1297 else |
|
1298 gripe_invalid_conversion ("string", "real matrix"); |
|
1299 } |
|
1300 break; |
|
1301 |
|
1302 case range_constant: |
|
1303 retval = range->matrix_value (); |
|
1304 break; |
|
1305 |
|
1306 default: |
|
1307 gripe_invalid_conversion (type_as_string (), "real matrix"); |
|
1308 break; |
|
1309 } |
|
1310 |
|
1311 return retval; |
|
1312 } |
|
1313 |
|
1314 Complex |
2086
|
1315 OCT_VAL_REP::complex_value (bool force_string_conv) const |
1299
|
1316 { |
|
1317 Complex retval (octave_NaN, octave_NaN); |
|
1318 |
|
1319 switch (type_tag) |
|
1320 { |
|
1321 case complex_scalar_constant: |
|
1322 retval = *complex_scalar; |
|
1323 break; |
|
1324 |
|
1325 case scalar_constant: |
|
1326 retval = scalar; |
|
1327 break; |
|
1328 |
|
1329 case complex_matrix_constant: |
|
1330 case matrix_constant: |
|
1331 { |
|
1332 if (user_pref.do_fortran_indexing && rows () > 0 && columns () > 0) |
|
1333 { |
|
1334 if (type_tag == complex_matrix_constant) |
|
1335 retval = complex_matrix->elem (0, 0); |
|
1336 else |
|
1337 retval = matrix->elem (0, 0); |
|
1338 } |
|
1339 else |
|
1340 gripe_invalid_conversion ("real matrix", "real scalar"); |
|
1341 } |
|
1342 break; |
|
1343 |
1572
|
1344 case char_matrix_constant: |
1299
|
1345 { |
1572
|
1346 int len = char_matrix->cols (); |
|
1347 if ((char_matrix->rows () == 1 && len == 1) |
|
1348 || (len > 1 && user_pref.do_fortran_indexing)) |
|
1349 retval = toascii ((int) char_matrix->elem (0, 0)); |
|
1350 else |
|
1351 gripe_invalid_conversion ("char matrix", "complex scalar"); |
|
1352 } |
|
1353 break; |
|
1354 |
|
1355 case char_matrix_constant_str: |
|
1356 { |
1827
|
1357 int flag = force_string_conv; |
1299
|
1358 if (! flag) |
|
1359 flag = user_pref.implicit_str_to_num_ok; |
|
1360 |
|
1361 if (flag < 0) |
|
1362 warn_implicit_conversion ("string", "complex scalar"); |
|
1363 |
1572
|
1364 int len = char_matrix->cols (); |
1355
|
1365 if (flag |
1572
|
1366 && ((char_matrix->rows () == 1 && len == 1) |
1355
|
1367 || (len > 1 && user_pref.do_fortran_indexing))) |
1572
|
1368 retval = toascii ((int) char_matrix->elem (0, 0)); |
1299
|
1369 else |
|
1370 gripe_invalid_conversion ("string", "complex scalar"); |
|
1371 } |
|
1372 break; |
|
1373 |
|
1374 case range_constant: |
|
1375 { |
|
1376 int nel = range->nelem (); |
|
1377 if (nel == 1 || (nel > 1 && user_pref.do_fortran_indexing)) |
|
1378 retval = range->base (); |
|
1379 else |
|
1380 gripe_invalid_conversion ("range", "complex scalar"); |
|
1381 } |
|
1382 break; |
|
1383 |
|
1384 default: |
|
1385 gripe_invalid_conversion (type_as_string (), "complex scalar"); |
|
1386 break; |
|
1387 } |
|
1388 |
|
1389 return retval; |
|
1390 } |
|
1391 |
|
1392 ComplexMatrix |
2086
|
1393 OCT_VAL_REP::complex_matrix_value (bool force_string_conv) const |
1299
|
1394 { |
|
1395 ComplexMatrix retval; |
|
1396 |
|
1397 switch (type_tag) |
|
1398 { |
|
1399 case scalar_constant: |
|
1400 retval = ComplexMatrix (1, 1, Complex (scalar)); |
|
1401 break; |
|
1402 |
|
1403 case complex_scalar_constant: |
|
1404 retval = ComplexMatrix (1, 1, *complex_scalar); |
|
1405 break; |
|
1406 |
|
1407 case matrix_constant: |
|
1408 retval = ComplexMatrix (*matrix); |
|
1409 break; |
|
1410 |
|
1411 case complex_matrix_constant: |
|
1412 retval = *complex_matrix; |
|
1413 break; |
|
1414 |
1572
|
1415 case char_matrix_constant: |
|
1416 retval = ComplexMatrix (*char_matrix); |
|
1417 break; |
|
1418 |
|
1419 case char_matrix_constant_str: |
1299
|
1420 { |
1827
|
1421 int flag = force_string_conv; |
1299
|
1422 if (! flag) |
|
1423 flag = user_pref.implicit_str_to_num_ok; |
|
1424 |
|
1425 if (flag < 0) |
|
1426 warn_implicit_conversion ("string", "complex matrix"); |
|
1427 |
|
1428 if (flag) |
1572
|
1429 retval = ComplexMatrix (*char_matrix); |
1299
|
1430 else |
1572
|
1431 gripe_invalid_conversion ("complex", "real matrix"); |
1299
|
1432 } |
|
1433 break; |
|
1434 |
|
1435 case range_constant: |
|
1436 retval = range->matrix_value (); |
|
1437 break; |
|
1438 |
|
1439 default: |
|
1440 gripe_invalid_conversion (type_as_string (), "complex matrix"); |
|
1441 break; |
|
1442 } |
|
1443 |
|
1444 return retval; |
|
1445 } |
|
1446 |
1572
|
1447 // XXX FIXME XXX -- this needs to try to do some conversions... |
|
1448 |
|
1449 charMatrix |
2086
|
1450 OCT_VAL_REP::char_matrix_value (bool force_string_conv) const |
1572
|
1451 { |
|
1452 charMatrix retval; |
|
1453 |
1827
|
1454 int flag = force_string_conv; |
1572
|
1455 if (! flag) |
|
1456 flag = user_pref.implicit_str_to_num_ok; |
|
1457 |
|
1458 switch (type_tag) |
|
1459 { |
|
1460 case char_matrix_constant: |
|
1461 case char_matrix_constant_str: |
|
1462 retval = *char_matrix; |
|
1463 break; |
|
1464 |
|
1465 default: |
1652
|
1466 if (! (rows () == 0 && columns () == 0)) |
|
1467 gripe_invalid_conversion (type_as_string (), "string"); |
1572
|
1468 break; |
|
1469 } |
|
1470 |
|
1471 return retval; |
|
1472 } |
|
1473 |
|
1474 charMatrix |
2086
|
1475 OCT_VAL_REP::all_strings (void) const |
1355
|
1476 { |
1572
|
1477 if (type_tag == char_matrix_constant_str) |
|
1478 return *char_matrix; |
1355
|
1479 else |
|
1480 { |
|
1481 gripe_invalid_conversion (type_as_string (), "string"); |
|
1482 return 0; |
|
1483 } |
|
1484 } |
|
1485 |
1728
|
1486 string |
2086
|
1487 OCT_VAL_REP::string_value (void) const |
1299
|
1488 { |
1728
|
1489 string retval; |
|
1490 |
1572
|
1491 if (type_tag == char_matrix_constant_str) |
1728
|
1492 retval = char_matrix->row_as_string (0); // XXX FIXME??? XXX |
1299
|
1493 else |
1728
|
1494 gripe_invalid_conversion (type_as_string (), "string"); |
|
1495 |
|
1496 return retval; |
1299
|
1497 } |
|
1498 |
|
1499 Range |
2086
|
1500 OCT_VAL_REP::range_value (void) const |
1299
|
1501 { |
|
1502 assert (type_tag == range_constant); |
|
1503 return *range; |
|
1504 } |
|
1505 |
|
1506 Octave_map |
2086
|
1507 OCT_VAL_REP::map_value (void) const |
1299
|
1508 { |
|
1509 assert (type_tag == map_constant); |
|
1510 return *a_map; |
|
1511 } |
|
1512 |
2086
|
1513 octave_value& |
|
1514 OCT_VAL_REP::lookup_map_element (const string& name, bool insert, bool silent) |
1299
|
1515 { |
2086
|
1516 static octave_value retval; |
1299
|
1517 |
|
1518 if (type_tag == map_constant) |
|
1519 { |
|
1520 Pix idx = a_map->seek (name); |
|
1521 |
|
1522 if (idx) |
|
1523 return a_map->contents (idx); |
|
1524 else if (insert) |
|
1525 return (*a_map) [name]; |
|
1526 else if (! silent) |
1755
|
1527 error ("structure has no member `%s'", name.c_str ()); |
1299
|
1528 } |
|
1529 else if (! silent) |
|
1530 error ("invalid structure access attempted"); |
|
1531 |
|
1532 return retval; |
|
1533 } |
|
1534 |
|
1535 // This could be made more efficient by doing all the work here rather |
|
1536 // than relying on matrix_value() to do any possible type conversions. |
|
1537 |
|
1538 ColumnVector |
2086
|
1539 OCT_VAL_REP::vector_value (bool force_string_conv, |
1827
|
1540 bool force_vector_conversion) const |
1299
|
1541 { |
|
1542 ColumnVector retval; |
|
1543 |
1827
|
1544 Matrix m = matrix_value (force_string_conv); |
1299
|
1545 |
|
1546 if (error_state) |
|
1547 return retval; |
|
1548 |
|
1549 int nr = m.rows (); |
|
1550 int nc = m.columns (); |
|
1551 if (nr == 1) |
|
1552 { |
|
1553 retval.resize (nc); |
|
1554 for (int i = 0; i < nc; i++) |
|
1555 retval.elem (i) = m (0, i); |
|
1556 } |
|
1557 else if (nc == 1) |
|
1558 { |
|
1559 retval.resize (nr); |
|
1560 for (int i = 0; i < nr; i++) |
|
1561 retval.elem (i) = m.elem (i, 0); |
|
1562 } |
|
1563 else if (nr > 0 && nc > 0 |
|
1564 && (user_pref.do_fortran_indexing || force_vector_conversion)) |
|
1565 { |
|
1566 retval.resize (nr * nc); |
|
1567 int k = 0; |
|
1568 for (int j = 0; j < nc; j++) |
|
1569 for (int i = 0; i < nr; i++) |
|
1570 retval.elem (k++) = m.elem (i, j); |
|
1571 } |
|
1572 else |
|
1573 gripe_invalid_conversion ("real matrix", "real vector"); |
|
1574 |
|
1575 return retval; |
|
1576 } |
|
1577 |
|
1578 // This could be made more efficient by doing all the work here rather |
|
1579 // than relying on complex_matrix_value() to do any possible type |
|
1580 // conversions. |
|
1581 |
|
1582 ComplexColumnVector |
2086
|
1583 OCT_VAL_REP::complex_vector_value (bool force_string_conv, |
1827
|
1584 bool force_vector_conversion) const |
1299
|
1585 { |
|
1586 ComplexColumnVector retval; |
|
1587 |
1827
|
1588 ComplexMatrix m = complex_matrix_value (force_string_conv); |
1299
|
1589 |
|
1590 if (error_state) |
|
1591 return retval; |
|
1592 |
|
1593 int nr = m.rows (); |
|
1594 int nc = m.columns (); |
|
1595 if (nr == 1) |
|
1596 { |
|
1597 retval.resize (nc); |
|
1598 for (int i = 0; i < nc; i++) |
|
1599 retval.elem (i) = m (0, i); |
|
1600 } |
|
1601 else if (nc == 1) |
|
1602 { |
|
1603 retval.resize (nr); |
|
1604 for (int i = 0; i < nr; i++) |
|
1605 retval.elem (i) = m.elem (i, 0); |
|
1606 } |
|
1607 else if (nr > 0 && nc > 0 |
|
1608 && (user_pref.do_fortran_indexing || force_vector_conversion)) |
|
1609 { |
|
1610 retval.resize (nr * nc); |
|
1611 int k = 0; |
|
1612 for (int j = 0; j < nc; j++) |
|
1613 for (int i = 0; i < nr; i++) |
|
1614 retval.elem (k++) = m.elem (i, j); |
|
1615 } |
|
1616 else |
|
1617 gripe_invalid_conversion ("complex matrix", "complex vector"); |
|
1618 |
|
1619 return retval; |
|
1620 } |
|
1621 |
2086
|
1622 octave_value |
|
1623 OCT_VAL_REP::convert_to_str (void) const |
1299
|
1624 { |
2086
|
1625 octave_value retval; |
1299
|
1626 |
|
1627 switch (type_tag) |
|
1628 { |
|
1629 case complex_scalar_constant: |
|
1630 case scalar_constant: |
|
1631 { |
|
1632 double d = double_value (); |
|
1633 |
|
1634 if (xisnan (d)) |
|
1635 { |
|
1636 ::error ("invalid conversion from NaN to character"); |
|
1637 return retval; |
|
1638 } |
|
1639 else |
|
1640 { |
1358
|
1641 // XXX FIXME XXX -- warn about out of range conversions? |
|
1642 |
1299
|
1643 int i = NINT (d); |
|
1644 char s[2]; |
|
1645 s[0] = (char) i; |
|
1646 s[1] = '\0'; |
2086
|
1647 retval = octave_value (s, 1); |
1299
|
1648 } |
|
1649 } |
|
1650 break; |
|
1651 |
|
1652 case complex_matrix_constant: |
|
1653 case matrix_constant: |
|
1654 { |
|
1655 if (rows () == 0 && columns () == 0) |
|
1656 { |
|
1657 char s = '\0'; |
2086
|
1658 retval = octave_value (&s, 1); |
1299
|
1659 } |
|
1660 else |
|
1661 { |
1355
|
1662 Matrix m = matrix_value (); |
|
1663 |
|
1664 int nr = m.rows (); |
|
1665 int nc = m.columns (); |
|
1666 |
|
1667 if (nr == 0 || nc == 0) |
1299
|
1668 { |
|
1669 char s = '\0'; |
2086
|
1670 retval = octave_value (&s, 1); |
1299
|
1671 } |
|
1672 else |
|
1673 { |
1572
|
1674 charMatrix chm (nr, nc); |
|
1675 |
|
1676 for (int j = 0; j < nc; j++) |
1299
|
1677 { |
1572
|
1678 for (int i = 0; i < nr; i++) |
1299
|
1679 { |
1355
|
1680 double d = m.elem (i, j); |
|
1681 |
|
1682 if (xisnan (d)) |
|
1683 { |
|
1684 ::error ("invalid conversion from NaN to character"); |
|
1685 return retval; |
|
1686 } |
|
1687 else |
|
1688 { |
1358
|
1689 // XXX FIXME XXX -- warn about out of |
|
1690 // range conversions? |
1355
|
1691 |
|
1692 int ival = NINT (d); |
1572
|
1693 chm.elem (i, j) = (char) ival; |
1355
|
1694 } |
1299
|
1695 } |
|
1696 } |
1355
|
1697 |
2086
|
1698 retval = octave_value (chm, 1); |
1299
|
1699 } |
|
1700 } |
|
1701 } |
|
1702 break; |
|
1703 |
|
1704 case range_constant: |
|
1705 { |
|
1706 Range r = range_value (); |
|
1707 double b = r.base (); |
|
1708 double incr = r.inc (); |
|
1709 int nel = r.nelem (); |
|
1710 char *s = new char [nel+1]; |
|
1711 s[nel] = '\0'; |
|
1712 for (int i = 0; i < nel; i++) |
|
1713 { |
|
1714 double d = b + i * incr; |
|
1715 |
|
1716 if (xisnan (d)) |
|
1717 { |
|
1718 ::error ("invalid conversion from NaN to character"); |
|
1719 delete [] s; |
|
1720 return retval; |
|
1721 } |
|
1722 else |
|
1723 { |
1358
|
1724 // XXX FIXME XXX -- warn about out of range |
|
1725 // conversions? |
|
1726 |
1299
|
1727 int ival = NINT (d); |
|
1728 s[i] = (char) ival; |
|
1729 } |
|
1730 } |
2086
|
1731 retval = octave_value (s, 1); |
1299
|
1732 delete [] s; |
|
1733 } |
|
1734 break; |
|
1735 |
1572
|
1736 case char_matrix_constant: |
2086
|
1737 retval = octave_value (*char_matrix, 1); |
1572
|
1738 break; |
|
1739 |
|
1740 case char_matrix_constant_str: |
2086
|
1741 retval = octave_value (*char_matrix, 1); |
1299
|
1742 break; |
|
1743 |
|
1744 default: |
|
1745 gripe_invalid_conversion (type_as_string (), "string"); |
|
1746 break; |
|
1747 } |
|
1748 |
|
1749 return retval; |
|
1750 } |
|
1751 |
|
1752 void |
2086
|
1753 OCT_VAL_REP::convert_to_row_or_column_vector (void) |
1299
|
1754 { |
|
1755 assert (type_tag == matrix_constant || type_tag == complex_matrix_constant); |
|
1756 |
|
1757 int nr = rows (); |
|
1758 int nc = columns (); |
|
1759 |
|
1760 if (nr == 1 || nc == 1) |
|
1761 return; |
|
1762 |
|
1763 int len = nr * nc; |
|
1764 |
|
1765 assert (len > 0); |
|
1766 |
|
1767 int new_nr = 1; |
|
1768 int new_nc = 1; |
|
1769 |
|
1770 if (user_pref.prefer_column_vectors) |
|
1771 new_nr = len; |
|
1772 else |
|
1773 new_nc = len; |
|
1774 |
|
1775 if (type_tag == matrix_constant) |
|
1776 { |
|
1777 Matrix *m = new Matrix (new_nr, new_nc); |
|
1778 |
|
1779 double *cop_out = matrix->fortran_vec (); |
|
1780 |
|
1781 for (int i = 0; i < len; i++) |
|
1782 { |
|
1783 if (new_nr == 1) |
|
1784 m->elem (0, i) = *cop_out++; |
|
1785 else |
|
1786 m->elem (i, 0) = *cop_out++; |
|
1787 } |
|
1788 |
|
1789 delete matrix; |
|
1790 matrix = m; |
|
1791 } |
|
1792 else |
|
1793 { |
|
1794 ComplexMatrix *cm = new ComplexMatrix (new_nr, new_nc); |
|
1795 |
|
1796 Complex *cop_out = complex_matrix->fortran_vec (); |
|
1797 |
|
1798 for (int i = 0; i < len; i++) |
|
1799 { |
|
1800 if (new_nr == 1) |
|
1801 cm->elem (0, i) = *cop_out++; |
|
1802 else |
|
1803 cm->elem (i, 0) = *cop_out++; |
|
1804 } |
|
1805 |
|
1806 delete complex_matrix; |
|
1807 complex_matrix = cm; |
|
1808 } |
|
1809 } |
|
1810 |
|
1811 void |
2086
|
1812 OCT_VAL_REP::convert_to_matrix_type (bool make_complex) |
1558
|
1813 { |
|
1814 switch (type_tag) |
|
1815 { |
|
1816 case complex_scalar_constant: |
|
1817 { |
|
1818 Complex *old_complex = complex_scalar; |
|
1819 complex_matrix = new ComplexMatrix (1, 1, *complex_scalar); |
|
1820 type_tag = complex_matrix_constant; |
|
1821 delete old_complex; |
|
1822 } |
|
1823 break; |
|
1824 |
|
1825 case scalar_constant: |
|
1826 { |
1581
|
1827 if (make_complex) |
|
1828 { |
|
1829 complex_matrix = new ComplexMatrix (1, 1, scalar); |
|
1830 type_tag = complex_matrix_constant; |
|
1831 } |
|
1832 else |
|
1833 { |
|
1834 matrix = new Matrix (1, 1, scalar); |
|
1835 type_tag = matrix_constant; |
|
1836 } |
1558
|
1837 } |
|
1838 break; |
|
1839 |
|
1840 case unknown_constant: |
|
1841 { |
1581
|
1842 if (make_complex) |
|
1843 { |
|
1844 complex_matrix = new ComplexMatrix (); |
|
1845 type_tag = complex_matrix_constant; |
|
1846 } |
|
1847 else |
|
1848 { |
|
1849 matrix = new Matrix (); |
|
1850 type_tag = matrix_constant; |
|
1851 } |
1558
|
1852 } |
|
1853 break; |
|
1854 |
1572
|
1855 case range_constant: |
|
1856 { |
1581
|
1857 if (make_complex) |
|
1858 { |
|
1859 ComplexMatrix *tmp = new ComplexMatrix (range->matrix_value ()); |
|
1860 delete range; |
|
1861 complex_matrix = tmp; |
|
1862 type_tag = complex_matrix_constant; |
|
1863 } |
|
1864 else |
|
1865 { |
|
1866 Matrix *tmp = new Matrix (range->matrix_value ()); |
|
1867 delete range; |
|
1868 matrix = tmp; |
|
1869 type_tag = matrix_constant; |
|
1870 } |
1572
|
1871 } |
|
1872 break; |
|
1873 |
1558
|
1874 default: |
|
1875 panic_impossible (); |
|
1876 break; |
|
1877 } |
|
1878 } |
|
1879 |
|
1880 void |
2086
|
1881 OCT_VAL_REP::force_numeric (bool force_string_conv) |
1299
|
1882 { |
|
1883 switch (type_tag) |
|
1884 { |
|
1885 case scalar_constant: |
|
1886 case matrix_constant: |
|
1887 case complex_scalar_constant: |
|
1888 case complex_matrix_constant: |
1572
|
1889 case char_matrix_constant: |
1299
|
1890 break; |
|
1891 |
1572
|
1892 case char_matrix_constant_str: |
1299
|
1893 { |
1827
|
1894 if (! force_string_conv && ! user_pref.implicit_str_to_num_ok) |
1299
|
1895 { |
1490
|
1896 ::error ("string to numeric conversion failed --\ |
|
1897 default conversion turned off"); |
1299
|
1898 return; |
|
1899 } |
|
1900 |
1572
|
1901 int nr = char_matrix->rows (); |
|
1902 int nc = char_matrix->cols (); |
1355
|
1903 |
|
1904 if (nr == 1 && nc == 1) |
1299
|
1905 { |
|
1906 type_tag = scalar_constant; |
1572
|
1907 double tmp = toascii ((int) char_matrix->elem (0, 0)); |
|
1908 delete char_matrix; |
|
1909 scalar = tmp; |
1299
|
1910 } |
1355
|
1911 else if (nr == 0 || nc == 0) |
1299
|
1912 { |
1572
|
1913 delete char_matrix; |
1299
|
1914 type_tag = matrix_constant; |
|
1915 matrix = new Matrix (0, 0); |
|
1916 } |
1355
|
1917 else if (nr > 0 && nc > 0) |
|
1918 { |
|
1919 type_tag = matrix_constant; |
|
1920 |
|
1921 Matrix *tm = new Matrix (nr, nc); |
|
1922 |
|
1923 for (int i = 0; i < nr; i++) |
|
1924 { |
|
1925 for (int j = 0; j < nc; j++) |
|
1926 { |
1572
|
1927 int c = (int) char_matrix->elem (i, j); |
1355
|
1928 tm->elem (i, j) = toascii (c); |
|
1929 } |
|
1930 } |
1572
|
1931 delete char_matrix; |
1355
|
1932 matrix = tm; |
|
1933 } |
1299
|
1934 else |
|
1935 panic_impossible (); |
|
1936 } |
|
1937 break; |
|
1938 |
|
1939 case range_constant: |
|
1940 { |
|
1941 int len = range->nelem (); |
|
1942 if (len > 1) |
|
1943 { |
|
1944 type_tag = matrix_constant; |
|
1945 Matrix *tm = new Matrix (1, len); |
|
1946 double b = range->base (); |
|
1947 double increment = range->inc (); |
|
1948 for (int i = 0; i < len; i++) |
|
1949 tm->elem (0, i) = b + i * increment; |
1572
|
1950 delete range; |
1299
|
1951 matrix = tm; |
|
1952 } |
|
1953 else if (len == 1) |
|
1954 { |
|
1955 type_tag = scalar_constant; |
|
1956 scalar = range->base (); |
|
1957 } |
|
1958 } |
|
1959 break; |
|
1960 |
|
1961 default: |
|
1962 gripe_invalid_conversion (type_as_string (), "numeric type"); |
|
1963 break; |
|
1964 } |
|
1965 } |
|
1966 |
2086
|
1967 octave_value |
|
1968 OCT_VAL_REP::make_numeric (bool force_string_conv) const |
1299
|
1969 { |
2086
|
1970 octave_value retval; |
1299
|
1971 |
|
1972 switch (type_tag) |
|
1973 { |
|
1974 case scalar_constant: |
1355
|
1975 retval = scalar; |
1299
|
1976 break; |
|
1977 |
|
1978 case matrix_constant: |
1355
|
1979 retval = *matrix; |
1299
|
1980 break; |
|
1981 |
|
1982 case complex_scalar_constant: |
1355
|
1983 retval = *complex_scalar; |
1299
|
1984 break; |
|
1985 |
|
1986 case complex_matrix_constant: |
1355
|
1987 retval = *complex_matrix; |
1299
|
1988 break; |
|
1989 |
1572
|
1990 case char_matrix_constant: |
|
1991 retval = *char_matrix; |
|
1992 break; |
|
1993 |
|
1994 case char_matrix_constant_str: |
|
1995 { |
1827
|
1996 int flag = force_string_conv; |
1572
|
1997 if (! flag) |
|
1998 flag = user_pref.implicit_str_to_num_ok; |
|
1999 |
|
2000 if (flag < 0) |
|
2001 warn_implicit_conversion ("string", "char matrix"); |
|
2002 |
|
2003 if (flag) |
|
2004 { |
|
2005 retval = *char_matrix; |
1827
|
2006 retval.force_numeric (force_string_conv); |
1572
|
2007 } |
|
2008 else |
|
2009 gripe_invalid_conversion ("string", "char matrix"); |
|
2010 } |
1299
|
2011 break; |
|
2012 |
|
2013 case range_constant: |
1355
|
2014 retval = *range; |
1827
|
2015 retval.force_numeric (force_string_conv); |
1299
|
2016 break; |
|
2017 |
|
2018 default: |
|
2019 gripe_invalid_conversion (type_as_string (), "numeric value"); |
|
2020 break; |
|
2021 } |
|
2022 |
|
2023 return retval; |
|
2024 } |
|
2025 |
|
2026 void |
2086
|
2027 OCT_VAL_REP::bump_value (tree_expression::type etype) |
1299
|
2028 { |
|
2029 switch (etype) |
|
2030 { |
|
2031 case tree_expression::increment: |
|
2032 switch (type_tag) |
|
2033 { |
|
2034 case scalar_constant: |
|
2035 scalar++; |
|
2036 break; |
|
2037 |
|
2038 case matrix_constant: |
|
2039 *matrix = *matrix + 1.0; |
|
2040 break; |
|
2041 |
|
2042 case complex_scalar_constant: |
|
2043 *complex_scalar = *complex_scalar + 1.0; |
|
2044 break; |
|
2045 |
|
2046 case complex_matrix_constant: |
|
2047 *complex_matrix = *complex_matrix + 1.0; |
|
2048 break; |
|
2049 |
|
2050 case range_constant: |
|
2051 range->set_base (range->base () + 1.0); |
|
2052 range->set_limit (range->limit () + 1.0); |
|
2053 break; |
|
2054 |
|
2055 default: |
|
2056 gripe_wrong_type_arg ("operator ++", type_as_string ()); |
|
2057 break; |
|
2058 } |
|
2059 break; |
|
2060 |
|
2061 case tree_expression::decrement: |
|
2062 switch (type_tag) |
|
2063 { |
|
2064 case scalar_constant: |
|
2065 scalar--; |
|
2066 break; |
|
2067 |
|
2068 case matrix_constant: |
|
2069 *matrix = *matrix - 1.0; |
|
2070 break; |
|
2071 |
|
2072 case range_constant: |
|
2073 range->set_base (range->base () - 1.0); |
|
2074 range->set_limit (range->limit () - 1.0); |
|
2075 break; |
|
2076 |
|
2077 default: |
|
2078 gripe_wrong_type_arg ("operator --", type_as_string ()); |
|
2079 break; |
|
2080 } |
|
2081 break; |
|
2082 |
|
2083 default: |
|
2084 panic_impossible (); |
|
2085 break; |
|
2086 } |
|
2087 } |
|
2088 |
|
2089 void |
2086
|
2090 OCT_VAL_REP::resize (int i, int j) |
1299
|
2091 { |
|
2092 switch (type_tag) |
|
2093 { |
|
2094 case matrix_constant: |
|
2095 matrix->resize (i, j); |
|
2096 break; |
|
2097 |
|
2098 case complex_matrix_constant: |
|
2099 complex_matrix->resize (i, j); |
|
2100 break; |
|
2101 |
|
2102 default: |
|
2103 gripe_wrong_type_arg ("resize", type_as_string ()); |
|
2104 break; |
|
2105 } |
|
2106 } |
|
2107 |
|
2108 void |
2086
|
2109 OCT_VAL_REP::resize (int i, int j, double val) |
1299
|
2110 { |
|
2111 switch (type_tag) |
|
2112 { |
|
2113 case matrix_constant: |
|
2114 matrix->resize (i, j, val); |
|
2115 break; |
|
2116 |
|
2117 case complex_matrix_constant: |
|
2118 complex_matrix->resize (i, j, val); |
|
2119 break; |
|
2120 |
|
2121 default: |
|
2122 gripe_wrong_type_arg ("resize", type_as_string ()); |
|
2123 break; |
|
2124 } |
|
2125 } |
|
2126 |
|
2127 void |
2086
|
2128 OCT_VAL_REP::stash_original_text (const string &s) |
1299
|
2129 { |
1755
|
2130 orig_text = s; |
1299
|
2131 } |
|
2132 |
|
2133 void |
2086
|
2134 OCT_VAL_REP::maybe_mutate (void) |
1299
|
2135 { |
|
2136 switch (type_tag) |
|
2137 { |
|
2138 case complex_scalar_constant: |
|
2139 if (::imag (*complex_scalar) == 0.0) |
|
2140 { |
|
2141 double d = ::real (*complex_scalar); |
|
2142 delete complex_scalar; |
|
2143 scalar = d; |
|
2144 type_tag = scalar_constant; |
|
2145 } |
|
2146 break; |
|
2147 |
|
2148 case complex_matrix_constant: |
|
2149 if (! any_element_is_complex (*complex_matrix)) |
|
2150 { |
|
2151 Matrix *m = new Matrix (::real (*complex_matrix)); |
|
2152 delete complex_matrix; |
|
2153 matrix = m; |
|
2154 type_tag = matrix_constant; |
|
2155 } |
|
2156 break; |
|
2157 |
|
2158 default: |
|
2159 break; |
|
2160 } |
|
2161 |
1358
|
2162 // Avoid calling rows() and columns() for things like magic_colon. |
1299
|
2163 |
|
2164 int nr = 1; |
|
2165 int nc = 1; |
|
2166 if (type_tag == matrix_constant |
|
2167 || type_tag == complex_matrix_constant |
|
2168 || type_tag == range_constant) |
|
2169 { |
|
2170 nr = rows (); |
|
2171 nc = columns (); |
|
2172 } |
|
2173 |
|
2174 switch (type_tag) |
|
2175 { |
|
2176 case matrix_constant: |
|
2177 if (nr == 1 && nc == 1) |
|
2178 { |
|
2179 double d = matrix->elem (0, 0); |
|
2180 delete matrix; |
|
2181 scalar = d; |
|
2182 type_tag = scalar_constant; |
|
2183 } |
|
2184 break; |
|
2185 |
|
2186 case complex_matrix_constant: |
|
2187 if (nr == 1 && nc == 1) |
|
2188 { |
|
2189 Complex c = complex_matrix->elem (0, 0); |
|
2190 delete complex_matrix; |
|
2191 complex_scalar = new Complex (c); |
|
2192 type_tag = complex_scalar_constant; |
|
2193 } |
|
2194 break; |
|
2195 |
|
2196 case range_constant: |
|
2197 if (nr == 1 && nc == 1) |
|
2198 { |
|
2199 double d = range->base (); |
|
2200 delete range; |
|
2201 scalar = d; |
|
2202 type_tag = scalar_constant; |
|
2203 } |
|
2204 break; |
|
2205 |
|
2206 default: |
|
2207 break; |
|
2208 } |
|
2209 } |
|
2210 |
|
2211 void |
2086
|
2212 OCT_VAL_REP::print (ostream& output_buf) |
1299
|
2213 { |
|
2214 if (error_state) |
|
2215 return; |
|
2216 |
|
2217 switch (type_tag) |
|
2218 { |
|
2219 case scalar_constant: |
1973
|
2220 octave_print_internal (output_buf, scalar, false); |
1299
|
2221 break; |
|
2222 |
|
2223 case matrix_constant: |
1973
|
2224 octave_print_internal (output_buf, *matrix, false, |
|
2225 struct_indent); |
1299
|
2226 break; |
|
2227 |
|
2228 case complex_scalar_constant: |
1973
|
2229 octave_print_internal (output_buf, *complex_scalar, false); |
1299
|
2230 break; |
|
2231 |
|
2232 case complex_matrix_constant: |
1973
|
2233 octave_print_internal (output_buf, *complex_matrix, false, |
|
2234 struct_indent); |
1299
|
2235 break; |
|
2236 |
1572
|
2237 case char_matrix_constant: |
1973
|
2238 octave_print_internal (output_buf, *char_matrix, false, |
|
2239 struct_indent); |
1572
|
2240 break; |
|
2241 |
|
2242 case char_matrix_constant_str: |
1973
|
2243 octave_print_internal (output_buf, *char_matrix, false, true, |
|
2244 struct_indent); |
1299
|
2245 break; |
|
2246 |
|
2247 case range_constant: |
1973
|
2248 octave_print_internal (output_buf, *range, false, struct_indent); |
1299
|
2249 break; |
|
2250 |
|
2251 case map_constant: |
|
2252 { |
1358
|
2253 // XXX FIXME XXX -- would be nice to print the output in some |
|
2254 // standard order. Maybe all substructures first, maybe |
|
2255 // alphabetize entries, etc. |
|
2256 |
2086
|
2257 begin_unwind_frame ("OCT_VAL_REP_print"); |
1299
|
2258 |
1973
|
2259 unwind_protect_int (struct_indent); |
1299
|
2260 unwind_protect_int (user_pref.struct_levels_to_print); |
|
2261 |
|
2262 if (user_pref.struct_levels_to_print-- > 0) |
|
2263 { |
1973
|
2264 output_buf.form ("\n%*s{\n", struct_indent, ""); |
|
2265 |
|
2266 increment_struct_indent (); |
|
2267 |
|
2268 Pix p = a_map->first (); |
|
2269 |
|
2270 while (p) |
1299
|
2271 { |
1973
|
2272 bool pad_after = false; |
|
2273 |
1755
|
2274 string key = a_map->key (p); |
2086
|
2275 octave_value val = a_map->contents (p); |
1299
|
2276 |
1973
|
2277 a_map->next (p); |
|
2278 |
|
2279 output_buf.form ("%*s%s =", struct_indent, |
1755
|
2280 "", key.c_str ()); |
|
2281 |
1973
|
2282 if (val.print_as_scalar ()) |
|
2283 output_buf << " "; |
|
2284 else if (val.print_as_structure ()) |
|
2285 { |
|
2286 if (p) |
|
2287 pad_after = true; |
|
2288 } |
|
2289 else |
|
2290 { |
|
2291 if (p) |
|
2292 pad_after = true; |
|
2293 |
|
2294 output_buf << "\n\n"; |
|
2295 } |
1299
|
2296 |
|
2297 val.print (output_buf); |
1973
|
2298 |
|
2299 if (pad_after) |
|
2300 output_buf << "\n"; |
1299
|
2301 } |
|
2302 |
1973
|
2303 decrement_struct_indent (); |
|
2304 |
|
2305 output_buf.form ("%*s%s", struct_indent, "", "}\n"); |
1299
|
2306 } |
|
2307 else |
1973
|
2308 output_buf << " <structure>\n"; |
1299
|
2309 |
2086
|
2310 run_unwind_frame ("OCT_VAL_REP_print"); |
1299
|
2311 } |
|
2312 break; |
|
2313 |
|
2314 case unknown_constant: |
|
2315 case magic_colon: |
|
2316 case all_va_args: |
|
2317 panic_impossible (); |
|
2318 break; |
|
2319 } |
|
2320 } |
|
2321 |
|
2322 void |
2086
|
2323 OCT_VAL_REP::print_code (ostream& os) |
1299
|
2324 { |
|
2325 switch (type_tag) |
|
2326 { |
|
2327 case scalar_constant: |
1755
|
2328 if (orig_text.empty ()) |
|
2329 octave_print_internal (os, scalar, 1); |
|
2330 else |
1299
|
2331 os << orig_text; |
|
2332 break; |
|
2333 |
|
2334 case matrix_constant: |
|
2335 octave_print_internal (os, *matrix, 1); |
|
2336 break; |
|
2337 |
|
2338 case complex_scalar_constant: |
|
2339 { |
|
2340 double re = complex_scalar->real (); |
|
2341 double im = complex_scalar->imag (); |
|
2342 |
1358
|
2343 // If we have the original text and a pure imaginary, just |
|
2344 // print the original text, because this must be a constant |
|
2345 // that was parsed as part of a function. |
1299
|
2346 |
1755
|
2347 if (! orig_text.empty () && re == 0.0 && im > 0.0) |
1299
|
2348 os << orig_text; |
|
2349 else |
|
2350 octave_print_internal (os, *complex_scalar, 1); |
|
2351 } |
|
2352 break; |
|
2353 |
|
2354 case complex_matrix_constant: |
|
2355 octave_print_internal (os, *complex_matrix, 1); |
|
2356 break; |
|
2357 |
1572
|
2358 case char_matrix_constant: |
|
2359 octave_print_internal (os, *char_matrix, 1); |
|
2360 break; |
|
2361 |
|
2362 case char_matrix_constant_str: |
|
2363 octave_print_internal (os, *char_matrix, 1, 1); |
1299
|
2364 break; |
|
2365 |
|
2366 case range_constant: |
|
2367 octave_print_internal (os, *range, 1); |
|
2368 break; |
|
2369 |
|
2370 case magic_colon: |
|
2371 os << ":"; |
|
2372 break; |
|
2373 |
|
2374 case all_va_args: |
|
2375 os << "all_va_args"; |
|
2376 break; |
|
2377 |
|
2378 case map_constant: |
|
2379 case unknown_constant: |
|
2380 panic_impossible (); |
|
2381 break; |
|
2382 } |
|
2383 } |
|
2384 |
|
2385 void |
2086
|
2386 OCT_VAL_REP::gripe_wrong_type_arg (const char *name, |
|
2387 const octave_value_rep& tcr) const |
1299
|
2388 { |
|
2389 if (name) |
|
2390 ::error ("%s: wrong type argument `%s'", name, tcr.type_as_string ()); |
|
2391 else |
|
2392 ::error ("wrong type argument `%s'", name, tcr.type_as_string ()); |
|
2393 } |
|
2394 |
|
2395 char * |
2086
|
2396 OCT_VAL_REP::type_as_string (void) const |
1299
|
2397 { |
|
2398 switch (type_tag) |
|
2399 { |
|
2400 case scalar_constant: |
|
2401 return "real scalar"; |
|
2402 |
|
2403 case matrix_constant: |
|
2404 return "real matrix"; |
|
2405 |
|
2406 case complex_scalar_constant: |
|
2407 return "complex scalar"; |
|
2408 |
|
2409 case complex_matrix_constant: |
|
2410 return "complex matrix"; |
|
2411 |
1572
|
2412 case char_matrix_constant: |
|
2413 return "char matrix"; |
|
2414 |
|
2415 case char_matrix_constant_str: |
1299
|
2416 return "string"; |
|
2417 |
|
2418 case range_constant: |
|
2419 return "range"; |
|
2420 |
|
2421 case map_constant: |
|
2422 return "structure"; |
|
2423 |
|
2424 default: |
|
2425 return "<unknown type>"; |
|
2426 } |
|
2427 } |
|
2428 |
2086
|
2429 octave_value |
|
2430 do_binary_op (octave_value& a, octave_value& b, tree_expression::type t) |
1299
|
2431 { |
2086
|
2432 octave_value retval; |
1299
|
2433 |
1827
|
2434 bool first_empty = (a.rows () == 0 || a.columns () == 0); |
|
2435 bool second_empty = (b.rows () == 0 || b.columns () == 0); |
1299
|
2436 |
|
2437 if (first_empty || second_empty) |
|
2438 { |
|
2439 int flag = user_pref.propagate_empty_matrices; |
|
2440 if (flag < 0) |
|
2441 warning ("binary operation on empty matrix"); |
|
2442 else if (flag == 0) |
|
2443 { |
|
2444 ::error ("invalid binary operation on empty matrix"); |
|
2445 return retval; |
|
2446 } |
|
2447 } |
|
2448 |
2086
|
2449 octave_value tmp_a = a.make_numeric (); |
1299
|
2450 |
|
2451 if (error_state) |
|
2452 return retval; |
|
2453 |
2086
|
2454 octave_value tmp_b = b.make_numeric (); |
1299
|
2455 |
|
2456 if (error_state) |
|
2457 return retval; |
|
2458 |
2086
|
2459 OCT_VAL_REP::constant_type a_type = tmp_a.const_type (); |
|
2460 OCT_VAL_REP::constant_type b_type = tmp_b.const_type (); |
1299
|
2461 |
|
2462 double d1, d2; |
|
2463 Matrix m1, m2; |
|
2464 Complex c1, c2; |
|
2465 ComplexMatrix cm1, cm2; |
|
2466 |
|
2467 switch (a_type) |
|
2468 { |
2086
|
2469 case OCT_VAL_REP::scalar_constant: |
1299
|
2470 |
|
2471 d1 = tmp_a.double_value (); |
|
2472 |
|
2473 switch (b_type) |
|
2474 { |
2086
|
2475 case OCT_VAL_REP::scalar_constant: |
1299
|
2476 d2 = tmp_b.double_value (); |
|
2477 retval = do_binary_op (d1, d2, t); |
|
2478 break; |
|
2479 |
2086
|
2480 case OCT_VAL_REP::matrix_constant: |
|
2481 case OCT_VAL_REP::char_matrix_constant: |
1299
|
2482 m2 = tmp_b.matrix_value (); |
|
2483 retval = do_binary_op (d1, m2, t); |
|
2484 break; |
|
2485 |
2086
|
2486 case OCT_VAL_REP::complex_scalar_constant: |
1299
|
2487 c2 = tmp_b.complex_value (); |
|
2488 retval = do_binary_op (d1, c2, t); |
|
2489 break; |
|
2490 |
2086
|
2491 case OCT_VAL_REP::complex_matrix_constant: |
1299
|
2492 cm2 = tmp_b.complex_matrix_value (); |
|
2493 retval = do_binary_op (d1, cm2, t); |
|
2494 break; |
|
2495 |
|
2496 default: |
|
2497 gripe_wrong_type_arg_for_binary_op (tmp_b); |
|
2498 break; |
|
2499 } |
|
2500 break; |
|
2501 |
2086
|
2502 case OCT_VAL_REP::matrix_constant: |
|
2503 case OCT_VAL_REP::char_matrix_constant: |
1299
|
2504 |
|
2505 m1 = tmp_a.matrix_value (); |
|
2506 |
|
2507 switch (b_type) |
|
2508 { |
2086
|
2509 case OCT_VAL_REP::scalar_constant: |
1299
|
2510 d2 = tmp_b.double_value (); |
|
2511 retval = do_binary_op (m1, d2, t); |
|
2512 break; |
|
2513 |
2086
|
2514 case OCT_VAL_REP::matrix_constant: |
|
2515 case OCT_VAL_REP::char_matrix_constant: |
1299
|
2516 m2 = tmp_b.matrix_value (); |
|
2517 retval = do_binary_op (m1, m2, t); |
|
2518 break; |
|
2519 |
2086
|
2520 case OCT_VAL_REP::complex_scalar_constant: |
1299
|
2521 c2 = tmp_b.complex_value (); |
|
2522 retval = do_binary_op (m1, c2, t); |
|
2523 break; |
|
2524 |
2086
|
2525 case OCT_VAL_REP::complex_matrix_constant: |
1299
|
2526 cm2 = tmp_b.complex_matrix_value (); |
|
2527 retval = do_binary_op (m1, cm2, t); |
|
2528 break; |
|
2529 |
|
2530 default: |
|
2531 gripe_wrong_type_arg_for_binary_op (tmp_b); |
|
2532 break; |
|
2533 } |
|
2534 break; |
|
2535 |
2086
|
2536 case OCT_VAL_REP::complex_scalar_constant: |
1299
|
2537 |
|
2538 c1 = tmp_a.complex_value (); |
|
2539 |
|
2540 switch (b_type) |
|
2541 { |
2086
|
2542 case OCT_VAL_REP::scalar_constant: |
1299
|
2543 d2 = tmp_b.double_value (); |
|
2544 retval = do_binary_op (c1, d2, t); |
|
2545 break; |
|
2546 |
2086
|
2547 case OCT_VAL_REP::matrix_constant: |
|
2548 case OCT_VAL_REP::char_matrix_constant: |
1299
|
2549 m2 = tmp_b.matrix_value (); |
|
2550 retval = do_binary_op (c1, m2, t); |
|
2551 break; |
|
2552 |
2086
|
2553 case OCT_VAL_REP::complex_scalar_constant: |
1299
|
2554 c2 = tmp_b.complex_value (); |
|
2555 retval = do_binary_op (c1, c2, t); |
|
2556 break; |
|
2557 |
2086
|
2558 case OCT_VAL_REP::complex_matrix_constant: |
1299
|
2559 cm2 = tmp_b.complex_matrix_value (); |
|
2560 retval = do_binary_op (c1, cm2, t); |
|
2561 break; |
|
2562 |
|
2563 default: |
|
2564 gripe_wrong_type_arg_for_binary_op (tmp_b); |
|
2565 break; |
|
2566 } |
|
2567 break; |
|
2568 |
2086
|
2569 case OCT_VAL_REP::complex_matrix_constant: |
1299
|
2570 |
|
2571 cm1 = tmp_a.complex_matrix_value (); |
|
2572 |
|
2573 switch (b_type) |
|
2574 { |
2086
|
2575 case OCT_VAL_REP::scalar_constant: |
1299
|
2576 d2 = tmp_b.double_value (); |
|
2577 retval = do_binary_op (cm1, d2, t); |
|
2578 break; |
|
2579 |
2086
|
2580 case OCT_VAL_REP::matrix_constant: |
|
2581 case OCT_VAL_REP::char_matrix_constant: |
1299
|
2582 m2 = tmp_b.matrix_value (); |
|
2583 retval = do_binary_op (cm1, m2, t); |
|
2584 break; |
|
2585 |
2086
|
2586 case OCT_VAL_REP::complex_scalar_constant: |
1299
|
2587 c2 = tmp_b.complex_value (); |
|
2588 retval = do_binary_op (cm1, c2, t); |
|
2589 break; |
|
2590 |
2086
|
2591 case OCT_VAL_REP::complex_matrix_constant: |
1299
|
2592 cm2 = tmp_b.complex_matrix_value (); |
|
2593 retval = do_binary_op (cm1, cm2, t); |
|
2594 break; |
|
2595 |
|
2596 default: |
|
2597 gripe_wrong_type_arg_for_binary_op (tmp_b); |
|
2598 break; |
|
2599 } |
|
2600 break; |
|
2601 |
|
2602 default: |
|
2603 gripe_wrong_type_arg_for_binary_op (tmp_a); |
|
2604 break; |
|
2605 } |
|
2606 |
|
2607 return retval; |
|
2608 } |
|
2609 |
2086
|
2610 octave_value |
|
2611 do_unary_op (octave_value& a, tree_expression::type t) |
1299
|
2612 { |
2086
|
2613 octave_value retval; |
1299
|
2614 |
|
2615 if (a.rows () == 0 || a.columns () == 0) |
|
2616 { |
|
2617 int flag = user_pref.propagate_empty_matrices; |
|
2618 if (flag < 0) |
|
2619 warning ("unary operation on empty matrix"); |
|
2620 else if (flag == 0) |
|
2621 { |
|
2622 ::error ("invalid unary operation on empty matrix"); |
|
2623 return retval; |
|
2624 } |
|
2625 } |
|
2626 |
2086
|
2627 octave_value tmp_a = a.make_numeric (); |
1299
|
2628 |
|
2629 if (error_state) |
|
2630 return retval; |
|
2631 |
|
2632 switch (tmp_a.const_type ()) |
|
2633 { |
2086
|
2634 case OCT_VAL_REP::scalar_constant: |
1299
|
2635 retval = do_unary_op (tmp_a.double_value (), t); |
|
2636 break; |
|
2637 |
2086
|
2638 case OCT_VAL_REP::matrix_constant: |
1299
|
2639 { |
|
2640 Matrix m = tmp_a.matrix_value (); |
|
2641 retval = do_unary_op (m, t); |
|
2642 } |
|
2643 break; |
|
2644 |
2086
|
2645 case OCT_VAL_REP::complex_scalar_constant: |
1299
|
2646 retval = do_unary_op (tmp_a.complex_value (), t); |
|
2647 break; |
|
2648 |
2086
|
2649 case OCT_VAL_REP::complex_matrix_constant: |
1299
|
2650 { |
|
2651 ComplexMatrix m = tmp_a.complex_matrix_value (); |
|
2652 retval = do_unary_op (m, t); |
|
2653 } |
|
2654 break; |
|
2655 |
|
2656 default: |
|
2657 gripe_wrong_type_arg_for_unary_op (tmp_a); |
|
2658 break; |
|
2659 } |
|
2660 |
|
2661 return retval; |
|
2662 } |
|
2663 |
|
2664 // Indexing operations for the tree-constant representation class. |
1558
|
2665 |
|
2666 void |
2086
|
2667 OCT_VAL_REP::clear_index (void) |
1558
|
2668 { |
|
2669 switch (type_tag) |
|
2670 { |
|
2671 case matrix_constant: |
|
2672 matrix->clear_index (); |
|
2673 break; |
|
2674 |
2086
|
2675 case OCT_VAL_REP::complex_matrix_constant: |
1558
|
2676 complex_matrix->clear_index (); |
|
2677 break; |
|
2678 |
1572
|
2679 case char_matrix_constant: |
|
2680 case char_matrix_constant_str: |
|
2681 char_matrix->clear_index (); |
|
2682 break; |
|
2683 |
1558
|
2684 default: |
|
2685 panic_impossible (); |
|
2686 break; |
|
2687 } |
|
2688 } |
|
2689 |
|
2690 #if 0 |
|
2691 void |
2086
|
2692 OCT_VAL_REP::set_index (double d) |
1558
|
2693 { |
|
2694 switch (type_tag) |
|
2695 { |
|
2696 case matrix_constant: |
|
2697 matrix->set_index (d); |
|
2698 break; |
|
2699 |
2086
|
2700 case OCT_VAL_REP::complex_matrix_constant: |
1558
|
2701 complex_matrix->set_index (d); |
|
2702 break; |
|
2703 |
2086
|
2704 case OCT_VAL_REP::char_matrix_constant: |
|
2705 case OCT_VAL_REP::char_matrix_constant_str: |
1572
|
2706 char_matrix->set_index (d); |
|
2707 break; |
|
2708 |
1558
|
2709 default: |
|
2710 panic_impossible (); |
|
2711 break; |
|
2712 } |
|
2713 } |
|
2714 #endif |
|
2715 |
|
2716 void |
2086
|
2717 OCT_VAL_REP::set_index (const Range& r) |
1558
|
2718 { |
|
2719 switch (type_tag) |
|
2720 { |
|
2721 case matrix_constant: |
|
2722 matrix->set_index (r); |
|
2723 break; |
|
2724 |
2086
|
2725 case OCT_VAL_REP::complex_matrix_constant: |
1558
|
2726 complex_matrix->set_index (r); |
|
2727 break; |
|
2728 |
2086
|
2729 case OCT_VAL_REP::char_matrix_constant: |
|
2730 case OCT_VAL_REP::char_matrix_constant_str: |
1572
|
2731 char_matrix->set_index (r); |
|
2732 break; |
|
2733 |
1558
|
2734 default: |
|
2735 panic_impossible (); |
|
2736 break; |
|
2737 } |
|
2738 } |
|
2739 |
|
2740 void |
2086
|
2741 OCT_VAL_REP::set_index (const ColumnVector& v) |
1558
|
2742 { |
|
2743 switch (type_tag) |
|
2744 { |
|
2745 case matrix_constant: |
|
2746 matrix->set_index (v); |
|
2747 break; |
|
2748 |
2086
|
2749 case OCT_VAL_REP::complex_matrix_constant: |
1558
|
2750 complex_matrix->set_index (v); |
|
2751 break; |
|
2752 |
2086
|
2753 case OCT_VAL_REP::char_matrix_constant: |
|
2754 case OCT_VAL_REP::char_matrix_constant_str: |
1572
|
2755 char_matrix->set_index (v); |
|
2756 break; |
|
2757 |
1558
|
2758 default: |
|
2759 panic_impossible (); |
|
2760 break; |
|
2761 } |
|
2762 } |
|
2763 |
|
2764 void |
2086
|
2765 OCT_VAL_REP::set_index (const Matrix& m) |
1558
|
2766 { |
|
2767 int nr = m.rows (); |
|
2768 int nc = m.cols (); |
|
2769 |
|
2770 if (nr <= 1 || nc <= 1 |
|
2771 || user_pref.do_fortran_indexing) |
|
2772 { |
|
2773 switch (type_tag) |
|
2774 { |
|
2775 case matrix_constant: |
|
2776 matrix->set_index (m); |
|
2777 break; |
|
2778 |
2086
|
2779 case OCT_VAL_REP::complex_matrix_constant: |
1558
|
2780 complex_matrix->set_index (m); |
|
2781 break; |
|
2782 |
2086
|
2783 case OCT_VAL_REP::char_matrix_constant: |
|
2784 case OCT_VAL_REP::char_matrix_constant_str: |
1572
|
2785 char_matrix->set_index (m); |
|
2786 break; |
|
2787 |
1558
|
2788 default: |
|
2789 panic_impossible (); |
|
2790 break; |
|
2791 } |
|
2792 } |
|
2793 else |
|
2794 ::error ("invalid matrix used as index"); |
|
2795 } |
|
2796 |
|
2797 // XXX FIXME XXX -- this should probably be handled some other way... |
|
2798 // The arg here is expected to be ':'. |
|
2799 void |
2086
|
2800 OCT_VAL_REP::set_index (char c) |
1558
|
2801 { |
|
2802 switch (type_tag) |
|
2803 { |
|
2804 case matrix_constant: |
|
2805 matrix->set_index (c); |
|
2806 break; |
|
2807 |
2086
|
2808 case OCT_VAL_REP::complex_matrix_constant: |
1558
|
2809 complex_matrix->set_index (c); |
|
2810 break; |
|
2811 |
2086
|
2812 case OCT_VAL_REP::char_matrix_constant: |
|
2813 case OCT_VAL_REP::char_matrix_constant_str: |
1572
|
2814 char_matrix->set_index (c); |
|
2815 break; |
|
2816 |
1558
|
2817 default: |
|
2818 panic_impossible (); |
|
2819 break; |
|
2820 } |
|
2821 } |
|
2822 |
|
2823 void |
2086
|
2824 OCT_VAL_REP::set_index (const octave_value_list& args, bool rhs_is_complex) |
1558
|
2825 { |
2115
|
2826 // XXX FIXME XXX -- it's not good that we have to list all the types |
|
2827 // that can be indexed here. |
|
2828 |
1558
|
2829 switch (type_tag) |
|
2830 { |
|
2831 case unknown_constant: |
|
2832 case scalar_constant: |
|
2833 case complex_scalar_constant: |
|
2834 case range_constant: |
1581
|
2835 convert_to_matrix_type (rhs_is_complex); |
1558
|
2836 break; |
|
2837 |
2115
|
2838 case matrix_constant: |
|
2839 case complex_matrix_constant: |
|
2840 case char_matrix_constant: |
|
2841 case char_matrix_constant_str: |
|
2842 break; |
|
2843 |
1558
|
2844 default: |
2115
|
2845 ::error ("indexing %s type not implemented", type_as_string ()); |
1558
|
2846 break; |
|
2847 } |
|
2848 |
2115
|
2849 if (! error_state) |
1558
|
2850 { |
2115
|
2851 int n = args.length (); |
|
2852 |
|
2853 for (int i = 0; i < n; i++) |
1558
|
2854 { |
2115
|
2855 octave_value arg = args (i); |
|
2856 |
|
2857 switch (arg.const_type ()) |
|
2858 { |
|
2859 case range_constant: |
|
2860 set_index (arg.range_value ()); |
|
2861 break; |
|
2862 |
|
2863 case magic_colon: |
|
2864 set_index (':'); |
|
2865 break; |
|
2866 |
|
2867 default: |
|
2868 set_index (arg.matrix_value ()); |
|
2869 break; |
|
2870 } |
|
2871 |
|
2872 if (error_state) |
|
2873 { |
|
2874 clear_index (); |
|
2875 break; |
|
2876 } |
1558
|
2877 } |
|
2878 } |
|
2879 } |
|
2880 |
1827
|
2881 static inline bool |
2086
|
2882 valid_scalar_indices (const octave_value_list& args) |
1558
|
2883 { |
|
2884 int nargin = args.length (); |
|
2885 |
|
2886 for (int i = 0; i < nargin; i++) |
|
2887 if (! args(i).valid_as_scalar_index ()) |
1827
|
2888 return false; |
|
2889 |
|
2890 return true; |
1558
|
2891 } |
1299
|
2892 |
2086
|
2893 octave_value |
|
2894 OCT_VAL_REP::do_index (const octave_value_list& args) |
1299
|
2895 { |
2086
|
2896 octave_value retval; |
1299
|
2897 |
|
2898 if (error_state) |
|
2899 return retval; |
|
2900 |
1827
|
2901 bool originally_scalar_type = is_scalar_type (); |
1558
|
2902 |
|
2903 if (originally_scalar_type && valid_scalar_indices (args)) |
1299
|
2904 { |
1558
|
2905 switch (type_tag) |
1299
|
2906 { |
1558
|
2907 case scalar_constant: |
|
2908 retval = scalar; |
|
2909 break; |
|
2910 |
|
2911 case complex_scalar_constant: |
|
2912 retval = *complex_scalar; |
1299
|
2913 break; |
|
2914 |
|
2915 default: |
1558
|
2916 panic_impossible (); |
1299
|
2917 break; |
|
2918 } |
|
2919 } |
|
2920 else |
|
2921 { |
1558
|
2922 set_index (args); |
|
2923 |
|
2924 if (! error_state) |
|
2925 { |
|
2926 switch (type_tag) |
|
2927 { |
|
2928 case range_constant: |
|
2929 force_numeric (); |
|
2930 // Fall through... |
|
2931 |
|
2932 case matrix_constant: |
|
2933 retval = Matrix (matrix->value ()); |
|
2934 break; |
|
2935 |
|
2936 case complex_matrix_constant: |
|
2937 retval = ComplexMatrix (complex_matrix->value ()); |
|
2938 break; |
|
2939 |
1572
|
2940 case char_matrix_constant: |
|
2941 retval = charMatrix (char_matrix->value ()); |
|
2942 break; |
|
2943 |
|
2944 case char_matrix_constant_str: |
2086
|
2945 retval = octave_value (charMatrix (char_matrix->value ()), 1); |
1572
|
2946 break; |
|
2947 |
1558
|
2948 default: |
|
2949 error ("can't index %s variables", type_as_string ()); |
|
2950 break; |
|
2951 } |
2090
|
2952 |
|
2953 // We may have converted this value from a scalar to a |
|
2954 // matrix to allow indexing to work. |
|
2955 |
|
2956 if (! error_state) |
|
2957 maybe_mutate (); |
1558
|
2958 } |
1299
|
2959 } |
|
2960 |
|
2961 return retval; |
|
2962 } |
|
2963 |
1558
|
2964 void |
2086
|
2965 OCT_VAL_REP::maybe_widen (OCT_VAL_REP::constant_type rhs_type) |
1299
|
2966 { |
1558
|
2967 switch (type_tag) |
1299
|
2968 { |
|
2969 case matrix_constant: |
1558
|
2970 switch (rhs_type) |
|
2971 { |
|
2972 case complex_scalar_constant: |
|
2973 case complex_matrix_constant: |
1299
|
2974 { |
1558
|
2975 ComplexMatrix *cm = new ComplexMatrix (*matrix); |
|
2976 delete matrix; |
|
2977 complex_matrix = cm; |
|
2978 type_tag = complex_matrix_constant; |
1299
|
2979 } |
1558
|
2980 break; |
|
2981 |
|
2982 default: |
|
2983 break; |
|
2984 } |
1299
|
2985 break; |
|
2986 |
1572
|
2987 case char_matrix_constant: |
|
2988 switch (rhs_type) |
|
2989 { |
|
2990 case scalar_constant: |
|
2991 case matrix_constant: |
|
2992 { |
|
2993 Matrix *m = new Matrix (*char_matrix); |
|
2994 delete matrix; |
|
2995 matrix = m; |
|
2996 type_tag = matrix_constant; |
|
2997 } |
|
2998 break; |
|
2999 |
|
3000 case complex_scalar_constant: |
|
3001 case complex_matrix_constant: |
|
3002 { |
|
3003 ComplexMatrix *cm = new ComplexMatrix (*char_matrix); |
|
3004 delete matrix; |
|
3005 complex_matrix = cm; |
|
3006 type_tag = complex_matrix_constant; |
|
3007 } |
|
3008 break; |
|
3009 |
|
3010 default: |
|
3011 break; |
|
3012 } |
|
3013 break; |
|
3014 |
1299
|
3015 default: |
|
3016 break; |
|
3017 } |
|
3018 } |
|
3019 |
|
3020 // Assignment operations for the tree-constant representation class. |
|
3021 |
|
3022 // Top-level tree-constant function that handles assignments. Only |
|
3023 // decide if the left-hand side is currently a scalar or a matrix and |
|
3024 // hand off to other functions to do the real work. |
|
3025 |
1572
|
3026 // XXX FIXME XXX -- need some other way to make these functions |
|
3027 // visible here (they should be in some header file...) |
|
3028 |
1558
|
3029 extern void assign (Array2<Complex>&, const Array2<Complex>&); |
|
3030 extern void assign (Array2<Complex>&, const Array2<double>&); |
1572
|
3031 extern void assign (Array2<Complex>&, const Array2<char>&); |
|
3032 |
1558
|
3033 extern void assign (Array2<double>&, const Array2<double>&); |
1572
|
3034 extern void assign (Array2<double>&, const Array2<char>&); |
|
3035 |
|
3036 extern void assign (Array2<char>&, const Array2<char>&); |
1558
|
3037 |
1299
|
3038 void |
2086
|
3039 OCT_VAL_REP::assign (octave_value& rhs, const octave_value_list& args) |
1299
|
3040 { |
1593
|
3041 // XXX FIXME XXX -- we should probably have special cases for rhs |
|
3042 // being a range type, since converting to a matrix can waste a lot |
|
3043 // of memory. |
|
3044 |
2086
|
3045 octave_value rhs_tmp = rhs; |
1593
|
3046 |
1652
|
3047 if (! (is_string () |
|
3048 && (rhs_tmp.is_string () |
|
3049 || rhs_tmp.is_zero_by_zero ()))) |
|
3050 { |
|
3051 rhs_tmp.force_numeric (); |
|
3052 |
|
3053 if (error_state) |
|
3054 return; |
|
3055 } |
|
3056 |
|
3057 if (rhs_tmp.is_string |
|
3058 && rhs_tmp.rows () == 1 |
|
3059 && rhs_tmp.columns () == 0) |
|
3060 { |
|
3061 rhs_tmp.force_numeric (1); |
|
3062 |
|
3063 if (error_state) |
|
3064 return; |
|
3065 } |
1299
|
3066 |
1572
|
3067 // An assignment to a range will normally require a conversion to a |
|
3068 // vector in the end anyway, since it will normally destroy the |
|
3069 // equally-spaced property of the range elements. This is not as |
|
3070 // memory efficient as possible, but it is much simpler than writing |
|
3071 // additional indexing and assignment functions especially for |
|
3072 // Ranges. |
|
3073 |
|
3074 if (is_defined () && ! (is_numeric_type () || is_string ())) |
1652
|
3075 { |
|
3076 force_numeric (); |
|
3077 |
|
3078 if (error_state) |
|
3079 return; |
|
3080 } |
|
3081 |
|
3082 if (! rhs_tmp.is_zero_by_zero ()) |
|
3083 { |
|
3084 maybe_widen (rhs_tmp.const_type ()); |
|
3085 |
|
3086 if (error_state) |
|
3087 return; |
|
3088 } |
|
3089 |
|
3090 set_index (args, rhs_tmp.is_complex_type ()); |
1299
|
3091 |
|
3092 if (error_state) |
|
3093 return; |
|
3094 |
1652
|
3095 switch (type_tag) |
1299
|
3096 { |
1652
|
3097 case complex_matrix_constant: |
|
3098 { |
|
3099 switch (rhs_tmp.const_type ()) |
1299
|
3100 { |
1652
|
3101 case complex_scalar_constant: |
|
3102 case complex_matrix_constant: |
|
3103 ::assign (*complex_matrix, rhs_tmp.complex_matrix_value ()); |
|
3104 break; |
|
3105 |
|
3106 case scalar_constant: |
|
3107 case matrix_constant: |
|
3108 ::assign (*complex_matrix, rhs_tmp.matrix_value ()); |
|
3109 break; |
|
3110 |
|
3111 default: |
|
3112 panic_impossible ();; |
|
3113 break; |
1299
|
3114 } |
1652
|
3115 } |
|
3116 break; |
|
3117 |
|
3118 case scalar_constant: |
|
3119 case matrix_constant: |
|
3120 { |
|
3121 switch (rhs_tmp.const_type ()) |
1572
|
3122 { |
1652
|
3123 case scalar_constant: |
|
3124 case matrix_constant: |
|
3125 ::assign (*matrix, rhs_tmp.matrix_value ()); |
|
3126 break; |
|
3127 |
|
3128 case char_matrix_constant: |
|
3129 ::assign (*matrix, rhs_tmp.char_matrix_value ()); |
|
3130 break; |
|
3131 |
|
3132 default: |
|
3133 panic_impossible (); |
|
3134 break; |
1572
|
3135 } |
1652
|
3136 } |
|
3137 break; |
|
3138 |
|
3139 case char_matrix_constant: |
|
3140 ::assign (*char_matrix, rhs_tmp.char_matrix_value ()); |
|
3141 break; |
|
3142 |
|
3143 case char_matrix_constant_str: |
|
3144 ::assign (*char_matrix, rhs_tmp.char_matrix_value ()); |
|
3145 if (char_matrix->rows () == 0 && char_matrix->columns () == 0) |
|
3146 char_matrix->resize (1, 0); |
|
3147 break; |
|
3148 |
|
3149 default: |
|
3150 panic_impossible (); |
|
3151 break; |
1299
|
3152 } |
1688
|
3153 |
|
3154 // Do the right thing for assignments like `x(1) = pi' when x is |
|
3155 // undefined before the assignment. |
|
3156 |
|
3157 if (is_matrix_type () || is_range ()) |
|
3158 maybe_mutate (); |
1299
|
3159 } |
|
3160 |
1827
|
3161 bool |
2086
|
3162 OCT_VAL_REP::print_as_scalar (void) |
1755
|
3163 { |
|
3164 int nr = rows (); |
|
3165 int nc = columns (); |
1827
|
3166 |
1755
|
3167 return (is_scalar_type () |
|
3168 || (is_string () && nr <= 1) |
|
3169 || (is_matrix_type () |
|
3170 && ((nr == 1 && nc == 1) |
|
3171 || nr == 0 |
|
3172 || nc == 0))); |
|
3173 } |
|
3174 |
1827
|
3175 bool |
2086
|
3176 OCT_VAL_REP::print_as_structure (void) |
1755
|
3177 { |
|
3178 return is_map (); |
|
3179 } |
|
3180 |
96
|
3181 /* |
1
|
3182 ;;; Local Variables: *** |
|
3183 ;;; mode: C++ *** |
|
3184 ;;; End: *** |
|
3185 */ |