00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <iostream>
00028
00029 #include "quit.h"
00030
00031 #include "data.h"
00032 #include "defun.h"
00033 #include "error.h"
00034 #include "oct-obj.h"
00035 #include "pt-arg-list.h"
00036 #include "pt-bp.h"
00037 #include "pt-exp.h"
00038 #include "pt-mat.h"
00039 #include "pt-walk.h"
00040 #include "utils.h"
00041 #include "ov.h"
00042 #include "variables.h"
00043
00044 #include "ov-cx-mat.h"
00045 #include "ov-flt-cx-mat.h"
00046 #include "ov-re-sparse.h"
00047 #include "ov-cx-sparse.h"
00048
00049
00050 char Vstring_fill_char = ' ';
00051
00052
00053
00054
00055
00056
00057
00058 class
00059 tm_row_const
00060 {
00061 private:
00062
00063 class
00064 tm_row_const_rep : public octave_base_list<octave_value>
00065 {
00066 public:
00067
00068 tm_row_const_rep (void)
00069 : count (1), dv (0, 0), all_str (false),
00070 all_sq_str (false), all_dq_str (false),
00071 some_str (false), all_real (false), all_cmplx (false),
00072 all_mt (true), any_cell (false), any_sparse (false),
00073 any_class (false), all_1x1 (false),
00074 first_elem_is_struct (false), class_nm (), ok (false)
00075 { }
00076
00077 tm_row_const_rep (const tree_argument_list& row)
00078 : count (1), dv (0, 0), all_str (false), all_sq_str (false),
00079 some_str (false), all_real (false), all_cmplx (false),
00080 all_mt (true), any_cell (false), any_sparse (false),
00081 any_class (false), all_1x1 (! row.empty ()),
00082 first_elem_is_struct (false), class_nm (), ok (false)
00083 { init (row); }
00084
00085 ~tm_row_const_rep (void) { }
00086
00087 octave_refcount<int> count;
00088
00089 dim_vector dv;
00090
00091 bool all_str;
00092 bool all_sq_str;
00093 bool all_dq_str;
00094 bool some_str;
00095 bool all_real;
00096 bool all_cmplx;
00097 bool all_mt;
00098 bool any_cell;
00099 bool any_sparse;
00100 bool any_class;
00101 bool all_1x1;
00102 bool first_elem_is_struct;
00103
00104 std::string class_nm;
00105
00106 bool ok;
00107
00108 void do_init_element (const octave_value&, bool&);
00109
00110 void init (const tree_argument_list&);
00111
00112 void cellify (void);
00113
00114 private:
00115
00116 tm_row_const_rep (const tm_row_const_rep&);
00117
00118 tm_row_const_rep& operator = (const tm_row_const_rep&);
00119
00120 };
00121
00122 public:
00123
00124 typedef tm_row_const_rep::iterator iterator;
00125 typedef tm_row_const_rep::const_iterator const_iterator;
00126
00127 tm_row_const (void)
00128 : rep (0) { }
00129
00130 tm_row_const (const tree_argument_list& row)
00131 : rep (new tm_row_const_rep (row)) { }
00132
00133 tm_row_const (const tm_row_const& x)
00134 : rep (x.rep)
00135 {
00136 if (rep)
00137 rep->count++;
00138 }
00139
00140 tm_row_const& operator = (const tm_row_const& x)
00141 {
00142 if (this != &x && rep != x.rep)
00143 {
00144 if (rep && --rep->count == 0)
00145 delete rep;
00146
00147 rep = x.rep;
00148
00149 if (rep)
00150 rep->count++;
00151 }
00152
00153 return *this;
00154 }
00155
00156 ~tm_row_const (void)
00157 {
00158 if (rep && --rep->count == 0)
00159 delete rep;
00160 }
00161
00162 octave_idx_type rows (void) { return rep->dv(0); }
00163 octave_idx_type cols (void) { return rep->dv(1); }
00164
00165 bool empty (void) const { return rep->empty (); }
00166
00167 size_t length (void) const { return rep->length (); }
00168
00169 dim_vector dims (void) { return rep->dv; }
00170
00171 bool all_strings_p (void) const { return rep->all_str; }
00172 bool all_sq_strings_p (void) const { return rep->all_sq_str; }
00173 bool all_dq_strings_p (void) const { return rep->all_dq_str; }
00174 bool some_strings_p (void) const { return rep->some_str; }
00175 bool all_real_p (void) const { return rep->all_real; }
00176 bool all_complex_p (void) const { return rep->all_cmplx; }
00177 bool all_empty_p (void) const { return rep->all_mt; }
00178 bool any_cell_p (void) const { return rep->any_cell; }
00179 bool any_sparse_p (void) const { return rep->any_sparse; }
00180 bool any_class_p (void) const { return rep->any_class; }
00181 bool all_1x1_p (void) const { return rep->all_1x1; }
00182 bool first_elem_struct_p (void) const { return rep->first_elem_is_struct; }
00183
00184 std::string class_name (void) const { return rep->class_nm; }
00185
00186 void cellify (void) { rep->cellify (); }
00187
00188 operator bool () const { return (rep && rep->ok); }
00189
00190 iterator begin (void) { return rep->begin (); }
00191 const_iterator begin (void) const { return rep->begin (); }
00192
00193 iterator end (void) { return rep->end (); }
00194 const_iterator end (void) const { return rep->end (); }
00195
00196 private:
00197
00198 tm_row_const_rep *rep;
00199 };
00200
00201 std::string
00202 get_concat_class (const std::string& c1, const std::string& c2)
00203 {
00204 std::string retval = octave_base_value::static_class_name ();
00205
00206 if (c1 == c2)
00207 retval = c1;
00208 else if (c1.empty ())
00209 retval = c2;
00210 else if (c2.empty ())
00211 retval = c1;
00212 else if (c1 == "class" || c2 == "class")
00213 retval = "class";
00214 else
00215 {
00216 bool c1_is_int = (c1 == "int8" || c1 == "uint8"
00217 || c1 == "int16" || c1 == "uint16"
00218 || c1 == "int32" || c1 == "uint32"
00219 || c1 == "int64" || c1 == "uint64");
00220 bool c2_is_int = (c2 == "int8" || c2 == "uint8"
00221 || c2 == "int16" || c2 == "uint16"
00222 || c2 == "int32" || c2 == "uint32"
00223 || c2 == "int64" || c2 == "uint64");
00224
00225 bool c1_is_char = (c1 == "char");
00226 bool c2_is_char = (c2 == "char");
00227
00228 bool c1_is_double = (c1 == "double");
00229 bool c2_is_double = (c2 == "double");
00230
00231 bool c1_is_single = (c1 == "single");
00232 bool c2_is_single = (c2 == "single");
00233
00234 bool c1_is_logical = (c1 == "logical");
00235 bool c2_is_logical = (c2 == "logical");
00236
00237 bool c1_is_built_in_type
00238 = (c1_is_int || c1_is_char || c1_is_double || c1_is_single
00239 || c1_is_logical);
00240
00241 bool c2_is_built_in_type
00242 = (c2_is_int || c2_is_char || c2_is_double || c2_is_single
00243 || c2_is_logical);
00244
00245
00246
00247 if (c1 == "struct" && c2 == c1)
00248 retval = c1;
00249 else if (c1 == "cell" || c2 == "cell")
00250 retval = "cell";
00251 else if (c1_is_char && c2_is_built_in_type)
00252 retval = c1;
00253 else if (c2_is_char && c1_is_built_in_type)
00254 retval = c2;
00255 else if (c1_is_int && c2_is_built_in_type)
00256 retval = c1;
00257 else if (c2_is_int && c1_is_built_in_type)
00258 retval = c2;
00259 else if (c1_is_single && c2_is_built_in_type)
00260 retval = c1;
00261 else if (c2_is_single && c1_is_built_in_type)
00262 retval = c2;
00263 else if (c1_is_double && c2_is_built_in_type)
00264 retval = c1;
00265 else if (c2_is_double && c1_is_built_in_type)
00266 retval = c2;
00267 else if (c1_is_logical && c2_is_logical)
00268 retval = c1;
00269 }
00270
00271 return retval;
00272 }
00273
00274 static void
00275 eval_error (const char *msg, const dim_vector& x, const dim_vector& y)
00276 {
00277 ::error ("%s (%s vs %s)", msg, x.str ().c_str (), y.str ().c_str ());
00278 }
00279
00280 void
00281 tm_row_const::tm_row_const_rep::do_init_element (const octave_value& val,
00282 bool& first_elem)
00283 {
00284 std::string this_elt_class_nm
00285 = val.is_object () ? std::string ("class") : val.class_name ();
00286
00287 class_nm = get_concat_class (class_nm, this_elt_class_nm);
00288
00289 dim_vector this_elt_dv = val.dims ();
00290
00291 if (! this_elt_dv.zero_by_zero ())
00292 {
00293 all_mt = false;
00294
00295 if (first_elem)
00296 {
00297 if (val.is_map ())
00298 first_elem_is_struct = true;
00299
00300 first_elem = false;
00301 }
00302 }
00303
00304 append (val);
00305
00306 if (all_str && ! val.is_string ())
00307 all_str = false;
00308
00309 if (all_sq_str && ! val.is_sq_string ())
00310 all_sq_str = false;
00311
00312 if (all_dq_str && ! val.is_dq_string ())
00313 all_dq_str = false;
00314
00315 if (! some_str && val.is_string ())
00316 some_str = true;
00317
00318 if (all_real && ! val.is_real_type ())
00319 all_real = false;
00320
00321 if (all_cmplx && ! (val.is_complex_type () || val.is_real_type ()))
00322 all_cmplx = false;
00323
00324 if (!any_cell && val.is_cell ())
00325 any_cell = true;
00326
00327 if (!any_sparse && val.is_sparse_type ())
00328 any_sparse = true;
00329
00330 if (!any_class && val.is_object ())
00331 any_class = true;
00332
00333 all_1x1 = all_1x1 && val.numel () == 1;
00334 }
00335
00336 void
00337 tm_row_const::tm_row_const_rep::init (const tree_argument_list& row)
00338 {
00339 all_str = true;
00340 all_sq_str = true;
00341 all_dq_str = true;
00342 all_real = true;
00343 all_cmplx = true;
00344 any_cell = false;
00345 any_sparse = false;
00346 any_class = false;
00347
00348 bool first_elem = true;
00349
00350 for (tree_argument_list::const_iterator p = row.begin ();
00351 p != row.end ();
00352 p++)
00353 {
00354 octave_quit ();
00355
00356 tree_expression *elt = *p;
00357
00358 octave_value tmp = elt->rvalue1 ();
00359
00360 if (error_state || tmp.is_undefined ())
00361 {
00362 ok = ! error_state;
00363 return;
00364 }
00365 else
00366 {
00367 if (tmp.is_cs_list ())
00368 {
00369 octave_value_list tlst = tmp.list_value ();
00370
00371 for (octave_idx_type i = 0; i < tlst.length (); i++)
00372 {
00373 octave_quit ();
00374
00375 do_init_element (tlst(i), first_elem);
00376 }
00377 }
00378 else
00379 do_init_element (tmp, first_elem);
00380 }
00381 }
00382
00383 if (any_cell && ! any_class && ! first_elem_is_struct)
00384 cellify ();
00385
00386 first_elem = true;
00387
00388 for (iterator p = begin (); p != end (); p++)
00389 {
00390 octave_quit ();
00391
00392 octave_value val = *p;
00393
00394 dim_vector this_elt_dv = val.dims ();
00395
00396 if (! this_elt_dv.zero_by_zero ())
00397 {
00398 all_mt = false;
00399
00400 if (first_elem)
00401 {
00402 first_elem = false;
00403 dv = this_elt_dv;
00404 }
00405 else if (! dv.hvcat (this_elt_dv, 1))
00406 {
00407 eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
00408 break;
00409 }
00410 }
00411 }
00412
00413 ok = ! error_state;
00414 }
00415
00416 void
00417 tm_row_const::tm_row_const_rep::cellify (void)
00418 {
00419 bool elt_changed = false;
00420
00421 for (iterator p = begin (); p != end (); p++)
00422 {
00423 octave_quit ();
00424
00425 if (! p->is_cell ())
00426 {
00427 elt_changed = true;
00428
00429 *p = Cell (*p);
00430 }
00431 }
00432
00433 if (elt_changed)
00434 {
00435 bool first_elem = true;
00436
00437 for (iterator p = begin (); p != end (); p++)
00438 {
00439 octave_quit ();
00440
00441 octave_value val = *p;
00442
00443 dim_vector this_elt_dv = val.dims ();
00444
00445 if (! this_elt_dv.zero_by_zero ())
00446 {
00447 if (first_elem)
00448 {
00449 first_elem = false;
00450 dv = this_elt_dv;
00451 }
00452 else if (! dv.hvcat (this_elt_dv, 1))
00453 {
00454 eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
00455 break;
00456 }
00457 }
00458 }
00459 }
00460 }
00461
00462 class
00463 tm_const : public octave_base_list<tm_row_const>
00464 {
00465 public:
00466
00467 tm_const (const tree_matrix& tm)
00468 : dv (0, 0), all_str (false), all_sq_str (false), all_dq_str (false),
00469 some_str (false), all_real (false), all_cmplx (false),
00470 all_mt (true), any_cell (false), any_sparse (false),
00471 any_class (false), class_nm (), ok (false)
00472 { init (tm); }
00473
00474 ~tm_const (void) { }
00475
00476 octave_idx_type rows (void) const { return dv.elem (0); }
00477 octave_idx_type cols (void) const { return dv.elem (1); }
00478
00479 dim_vector dims (void) const { return dv; }
00480
00481 bool all_strings_p (void) const { return all_str; }
00482 bool all_sq_strings_p (void) const { return all_sq_str; }
00483 bool all_dq_strings_p (void) const { return all_dq_str; }
00484 bool some_strings_p (void) const { return some_str; }
00485 bool all_real_p (void) const { return all_real; }
00486 bool all_complex_p (void) const { return all_cmplx; }
00487 bool all_empty_p (void) const { return all_mt; }
00488 bool any_cell_p (void) const { return any_cell; }
00489 bool any_sparse_p (void) const { return any_sparse; }
00490 bool any_class_p (void) const { return any_class; }
00491 bool all_1x1_p (void) const { return all_1x1; }
00492
00493 std::string class_name (void) const { return class_nm; }
00494
00495 operator bool () const { return ok; }
00496
00497 private:
00498
00499 dim_vector dv;
00500
00501 bool all_str;
00502 bool all_sq_str;
00503 bool all_dq_str;
00504 bool some_str;
00505 bool all_real;
00506 bool all_cmplx;
00507 bool all_mt;
00508 bool any_cell;
00509 bool any_sparse;
00510 bool any_class;
00511 bool all_1x1;
00512
00513 std::string class_nm;
00514
00515 bool ok;
00516
00517 tm_const (void);
00518
00519 tm_const (const tm_const&);
00520
00521 tm_const& operator = (const tm_const&);
00522
00523 void init (const tree_matrix& tm);
00524 };
00525
00526 void
00527 tm_const::init (const tree_matrix& tm)
00528 {
00529 all_str = true;
00530 all_sq_str = true;
00531 all_dq_str = true;
00532 all_real = true;
00533 all_cmplx = true;
00534 any_cell = false;
00535 any_sparse = false;
00536 any_class = false;
00537 all_1x1 = ! tm.empty ();
00538
00539 bool first_elem = true;
00540 bool first_elem_is_struct = false;
00541
00542
00543
00544
00545
00546
00547 for (tree_matrix::const_iterator p = tm.begin (); p != tm.end (); p++)
00548 {
00549 octave_quit ();
00550
00551 tree_argument_list *elt = *p;
00552
00553 tm_row_const tmp (*elt);
00554
00555 if (first_elem)
00556 {
00557 first_elem_is_struct = tmp.first_elem_struct_p ();
00558
00559 first_elem = false;
00560 }
00561
00562 if (tmp && ! tmp.empty ())
00563 {
00564 if (all_str && ! tmp.all_strings_p ())
00565 all_str = false;
00566
00567 if (all_sq_str && ! tmp.all_sq_strings_p ())
00568 all_sq_str = false;
00569
00570 if (all_dq_str && ! tmp.all_dq_strings_p ())
00571 all_dq_str = false;
00572
00573 if (! some_str && tmp.some_strings_p ())
00574 some_str = true;
00575
00576 if (all_real && ! tmp.all_real_p ())
00577 all_real = false;
00578
00579 if (all_cmplx && ! tmp.all_complex_p ())
00580 all_cmplx = false;
00581
00582 if (all_mt && ! tmp.all_empty_p ())
00583 all_mt = false;
00584
00585 if (!any_cell && tmp.any_cell_p ())
00586 any_cell = true;
00587
00588 if (!any_sparse && tmp.any_sparse_p ())
00589 any_sparse = true;
00590
00591 if (!any_class && tmp.any_class_p ())
00592 any_class = true;
00593
00594 all_1x1 = all_1x1 && tmp.all_1x1_p ();
00595
00596 append (tmp);
00597 }
00598 else
00599 break;
00600 }
00601
00602 if (! error_state)
00603 {
00604 if (any_cell && ! any_class && ! first_elem_is_struct)
00605 {
00606 for (iterator q = begin (); q != end (); q++)
00607 {
00608 octave_quit ();
00609
00610 q->cellify ();
00611 }
00612 }
00613
00614 first_elem = true;
00615
00616 for (iterator q = begin (); q != end (); q++)
00617 {
00618 octave_quit ();
00619
00620 tm_row_const elt = *q;
00621
00622 octave_idx_type this_elt_nr = elt.rows ();
00623 octave_idx_type this_elt_nc = elt.cols ();
00624
00625 std::string this_elt_class_nm = elt.class_name ();
00626 class_nm = get_concat_class (class_nm, this_elt_class_nm);
00627
00628 dim_vector this_elt_dv = elt.dims ();
00629
00630 all_mt = false;
00631
00632 if (first_elem)
00633 {
00634 first_elem = false;
00635
00636 dv = this_elt_dv;
00637 }
00638 else if (all_str && dv.length () == 2
00639 && this_elt_dv.length () == 2)
00640 {
00641
00642
00643 if (this_elt_nc > cols ())
00644 dv(1) = this_elt_nc;
00645 dv(0) += this_elt_nr;
00646 }
00647 else if (! dv.hvcat (this_elt_dv, 0))
00648 {
00649 eval_error ("vertical dimensions mismatch", dv, this_elt_dv);
00650 return;
00651 }
00652 }
00653 }
00654
00655 ok = ! error_state;
00656 }
00657
00658 tree_matrix::~tree_matrix (void)
00659 {
00660 while (! empty ())
00661 {
00662 iterator p = begin ();
00663 delete *p;
00664 erase (p);
00665 }
00666 }
00667
00668 bool
00669 tree_matrix::has_magic_end (void) const
00670 {
00671 for (const_iterator p = begin (); p != end (); p++)
00672 {
00673 octave_quit ();
00674
00675 tree_argument_list *elt = *p;
00676
00677 if (elt && elt->has_magic_end ())
00678 return true;
00679 }
00680
00681 return false;
00682 }
00683
00684 bool
00685 tree_matrix::all_elements_are_constant (void) const
00686 {
00687 for (const_iterator p = begin (); p != end (); p++)
00688 {
00689 octave_quit ();
00690
00691 tree_argument_list *elt = *p;
00692
00693 if (! elt->all_elements_are_constant ())
00694 return false;
00695 }
00696
00697 return true;
00698 }
00699
00700 octave_value_list
00701 tree_matrix::rvalue (int nargout)
00702 {
00703 octave_value_list retval;
00704
00705 if (nargout > 1)
00706 error ("invalid number of output arguments for matrix list");
00707 else
00708 retval = rvalue1 (nargout);
00709
00710 return retval;
00711 }
00712
00713 void
00714 maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p)
00715 {
00716 if (! (all_dq_strings_p || all_sq_strings_p))
00717 warning_with_id ("Octave:mixed-string-concat",
00718 "concatenation of different character string types may have unintended consequences");
00719 }
00720
00721 template<class TYPE, class T>
00722 static void
00723 single_type_concat (Array<T>& result,
00724 tm_const& tmp)
00725 {
00726 octave_idx_type r = 0, c = 0;
00727
00728 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
00729 {
00730 tm_row_const row = *p;
00731
00732 if (row.dims ().any_zero ())
00733 continue;
00734
00735 for (tm_row_const::iterator q = row.begin ();
00736 q != row.end ();
00737 q++)
00738 {
00739 octave_quit ();
00740
00741 TYPE ra = octave_value_extract<TYPE> (*q);
00742
00743
00744 if (! error_state)
00745 {
00746 if (! ra.is_empty ())
00747 {
00748 result.insert (ra, r, c);
00749
00750 if (! error_state)
00751 c += ra.columns ();
00752 else
00753 return;
00754 }
00755 }
00756 else
00757 return;
00758 }
00759
00760 r += row.rows ();
00761 c = 0;
00762 }
00763 }
00764
00765 template<class TYPE, class T>
00766 static void
00767 single_type_concat (Array<T>& result,
00768 const dim_vector& dv,
00769 tm_const& tmp)
00770 {
00771 if (dv.any_zero ())
00772 {
00773 result = Array<T> (dv);
00774 return;
00775 }
00776
00777 if (tmp.length () == 1)
00778 {
00779
00780
00781 tm_row_const& row = tmp.front ();
00782 if (! (equal_types<T, char>::value || equal_types<T, octave_value>::value)
00783 && row.all_1x1_p ())
00784 {
00785
00786 result.clear (dv);
00787 assert (result.numel () == row.length ());
00788 octave_idx_type i = 0;
00789 for (tm_row_const::iterator q = row.begin ();
00790 q != row.end () && ! error_state; q++)
00791 result(i++) = octave_value_extract<T> (*q);
00792
00793 return;
00794 }
00795
00796 octave_idx_type ncols = row.length (), i = 0;
00797 OCTAVE_LOCAL_BUFFER (Array<T>, array_list, ncols);
00798
00799 for (tm_row_const::iterator q = row.begin ();
00800 q != row.end () && ! error_state;
00801 q++)
00802 {
00803 octave_quit ();
00804
00805 array_list[i] = octave_value_extract<TYPE> (*q);
00806 i++;
00807 }
00808
00809 if (! error_state)
00810 result = Array<T>::cat (-2, ncols, array_list);
00811 }
00812 else
00813 {
00814 result = Array<T> (dv);
00815 single_type_concat<TYPE> (result, tmp);
00816 }
00817 }
00818
00819 template<class TYPE, class T>
00820 static void
00821 single_type_concat (Sparse<T>& result,
00822 const dim_vector& dv,
00823 tm_const& tmp)
00824 {
00825 if (dv.any_zero ())
00826 {
00827 result = Sparse<T> (dv);
00828 return;
00829 }
00830
00831
00832
00833
00834 octave_idx_type nrows = tmp.length (), j = 0;
00835 OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_row_list, nrows);
00836 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
00837 {
00838 tm_row_const row = *p;
00839 octave_idx_type ncols = row.length (), i = 0;
00840 OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_list, ncols);
00841
00842 for (tm_row_const::iterator q = row.begin ();
00843 q != row.end () && ! error_state;
00844 q++)
00845 {
00846 octave_quit ();
00847
00848 sparse_list[i] = octave_value_extract<TYPE> (*q);
00849 i++;
00850 }
00851
00852 Sparse<T> stmp = Sparse<T>::cat (-2, ncols, sparse_list);
00853 sparse_row_list[j] = stmp;
00854 j++;
00855 }
00856
00857 result = Sparse<T>::cat (-1, nrows, sparse_row_list);
00858 }
00859
00860 template<class MAP>
00861 static void
00862 single_type_concat (octave_map& result,
00863 const dim_vector& dv,
00864 tm_const& tmp)
00865 {
00866 if (dv.any_zero ())
00867 {
00868 result = octave_map (dv);
00869 return;
00870 }
00871
00872 octave_idx_type nrows = tmp.length (), j = 0;
00873 OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows);
00874 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
00875 {
00876 tm_row_const row = *p;
00877 octave_idx_type ncols = row.length (), i = 0;
00878 OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols);
00879
00880 for (tm_row_const::iterator q = row.begin ();
00881 q != row.end () && ! error_state;
00882 q++)
00883 {
00884 octave_quit ();
00885
00886 map_list[i] = octave_value_extract<MAP> (*q);
00887 i++;
00888 }
00889
00890 octave_map mtmp = octave_map::cat (-2, ncols, map_list);
00891 map_row_list[j] = mtmp;
00892 j++;
00893 }
00894
00895 result = octave_map::cat (-1, nrows, map_row_list);
00896 }
00897
00898 template<class TYPE>
00899 static octave_value
00900 do_single_type_concat (const dim_vector& dv,
00901 tm_const& tmp)
00902 {
00903 TYPE result;
00904
00905 single_type_concat<TYPE> (result, dv, tmp);
00906
00907 return result;
00908 }
00909
00910 template<>
00911 octave_value
00912 do_single_type_concat<octave_map> (const dim_vector& dv,
00913 tm_const& tmp)
00914 {
00915 octave_map result;
00916
00917 if (tmp.all_1x1_p ())
00918 single_type_concat<octave_scalar_map> (result, dv, tmp);
00919 else
00920 single_type_concat<octave_map> (result, dv, tmp);
00921
00922 return result;
00923 }
00924
00925 static octave_value
00926 do_class_concat (tm_const& tmc)
00927 {
00928 octave_value retval;
00929
00930 octave_value_list rows (tmc.length (), octave_value ());
00931
00932 octave_idx_type j = 0;
00933 for (tm_const::iterator p = tmc.begin (); p != tmc.end (); p++)
00934 {
00935 octave_quit ();
00936
00937 tm_row_const tmrc = *p;
00938
00939 if (tmrc.length () == 1)
00940 rows(j++) = *(tmrc.begin ());
00941 else
00942 {
00943 octave_value_list row (tmrc.length (), octave_value ());
00944
00945 octave_idx_type i = 0;
00946 for (tm_row_const::iterator q = tmrc.begin (); q != tmrc.end (); q++)
00947 row(i++) = *q;
00948
00949 rows(j++) = do_class_concat (row, "horzcat", 1);
00950 }
00951 }
00952
00953 if (! error_state)
00954 {
00955 if (rows.length () == 1)
00956 retval = rows(0);
00957 else
00958 retval = do_class_concat (rows, "vertcat", 0);
00959 }
00960
00961 return retval;
00962 }
00963
00964 octave_value
00965 tree_matrix::rvalue1 (int)
00966 {
00967 octave_value retval = Matrix ();
00968
00969 bool all_sq_strings_p = false;
00970 bool all_dq_strings_p = false;
00971 bool all_empty_p = false;
00972 bool all_real_p = false;
00973 bool any_sparse_p = false;
00974 bool any_class_p = false;
00975 bool frc_str_conv = false;
00976
00977 tm_const tmp (*this);
00978
00979 if (tmp && ! tmp.empty ())
00980 {
00981 dim_vector dv = tmp.dims ();
00982 all_sq_strings_p = tmp.all_sq_strings_p ();
00983 all_dq_strings_p = tmp.all_dq_strings_p ();
00984 all_empty_p = tmp.all_empty_p ();
00985 all_real_p = tmp.all_real_p ();
00986 any_sparse_p = tmp.any_sparse_p ();
00987 any_class_p = tmp.any_class_p ();
00988 frc_str_conv = tmp.some_strings_p ();
00989
00990
00991
00992 std::string result_type = tmp.class_name ();
00993
00994 if (any_class_p)
00995 {
00996 retval = do_class_concat (tmp);
00997 }
00998 else if (result_type == "double")
00999 {
01000 if (any_sparse_p)
01001 {
01002 if (all_real_p)
01003 retval = do_single_type_concat<SparseMatrix> (dv, tmp);
01004 else
01005 retval = do_single_type_concat<SparseComplexMatrix> (dv, tmp);
01006 }
01007 else
01008 {
01009 if (all_real_p)
01010 retval = do_single_type_concat<NDArray> (dv, tmp);
01011 else
01012 retval = do_single_type_concat<ComplexNDArray> (dv, tmp);
01013 }
01014 }
01015 else if (result_type == "single")
01016 {
01017 if (all_real_p)
01018 retval = do_single_type_concat<FloatNDArray> (dv, tmp);
01019 else
01020 retval = do_single_type_concat<FloatComplexNDArray> (dv, tmp);
01021 }
01022 else if (result_type == "char")
01023 {
01024 char type = all_dq_strings_p ? '"' : '\'';
01025
01026 maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
01027
01028 charNDArray result (dv, Vstring_fill_char);
01029
01030 single_type_concat<charNDArray> (result, tmp);
01031
01032 retval = octave_value (result, type);
01033 }
01034 else if (result_type == "logical")
01035 {
01036 if (any_sparse_p)
01037 retval = do_single_type_concat<SparseBoolMatrix> (dv, tmp);
01038 else
01039 retval = do_single_type_concat<boolNDArray> (dv, tmp);
01040 }
01041 else if (result_type == "int8")
01042 retval = do_single_type_concat<int8NDArray> (dv, tmp);
01043 else if (result_type == "int16")
01044 retval = do_single_type_concat<int16NDArray> (dv, tmp);
01045 else if (result_type == "int32")
01046 retval = do_single_type_concat<int32NDArray> (dv, tmp);
01047 else if (result_type == "int64")
01048 retval = do_single_type_concat<int64NDArray> (dv, tmp);
01049 else if (result_type == "uint8")
01050 retval = do_single_type_concat<uint8NDArray> (dv, tmp);
01051 else if (result_type == "uint16")
01052 retval = do_single_type_concat<uint16NDArray> (dv, tmp);
01053 else if (result_type == "uint32")
01054 retval = do_single_type_concat<uint32NDArray> (dv, tmp);
01055 else if (result_type == "uint64")
01056 retval = do_single_type_concat<uint64NDArray> (dv, tmp);
01057 else if (result_type == "cell")
01058 retval = do_single_type_concat<Cell> (dv, tmp);
01059 else if (result_type == "struct")
01060 retval = do_single_type_concat<octave_map> (dv, tmp);
01061 else
01062 {
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 octave_value ctmp;
01081
01082
01083
01084 if (any_sparse_p)
01085 {
01086
01087
01088 if (all_real_p)
01089 ctmp = octave_sparse_matrix ().resize (dv);
01090 else
01091 ctmp = octave_sparse_complex_matrix ().resize (dv);
01092 }
01093 else
01094 {
01095 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
01096 {
01097 octave_quit ();
01098
01099 tm_row_const row = *p;
01100
01101 for (tm_row_const::iterator q = row.begin ();
01102 q != row.end (); q++)
01103 {
01104 octave_quit ();
01105
01106 ctmp = *q;
01107
01108 if (! ctmp.all_zero_dims ())
01109 goto found_non_empty;
01110 }
01111 }
01112
01113 ctmp = (*(tmp.begin() -> begin()));
01114
01115 found_non_empty:
01116
01117 if (! all_empty_p)
01118 ctmp = ctmp.resize (dim_vector (0,0)).resize (dv);
01119 }
01120
01121 if (! error_state)
01122 {
01123
01124
01125
01126 int dv_len = dv.length ();
01127 octave_idx_type ntmp = dv_len > 1 ? dv_len : 2;
01128 Array<octave_idx_type> ra_idx (dim_vector (ntmp, 1), 0);
01129
01130 for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
01131 {
01132 octave_quit ();
01133
01134 tm_row_const row = *p;
01135
01136 for (tm_row_const::iterator q = row.begin ();
01137 q != row.end ();
01138 q++)
01139 {
01140 octave_quit ();
01141
01142 octave_value elt = *q;
01143
01144 if (elt.is_empty ())
01145 continue;
01146
01147 ctmp = do_cat_op (ctmp, elt, ra_idx);
01148
01149 if (error_state)
01150 goto done;
01151
01152 ra_idx (1) += elt.columns ();
01153 }
01154
01155 ra_idx (0) += row.rows ();
01156 ra_idx (1) = 0;
01157 }
01158
01159 retval = ctmp;
01160
01161 if (frc_str_conv && ! retval.is_string ())
01162 retval = retval.convert_to_str ();
01163 }
01164 }
01165 }
01166
01167 done:
01168 return retval;
01169 }
01170
01171 tree_expression *
01172 tree_matrix::dup (symbol_table::scope_id scope,
01173 symbol_table::context_id context) const
01174 {
01175 tree_matrix *new_matrix = new tree_matrix (0, line (), column ());
01176
01177 for (const_iterator p = begin (); p != end (); p++)
01178 {
01179 const tree_argument_list *elt = *p;
01180
01181 new_matrix->append (elt ? elt->dup (scope, context) : 0);
01182 }
01183
01184 new_matrix->copy_base (*this);
01185
01186 return new_matrix;
01187 }
01188
01189 void
01190 tree_matrix::accept (tree_walker& tw)
01191 {
01192 tw.visit_matrix (*this);
01193 }
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 DEFUN (string_fill_char, args, nargout,
01391 "-*- texinfo -*-\n\
01392 @deftypefn {Built-in Function} {@var{val} =} string_fill_char ()\n\
01393 @deftypefnx {Built-in Function} {@var{old_val} =} string_fill_char (@var{new_val})\n\
01394 @deftypefnx {Built-in Function} {} string_fill_char (@var{new_val}, \"local\")\n\
01395 Query or set the internal variable used to pad all rows of a character\n\
01396 matrix to the same length. It must be a single character. The default\n\
01397 value is @code{\" \"} (a single space). For example:\n\
01398 \n\
01399 @example\n\
01400 @group\n\
01401 string_fill_char (\"X\");\n\
01402 [ \"these\"; \"are\"; \"strings\" ]\n\
01403 @result{} \"theseXX\"\n\
01404 \"areXXXX\"\n\
01405 \"strings\"\n\
01406 @end group\n\
01407 @end example\n\
01408 \n\
01409 When called from inside a function with the \"local\" option, the variable is\n\
01410 changed locally for the function and any subroutines it calls. The original\n\
01411 variable value is restored when exiting the function.\n\
01412 @end deftypefn")
01413 {
01414 return SET_INTERNAL_VARIABLE (string_fill_char);
01415 }
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430