Mercurial > hg > octave-nkf
comparison src/pt-mat.cc @ 13144:c99f24c10ca3
fix vertical concatenation involving cell arrays
* pt-mat.cc (tm_row_const::tm_row_const_rep::cellify): New function.
(tm_row_const::tm_row_const_rep::init): Use it. Call octave_quit in
all loops.
(tm_row_const::cellify): New function.
(tm_row_const::first_elem_struct_p): New function.
(tm_const::any_cell): New data member. Adjust constructor
initialization lists.
(tm_const::any_cell_p): New function.
(tm_const::init): Handle concatenation of cells.
* pt-mat.cc: Additional test for concatentation with cell arrays.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 15 Sep 2011 22:03:58 -0400 |
parents | d803d2702a39 |
children | cf5ebc0e47e4 |
comparison
equal
deleted
inserted
replaced
13143:bda7b080f205 | 13144:c99f24c10ca3 |
---|---|
106 | 106 |
107 void do_init_element (const octave_value&, bool&); | 107 void do_init_element (const octave_value&, bool&); |
108 | 108 |
109 void init (const tree_argument_list&); | 109 void init (const tree_argument_list&); |
110 | 110 |
111 void cellify (void); | |
112 | |
111 private: | 113 private: |
112 | 114 |
113 tm_row_const_rep (const tm_row_const_rep&); | 115 tm_row_const_rep (const tm_row_const_rep&); |
114 | 116 |
115 tm_row_const_rep& operator = (const tm_row_const_rep&); | 117 tm_row_const_rep& operator = (const tm_row_const_rep&); |
175 bool all_empty_p (void) const { return rep->all_mt; } | 177 bool all_empty_p (void) const { return rep->all_mt; } |
176 bool any_cell_p (void) const { return rep->any_cell; } | 178 bool any_cell_p (void) const { return rep->any_cell; } |
177 bool any_sparse_p (void) const { return rep->any_sparse; } | 179 bool any_sparse_p (void) const { return rep->any_sparse; } |
178 bool any_class_p (void) const { return rep->any_class; } | 180 bool any_class_p (void) const { return rep->any_class; } |
179 bool all_1x1_p (void) const { return rep->all_1x1; } | 181 bool all_1x1_p (void) const { return rep->all_1x1; } |
182 bool first_elem_struct_p (void) const { return rep->first_elem_is_struct; } | |
180 | 183 |
181 std::string class_name (void) const { return rep->class_nm; } | 184 std::string class_name (void) const { return rep->class_nm; } |
185 | |
186 void cellify (void) { rep->cellify (); } | |
182 | 187 |
183 operator bool () const { return (rep && rep->ok); } | 188 operator bool () const { return (rep && rep->ok); } |
184 | 189 |
185 iterator begin (void) { return rep->begin (); } | 190 iterator begin (void) { return rep->begin (); } |
186 const_iterator begin (void) const { return rep->begin (); } | 191 const_iterator begin (void) const { return rep->begin (); } |
374 do_init_element (tmp, first_elem); | 379 do_init_element (tmp, first_elem); |
375 } | 380 } |
376 } | 381 } |
377 | 382 |
378 if (any_cell && ! any_class && ! first_elem_is_struct) | 383 if (any_cell && ! any_class && ! first_elem_is_struct) |
379 { | 384 cellify (); |
380 for (iterator p = begin (); p != end (); p++) | |
381 { | |
382 if (! p->is_cell ()) | |
383 *p = Cell (*p); | |
384 } | |
385 } | |
386 | 385 |
387 first_elem = true; | 386 first_elem = true; |
388 | 387 |
389 for (iterator p = begin (); p != end (); p++) | 388 for (iterator p = begin (); p != end (); p++) |
390 { | 389 { |
390 octave_quit (); | |
391 | |
391 octave_value val = *p; | 392 octave_value val = *p; |
392 | 393 |
393 dim_vector this_elt_dv = val.dims (); | 394 dim_vector this_elt_dv = val.dims (); |
394 | 395 |
395 if (! this_elt_dv.zero_by_zero ()) | 396 if (! this_elt_dv.zero_by_zero ()) |
408 } | 409 } |
409 } | 410 } |
410 } | 411 } |
411 | 412 |
412 ok = ! error_state; | 413 ok = ! error_state; |
414 } | |
415 | |
416 void | |
417 tm_row_const::tm_row_const_rep::cellify (void) | |
418 { | |
419 bool elt_changed = false; | |
420 | |
421 for (iterator p = begin (); p != end (); p++) | |
422 { | |
423 octave_quit (); | |
424 | |
425 if (! p->is_cell ()) | |
426 { | |
427 elt_changed = true; | |
428 | |
429 *p = Cell (*p); | |
430 } | |
431 } | |
432 | |
433 if (elt_changed) | |
434 { | |
435 bool first_elem = true; | |
436 | |
437 for (iterator p = begin (); p != end (); p++) | |
438 { | |
439 octave_quit (); | |
440 | |
441 octave_value val = *p; | |
442 | |
443 dim_vector this_elt_dv = val.dims (); | |
444 | |
445 if (! this_elt_dv.zero_by_zero ()) | |
446 { | |
447 if (first_elem) | |
448 { | |
449 first_elem = false; | |
450 dv = this_elt_dv; | |
451 } | |
452 else if (! dv.hvcat (this_elt_dv, 1)) | |
453 { | |
454 eval_error ("horizontal dimensions mismatch", dv, this_elt_dv); | |
455 break; | |
456 } | |
457 } | |
458 } | |
459 } | |
413 } | 460 } |
414 | 461 |
415 void | 462 void |
416 tm_row_const::tm_row_const_rep::eval_warning (const char *msg, int l, | 463 tm_row_const::tm_row_const_rep::eval_warning (const char *msg, int l, |
417 int c) const | 464 int c) const |
429 public: | 476 public: |
430 | 477 |
431 tm_const (const tree_matrix& tm) | 478 tm_const (const tree_matrix& tm) |
432 : dv (0, 0), all_str (false), all_sq_str (false), all_dq_str (false), | 479 : dv (0, 0), all_str (false), all_sq_str (false), all_dq_str (false), |
433 some_str (false), all_real (false), all_cmplx (false), | 480 some_str (false), all_real (false), all_cmplx (false), |
434 all_mt (true), any_sparse (false), any_class (false), | 481 all_mt (true), any_cell (false), any_sparse (false), |
435 class_nm (), ok (false) | 482 any_class (false), class_nm (), ok (false) |
436 { init (tm); } | 483 { init (tm); } |
437 | 484 |
438 ~tm_const (void) { } | 485 ~tm_const (void) { } |
439 | 486 |
440 octave_idx_type rows (void) const { return dv.elem (0); } | 487 octave_idx_type rows (void) const { return dv.elem (0); } |
447 bool all_dq_strings_p (void) const { return all_dq_str; } | 494 bool all_dq_strings_p (void) const { return all_dq_str; } |
448 bool some_strings_p (void) const { return some_str; } | 495 bool some_strings_p (void) const { return some_str; } |
449 bool all_real_p (void) const { return all_real; } | 496 bool all_real_p (void) const { return all_real; } |
450 bool all_complex_p (void) const { return all_cmplx; } | 497 bool all_complex_p (void) const { return all_cmplx; } |
451 bool all_empty_p (void) const { return all_mt; } | 498 bool all_empty_p (void) const { return all_mt; } |
499 bool any_cell_p (void) const { return any_cell; } | |
452 bool any_sparse_p (void) const { return any_sparse; } | 500 bool any_sparse_p (void) const { return any_sparse; } |
453 bool any_class_p (void) const { return any_class; } | 501 bool any_class_p (void) const { return any_class; } |
454 bool all_1x1_p (void) const { return all_1x1; } | 502 bool all_1x1_p (void) const { return all_1x1; } |
455 | 503 |
456 std::string class_name (void) const { return class_nm; } | 504 std::string class_name (void) const { return class_nm; } |
466 bool all_dq_str; | 514 bool all_dq_str; |
467 bool some_str; | 515 bool some_str; |
468 bool all_real; | 516 bool all_real; |
469 bool all_cmplx; | 517 bool all_cmplx; |
470 bool all_mt; | 518 bool all_mt; |
519 bool any_cell; | |
471 bool any_sparse; | 520 bool any_sparse; |
472 bool any_class; | 521 bool any_class; |
473 bool all_1x1; | 522 bool all_1x1; |
474 | 523 |
475 std::string class_nm; | 524 std::string class_nm; |
491 all_str = true; | 540 all_str = true; |
492 all_sq_str = true; | 541 all_sq_str = true; |
493 all_dq_str = true; | 542 all_dq_str = true; |
494 all_real = true; | 543 all_real = true; |
495 all_cmplx = true; | 544 all_cmplx = true; |
545 any_cell = false; | |
496 any_sparse = false; | 546 any_sparse = false; |
497 any_class = false; | 547 any_class = false; |
498 all_1x1 = ! empty (); | 548 all_1x1 = ! empty (); |
499 | 549 |
500 bool first_elem = true; | 550 bool first_elem = true; |
551 bool first_elem_is_struct = false; | |
501 | 552 |
502 // Just eval and figure out if what we have is complex or all | 553 // Just eval and figure out if what we have is complex or all |
503 // strings. We can't check columns until we know that this is a | 554 // strings. We can't check columns until we know that this is a |
504 // numeric matrix -- collections of strings can have elements of | 555 // numeric matrix -- collections of strings can have elements of |
505 // different lengths. | 556 // different lengths. |
510 | 561 |
511 tree_argument_list *elt = *p; | 562 tree_argument_list *elt = *p; |
512 | 563 |
513 tm_row_const tmp (*elt); | 564 tm_row_const tmp (*elt); |
514 | 565 |
566 if (first_elem) | |
567 { | |
568 first_elem_is_struct = tmp.first_elem_struct_p (); | |
569 | |
570 first_elem = false; | |
571 } | |
572 | |
515 if (tmp && ! tmp.empty ()) | 573 if (tmp && ! tmp.empty ()) |
516 { | 574 { |
517 if (all_str && ! tmp.all_strings_p ()) | 575 if (all_str && ! tmp.all_strings_p ()) |
518 all_str = false; | 576 all_str = false; |
519 | 577 |
533 all_cmplx = false; | 591 all_cmplx = false; |
534 | 592 |
535 if (all_mt && ! tmp.all_empty_p ()) | 593 if (all_mt && ! tmp.all_empty_p ()) |
536 all_mt = false; | 594 all_mt = false; |
537 | 595 |
596 if (!any_cell && tmp.any_cell_p ()) | |
597 any_cell = true; | |
598 | |
538 if (!any_sparse && tmp.any_sparse_p ()) | 599 if (!any_sparse && tmp.any_sparse_p ()) |
539 any_sparse = true; | 600 any_sparse = true; |
540 | 601 |
541 if (!any_class && tmp.any_class_p ()) | 602 if (!any_class && tmp.any_class_p ()) |
542 any_class = true; | 603 any_class = true; |
549 break; | 610 break; |
550 } | 611 } |
551 | 612 |
552 if (! error_state) | 613 if (! error_state) |
553 { | 614 { |
615 iterator p = begin (); | |
616 | |
617 if (any_cell && ! any_class && ! first_elem_is_struct) | |
618 { | |
619 for (iterator p = begin (); p != end (); p++) | |
620 { | |
621 octave_quit (); | |
622 | |
623 p->cellify (); | |
624 } | |
625 } | |
626 | |
627 first_elem = true; | |
628 | |
554 for (iterator p = begin (); p != end (); p++) | 629 for (iterator p = begin (); p != end (); p++) |
555 { | 630 { |
556 octave_quit (); | 631 octave_quit (); |
557 | 632 |
558 tm_row_const elt = *p; | 633 tm_row_const elt = *p; |
1159 /* | 1234 /* |
1160 %% test concatenation with all zero matrices | 1235 %% test concatenation with all zero matrices |
1161 %!assert([ '' 65*ones(1,10) ], 'AAAAAAAAAA'); | 1236 %!assert([ '' 65*ones(1,10) ], 'AAAAAAAAAA'); |
1162 %!assert([ 65*ones(1,10) '' ], 'AAAAAAAAAA'); | 1237 %!assert([ 65*ones(1,10) '' ], 'AAAAAAAAAA'); |
1163 | 1238 |
1239 %!test | |
1240 %! c = {'foo'; 'bar'; 'bazoloa'}; | |
1241 %! assert ([c; 'a'; 'bc'; 'def'], {'foo'; 'bar'; 'bazoloa'; 'a'; 'bc'; 'def'}); | |
1242 | |
1164 %!assert (class ([int64(1), int64(1)]), 'int64') | 1243 %!assert (class ([int64(1), int64(1)]), 'int64') |
1165 %!assert (class ([int64(1), int32(1)]), 'int64') | 1244 %!assert (class ([int64(1), int32(1)]), 'int64') |
1166 %!assert (class ([int64(1), int16(1)]), 'int64') | 1245 %!assert (class ([int64(1), int16(1)]), 'int64') |
1167 %!assert (class ([int64(1), int8(1)]), 'int64') | 1246 %!assert (class ([int64(1), int8(1)]), 'int64') |
1168 %!assert (class ([int64(1), uint64(1)]), 'int64') | 1247 %!assert (class ([int64(1), uint64(1)]), 'int64') |