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 }