00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include "error.h"
00029 #include "str-vec.h"
00030
00031 #include "oct-map.h"
00032 #include "utils.h"
00033
00034 octave_fields::octave_fields (const string_vector& fields)
00035 : rep (new fields_rep)
00036 {
00037 octave_idx_type n = fields.numel ();
00038 for (octave_idx_type i = 0; i < n; i++)
00039 (*rep)[fields(i)] = i;
00040 }
00041
00042 octave_fields::octave_fields (const char * const *fields)
00043 : rep (new fields_rep)
00044 {
00045 octave_idx_type n = 0;
00046 while (*fields)
00047 (*rep)[std::string (*fields++)] = n++;
00048 }
00049
00050 bool
00051 octave_fields::isfield (const std::string& field) const
00052 {
00053 return rep->find (field) != rep->end ();
00054 }
00055
00056 octave_idx_type
00057 octave_fields::getfield (const std::string& field) const
00058 {
00059 fields_rep::iterator p = rep->find (field);
00060 return (p != rep->end ()) ? p->second : -1;
00061 }
00062
00063 octave_idx_type
00064 octave_fields::getfield (const std::string& field)
00065 {
00066 fields_rep::iterator p = rep->find (field);
00067 if (p != rep->end ())
00068 return p->second;
00069 else
00070 {
00071 make_unique ();
00072 octave_idx_type n = rep->size ();
00073 return (*rep)[field] = n;
00074 }
00075 }
00076
00077 octave_idx_type
00078 octave_fields::rmfield (const std::string& field)
00079 {
00080 fields_rep::iterator p = rep->find (field);
00081 if (p == rep->end ())
00082 return -1;
00083 else
00084 {
00085 octave_idx_type n = p->second;
00086 make_unique ();
00087 rep->erase (field);
00088 for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++)
00089 {
00090 if (q->second >= n)
00091 q->second--;
00092 }
00093
00094 return n;
00095 }
00096 }
00097
00098 void
00099 octave_fields::orderfields (Array<octave_idx_type>& perm)
00100 {
00101 octave_idx_type n = rep->size ();
00102 perm.clear (n, 1);
00103
00104 make_unique ();
00105 octave_idx_type i = 0;
00106 for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++)
00107 {
00108 octave_idx_type j = q->second;
00109 q->second = i;
00110 perm(i++) = j;
00111 }
00112 }
00113
00114 bool
00115 octave_fields::equal_up_to_order (const octave_fields& other,
00116 octave_idx_type* perm) const
00117 {
00118 bool retval = true;
00119
00120 iterator p = begin (), q = other.begin ();
00121 for (; p != end () && q != other.end (); p++, q++)
00122 {
00123 if (p->first == q->first)
00124 perm[p->second] = q->second;
00125 else
00126 {
00127 retval = false;
00128 break;
00129 }
00130 }
00131
00132 retval = (p == end () && q == other.end ());
00133
00134 return retval;
00135 }
00136
00137 bool
00138 octave_fields::equal_up_to_order (const octave_fields& other,
00139 Array<octave_idx_type>& perm) const
00140 {
00141 octave_idx_type n = nfields ();
00142 if (perm.length () != n)
00143 perm.clear (1, n);
00144
00145 return equal_up_to_order (other, perm.fortran_vec ());
00146 }
00147
00148 string_vector
00149 octave_fields::fieldnames (void) const
00150 {
00151 octave_idx_type n = nfields ();
00152 string_vector retval(n);
00153
00154 for (iterator p = begin (); p != end (); p++)
00155 retval.xelem(p->second) = p->first;
00156
00157 return retval;
00158 }
00159
00160 octave_value
00161 octave_scalar_map::getfield (const std::string& k) const
00162 {
00163 octave_idx_type idx = xkeys.getfield (k);
00164 return (idx >= 0) ? xvals[idx] : octave_value ();
00165 }
00166
00167 void
00168 octave_scalar_map::setfield (const std::string& k, const octave_value& val)
00169 {
00170 octave_idx_type idx = xkeys.getfield (k);
00171 if (idx < static_cast<octave_idx_type> (xvals.size ()))
00172 xvals[idx] = val;
00173 else
00174 xvals.push_back (val);
00175 }
00176
00177 void
00178 octave_scalar_map::rmfield (const std::string& k)
00179 {
00180 octave_idx_type idx = xkeys.rmfield (k);
00181 if (idx >= 0)
00182 xvals.erase (xvals.begin () + idx);
00183 }
00184
00185 octave_scalar_map
00186 octave_scalar_map::orderfields (void) const
00187 {
00188 Array<octave_idx_type> perm;
00189 return orderfields (perm);
00190 }
00191
00192 octave_scalar_map
00193 octave_scalar_map::orderfields (Array<octave_idx_type>& perm) const
00194 {
00195 octave_scalar_map retval (xkeys);
00196 retval.xkeys.orderfields (perm);
00197
00198 octave_idx_type nf = nfields ();
00199 for (octave_idx_type i = 0; i < nf; i++)
00200 retval.xvals[i] = xvals[perm.xelem(i)];
00201
00202 return retval;
00203 }
00204
00205 octave_scalar_map
00206 octave_scalar_map::orderfields (const octave_scalar_map& other,
00207 Array<octave_idx_type>& perm) const
00208 {
00209 if (xkeys.is_same (other.xkeys))
00210 return *this;
00211 else
00212 {
00213 octave_scalar_map retval (other.xkeys);
00214 if (other.xkeys.equal_up_to_order (xkeys, perm))
00215 {
00216 octave_idx_type nf = nfields ();
00217 for (octave_idx_type i = 0; i < nf; i++)
00218 retval.xvals[i] = xvals[perm.xelem(i)];
00219 }
00220 else
00221 error ("orderfields: structs must have same fields up to order");
00222
00223 return retval;
00224 }
00225 }
00226
00227 octave_value
00228 octave_scalar_map::contents (const std::string& k) const
00229 {
00230 return getfield (k);
00231 }
00232
00233 octave_value&
00234 octave_scalar_map::contents (const std::string& k)
00235 {
00236 octave_idx_type idx = xkeys.getfield (k);
00237 if (idx >= static_cast<octave_idx_type> (xvals.size ()))
00238 xvals.resize (idx+1);
00239 return xvals[idx];
00240 }
00241
00242 octave_map::octave_map (const octave_scalar_map& m)
00243 : xkeys (m.xkeys), xvals (), dimensions (1, 1)
00244 {
00245 octave_idx_type nf = m.nfields ();
00246 xvals.reserve (nf);
00247 for (octave_idx_type i = 0; i < nf; i++)
00248 {
00249 xvals.push_back (Cell (dimensions));
00250 xvals[i].xelem(0) = m.xvals[i];
00251 }
00252 }
00253
00254 octave_map::octave_map (const Octave_map& m)
00255 : xkeys (m.keys ()), xvals (m.nfields ()), dimensions (m.dims ())
00256 {
00257 for (iterator p = begin (); p != end (); p++)
00258 contents(p) = m.contents (key (p));
00259
00260 optimize_dimensions ();
00261 }
00262
00263 Cell
00264 octave_map::getfield (const std::string& k) const
00265 {
00266 octave_idx_type idx = xkeys.getfield (k);
00267 return (idx >= 0) ? xvals[idx] : Cell ();
00268 }
00269
00270 void
00271 octave_map::setfield (const std::string& k, const Cell& val)
00272 {
00273 if (nfields () == 0)
00274 dimensions = val.dims ();
00275
00276 if (val.dims () == dimensions)
00277 {
00278 octave_idx_type idx = xkeys.getfield (k);
00279 if (idx < static_cast<octave_idx_type> (xvals.size ()))
00280 xvals[idx] = val;
00281 else
00282 xvals.push_back (val);
00283 }
00284 else
00285 error ("octave_map::setfield: internal error");
00286 }
00287
00288 void
00289 octave_map::rmfield (const std::string& k)
00290 {
00291 octave_idx_type idx = xkeys.rmfield (k);
00292 if (idx >= 0)
00293 xvals.erase (xvals.begin () + idx);
00294 }
00295
00296 octave_map
00297 octave_map::orderfields (void) const
00298 {
00299 Array<octave_idx_type> perm;
00300 return orderfields (perm);
00301 }
00302
00303 octave_map
00304 octave_map::orderfields (Array<octave_idx_type>& perm) const
00305 {
00306 octave_map retval (xkeys);
00307 retval.xkeys.orderfields (perm);
00308
00309 octave_idx_type nf = nfields ();
00310 for (octave_idx_type i = 0; i < nf; i++)
00311 retval.xvals[i] = xvals[perm.xelem(i)];
00312
00313 return retval;
00314 }
00315
00316 octave_map
00317 octave_map::orderfields (const octave_map& other,
00318 Array<octave_idx_type>& perm) const
00319 {
00320 if (xkeys.is_same (other.xkeys))
00321 return *this;
00322 else
00323 {
00324 octave_map retval (other.xkeys);
00325 if (other.xkeys.equal_up_to_order (xkeys, perm))
00326 {
00327 octave_idx_type nf = nfields ();
00328 for (octave_idx_type i = 0; i < nf; i++)
00329 retval.xvals[i] = xvals[perm.xelem(i)];
00330 }
00331 else
00332 error ("orderfields: structs must have same fields up to order");
00333
00334 return retval;
00335 }
00336 }
00337
00338 Cell
00339 octave_map::contents (const std::string& k) const
00340 {
00341 return getfield (k);
00342 }
00343
00344 Cell&
00345 octave_map::contents (const std::string& k)
00346 {
00347 octave_idx_type idx = xkeys.getfield (k);
00348 if (idx >= static_cast<octave_idx_type> (xvals.size ()))
00349 xvals.push_back (Cell (dimensions));
00350 return xvals[idx];
00351 }
00352
00353 void
00354 octave_map::extract_scalar (octave_scalar_map& dest,
00355 octave_idx_type idx) const
00356 {
00357 octave_idx_type nf = nfields ();
00358 for (octave_idx_type i = 0; i < nf; i++)
00359 dest.xvals[i] = xvals[i](idx);
00360 }
00361
00362 octave_scalar_map
00363 octave_map::checkelem (octave_idx_type n) const
00364 {
00365 octave_scalar_map retval (xkeys);
00366
00367
00368 extract_scalar (retval, compute_index (n, dimensions));
00369
00370 return retval;
00371 }
00372
00373 octave_scalar_map
00374 octave_map::checkelem (octave_idx_type i, octave_idx_type j) const
00375 {
00376 octave_scalar_map retval (xkeys);
00377
00378
00379 extract_scalar (retval, compute_index (i, j, dimensions));
00380
00381 return retval;
00382 }
00383
00384 octave_scalar_map
00385 octave_map::checkelem (const Array<octave_idx_type>& ra_idx) const
00386 {
00387 octave_scalar_map retval (xkeys);
00388
00389
00390 extract_scalar (retval, compute_index (ra_idx, dimensions));
00391
00392 return retval;
00393 }
00394
00395 octave_scalar_map
00396 octave_map::fast_elem_extract (octave_idx_type n) const
00397 {
00398 octave_scalar_map retval (xkeys);
00399
00400 extract_scalar (retval, n);
00401
00402 return retval;
00403 }
00404
00405 bool
00406 octave_map::fast_elem_insert (octave_idx_type n,
00407 const octave_scalar_map& rhs)
00408 {
00409 bool retval = false;
00410
00411 octave_idx_type nf = nfields ();
00412 if (rhs.xkeys.is_same (xkeys))
00413 {
00414 for (octave_idx_type i = 0; i < nf; i++)
00415 xvals[i](n) = rhs.xvals[i];
00416
00417 retval = true;
00418 }
00419 else
00420 {
00421 OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, nf);
00422 if (xkeys.equal_up_to_order (rhs.xkeys, perm))
00423 {
00424 for (octave_idx_type i = 0; i < nf; i++)
00425 xvals[i](n) = rhs.xvals[perm[i]];
00426
00427 retval = true;
00428 }
00429 }
00430
00431 return retval;
00432 }
00433
00434 octave_map
00435 octave_map::squeeze (void) const
00436 {
00437 octave_map retval (*this);
00438 octave_idx_type nf = nfields ();
00439
00440 retval.dimensions = dimensions.squeeze ();
00441
00442 for (octave_idx_type i = 0; i < nf; i++)
00443 retval.xvals[i] = xvals[i].squeeze ();
00444
00445 retval.optimize_dimensions ();
00446
00447 return retval;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457 octave_map
00458 octave_map::permute (const Array<int>& vec, bool inv) const
00459 {
00460 octave_map retval (xkeys);
00461 octave_idx_type nf = nfields ();
00462
00463 for (octave_idx_type i = 0; i < nf; i++)
00464 retval.xvals[i] = xvals[i].permute (vec, inv);
00465
00466
00467
00468
00469
00470 if (nf > 0)
00471 retval.dimensions = retval.xvals[0].dims ();
00472 else
00473 {
00474 Array<char> dummy (dimensions);
00475 dummy = dummy.permute (vec, inv);
00476 retval.dimensions = dummy.dims ();
00477 }
00478
00479 retval.optimize_dimensions ();
00480
00481 return retval;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491 octave_map
00492 octave_map::transpose (void) const
00493 {
00494 assert (ndims () == 2);
00495
00496 octave_map retval (xkeys);
00497
00498 retval.dimensions = dim_vector (dimensions (1), dimensions (0));
00499
00500 octave_idx_type nf = nfields ();
00501 for (octave_idx_type i = 0; i < nf; i++)
00502 retval.xvals[i] = xvals[i].transpose ();
00503
00504 retval.optimize_dimensions ();
00505
00506 return retval;
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 octave_map
00519 octave_map::reshape (const dim_vector& dv) const
00520 {
00521 octave_map retval (xkeys);
00522 retval.dimensions = dv;
00523
00524 octave_idx_type nf = nfields ();
00525 if (nf > 0)
00526 {
00527 retval.xvals.reserve (nf);
00528 for (octave_idx_type i = 0; i < nf; i++)
00529 retval.xvals[i] = xvals[i].reshape (dv);
00530 }
00531 else
00532 {
00533
00534
00535 Array<char> dummy (dimensions);
00536 dummy.reshape (dv);
00537 }
00538
00539 retval.optimize_dimensions ();
00540
00541 return retval;
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551 void
00552 octave_map::resize (const dim_vector& dv, bool fill)
00553 {
00554 octave_idx_type nf = nfields ();
00555 if (nf > 0)
00556 {
00557 for (octave_idx_type i = 0; i < nf; i++)
00558 {
00559 if (fill)
00560 xvals[i].resize (dv, Cell::resize_fill_value ());
00561 else
00562 xvals[i].resize (dv);
00563 }
00564 }
00565 else
00566 {
00567
00568
00569 Array<char> dummy (dimensions);
00570 dummy.resize (dv);
00571 }
00572
00573 dimensions = dv;
00574 optimize_dimensions ();
00575 }
00576
00577 void
00578 octave_map::do_cat (int dim, octave_idx_type n, const octave_scalar_map *map_list,
00579 octave_map& retval)
00580 {
00581 octave_idx_type nf = retval.nfields ();
00582 retval.xvals.reserve (nf);
00583
00584 dim_vector& rd = retval.dimensions;
00585 rd.resize (dim+1, 1);
00586 rd(0) = rd(1) = 1;
00587 rd(dim) = n;
00588
00589 for (octave_idx_type j = 0; j < nf; j++)
00590 {
00591 retval.xvals.push_back (Cell (rd));
00592 assert (retval.xvals[j].numel () == n);
00593 for (octave_idx_type i = 0; i < n; i++)
00594 retval.xvals[j].xelem(i) = map_list[i].xvals[j];
00595 }
00596 }
00597
00598 void
00599 octave_map::do_cat (int dim, octave_idx_type n, const octave_map *map_list,
00600 octave_map& retval)
00601 {
00602 octave_idx_type nf = retval.nfields ();
00603 retval.xvals.reserve (nf);
00604
00605 OCTAVE_LOCAL_BUFFER (Array<octave_value>, field_list, n);
00606
00607 for (octave_idx_type j = 0; j < nf; j++)
00608 {
00609 for (octave_idx_type i = 0; i < n; i++)
00610 field_list[i] = map_list[i].xvals[j];
00611
00612 retval.xvals.push_back (Array<octave_value>::cat (dim, n, field_list));
00613 if (j == 0)
00614 retval.dimensions = retval.xvals[j].dims ();
00615 }
00616 }
00617
00618
00619 void permute_to_correct_order1 (const octave_scalar_map& ref, const octave_scalar_map& src,
00620 octave_scalar_map& dest, Array<octave_idx_type>& perm)
00621 {
00622 dest = src.orderfields (ref, perm);
00623 }
00624
00625
00626 void permute_to_correct_order1 (const octave_map& ref, const octave_map& src,
00627 octave_map& dest, Array<octave_idx_type>& perm)
00628 {
00629 if (src.nfields () == 0 && src.is_empty ())
00630 dest = octave_map (src.dims (), ref.keys ());
00631 else
00632 dest = src.orderfields (ref, perm);
00633 }
00634
00635 template <class map>
00636 static void
00637 permute_to_correct_order (octave_idx_type n, octave_idx_type nf,
00638 octave_idx_type idx, const map *map_list,
00639 map *new_map_list)
00640 {
00641 new_map_list[idx] = map_list[idx];
00642
00643 Array<octave_idx_type> perm (dim_vector (1, nf));
00644
00645 for (octave_idx_type i = 0; i < n; i++)
00646 {
00647 if (i == idx)
00648 continue;
00649
00650 permute_to_correct_order1 (map_list[idx], map_list[i], new_map_list[i], perm);
00651
00652 if (error_state)
00653 {
00654
00655 (*current_liboctave_error_handler)
00656 ("cat: field names mismatch in concatenating structs");
00657 break;
00658 }
00659 }
00660 }
00661
00662
00663 octave_map
00664 octave_map::cat (int dim, octave_idx_type n, const octave_scalar_map *map_list)
00665 {
00666 octave_map retval;
00667
00668
00669 if (dim == -1 || dim == -2)
00670 dim = -dim - 1;
00671 else if (dim < 0)
00672 (*current_liboctave_error_handler)
00673 ("cat: invalid dimension");
00674
00675 if (n == 1)
00676 retval = map_list[0];
00677 else if (n > 1)
00678 {
00679 octave_idx_type idx, nf = 0;
00680 for (idx = 0; idx < n; idx++)
00681 {
00682 nf = map_list[idx].nfields ();
00683 if (nf > 0)
00684 {
00685 retval.xkeys = map_list[idx].xkeys;
00686 break;
00687 }
00688 }
00689
00690 if (nf > 0)
00691 {
00692
00693 bool all_same = true;
00694 for (octave_idx_type i = 0; i < n; i++)
00695 {
00696 all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys);
00697 if (! all_same)
00698 break;
00699 }
00700
00701 if (all_same)
00702 do_cat (dim, n, map_list, retval);
00703 else
00704 {
00705
00706 OCTAVE_LOCAL_BUFFER (octave_scalar_map, new_map_list, n);
00707
00708 permute_to_correct_order (n, nf, idx, map_list, new_map_list);
00709
00710 do_cat (dim, n, new_map_list, retval);
00711 }
00712
00713 }
00714 else
00715 {
00716 dim_vector& rd = retval.dimensions;
00717 rd.resize (dim+1, 1);
00718 rd(0) = rd(1) = 1;
00719 rd(dim) = n;
00720 }
00721
00722 retval.optimize_dimensions ();
00723 }
00724
00725 return retval;
00726 }
00727
00728 octave_map
00729 octave_map::cat (int dim, octave_idx_type n, const octave_map *map_list)
00730 {
00731 octave_map retval;
00732
00733
00734 if (dim == -1 || dim == -2)
00735 dim = -dim - 1;
00736 else if (dim < 0)
00737 (*current_liboctave_error_handler)
00738 ("cat: invalid dimension");
00739
00740 if (n == 1)
00741 retval = map_list[0];
00742 else if (n > 1)
00743 {
00744 octave_idx_type idx, nf = 0;
00745
00746 for (idx = 0; idx < n; idx++)
00747 {
00748 nf = map_list[idx].nfields ();
00749 if (nf > 0)
00750 {
00751 retval.xkeys = map_list[idx].xkeys;
00752 break;
00753 }
00754 }
00755
00756
00757 bool all_same = true;
00758
00759 if (nf > 0)
00760 {
00761 for (octave_idx_type i = 0; i < n; i++)
00762 {
00763 all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys);
00764
00765 if (! all_same)
00766 break;
00767 }
00768 }
00769
00770 if (all_same && nf > 0)
00771 do_cat (dim, n, map_list, retval);
00772 else
00773 {
00774 if (nf > 0)
00775 {
00776
00777 OCTAVE_LOCAL_BUFFER (octave_map, new_map_list, n);
00778
00779 permute_to_correct_order (n, nf, idx, map_list, new_map_list);
00780
00781 do_cat (dim, n, new_map_list, retval);
00782 }
00783 else
00784 {
00785 dim_vector dv = map_list[0].dimensions;
00786
00787 for (octave_idx_type i = 1; i < n; i++)
00788 {
00789 if (! dv.concat (map_list[i].dimensions, dim))
00790 {
00791 error ("dimension mismatch in struct concatenation");
00792 return retval;
00793 }
00794 }
00795
00796 retval.dimensions = dv;
00797 }
00798 }
00799
00800 retval.optimize_dimensions ();
00801 }
00802
00803 return retval;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826 octave_map
00827 octave_map::index (const idx_vector& i, bool resize_ok) const
00828 {
00829 octave_map retval (xkeys);
00830 octave_idx_type nf = nfields ();
00831
00832 for (octave_idx_type k = 0; k < nf; k++)
00833 retval.xvals[k] = xvals[k].index (i, resize_ok);
00834
00835 if (nf > 0)
00836 retval.dimensions = retval.xvals[0].dims ();
00837 else
00838 {
00839
00840 Array<char> dummy (dimensions);
00841 dummy = dummy.index (i, resize_ok);
00842 retval.dimensions = dummy.dims ();
00843 }
00844
00845 retval.optimize_dimensions ();
00846
00847 return retval;
00848 }
00849
00850 octave_map
00851 octave_map::index (const idx_vector& i, const idx_vector& j,
00852 bool resize_ok) const
00853 {
00854 octave_map retval (xkeys);
00855 octave_idx_type nf = nfields ();
00856
00857 for (octave_idx_type k = 0; k < nf; k++)
00858 retval.xvals[k] = xvals[k].index (i, j, resize_ok);
00859
00860 if (nf > 0)
00861 retval.dimensions = retval.xvals[0].dims ();
00862 else
00863 {
00864
00865 Array<char> dummy (dimensions);
00866 dummy = dummy.index (i, j, resize_ok);
00867 retval.dimensions = dummy.dims ();
00868 }
00869
00870 retval.optimize_dimensions ();
00871
00872 return retval;
00873 }
00874
00875 octave_map
00876 octave_map::index (const Array<idx_vector>& ia, bool resize_ok) const
00877 {
00878 octave_map retval (xkeys);
00879 octave_idx_type nf = nfields ();
00880
00881 for (octave_idx_type k = 0; k < nf; k++)
00882 retval.xvals[k] = xvals[k].index (ia, resize_ok);
00883
00884 if (nf > 0)
00885 retval.dimensions = retval.xvals[0].dims ();
00886 else
00887 {
00888
00889 Array<char> dummy (dimensions);
00890 dummy = dummy.index (ia, resize_ok);
00891 retval.dimensions = dummy.dims ();
00892 }
00893
00894 retval.optimize_dimensions ();
00895
00896 return retval;
00897 }
00898
00899 octave_map
00900 octave_map::index (const octave_value_list& idx, bool resize_ok) const
00901 {
00902 octave_idx_type n_idx = idx.length ();
00903 octave_map retval;
00904
00905 switch (n_idx)
00906 {
00907 case 1:
00908 {
00909 idx_vector i = idx(0).index_vector ();
00910
00911 if (! error_state)
00912 retval = index (i, resize_ok);
00913 }
00914 break;
00915
00916 case 2:
00917 {
00918 idx_vector i = idx(0).index_vector ();
00919
00920 if (! error_state)
00921 {
00922 idx_vector j = idx(1).index_vector ();
00923
00924 retval = index (i, j, resize_ok);
00925 }
00926 }
00927 break;
00928
00929 default:
00930 {
00931 Array<idx_vector> ia (dim_vector (n_idx, 1));
00932
00933 for (octave_idx_type i = 0; i < n_idx; i++)
00934 {
00935 ia(i) = idx(i).index_vector ();
00936
00937 if (error_state)
00938 break;
00939 }
00940
00941 if (! error_state)
00942 retval = index (ia, resize_ok);
00943 }
00944 break;
00945 }
00946
00947 return retval;
00948 }
00949
00950
00951 octave_map
00952 octave_map::column (octave_idx_type k) const
00953 {
00954 return index (idx_vector::colon, k);
00955 }
00956
00957 octave_map
00958 octave_map::page (octave_idx_type k) const
00959 {
00960 static Array<idx_vector> ia (dim_vector (3, 1), idx_vector::colon);
00961
00962 ia(2) = k;
00963 return index (ia);
00964 }
00965
00966 void
00967 octave_map::assign (const idx_vector& i, const octave_map& rhs)
00968 {
00969 if (rhs.xkeys.is_same (xkeys))
00970 {
00971 octave_idx_type nf = nfields ();
00972
00973 for (octave_idx_type k = 0; k < nf; k++)
00974 xvals[k].assign (i, rhs.xvals[k], Matrix ());
00975
00976 if (nf > 0)
00977 dimensions = xvals[0].dims ();
00978 else
00979 {
00980
00981 Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
00982 dummy.assign (i, rhs_dummy);;
00983 dimensions = dummy.dims ();
00984 }
00985
00986 optimize_dimensions ();
00987 }
00988 else if (nfields () == 0)
00989 {
00990 octave_map tmp (dimensions, rhs.xkeys);
00991 tmp.assign (i, rhs);
00992 *this = tmp;
00993 }
00994 else
00995 {
00996 Array<octave_idx_type> perm;
00997 octave_map rhs1 = rhs.orderfields (*this, perm);
00998 if (! error_state)
00999 {
01000 assert (rhs1.xkeys.is_same (xkeys));
01001 assign (i, rhs1);
01002 }
01003 else
01004 error ("incompatible fields in struct assignment");
01005 }
01006 }
01007
01008 void
01009 octave_map::assign (const idx_vector& i, const idx_vector& j,
01010 const octave_map& rhs)
01011 {
01012 if (rhs.xkeys.is_same (xkeys))
01013 {
01014 octave_idx_type nf = nfields ();
01015
01016 for (octave_idx_type k = 0; k < nf; k++)
01017 xvals[k].assign (i, j, rhs.xvals[k], Matrix ());
01018
01019 if (nf > 0)
01020 dimensions = xvals[0].dims ();
01021 else
01022 {
01023
01024 Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
01025 dummy.assign (i, j, rhs_dummy);;
01026 dimensions = dummy.dims ();
01027 }
01028
01029 optimize_dimensions ();
01030 }
01031 else if (nfields () == 0)
01032 {
01033 octave_map tmp (dimensions, rhs.xkeys);
01034 tmp.assign (i, j, rhs);
01035 *this = tmp;
01036 }
01037 else
01038 {
01039 Array<octave_idx_type> perm;
01040 octave_map rhs1 = rhs.orderfields (*this, perm);
01041 if (! error_state)
01042 {
01043 assert (rhs1.xkeys.is_same (xkeys));
01044 assign (i, j, rhs1);
01045 }
01046 else
01047 error ("incompatible fields in struct assignment");
01048 }
01049 }
01050
01051 void
01052 octave_map::assign (const Array<idx_vector>& ia,
01053 const octave_map& rhs)
01054 {
01055 if (rhs.xkeys.is_same (xkeys))
01056 {
01057 octave_idx_type nf = nfields ();
01058
01059 for (octave_idx_type k = 0; k < nf; k++)
01060 xvals[k].assign (ia, rhs.xvals[k], Matrix ());
01061
01062 if (nf > 0)
01063 dimensions = xvals[0].dims ();
01064 else
01065 {
01066
01067 Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
01068 dummy.assign (ia, rhs_dummy);;
01069 dimensions = dummy.dims ();
01070 }
01071
01072 optimize_dimensions ();
01073 }
01074 else if (nfields () == 0)
01075 {
01076 octave_map tmp (dimensions, rhs.xkeys);
01077 tmp.assign (ia, rhs);
01078 *this = tmp;
01079 }
01080 else
01081 {
01082 Array<octave_idx_type> perm;
01083 octave_map rhs1 = rhs.orderfields (*this, perm);
01084 if (! error_state)
01085 {
01086 assert (rhs1.xkeys.is_same (xkeys));
01087 assign (ia, rhs1);
01088 }
01089 else
01090 error ("incompatible fields in struct assignment");
01091 }
01092 }
01093
01094 void
01095 octave_map::assign (const octave_value_list& idx, const octave_map& rhs)
01096 {
01097 octave_idx_type n_idx = idx.length ();
01098
01099 switch (n_idx)
01100 {
01101 case 1:
01102 {
01103 idx_vector i = idx(0).index_vector ();
01104
01105 if (! error_state)
01106 assign (i, rhs);
01107 }
01108 break;
01109
01110 case 2:
01111 {
01112 idx_vector i = idx(0).index_vector ();
01113
01114 if (! error_state)
01115 {
01116 idx_vector j = idx(1).index_vector ();
01117
01118 assign (i, j, rhs);
01119 }
01120 }
01121 break;
01122
01123 default:
01124 {
01125 Array<idx_vector> ia (dim_vector (n_idx, 1));
01126
01127 for (octave_idx_type i = 0; i < n_idx; i++)
01128 {
01129 ia(i) = idx(i).index_vector ();
01130
01131 if (error_state)
01132 break;
01133 }
01134
01135 if (! error_state)
01136 assign (ia, rhs);
01137 }
01138 break;
01139 }
01140 }
01141
01142 void
01143 octave_map::assign (const octave_value_list& idx, const std::string& k,
01144 const Cell& rhs)
01145 {
01146 Cell tmp;
01147 iterator p = seek (k);
01148 Cell& ref = p != end () ? contents (p) : tmp;
01149
01150 if (&ref == &tmp)
01151 ref = Cell (dimensions);
01152
01153 ref.assign (idx, rhs);
01154
01155 if (! error_state && ref.dims () != dimensions)
01156 {
01157 dimensions = ref.dims ();
01158
01159 octave_idx_type nf = nfields ();
01160 for (octave_idx_type i = 0; i < nf; i++)
01161 {
01162 if (&xvals[i] != &ref)
01163 xvals[i].resize (dimensions, Cell::resize_fill_value ());
01164 }
01165
01166 optimize_dimensions ();
01167 }
01168
01169 if (! error_state && &ref == &tmp)
01170 setfield (k, tmp);
01171 }
01172
01173
01174
01175
01176
01177
01178
01179
01180 void
01181 octave_map::delete_elements (const idx_vector& i)
01182 {
01183 octave_idx_type nf = nfields ();
01184 for (octave_idx_type k = 0; k < nf; k++)
01185 xvals[k].delete_elements (i);
01186
01187 if (nf > 0)
01188 dimensions = xvals[0].dims ();
01189 else
01190 {
01191
01192 Array<char> dummy (dimensions);
01193 dummy.delete_elements (i);
01194 dimensions = dummy.dims ();
01195 }
01196
01197 optimize_dimensions ();
01198 }
01199
01200 void
01201 octave_map::delete_elements (int dim, const idx_vector& i)
01202 {
01203 octave_idx_type nf = nfields ();
01204 for (octave_idx_type k = 0; k < nf; k++)
01205 xvals[k].delete_elements (dim, i);
01206
01207 if (nf > 0)
01208 dimensions = xvals[0].dims ();
01209 else
01210 {
01211
01212 Array<char> dummy (dimensions);
01213 dummy.delete_elements (dim, i);
01214 dimensions = dummy.dims ();
01215 }
01216
01217 optimize_dimensions ();
01218 }
01219
01220 void
01221 octave_map::delete_elements (const Array<idx_vector>& ia)
01222 {
01223 octave_idx_type nf = nfields ();
01224 for (octave_idx_type k = 0; k < nf; k++)
01225 xvals[k].delete_elements (ia);
01226
01227 if (nf > 0)
01228 dimensions = xvals[0].dims ();
01229 else
01230 {
01231
01232 Array<char> dummy (dimensions);
01233 dummy.delete_elements (ia);
01234 dimensions = dummy.dims ();
01235 }
01236
01237 optimize_dimensions ();
01238 }
01239
01240 void
01241 octave_map::delete_elements (const octave_value_list& idx)
01242 {
01243 octave_idx_type n_idx = idx.length ();
01244
01245 Array<idx_vector> ia (dim_vector (n_idx, 1));
01246
01247 for (octave_idx_type i = 0; i < n_idx; i++)
01248 {
01249 ia(i) = idx(i).index_vector ();
01250
01251 if (error_state)
01252 break;
01253 }
01254
01255 if (! error_state)
01256 delete_elements (ia);
01257 }
01258
01259
01260
01261
01262
01263
01264
01265
01266 octave_map
01267 octave_map::concat (const octave_map& rb, const Array<octave_idx_type>& ra_idx)
01268 {
01269 if (nfields () == rb.nfields ())
01270 {
01271 for (const_iterator pa = begin (); pa != end (); pa++)
01272 {
01273 const_iterator pb = rb.seek (key(pa));
01274
01275 if (pb == rb.end ())
01276 {
01277 error ("field name mismatch in structure concatenation");
01278 break;
01279 }
01280
01281 contents(pa).insert (rb.contents(pb), ra_idx);
01282 }
01283 }
01284 else
01285 {
01286 dim_vector dv = dims ();
01287
01288 if (dv.all_zero ())
01289 *this = rb;
01290 else if (! rb.dims ().all_zero ())
01291 error ("invalid structure concatenation");
01292 }
01293
01294 return *this;
01295 }
01296
01297 void
01298 octave_map::optimize_dimensions (void)
01299 {
01300 octave_idx_type nf = nfields ();
01301
01302 for (octave_idx_type i = 0; i < nf; i++)
01303 {
01304 if (! xvals[i].optimize_dimensions (dimensions))
01305 {
01306 error ("internal error: dimension mismatch across fields in struct");
01307 break;
01308 }
01309 }
01310
01311 }
01312
01313 Octave_map::Octave_map (const dim_vector& dv, const Cell& key_vals)
01314 : map (), key_list (), dimensions (dv)
01315 {
01316 Cell c (dv);
01317
01318 if (key_vals.is_cellstr ())
01319 {
01320 for (octave_idx_type i = 0; i < key_vals.numel (); i++)
01321 {
01322 std::string k = key_vals(i).string_value ();
01323 map[k] = c;
01324 key_list.push_back (k);
01325 }
01326 }
01327 else
01328 error ("Octave_map: expecting keys to be cellstr");
01329 }
01330
01331 Octave_map::Octave_map (const octave_map& m)
01332 : map (), key_list (), dimensions (m.dims ())
01333 {
01334 for (octave_map::const_iterator p = m.begin (); p != m.end (); p++)
01335 map[m.key (p)] = m.contents (p);
01336 const string_vector mkeys = m.fieldnames ();
01337 for (octave_idx_type i = 0; i < mkeys.numel (); i++)
01338 key_list.push_back (mkeys(i));
01339 }
01340
01341 Octave_map
01342 Octave_map::squeeze (void) const
01343 {
01344 Octave_map retval (dims ().squeeze ());
01345
01346 for (const_iterator pa = begin (); pa != end (); pa++)
01347 {
01348 Cell tmp = contents (pa).squeeze ();
01349
01350 if (error_state)
01351 break;
01352
01353 retval.assign (key (pa), tmp);
01354 }
01355
01356
01357 retval.key_list = key_list;
01358
01359 return retval;
01360 }
01361
01362 Octave_map
01363 Octave_map::permute (const Array<int>& vec, bool inv) const
01364 {
01365 Octave_map retval (dims ());
01366
01367 for (const_iterator pa = begin (); pa != end (); pa++)
01368 {
01369 Cell tmp = contents (pa).permute (vec, inv);
01370
01371 if (error_state)
01372 break;
01373
01374 retval.assign (key (pa), tmp);
01375 }
01376
01377
01378 retval.key_list = key_list;
01379
01380 return retval;
01381 }
01382
01383 Cell&
01384 Octave_map::contents (const std::string& k)
01385 {
01386 maybe_add_to_key_list (k);
01387
01388 return map[k];
01389 }
01390
01391 Cell
01392 Octave_map::contents (const std::string& k) const
01393 {
01394 const_iterator p = seek (k);
01395
01396 return p != end () ? p->second : Cell ();
01397 }
01398
01399 int
01400 Octave_map::intfield (const std::string& k, int def_val) const
01401 {
01402 int retval = def_val;
01403
01404 Cell c = contents (k);
01405
01406 if (! c.is_empty ())
01407 retval = c(0).int_value ();
01408
01409 return retval;
01410 }
01411
01412 std::string
01413 Octave_map::stringfield (const std::string& k,
01414 const std::string& def_val) const
01415 {
01416 std::string retval = def_val;
01417
01418 Cell c = contents (k);
01419
01420 if (! c.is_empty ())
01421 retval = c(0).string_value ();
01422
01423 return retval;
01424 }
01425
01426 string_vector
01427 Octave_map::keys (void) const
01428 {
01429 assert (nfields () == key_list.size ());
01430
01431 return string_vector (key_list);
01432 }
01433
01434 Octave_map
01435 Octave_map::transpose (void) const
01436 {
01437 assert (ndims () == 2);
01438
01439 dim_vector dv = dims ();
01440
01441 octave_idx_type nr = dv(0);
01442 octave_idx_type nc = dv(1);
01443
01444 dim_vector new_dims (nc, nr);
01445
01446 Octave_map retval (new_dims);
01447
01448 for (const_iterator p = begin (); p != end (); p++)
01449 retval.assign (key(p), Cell (contents(p).transpose ()));
01450
01451
01452 retval.key_list = key_list;
01453
01454 return retval;
01455 }
01456
01457 Octave_map
01458 Octave_map::reshape (const dim_vector& new_dims) const
01459 {
01460 Octave_map retval;
01461
01462 if (new_dims != dims ())
01463 {
01464 for (const_iterator p = begin (); p != end (); p++)
01465 retval.assign (key(p), contents(p).reshape (new_dims));
01466
01467 retval.dimensions = new_dims;
01468
01469
01470 retval.key_list = key_list;
01471 }
01472 else
01473 retval = *this;
01474
01475 return retval;
01476 }
01477
01478 void
01479 Octave_map::resize (const dim_vector& dv, bool fill)
01480 {
01481 if (dv != dims ())
01482 {
01483 if (nfields () == 0)
01484 dimensions = dv;
01485 else
01486 {
01487 for (const_iterator p = begin (); p != end (); p++)
01488 {
01489 Cell tmp = contents(p);
01490
01491 if (fill)
01492 tmp.resize (dv, Cell::resize_fill_value ());
01493 else
01494 tmp.resize (dv);
01495
01496 dimensions = dv;
01497
01498 assign (key(p), tmp);
01499 }
01500 }
01501 }
01502 }
01503
01504 Octave_map
01505 Octave_map::concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx)
01506 {
01507 Octave_map retval;
01508
01509 if (nfields () == rb.nfields ())
01510 {
01511 for (const_iterator pa = begin (); pa != end (); pa++)
01512 {
01513 const_iterator pb = rb.seek (key(pa));
01514
01515 if (pb == rb.end ())
01516 {
01517 error ("field name mismatch in structure concatenation");
01518 break;
01519 }
01520
01521 retval.assign (key(pa),
01522 contents(pa).insert (rb.contents(pb), ra_idx));
01523 }
01524
01525
01526 retval.key_list = key_list;
01527 }
01528 else
01529 {
01530 dim_vector dv = dims ();
01531
01532 if (dv.all_zero ())
01533 retval = rb;
01534 else
01535 {
01536 dv = rb.dims ();
01537
01538 if (dv.all_zero ())
01539 retval = *this;
01540 else
01541 error ("invalid structure concatenation");
01542 }
01543 }
01544
01545 return retval;
01546 }
01547
01548 static bool
01549 keys_ok (const Octave_map& a, const Octave_map& b, string_vector& keys)
01550 {
01551 bool retval = false;
01552
01553 keys = string_vector ();
01554
01555 if (a.nfields () == 0)
01556 {
01557 keys = b.keys ();
01558 retval = true;
01559 }
01560 else
01561 {
01562 string_vector a_keys = a.keys().sort ();
01563 string_vector b_keys = b.keys().sort ();
01564
01565 octave_idx_type a_len = a_keys.length ();
01566 octave_idx_type b_len = b_keys.length ();
01567
01568 if (a_len == b_len)
01569 {
01570 for (octave_idx_type i = 0; i < a_len; i++)
01571 {
01572 if (a_keys[i] != b_keys[i])
01573 goto done;
01574 }
01575
01576 keys = a_keys;
01577 retval = true;
01578 }
01579 }
01580
01581 done:
01582 return retval;
01583 }
01584
01585 Octave_map&
01586 Octave_map::maybe_delete_elements (const octave_value_list& idx)
01587 {
01588 string_vector t_keys = keys();
01589 octave_idx_type len = t_keys.length ();
01590
01591 if (len > 0)
01592 {
01593 for (octave_idx_type i = 0; i < len; i++)
01594 {
01595 std::string k = t_keys[i];
01596
01597 contents(k).delete_elements (idx);
01598
01599 if (error_state)
01600 break;
01601 }
01602
01603 if (!error_state)
01604 dimensions = contents(t_keys[0]).dims();
01605 }
01606
01607 return *this;
01608 }
01609
01610 Octave_map&
01611 Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs)
01612 {
01613 string_vector t_keys;
01614
01615 if (keys_ok (*this, rhs, t_keys))
01616 {
01617 octave_idx_type len = t_keys.length ();
01618
01619 if (len == 0)
01620 {
01621 Cell tmp_lhs (dims ());
01622 Cell tmp_rhs (rhs.dims ());
01623
01624 tmp_lhs.assign (idx, tmp_rhs, Matrix ());
01625
01626 if (! error_state)
01627 resize (tmp_lhs.dims ());
01628 else
01629 error ("size mismatch in structure assignment");
01630 }
01631 else
01632 {
01633 for (octave_idx_type i = 0; i < len; i++)
01634 {
01635 std::string k = t_keys[i];
01636
01637 Cell t_rhs = rhs.contents (k);
01638
01639 assign (idx, k, t_rhs);
01640
01641 if (error_state)
01642 break;
01643 }
01644 }
01645 }
01646 else
01647 error ("field name mismatch in structure assignment");
01648
01649 return *this;
01650 }
01651
01652 Octave_map&
01653 Octave_map::assign (const octave_value_list& idx, const std::string& k,
01654 const Cell& rhs)
01655 {
01656 Cell tmp;
01657
01658 if (contains (k))
01659 tmp = map[k];
01660 else
01661 tmp = Cell (dimensions);
01662
01663 tmp.assign (idx, rhs);
01664
01665 if (! error_state)
01666 {
01667 dim_vector tmp_dims = tmp.dims ();
01668
01669 if (tmp_dims != dimensions)
01670 {
01671 for (iterator p = begin (); p != end (); p++)
01672 contents(p).resize (tmp_dims, Cell::resize_fill_value ());
01673
01674 dimensions = tmp_dims;
01675 }
01676
01677 maybe_add_to_key_list (k);
01678
01679 map[k] = tmp;
01680 }
01681
01682 return *this;
01683 }
01684
01685 Octave_map&
01686 Octave_map::assign (const std::string& k, const octave_value& rhs)
01687 {
01688 if (nfields () == 0)
01689 {
01690 maybe_add_to_key_list (k);
01691
01692 map[k] = Cell (rhs);
01693
01694 dimensions = dim_vector (1, 1);
01695 }
01696 else
01697 {
01698 dim_vector dv = dims ();
01699
01700 if (dv.all_ones ())
01701 {
01702 maybe_add_to_key_list (k);
01703
01704 map[k] = Cell (rhs);
01705 }
01706 else
01707 error ("invalid structure assignment");
01708 }
01709
01710 return *this;
01711 }
01712
01713 Octave_map&
01714 Octave_map::assign (const std::string& k, const Cell& rhs)
01715 {
01716 if (nfields () == 0)
01717 {
01718 maybe_add_to_key_list (k);
01719
01720 map[k] = rhs;
01721
01722 dimensions = rhs.dims ();
01723 }
01724 else
01725 {
01726 if (dims () == rhs.dims ())
01727 {
01728 maybe_add_to_key_list (k);
01729
01730 map[k] = rhs;
01731 }
01732 else
01733 error ("invalid structure assignment");
01734 }
01735
01736 return *this;
01737 }
01738
01739 Octave_map
01740 Octave_map::index (const octave_value_list& idx, bool resize_ok) const
01741 {
01742 Octave_map retval;
01743
01744 octave_idx_type n_idx = idx.length ();
01745
01746 if (n_idx > 0)
01747 {
01748 Array<idx_vector> ra_idx (dim_vector (n_idx, 1));
01749
01750 for (octave_idx_type i = 0; i < n_idx; i++)
01751 {
01752 ra_idx(i) = idx(i).index_vector ();
01753 if (error_state)
01754 break;
01755 }
01756
01757 if (! error_state)
01758 {
01759 for (const_iterator p = begin (); p != end (); p++)
01760 {
01761 Cell tmp = contents (p);
01762
01763 tmp = tmp.Array<octave_value>::index (ra_idx, resize_ok);
01764
01765 if (error_state)
01766 break;
01767
01768 retval.assign (key(p), tmp);
01769 }
01770
01771
01772 retval.key_list = key_list;
01773 }
01774 }
01775 else
01776 retval = *this;
01777
01778 return retval;
01779 }