Mercurial > octave-nkf
comparison src/pt-mat.cc @ 5502:dae5ba706ff2
[project @ 2005-10-20 06:37:30 by jwe]
author | jwe |
---|---|
date | Thu, 20 Oct 2005 06:37:30 +0000 |
parents | a495ec7ee3d3 |
children | e0011660696c |
comparison
equal
deleted
inserted
replaced
5501:f2b9aa13f2bf | 5502:dae5ba706ff2 |
---|---|
24 #ifdef HAVE_CONFIG_H | 24 #ifdef HAVE_CONFIG_H |
25 #include <config.h> | 25 #include <config.h> |
26 #endif | 26 #endif |
27 | 27 |
28 #include <iostream> | 28 #include <iostream> |
29 | |
30 #include "quit.h" | |
29 | 31 |
30 #include "defun.h" | 32 #include "defun.h" |
31 #include "error.h" | 33 #include "error.h" |
32 #include "oct-obj.h" | 34 #include "oct-obj.h" |
33 #include "pt-arg-list.h" | 35 #include "pt-arg-list.h" |
65 public: | 67 public: |
66 | 68 |
67 tm_row_const_rep (void) | 69 tm_row_const_rep (void) |
68 : count (1), dv (), all_str (false), | 70 : count (1), dv (), all_str (false), |
69 all_sq_str (false), all_dq_str (false), | 71 all_sq_str (false), all_dq_str (false), |
70 some_str (false), is_cmplx (false), all_mt (true), ok (false) { } | 72 some_str (false), all_real (false), all_cmplx (false), |
73 all_mt (true), ok (false) { } | |
71 | 74 |
72 tm_row_const_rep (const tree_argument_list& row) | 75 tm_row_const_rep (const tree_argument_list& row) |
73 : count (1), dv (), all_str (false), all_sq_str (false), | 76 : count (1), dv (), all_str (false), all_sq_str (false), |
74 some_str (false), is_cmplx (false), all_mt (true), ok (false) | 77 some_str (false), all_real (false), all_cmplx (false), |
78 all_mt (true), ok (false) | |
75 { init (row); } | 79 { init (row); } |
76 | 80 |
77 ~tm_row_const_rep (void) { } | 81 ~tm_row_const_rep (void) { } |
78 | 82 |
79 int count; | 83 int count; |
82 | 86 |
83 bool all_str; | 87 bool all_str; |
84 bool all_sq_str; | 88 bool all_sq_str; |
85 bool all_dq_str; | 89 bool all_dq_str; |
86 bool some_str; | 90 bool some_str; |
87 bool is_cmplx; | 91 bool all_real; |
92 bool all_cmplx; | |
88 bool all_mt; | 93 bool all_mt; |
89 | 94 |
90 bool ok; | 95 bool ok; |
91 | 96 |
92 bool do_init_element (tree_expression *, const octave_value&, bool&); | 97 bool do_init_element (tree_expression *, const octave_value&, bool&); |
155 | 160 |
156 bool all_strings_p (void) const { return rep->all_str; } | 161 bool all_strings_p (void) const { return rep->all_str; } |
157 bool all_sq_strings_p (void) const { return rep->all_sq_str; } | 162 bool all_sq_strings_p (void) const { return rep->all_sq_str; } |
158 bool all_dq_strings_p (void) const { return rep->all_dq_str; } | 163 bool all_dq_strings_p (void) const { return rep->all_dq_str; } |
159 bool some_strings_p (void) const { return rep->some_str; } | 164 bool some_strings_p (void) const { return rep->some_str; } |
160 bool complex_p (void) const { return rep->is_cmplx; } | 165 bool all_real_p (void) const { return rep->all_real; } |
166 bool all_complex_p (void) const { return rep->all_cmplx; } | |
161 bool all_empty_p (void) const { return rep->all_mt; } | 167 bool all_empty_p (void) const { return rep->all_mt; } |
162 | 168 |
163 operator bool () const { return (rep && rep->ok); } | 169 operator bool () const { return (rep && rep->ok); } |
164 | 170 |
165 iterator begin (void) { return rep->begin (); } | 171 iterator begin (void) { return rep->begin (); } |
181 octave_idx_type this_elt_nr = val.rows (); | 187 octave_idx_type this_elt_nr = val.rows (); |
182 octave_idx_type this_elt_nc = val.columns (); | 188 octave_idx_type this_elt_nc = val.columns (); |
183 | 189 |
184 dim_vector this_elt_dv = val.dims (); | 190 dim_vector this_elt_dv = val.dims (); |
185 | 191 |
186 if (!this_elt_dv.all_zero ()) | 192 if (! this_elt_dv.all_zero ()) |
187 { | 193 { |
188 all_mt = false; | 194 all_mt = false; |
189 | 195 |
190 if (first_elem) | 196 if (first_elem) |
191 { | 197 { |
254 all_dq_str = false; | 260 all_dq_str = false; |
255 | 261 |
256 if (! some_str && val.is_string ()) | 262 if (! some_str && val.is_string ()) |
257 some_str = true; | 263 some_str = true; |
258 | 264 |
259 if (! is_cmplx && val.is_complex_type ()) | 265 if (all_real && ! val.is_real_type ()) |
260 is_cmplx = true; | 266 all_real = false; |
267 | |
268 if (all_cmplx && ! (val.is_complex_type () || val.is_real_type ())) | |
269 all_cmplx = false; | |
261 | 270 |
262 return true; | 271 return true; |
263 } | 272 } |
264 | 273 |
265 void | 274 void |
266 tm_row_const::tm_row_const_rep::init (const tree_argument_list& row) | 275 tm_row_const::tm_row_const_rep::init (const tree_argument_list& row) |
267 { | 276 { |
268 all_str = true; | 277 all_str = true; |
269 all_sq_str = true; | 278 all_sq_str = true; |
270 all_dq_str = true; | 279 all_dq_str = true; |
280 all_real = true; | |
281 all_cmplx = true; | |
271 | 282 |
272 bool first_elem = true; | 283 bool first_elem = true; |
273 | 284 |
274 for (tree_argument_list::const_iterator p = row.begin (); | 285 for (tree_argument_list::const_iterator p = row.begin (); |
275 p != row.end (); | 286 p != row.end (); |
276 p++) | 287 p++) |
277 { | 288 { |
289 OCTAVE_QUIT; | |
290 | |
278 tree_expression *elt = *p; | 291 tree_expression *elt = *p; |
279 | 292 |
280 octave_value tmp = elt->rvalue (); | 293 octave_value tmp = elt->rvalue (); |
281 | 294 |
282 if (error_state || tmp.is_undefined ()) | 295 if (error_state || tmp.is_undefined ()) |
287 { | 300 { |
288 octave_value_list tlst = tmp.list_value (); | 301 octave_value_list tlst = tmp.list_value (); |
289 | 302 |
290 for (octave_idx_type i = 0; i < tlst.length (); i++) | 303 for (octave_idx_type i = 0; i < tlst.length (); i++) |
291 { | 304 { |
305 OCTAVE_QUIT; | |
306 | |
292 if (! do_init_element (elt, tlst(i), first_elem)) | 307 if (! do_init_element (elt, tlst(i), first_elem)) |
293 goto done; | 308 goto done; |
294 } | 309 } |
295 } | 310 } |
296 else | 311 else |
341 { | 356 { |
342 public: | 357 public: |
343 | 358 |
344 tm_const (const tree_matrix& tm) | 359 tm_const (const tree_matrix& tm) |
345 : dv (), all_str (false), all_sq_str (false), all_dq_str (false), | 360 : dv (), all_str (false), all_sq_str (false), all_dq_str (false), |
346 some_str (false), is_cmplx (false), all_mt (true), ok (false) | 361 some_str (false), all_real (false), all_cmplx (false), |
362 all_mt (true), ok (false) | |
347 { init (tm); } | 363 { init (tm); } |
348 | 364 |
349 ~tm_const (void) { } | 365 ~tm_const (void) { } |
350 | 366 |
351 octave_idx_type rows (void) const { return (dv.length () > 0 ? dv.elem (0) : 0); } | 367 octave_idx_type rows (void) const { return (dv.length () > 0 ? dv.elem (0) : 0); } |
355 | 371 |
356 bool all_strings_p (void) const { return all_str; } | 372 bool all_strings_p (void) const { return all_str; } |
357 bool all_sq_strings_p (void) const { return all_sq_str; } | 373 bool all_sq_strings_p (void) const { return all_sq_str; } |
358 bool all_dq_strings_p (void) const { return all_dq_str; } | 374 bool all_dq_strings_p (void) const { return all_dq_str; } |
359 bool some_strings_p (void) const { return some_str; } | 375 bool some_strings_p (void) const { return some_str; } |
360 bool complex_p (void) const { return is_cmplx; } | 376 bool all_real_p (void) const { return all_real; } |
377 bool all_complex_p (void) const { return all_cmplx; } | |
361 bool all_empty_p (void) const { return all_mt; } | 378 bool all_empty_p (void) const { return all_mt; } |
362 | 379 |
363 operator bool () const { return ok; } | 380 operator bool () const { return ok; } |
364 | 381 |
365 private: | 382 private: |
368 | 385 |
369 bool all_str; | 386 bool all_str; |
370 bool all_sq_str; | 387 bool all_sq_str; |
371 bool all_dq_str; | 388 bool all_dq_str; |
372 bool some_str; | 389 bool some_str; |
373 bool is_cmplx; | 390 bool all_real; |
391 bool all_cmplx; | |
374 bool all_mt; | 392 bool all_mt; |
375 | 393 |
376 bool ok; | 394 bool ok; |
377 | 395 |
378 tm_const (void); | 396 tm_const (void); |
388 tm_const::init (const tree_matrix& tm) | 406 tm_const::init (const tree_matrix& tm) |
389 { | 407 { |
390 all_str = true; | 408 all_str = true; |
391 all_sq_str = true; | 409 all_sq_str = true; |
392 all_dq_str = true; | 410 all_dq_str = true; |
411 all_real = true; | |
412 all_cmplx = true; | |
393 | 413 |
394 bool first_elem = true; | 414 bool first_elem = true; |
395 | 415 |
396 // Just eval and figure out if what we have is complex or all | 416 // Just eval and figure out if what we have is complex or all |
397 // strings. We can't check columns until we know that this is a | 417 // strings. We can't check columns until we know that this is a |
398 // numeric matrix -- collections of strings can have elements of | 418 // numeric matrix -- collections of strings can have elements of |
399 // different lengths. | 419 // different lengths. |
400 | 420 |
401 for (tree_matrix::const_iterator p = tm.begin (); p != tm.end (); p++) | 421 for (tree_matrix::const_iterator p = tm.begin (); p != tm.end (); p++) |
402 { | 422 { |
423 OCTAVE_QUIT; | |
424 | |
403 tree_argument_list *elt = *p; | 425 tree_argument_list *elt = *p; |
404 | 426 |
405 tm_row_const tmp (*elt); | 427 tm_row_const tmp (*elt); |
406 | 428 |
407 if (tmp) | 429 if (tmp) |
416 all_dq_str = false; | 438 all_dq_str = false; |
417 | 439 |
418 if (! some_str && tmp.some_strings_p ()) | 440 if (! some_str && tmp.some_strings_p ()) |
419 some_str = true; | 441 some_str = true; |
420 | 442 |
421 if (! is_cmplx && tmp.complex_p ()) | 443 if (all_real && ! tmp.all_real_p ()) |
422 is_cmplx = true; | 444 all_real = false; |
445 | |
446 if (all_cmplx && ! tmp.all_complex_p ()) | |
447 all_cmplx = false; | |
423 | 448 |
424 if (all_mt && ! tmp.all_empty_p ()) | 449 if (all_mt && ! tmp.all_empty_p ()) |
425 all_mt = false; | 450 all_mt = false; |
426 | 451 |
427 append (tmp); | 452 append (tmp); |
432 | 457 |
433 if (! error_state) | 458 if (! error_state) |
434 { | 459 { |
435 for (iterator p = begin (); p != end (); p++) | 460 for (iterator p = begin (); p != end (); p++) |
436 { | 461 { |
462 OCTAVE_QUIT; | |
463 | |
437 tm_row_const elt = *p; | 464 tm_row_const elt = *p; |
438 | 465 |
439 octave_idx_type this_elt_nr = elt.rows (); | 466 octave_idx_type this_elt_nr = elt.rows (); |
440 octave_idx_type this_elt_nc = elt.cols (); | 467 octave_idx_type this_elt_nc = elt.cols (); |
441 | 468 |
529 bool | 556 bool |
530 tree_matrix::has_magic_end (void) const | 557 tree_matrix::has_magic_end (void) const |
531 { | 558 { |
532 for (const_iterator p = begin (); p != end (); p++) | 559 for (const_iterator p = begin (); p != end (); p++) |
533 { | 560 { |
561 OCTAVE_QUIT; | |
562 | |
534 tree_argument_list *elt = *p; | 563 tree_argument_list *elt = *p; |
535 | 564 |
536 if (elt && elt->has_magic_end ()) | 565 if (elt && elt->has_magic_end ()) |
537 return true; | 566 return true; |
538 } | 567 } |
543 bool | 572 bool |
544 tree_matrix::all_elements_are_constant (void) const | 573 tree_matrix::all_elements_are_constant (void) const |
545 { | 574 { |
546 for (const_iterator p = begin (); p != end (); p++) | 575 for (const_iterator p = begin (); p != end (); p++) |
547 { | 576 { |
577 OCTAVE_QUIT; | |
578 | |
548 tree_argument_list *elt = *p; | 579 tree_argument_list *elt = *p; |
549 | 580 |
550 if (! elt->all_elements_are_constant ()) | 581 if (! elt->all_elements_are_constant ()) |
551 return false; | 582 return false; |
552 } | 583 } |
574 { | 605 { |
575 if (Vwarn_string_concat && ! (all_dq_strings_p || all_sq_strings_p)) | 606 if (Vwarn_string_concat && ! (all_dq_strings_p || all_sq_strings_p)) |
576 ::warning ("concatenation of different character string types may have unintended consequences"); | 607 ::warning ("concatenation of different character string types may have unintended consequences"); |
577 } | 608 } |
578 | 609 |
610 #define SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR) \ | |
611 do \ | |
612 { \ | |
613 int dv_len = dv.length (); \ | |
614 Array<octave_idx_type> ra_idx (dv_len > 1 ? dv_len : 2, 0); \ | |
615 \ | |
616 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) \ | |
617 { \ | |
618 OCTAVE_QUIT; \ | |
619 \ | |
620 tm_row_const row = *p; \ | |
621 \ | |
622 for (tm_row_const::iterator q = row.begin (); \ | |
623 q != row.end (); \ | |
624 q++) \ | |
625 { \ | |
626 OCTAVE_QUIT; \ | |
627 \ | |
628 TYPE ra = q->EXTRACTOR (); \ | |
629 \ | |
630 if (! error_state) \ | |
631 { \ | |
632 result.insert (ra, ra_idx); \ | |
633 \ | |
634 if (! error_state) \ | |
635 ra_idx(1) += ra.columns (); \ | |
636 else \ | |
637 goto done; \ | |
638 } \ | |
639 else \ | |
640 goto done; \ | |
641 } \ | |
642 \ | |
643 ra_idx(0) += row.rows (); \ | |
644 ra_idx(1) = 0; \ | |
645 } \ | |
646 } \ | |
647 while (0) | |
648 | |
579 octave_value | 649 octave_value |
580 tree_matrix::rvalue (void) | 650 tree_matrix::rvalue (void) |
581 { | 651 { |
582 octave_value retval; | 652 octave_value retval; |
583 | 653 |
584 bool all_strings_p = false; | 654 bool all_strings_p = false; |
585 bool all_sq_strings_p = false; | 655 bool all_sq_strings_p = false; |
586 bool all_dq_strings_p = false; | 656 bool all_dq_strings_p = false; |
587 bool all_empty_p = false; | 657 bool all_empty_p = false; |
658 bool all_real_p = false; | |
659 bool all_complex_p = false; | |
588 bool frc_str_conv = false; | 660 bool frc_str_conv = false; |
589 | 661 |
590 tm_const tmp (*this); | 662 tm_const tmp (*this); |
591 | 663 |
592 if (tmp) | 664 if (tmp) |
594 dim_vector dv = tmp.dims (); | 666 dim_vector dv = tmp.dims (); |
595 all_strings_p = tmp.all_strings_p (); | 667 all_strings_p = tmp.all_strings_p (); |
596 all_sq_strings_p = tmp.all_sq_strings_p (); | 668 all_sq_strings_p = tmp.all_sq_strings_p (); |
597 all_dq_strings_p = tmp.all_dq_strings_p (); | 669 all_dq_strings_p = tmp.all_dq_strings_p (); |
598 all_empty_p = tmp.all_empty_p (); | 670 all_empty_p = tmp.all_empty_p (); |
671 all_real_p = tmp.all_real_p (); | |
672 all_complex_p = tmp.all_complex_p (); | |
599 frc_str_conv = tmp.some_strings_p (); | 673 frc_str_conv = tmp.some_strings_p (); |
600 | 674 |
601 // XXX FIXME XX | 675 // Try to speed up the common cases. |
602 // The previous version of this code obtained the return type and | 676 |
603 // initialized an array of the correct type. However the return type | |
604 // is now built-up from the return types of do_cat_op. Should we special | |
605 // case the situation where there are only NDArray and ComplexNDArray | |
606 // elements, or things like boolMatrix that widen to them, and do the | |
607 // correct initialization? How to do this? Will it be faster? Check against | |
608 // version 2.1.57 | |
609 | |
610 | |
611 // The line below might seem crazy, since we take a copy | |
612 // of the first argument, resize it to be empty and then resize | |
613 // it to be full. This is done since it means that there is no | |
614 // recopying of data, as would happen if we used a single resize. | |
615 // It should be noted that resize operation is also significantly | |
616 // slower than the do_cat_op function, so it makes sense to have an | |
617 // empty matrix and copy all data. | |
618 // | |
619 // We might also start with a empty octave_value using | |
620 // ctmp = octave_value_typeinfo::lookup_type | |
621 // (tmp.begin() -> begin() -> type_name()); | |
622 // and then directly resize. However, for some types there might be | |
623 // some additional setup needed, and so this should be avoided. | |
624 | |
625 octave_value ctmp; | |
626 if (all_strings_p) | 677 if (all_strings_p) |
627 { | 678 { |
628 char type = all_sq_strings_p ? '\'' : '"'; | 679 char type = all_sq_strings_p ? '\'' : '"'; |
629 | 680 |
630 maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p); | 681 maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p); |
631 | 682 |
632 if (all_empty_p) | 683 charNDArray result (dv, Vstring_fill_char); |
633 ctmp = octave_value (charNDArray (), true, type); | 684 |
634 else | 685 SINGLE_TYPE_CONCAT (charNDArray, char_array_value); |
635 ctmp = octave_value (charNDArray (dv, Vstring_fill_char), | 686 |
636 true, type); | 687 retval = octave_value (result, true, type); |
688 } | |
689 else if (all_real_p) | |
690 { | |
691 NDArray result (dv); | |
692 | |
693 SINGLE_TYPE_CONCAT (NDArray, array_value); | |
694 | |
695 retval = result; | |
696 } | |
697 else if (all_complex_p) | |
698 { | |
699 ComplexNDArray result (dv); | |
700 | |
701 SINGLE_TYPE_CONCAT (ComplexNDArray, complex_array_value); | |
702 | |
703 retval = result; | |
637 } | 704 } |
638 else | 705 else |
639 { | 706 { |
707 // The line below might seem crazy, since we take a copy of | |
708 // the first argument, resize it to be empty and then resize | |
709 // it to be full. This is done since it means that there is | |
710 // no recopying of data, as would happen if we used a single | |
711 // resize. It should be noted that resize operation is also | |
712 // significantly slower than the do_cat_op function, so it | |
713 // makes sense to have an empty matrix and copy all data. | |
714 // | |
715 // We might also start with a empty octave_value using | |
716 // | |
717 // ctmp = octave_value_typeinfo::lookup_type | |
718 // (tmp.begin() -> begin() -> type_name()); | |
719 // | |
720 // and then directly resize. However, for some types there | |
721 // might be some additional setup needed, and so this should | |
722 // be avoided. | |
723 | |
724 octave_value ctmp; | |
725 | |
640 // Find the first non-empty object | 726 // Find the first non-empty object |
727 | |
641 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) | 728 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) |
642 { | 729 { |
730 OCTAVE_QUIT; | |
731 | |
643 tm_row_const row = *p; | 732 tm_row_const row = *p; |
733 | |
644 for (tm_row_const::iterator q = row.begin (); | 734 for (tm_row_const::iterator q = row.begin (); |
645 q != row.end (); q++) | 735 q != row.end (); q++) |
646 { | 736 { |
737 OCTAVE_QUIT; | |
738 | |
647 ctmp = *q; | 739 ctmp = *q; |
740 | |
648 if (! ctmp.all_zero_dims ()) | 741 if (! ctmp.all_zero_dims ()) |
649 goto found_non_empty; | 742 goto found_non_empty; |
650 } | 743 } |
651 } | 744 } |
652 | 745 |
653 ctmp = (*(tmp.begin() -> begin())); | 746 ctmp = (*(tmp.begin() -> begin())); |
654 | 747 |
655 found_non_empty: | 748 found_non_empty: |
749 | |
656 if (! all_empty_p) | 750 if (! all_empty_p) |
657 ctmp = ctmp.resize (dim_vector (0,0)).resize (dv); | 751 ctmp = ctmp.resize (dim_vector (0,0)).resize (dv); |
752 | |
753 if (! error_state) | |
754 { | |
755 // Now, extract the values from the individual elements and | |
756 // insert them in the result matrix. | |
757 | |
758 int dv_len = dv.length (); | |
759 Array<int> ra_idx (dv_len > 1 ? dv_len : 2, 0); | |
760 | |
761 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) | |
762 { | |
763 OCTAVE_QUIT; | |
764 | |
765 tm_row_const row = *p; | |
766 | |
767 for (tm_row_const::iterator q = row.begin (); | |
768 q != row.end (); | |
769 q++) | |
770 { | |
771 OCTAVE_QUIT; | |
772 | |
773 octave_value elt = *q; | |
774 | |
775 ctmp = do_cat_op (ctmp, elt, ra_idx); | |
776 | |
777 if (error_state) | |
778 goto done; | |
779 | |
780 ra_idx (1) += elt.columns (); | |
781 } | |
782 | |
783 ra_idx (0) += row.rows (); | |
784 ra_idx (1) = 0; | |
785 } | |
786 | |
787 retval = ctmp; | |
788 | |
789 if (frc_str_conv && ! retval.is_string ()) | |
790 retval = retval.convert_to_str (); | |
791 } | |
658 } | 792 } |
659 | |
660 if (error_state) | |
661 goto done; | |
662 | |
663 // Now, extract the values from the individual elements and | |
664 // insert them in the result matrix. | |
665 int dv_len = dv.length (); | |
666 Array<int> ra_idx (dv_len > 1 ? dv_len : 2, 0); | |
667 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) | |
668 { | |
669 tm_row_const row = *p; | |
670 for (tm_row_const::iterator q = row.begin (); q != row.end (); q++) | |
671 { | |
672 octave_value elt = *q; | |
673 | |
674 ctmp = do_cat_op (ctmp, elt, ra_idx); | |
675 if (error_state) | |
676 goto done; | |
677 ra_idx (1) += elt.columns (); | |
678 } | |
679 ra_idx (0) += row.rows (); | |
680 ra_idx (1) = 0; | |
681 } | |
682 retval = ctmp; | |
683 if (frc_str_conv && ! retval.is_string ()) | |
684 retval = retval.convert_to_str (); | |
685 } | 793 } |
686 | 794 |
687 done: | 795 done: |
688 return retval; | 796 return retval; |
689 } | 797 } |