GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-map.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1995-2017 John W. Eaton
4 Copyright (C) 2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include "Array-util.h"
29 #include "error.h"
30 #include "oct-locbuf.h"
31 #include "str-vec.h"
32 
33 #include "oct-map.h"
34 #include "utils.h"
35 
38 {
39  static fields_rep nr;
40  return &nr;
41 }
42 
44  : rep (new fields_rep)
45 {
46  octave_idx_type n = fields.numel ();
47  for (octave_idx_type i = 0; i < n; i++)
48  (*rep)[fields(i)] = i;
49 }
50 
51 octave_fields::octave_fields (const char * const *fields)
52  : rep (new fields_rep)
53 {
54  octave_idx_type n = 0;
55  while (*fields)
56  (*rep)[std::string (*fields++)] = n++;
57 }
58 
59 bool
60 octave_fields::isfield (const std::string& field) const
61 {
62  return rep->find (field) != rep->end ();
63 }
64 
67 {
68  fields_rep::iterator p = rep->find (field);
69  return (p != rep->end ()) ? p->second : -1;
70 }
71 
74 {
75  fields_rep::iterator p = rep->find (field);
76  if (p != rep->end ())
77  return p->second;
78  else
79  {
80  make_unique ();
81  octave_idx_type n = rep->size ();
82  return (*rep)[field] = n;
83  }
84 }
85 
88 {
89  fields_rep::iterator p = rep->find (field);
90  if (p == rep->end ())
91  return -1;
92  else
93  {
94  octave_idx_type n = p->second;
95  make_unique ();
96  rep->erase (field);
97  for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++)
98  {
99  if (q->second >= n)
100  q->second--;
101  }
102 
103  return n;
104  }
105 }
106 
107 void
109 {
110  octave_idx_type n = rep->size ();
111  perm.clear (n, 1);
112 
113  make_unique ();
114  octave_idx_type i = 0;
115  for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++)
116  {
117  octave_idx_type j = q->second;
118  q->second = i;
119  perm(i++) = j;
120  }
121 }
122 
123 bool
125  octave_idx_type* perm) const
126 {
127  bool retval = true;
128 
129  iterator p = begin ();
130  iterator q = other.begin ();
131  for (; p != end () && q != other.end (); p++, q++)
132  {
133  if (p->first == q->first)
134  perm[p->second] = q->second;
135  else
136  {
137  retval = false;
138  break;
139  }
140  }
141 
142  retval = (p == end () && q == other.end ());
143 
144  return retval;
145 }
146 
147 bool
149  Array<octave_idx_type>& perm) const
150 {
151  octave_idx_type n = nfields ();
152  if (perm.numel () != n)
153  perm.clear (1, n);
154 
155  return equal_up_to_order (other, perm.fortran_vec ());
156 }
157 
160 {
161  octave_idx_type n = nfields ();
163 
164  for (iterator p = begin (); p != end (); p++)
165  retval.xelem (p->second) = p->first;
166 
167  return retval;
168 }
169 
172 {
173  octave_idx_type idx = xkeys.getfield (k);
174  return (idx >= 0) ? xvals[idx] : octave_value ();
175 }
176 
177 void
179 {
180  octave_idx_type idx = xkeys.getfield (k);
181  if (idx < static_cast<octave_idx_type> (xvals.size ()))
182  xvals[idx] = val;
183  else
184  xvals.push_back (val);
185 }
186 
187 void
189 {
190  octave_idx_type idx = xkeys.rmfield (k);
191  if (idx >= 0)
192  xvals.erase (xvals.begin () + idx);
193 }
194 
197 {
199  return orderfields (perm);
200 }
201 
204 {
206  retval.xkeys.orderfields (perm);
207 
208  octave_idx_type nf = nfields ();
209  for (octave_idx_type i = 0; i < nf; i++)
210  retval.xvals[i] = xvals[perm.xelem (i)];
211 
212  return retval;
213 }
214 
217  Array<octave_idx_type>& perm) const
218 {
219  if (xkeys.is_same (other.xkeys))
220  return *this;
221  else
222  {
224  if (! other.xkeys.equal_up_to_order (xkeys, perm))
225  error ("orderfields: structs must have same fields up to order");
226 
227  octave_idx_type nf = nfields ();
228  for (octave_idx_type i = 0; i < nf; i++)
229  retval.xvals[i] = xvals[perm.xelem (i)];
230 
231  return retval;
232  }
233 }
234 
237 {
238  return getfield (k);
239 }
240 
243 {
244  octave_idx_type idx = xkeys.getfield (k);
245  if (idx >= static_cast<octave_idx_type> (xvals.size ()))
246  xvals.resize (idx+1);
247  return xvals[idx];
248 }
249 
251  : xkeys (m.xkeys), xvals (), dimensions (1, 1)
252 {
253  octave_idx_type nf = m.nfields ();
254  xvals.reserve (nf);
255  for (octave_idx_type i = 0; i < nf; i++)
256  {
257  xvals.push_back (Cell (dimensions));
258  xvals[i].xelem (0) = m.xvals[i];
259  }
260 }
261 
262 Cell
264 {
265  octave_idx_type idx = xkeys.getfield (k);
266  return (idx >= 0) ? xvals[idx] : Cell ();
267 }
268 
269 void
271 {
272  if (nfields () == 0)
273  dimensions = val.dims ();
274 
275  if (val.dims () != dimensions)
276  error ("octave_map::setfield: internal error");
277 
278  octave_idx_type idx = xkeys.getfield (k);
279  if (idx < static_cast<octave_idx_type> (xvals.size ()))
280  xvals[idx] = val;
281  else
282  xvals.push_back (val);
283 }
284 
285 void
287 {
288  octave_idx_type idx = xkeys.rmfield (k);
289  if (idx >= 0)
290  xvals.erase (xvals.begin () + idx);
291 }
292 
295 {
297  return orderfields (perm);
298 }
299 
302 {
304  retval.xkeys.orderfields (perm);
305 
306  octave_idx_type nf = nfields ();
307  for (octave_idx_type i = 0; i < nf; i++)
308  retval.xvals[i] = xvals[perm.xelem (i)];
309 
310  return retval;
311 }
312 
315  Array<octave_idx_type>& perm) const
316 {
317  if (xkeys.is_same (other.xkeys))
318  return *this;
319  else
320  {
321  octave_map retval (other.xkeys);
322  if (! other.xkeys.equal_up_to_order (xkeys, perm))
323  error ("orderfields: structs must have same fields up to order");
324 
325  octave_idx_type nf = nfields ();
326  for (octave_idx_type i = 0; i < nf; i++)
327  retval.xvals[i] = xvals[perm.xelem (i)];
328 
329  return retval;
330  }
331 }
332 
333 Cell
335 {
336  return getfield (k);
337 }
338 
339 Cell&
341 {
342  octave_idx_type idx = xkeys.getfield (k);
343  if (idx >= static_cast<octave_idx_type> (xvals.size ()))
344  xvals.push_back (Cell (dimensions)); // auto-set correct dims.
345  return xvals[idx];
346 }
347 
348 void
350  octave_idx_type idx) const
351 {
352  octave_idx_type nf = nfields ();
353  for (octave_idx_type i = 0; i < nf; i++)
354  dest.xvals[i] = xvals[i](idx);
355 }
356 
359 {
361 
362  // Optimize this so that there is just one check.
363  extract_scalar (retval, compute_index (n, dimensions));
364 
365  return retval;
366 }
367 
370 {
372 
373  // Optimize this so that there is just one check.
374  extract_scalar (retval, compute_index (i, j, dimensions));
375 
376  return retval;
377 }
378 
381 {
383 
384  // Optimize this so that there is just one check.
385  extract_scalar (retval, compute_index (ra_idx, dimensions));
386 
387  return retval;
388 }
389 
392 {
394 
395  extract_scalar (retval, n);
396 
397  return retval;
398 }
399 
400 bool
402  const octave_scalar_map& rhs)
403 {
404  bool retval = false;
405 
406  octave_idx_type nf = nfields ();
407  if (rhs.xkeys.is_same (xkeys))
408  {
409  for (octave_idx_type i = 0; i < nf; i++)
410  xvals[i](n) = rhs.xvals[i];
411 
412  retval = true;
413  }
414  else
415  {
417  if (xkeys.equal_up_to_order (rhs.xkeys, perm))
418  {
419  for (octave_idx_type i = 0; i < nf; i++)
420  xvals[i](n) = rhs.xvals[perm[i]];
421 
422  retval = true;
423  }
424  }
425 
426  return retval;
427 }
428 
431 {
432  octave_map retval (*this);
433  octave_idx_type nf = nfields ();
434 
435  retval.dimensions = dimensions.squeeze ();
436 
437  for (octave_idx_type i = 0; i < nf; i++)
438  retval.xvals[i] = xvals[i].squeeze ();
439 
440  retval.optimize_dimensions ();
441 
442  return retval;
443 }
444 
445 /*
446 ## test preservation of xkeys by squeeze
447 %!test
448 %! x(1,1,1,1).d = 10; x(3,5,1,7).a = "b"; x(2,4,1,7).f = 27;
449 %! assert (fieldnames (squeeze (x)), {"d"; "a"; "f"});
450 */
451 
453 octave_map::permute (const Array<int>& vec, bool inv) const
454 {
456  octave_idx_type nf = nfields ();
457 
458  for (octave_idx_type i = 0; i < nf; i++)
459  retval.xvals[i] = xvals[i].permute (vec, inv);
460 
461  // FIXME:
462  // There is no dim_vector::permute for technical reasons.
463  // We pick the dim vector from results if possible, otherwise use a dummy
464  // array to get it. Need (?) a better solution to this problem.
465  if (nf > 0)
466  retval.dimensions = retval.xvals[0].dims ();
467  else
468  {
469  Array<char> dummy (dimensions);
470  dummy = dummy.permute (vec, inv);
471  retval.dimensions = dummy.dims ();
472  }
473 
474  retval.optimize_dimensions ();
475 
476  return retval;
477 }
478 
479 /*
480 ## test preservation of key order by permute
481 %!test
482 %! x(1,1,1,1).d = 10; x(3,5,1,7).a = "b"; x(2,4,1,7).f = 27;
483 %! assert (fieldnames (permute (x, [3, 4, 1, 2])), {"d"; "a"; "f"});
484 */
485 
488 {
489  assert (ndims () == 2);
490 
492 
493  retval.dimensions = dim_vector (dimensions (1), dimensions (0));
494 
495  octave_idx_type nf = nfields ();
496  for (octave_idx_type i = 0; i < nf; i++)
497  retval.xvals[i] = xvals[i].transpose ();
498 
499  retval.optimize_dimensions ();
500 
501  return retval;
502 }
503 
504 /*
505 ## test preservation of key order by transpose
506 %!test
507 %! x(1,1).d = 10; x(3,5).a = "b"; x(2,4).f = 27;
508 %! assert (fieldnames (transpose (x)), {"d"; "a"; "f"});
509 %! assert (fieldnames (x'), {"d"; "a"; "f"});
510 %! assert (fieldnames (x.'), {"d"; "a"; "f"});
511 */
512 
515 {
517  retval.dimensions = dv;
518 
519  octave_idx_type nf = nfields ();
520  if (nf > 0)
521  {
522  retval.xvals.reserve (nf);
523  for (octave_idx_type i = 0; i < nf; i++)
524  retval.xvals[i] = xvals[i].reshape (dv);
525  }
526  else
527  {
528  // FIXME: Do it with a dummy array, to reuse error message.
529  // Need (?) a better solution.
530  Array<char> dummy (dimensions);
531  dummy.reshape (dv);
532  }
533 
534  retval.optimize_dimensions ();
535 
536  return retval;
537 }
538 
539 /*
540 ## test preservation of key order by reshape
541 %!test
542 %! x(1,1).d = 10; x(4,6).a = "b"; x(2,4).f = 27;
543 %! assert (fieldnames (reshape (x, 3, 8)), {"d"; "a"; "f"});
544 */
545 
546 void
547 octave_map::resize (const dim_vector& dv, bool fill)
548 {
549  octave_idx_type nf = nfields ();
550  if (nf > 0)
551  {
552  for (octave_idx_type i = 0; i < nf; i++)
553  {
554  if (fill)
555  xvals[i].resize (dv, Matrix ());
556  else
557  xvals[i].resize (dv);
558  }
559  }
560  else
561  {
562  // FIXME: Do it with a dummy array, to reuse error message.
563  // Need (?) a better solution.
564  Array<char> dummy (dimensions);
565  dummy.resize (dv);
566  }
567 
568  dimensions = dv;
570 }
571 
572 void
574  const octave_scalar_map *map_list,
576 {
577  octave_idx_type nf = retval.nfields ();
578  retval.xvals.reserve (nf);
579 
580  dim_vector& rd = retval.dimensions;
581  rd.resize (dim+1, 1);
582  rd(0) = rd(1) = 1;
583  rd(dim) = n;
584 
585  for (octave_idx_type j = 0; j < nf; j++)
586  {
587  retval.xvals.push_back (Cell (rd));
588  assert (retval.xvals[j].numel () == n);
589  for (octave_idx_type i = 0; i < n; i++)
590  retval.xvals[j].xelem (i) = map_list[i].xvals[j];
591  }
592 }
593 
594 void
595 octave_map::do_cat (int dim, octave_idx_type n, const octave_map *map_list,
597 {
598  octave_idx_type nf = retval.nfields ();
599  retval.xvals.reserve (nf);
600 
601  OCTAVE_LOCAL_BUFFER (Array<octave_value>, field_list, n);
602 
603  for (octave_idx_type j = 0; j < nf; j++)
604  {
605  for (octave_idx_type i = 0; i < n; i++)
606  field_list[i] = map_list[i].xvals[j];
607 
608  retval.xvals.push_back (Array<octave_value>::cat (dim, n, field_list));
609  if (j == 0)
610  retval.dimensions = retval.xvals[j].dims ();
611  }
612 }
613 
614 // This is just a wrapper.
616  const octave_scalar_map& src,
617  octave_scalar_map& dest,
619 {
620  dest = src.orderfields (ref, perm);
621 }
622 
623 // In non-scalar case, we also promote empty structs without fields.
624 void permute_to_correct_order1 (const octave_map& ref, const octave_map& src,
625  octave_map& dest, Array<octave_idx_type>& perm)
626 {
627  if (src.nfields () == 0 && src.is_empty ())
628  dest = octave_map (src.dims (), ref.keys ());
629  else
630  dest = src.orderfields (ref, perm);
631 }
632 
633 template <typename map>
634 static void
636  octave_idx_type idx, const map *map_list,
637  map *new_map_list)
638 {
639  new_map_list[idx] = map_list[idx];
640 
641  Array<octave_idx_type> perm (dim_vector (1, nf));
642 
643  try
644  {
645  for (octave_idx_type i = 0; i < n; i++)
646  {
647  if (i == idx)
648  continue;
649 
650  permute_to_correct_order1 (map_list[idx], map_list[i],
651  new_map_list[i], perm);
652  }
653  }
654  catch (octave::execution_exception& e)
655  {
656  error (e, "cat: field names mismatch in concatenating structs");
657  }
658 }
659 
661 octave_map::cat (int dim, octave_idx_type n, const octave_scalar_map *map_list)
662 {
664 
665  // Allow dim = -1, -2 for compatibility, though it makes no difference here.
666  if (dim == -1 || dim == -2)
667  dim = -dim - 1;
668  else if (dim < 0)
669  error ("cat: invalid dimension");
670 
671  if (n == 1)
672  retval = map_list[0];
673  else if (n > 1)
674  {
675  octave_idx_type idx, nf = 0;
676  for (idx = 0; idx < n; idx++)
677  {
678  nf = map_list[idx].nfields ();
679  if (nf > 0)
680  {
681  retval.xkeys = map_list[idx].xkeys;
682  break;
683  }
684  }
685 
686  if (nf > 0)
687  {
688  // Try the fast case.
689  bool all_same = true;
690  for (octave_idx_type i = 0; i < n; i++)
691  {
692  all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys);
693  if (! all_same)
694  break;
695  }
696 
697  if (all_same)
698  do_cat (dim, n, map_list, retval);
699  else
700  {
701  // permute all structures to common order.
702  OCTAVE_LOCAL_BUFFER (octave_scalar_map, new_map_list, n);
703 
704  permute_to_correct_order (n, nf, idx, map_list, new_map_list);
705 
706  do_cat (dim, n, new_map_list, retval);
707  }
708 
709  }
710  else
711  {
712  dim_vector& rd = retval.dimensions;
713  rd.resize (dim+1, 1);
714  rd(0) = rd(1) = 1;
715  rd(dim) = n;
716  }
717 
718  retval.optimize_dimensions ();
719  }
720 
721  return retval;
722 }
723 
725 octave_map::cat (int dim, octave_idx_type n, const octave_map *map_list)
726 {
728 
729  // Allow dim = -1, -2 for compatibility, though it makes no difference here.
730  if (dim == -1 || dim == -2)
731  dim = -dim - 1;
732  else if (dim < 0)
733  error ("cat: invalid dimension");
734 
735  if (n == 1)
736  retval = map_list[0];
737  else if (n > 1)
738  {
739  octave_idx_type idx, nf = 0;
740 
741  for (idx = 0; idx < n; idx++)
742  {
743  nf = map_list[idx].nfields ();
744  if (nf > 0)
745  {
746  retval.xkeys = map_list[idx].xkeys;
747  break;
748  }
749  }
750 
751  // Try the fast case.
752  bool all_same = true;
753 
754  if (nf > 0)
755  {
756  for (octave_idx_type i = 0; i < n; i++)
757  {
758  all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys);
759 
760  if (! all_same)
761  break;
762  }
763  }
764 
765  if (all_same && nf > 0)
766  do_cat (dim, n, map_list, retval);
767  else
768  {
769  if (nf > 0)
770  {
771  // permute all structures to correct order.
772  OCTAVE_LOCAL_BUFFER (octave_map, new_map_list, n);
773 
774  permute_to_correct_order (n, nf, idx, map_list, new_map_list);
775 
776  do_cat (dim, n, new_map_list, retval);
777  }
778  else
779  {
780  dim_vector dv = map_list[0].dimensions;
781 
782  for (octave_idx_type i = 1; i < n; i++)
783  {
784  if (! dv.concat (map_list[i].dimensions, dim))
785  error ("dimension mismatch in struct concatenation");
786  }
787 
788  retval.dimensions = dv;
789  }
790  }
791 
792  retval.optimize_dimensions ();
793  }
794 
795  return retval;
796 }
797 
798 /*
799 ## test preservation of key order by concatenation
800 %!test
801 %! x(1, 1).d = 10; x(4, 6).a = "b"; x(2, 4).f = 27;
802 %! y(1, 6).f = 11; y(1, 6).a = "c"; y(1, 6).d = 33;
803 %! assert (fieldnames ([x; y]), {"d"; "a"; "f"});
804 
805 %!test
806 %! s = struct ();
807 %! sr = [s,s];
808 %! sc = [s;s];
809 %! sm = [s,s;s,s];
810 %! assert (numfields (sr), 0);
811 %! assert (numfields (sc), 0);
812 %! assert (numfields (sm), 0);
813 %! assert (size (sr), [1, 2]);
814 %! assert (size (sc), [2, 1]);
815 %! assert (size (sm), [2, 2]);
816 */
817 
819 octave_map::index (const idx_vector& i, bool resize_ok) const
820 {
822  octave_idx_type nf = nfields ();
823 
824  for (octave_idx_type k = 0; k < nf; k++)
825  retval.xvals[k] = xvals[k].index (i, resize_ok);
826 
827  if (nf > 0)
828  retval.dimensions = retval.xvals[0].dims ();
829  else
830  {
831  // Use dummy array. FIXME: Need(?) a better solution.
832  Array<char> dummy (dimensions);
833  dummy = dummy.index (i, resize_ok);
834  retval.dimensions = dummy.dims ();
835  }
836 
837  retval.optimize_dimensions ();
838 
839  return retval;
840 }
841 
844  bool resize_ok) const
845 {
847  octave_idx_type nf = nfields ();
848 
849  for (octave_idx_type k = 0; k < nf; k++)
850  retval.xvals[k] = xvals[k].index (i, j, resize_ok);
851 
852  if (nf > 0)
853  retval.dimensions = retval.xvals[0].dims ();
854  else
855  {
856  // Use dummy array. FIXME: Need(?) a better solution.
857  Array<char> dummy (dimensions);
858  dummy = dummy.index (i, j, resize_ok);
859  retval.dimensions = dummy.dims ();
860  }
861 
862  retval.optimize_dimensions ();
863 
864  return retval;
865 }
866 
868 octave_map::index (const Array<idx_vector>& ia, bool resize_ok) const
869 {
871  octave_idx_type nf = nfields ();
872 
873  for (octave_idx_type k = 0; k < nf; k++)
874  retval.xvals[k] = xvals[k].index (ia, resize_ok);
875 
876  if (nf > 0)
877  retval.dimensions = retval.xvals[0].dims ();
878  else
879  {
880  // Use dummy array. FIXME: Need(?) a better solution.
881  Array<char> dummy (dimensions);
882  dummy = dummy.index (ia, resize_ok);
883  retval.dimensions = dummy.dims ();
884  }
885 
886  retval.optimize_dimensions ();
887 
888  return retval;
889 }
890 
892 octave_map::index (const octave_value_list& idx, bool resize_ok) const
893 {
894  octave_idx_type n_idx = idx.length ();
896 
897  // If we catch an indexing error in index_vector, we flag an error in
898  // index k. Ensure it is the right value befor each idx_vector call.
899  // Same variable as used in the for loop in the default case.
900 
901  octave_idx_type k = 0;
902 
903  try
904  {
905  switch (n_idx)
906  {
907  case 1:
908  {
909  idx_vector i = idx(0).index_vector ();
910 
911  retval = index (i, resize_ok);
912  }
913  break;
914 
915  case 2:
916  {
917  idx_vector i = idx(0).index_vector ();
918 
919  k = 1;
920  idx_vector j = idx(1).index_vector ();
921 
922  retval = index (i, j, resize_ok);
923  }
924  break;
925 
926  default:
927  {
928  Array<idx_vector> ia (dim_vector (n_idx, 1));
929 
930  for (k = 0; k < n_idx; k++)
931  ia(k) = idx(k).index_vector ();
932 
933  retval = index (ia, resize_ok);
934  }
935  break;
936  }
937  }
938  catch (octave::index_exception& e)
939  {
940  // Rethrow to allow more info to be reported later.
941  e.set_pos_if_unset (n_idx, k+1);
942  throw;
943  }
944 
945  return retval;
946 }
947 
948 // Perhaps one day these will be optimized. Right now, they just call index.
951 {
952  return index (idx_vector::colon, k);
953 }
954 
957 {
958  static Array<idx_vector> ia (dim_vector (3, 1), idx_vector::colon);
959 
960  ia(2) = k;
961  return index (ia);
962 }
963 
964 void
966 {
967  if (rhs.xkeys.is_same (xkeys))
968  {
969  octave_idx_type nf = nfields ();
970 
971  for (octave_idx_type k = 0; k < nf; k++)
972  xvals[k].assign (i, rhs.xvals[k], Matrix ());
973 
974  if (nf > 0)
975  dimensions = xvals[0].dims ();
976  else
977  {
978  // Use dummy array. FIXME: Need(?) a better solution.
979  Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
980  dummy.assign (i, rhs_dummy);;
981  dimensions = dummy.dims ();
982  }
983 
985  }
986  else if (nfields () == 0)
987  {
989  tmp.assign (i, rhs);
990  *this = tmp;
991  }
992  else
993  {
995  octave_map rhs1;
996 
997  try
998  {
999  rhs1 = rhs.orderfields (*this, perm);
1000  }
1001  catch (octave::execution_exception& e)
1002  {
1003  error (e, "incompatible fields in struct assignment");
1004  }
1005 
1006  assert (rhs1.xkeys.is_same (xkeys));
1007  assign (i, rhs1);
1008  }
1009 }
1010 
1011 void
1013  const octave_map& rhs)
1014 {
1015  if (rhs.xkeys.is_same (xkeys))
1016  {
1017  octave_idx_type nf = nfields ();
1018 
1019  for (octave_idx_type k = 0; k < nf; k++)
1020  xvals[k].assign (i, j, rhs.xvals[k], Matrix ());
1021 
1022  if (nf > 0)
1023  dimensions = xvals[0].dims ();
1024  else
1025  {
1026  // Use dummy array. FIXME: Need(?) a better solution.
1027  Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
1028  dummy.assign (i, j, rhs_dummy);;
1029  dimensions = dummy.dims ();
1030  }
1031 
1033  }
1034  else if (nfields () == 0)
1035  {
1036  octave_map tmp (dimensions, rhs.xkeys);
1037  tmp.assign (i, j, rhs);
1038  *this = tmp;
1039  }
1040  else
1041  {
1043  octave_map rhs1;
1044 
1045  try
1046  {
1047  rhs1 = rhs.orderfields (*this, perm);
1048  }
1049  catch (octave::execution_exception& e)
1050  {
1051  error (e, "incompatible fields in struct assignment");
1052  }
1053 
1054  assert (rhs1.xkeys.is_same (xkeys));
1055  assign (i, j, rhs1);
1056  }
1057 }
1058 
1059 void
1061  const octave_map& rhs)
1062 {
1063  if (rhs.xkeys.is_same (xkeys))
1064  {
1065  octave_idx_type nf = nfields ();
1066 
1067  for (octave_idx_type k = 0; k < nf; k++)
1068  xvals[k].assign (ia, rhs.xvals[k], Matrix ());
1069 
1070  if (nf > 0)
1071  dimensions = xvals[0].dims ();
1072  else
1073  {
1074  // Use dummy array. FIXME: Need(?) a better solution.
1075  Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
1076  dummy.assign (ia, rhs_dummy);;
1077  dimensions = dummy.dims ();
1078  }
1079 
1081  }
1082  else if (nfields () == 0)
1083  {
1084  octave_map tmp (dimensions, rhs.xkeys);
1085  tmp.assign (ia, rhs);
1086  *this = tmp;
1087  }
1088  else
1089  {
1091  octave_map rhs1;
1092 
1093  try
1094  {
1095  rhs1 = rhs.orderfields (*this, perm);
1096  }
1097  catch (octave::execution_exception& e)
1098  {
1099  error (e, "incompatible fields in struct assignment");
1100  }
1101 
1102  assert (rhs1.xkeys.is_same (xkeys));
1103  assign (ia, rhs1);
1104  }
1105 }
1106 
1107 void
1109 {
1110  octave_idx_type n_idx = idx.length ();
1111 
1112  // If we catch an indexing error in index_vector, we flag an error in
1113  // index k. Ensure it is the right value befor each idx_vector call.
1114  // Same variable as used in the for loop in the default case.
1115 
1116  octave_idx_type k = 0;
1117 
1118  try
1119  {
1120  switch (n_idx)
1121  {
1122  case 1:
1123  {
1124  idx_vector i = idx(0).index_vector ();
1125 
1126  assign (i, rhs);
1127  }
1128  break;
1129 
1130  case 2:
1131  {
1132  idx_vector i = idx(0).index_vector ();
1133 
1134  k = 1;
1135  idx_vector j = idx(1).index_vector ();
1136 
1137  assign (i, j, rhs);
1138  }
1139  break;
1140 
1141  default:
1142  {
1143  Array<idx_vector> ia (dim_vector (n_idx, 1));
1144 
1145  for (k = 0; k < n_idx; k++)
1146  ia(k) = idx(k).index_vector ();
1147 
1148  assign (ia, rhs);
1149  }
1150  break;
1151  }
1152  }
1153  catch (octave::index_exception& e)
1154  {
1155  // Rethrow to allow more info to be reported later.
1156  e.set_pos_if_unset (n_idx, k+1);
1157  throw;
1158  }
1159 }
1160 
1161 void
1163  const Cell& rhs)
1164 {
1165  Cell tmp;
1166  iterator p = seek (k);
1167  Cell& ref = p != end () ? contents (p) : tmp;
1168 
1169  if (&ref == &tmp)
1170  ref = Cell (dimensions);
1171 
1172  ref.assign (idx, rhs);
1173 
1174  if (ref.dims () != dimensions)
1175  {
1176  dimensions = ref.dims ();
1177 
1178  octave_idx_type nf = nfields ();
1179  for (octave_idx_type i = 0; i < nf; i++)
1180  {
1181  if (&xvals[i] != &ref)
1182  xvals[i].resize (dimensions, Matrix ());
1183  }
1184 
1186  }
1187 
1188  if (&ref == &tmp)
1189  setfield (k, tmp);
1190 }
1191 
1192 /*
1193 %!test
1194 %! rhs.b = 1;
1195 %! a(3) = rhs;
1196 %! assert ({a.b}, {[], [], 1});
1197 */
1198 
1199 void
1201 {
1202  octave_idx_type nf = nfields ();
1203  for (octave_idx_type k = 0; k < nf; k++)
1204  xvals[k].delete_elements (i);
1205 
1206  if (nf > 0)
1207  dimensions = xvals[0].dims ();
1208  else
1209  {
1210  // Use dummy array. FIXME: Need(?) a better solution.
1211  Array<char> dummy (dimensions);
1212  dummy.delete_elements (i);
1213  dimensions = dummy.dims ();
1214  }
1215 
1217 }
1218 
1219 void
1221 {
1222  octave_idx_type nf = nfields ();
1223  for (octave_idx_type k = 0; k < nf; k++)
1224  xvals[k].delete_elements (dim, i);
1225 
1226  if (nf > 0)
1227  dimensions = xvals[0].dims ();
1228  else
1229  {
1230  // Use dummy array. FIXME: Need(?) a better solution.
1231  Array<char> dummy (dimensions);
1232  dummy.delete_elements (dim, i);
1233  dimensions = dummy.dims ();
1234  }
1235 
1237 }
1238 
1239 void
1241 {
1242  octave_idx_type nf = nfields ();
1243  for (octave_idx_type k = 0; k < nf; k++)
1244  xvals[k].delete_elements (ia);
1245 
1246  if (nf > 0)
1247  dimensions = xvals[0].dims ();
1248  else
1249  {
1250  // Use dummy array. FIXME: Need(?) a better solution.
1251  Array<char> dummy (dimensions);
1252  dummy.delete_elements (ia);
1253  dimensions = dummy.dims ();
1254  }
1255 
1257 }
1258 
1259 void
1261 {
1262  octave_idx_type n_idx = idx.length ();
1263 
1264  Array<idx_vector> ia (dim_vector (n_idx, 1));
1265 
1266  for (octave_idx_type i = 0; i < n_idx; i++)
1267  {
1268  try
1269  {
1270  ia(i) = idx(i).index_vector ();
1271  }
1272  catch (octave::index_exception& e)
1273  {
1274  // Rethrow to allow more info to be reported later.
1275  e.set_pos_if_unset (n_idx, i+1);
1276  throw;
1277  }
1278  }
1279 
1280  delete_elements (ia);
1281 }
1282 
1283 /*
1284 ## test preservation of key order by indexing
1285 %!test
1286 %! x(1, 1).d = 10; x(4, 6).a = "b"; x(2, 4).f = 27;
1287 %! assert (fieldnames (x([1, 2], [2:5])), {"d"; "a"; "f"});
1288 */
1289 
1290 octave_map
1292 {
1293  if (nfields () == rb.nfields ())
1294  {
1295  for (const_iterator pa = begin (); pa != end (); pa++)
1296  {
1297  const_iterator pb = rb.seek (key(pa));
1298 
1299  if (pb == rb.end ())
1300  error ("field name mismatch in structure concatenation");
1301 
1302  contents(pa).insert (rb.contents (pb), ra_idx);
1303  }
1304  }
1305  else
1306  {
1307  dim_vector dv = dims ();
1308 
1309  if (dv.all_zero ())
1310  *this = rb;
1311  else if (! rb.dims ().all_zero ())
1312  error ("invalid structure concatenation");
1313  }
1314 
1315  return *this;
1316 }
1317 
1318 void
1320 {
1321  octave_idx_type nf = nfields ();
1322 
1323  for (octave_idx_type i = 0; i < nf; i++)
1324  {
1326  error ("internal error: dimension mismatch across fields in struct");
1327  }
1328 
1329 }
octave_idx_type compute_index(octave_idx_type n, const dim_vector &dims)
Definition: Array-util.cc:176
string_vector keys(void) const
Definition: oct-map.h:338
octave_map column(octave_idx_type k) const
Definition: oct-map.cc:950
const Cell & contents(const_iterator p) const
Definition: oct-map.h:313
dim_vector dimensions
Definition: oct-map.h:460
scalar structure containing the fields
Definition: ov-struct.cc:1688
octave_map orderfields(void) const
Definition: oct-map.cc:294
Definition: Cell.h:37
octave_idx_type nfields(void) const
Definition: oct-map.h:203
static octave_map cat(int dim, octave_idx_type n, const octave_scalar_map *map_list)
Definition: oct-map.cc:661
void delete_elements(const idx_vector &i)
Definition: oct-map.cc:1200
const octave_base_value const Array< octave_idx_type > & ra_idx
bool equal_up_to_order(const octave_fields &other, octave_idx_type *perm) const
Definition: oct-map.cc:124
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:347
Array< T > permute(const Array< octave_idx_type > &vec, bool inv=false) const
Definition: Array.cc:451
static const idx_vector colon
Definition: idx-vector.h:482
octave_map page(octave_idx_type k) const
Definition: oct-map.cc:956
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:5068
void set_pos_if_unset(octave_idx_type nd_arg, octave_idx_type dim_arg)
void delete_elements(const idx_vector &i)
Deleting elements.
Definition: Array.cc:1407
octave_idx_type length(void) const
Definition: ovl.h:96
const octave_value & contents(const_iterator p) const
Definition: oct-map.h:190
const_iterator iterator
Definition: oct-map.h:301
bool is_same(const octave_fields &other) const
Definition: oct-map.h:138
static void permute_to_correct_order(octave_idx_type n, octave_idx_type nf, octave_idx_type idx, const map *map_list, map *new_map_list)
Definition: oct-map.cc:635
for large enough k
Definition: lu.cc:606
void resize(int n, int fill_value=0)
Definition: dim-vector.h:316
void assign(const octave_value_list &idx, const Cell &rhs, const octave_value &fill_val=Matrix())
Definition: Cell.cc:223
void error(const char *fmt,...)
Definition: error.cc:570
bool isfield(const std::string &name) const
Definition: oct-map.cc:60
octave_scalar_map orderfields(void) const
Definition: oct-map.cc:196
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:178
octave_map squeeze(void) const
Definition: oct-map.cc:430
const_iterator end(void) const
Definition: oct-map.h:102
octave_fields(void)
Definition: oct-map.h:60
std::vector< Cell > xvals
Definition: oct-map.h:459
Cell getfield(const std::string &key) const
Definition: oct-map.cc:263
octave_idx_type rmfield(const std::string &name)
Definition: oct-map.cc:87
i e
Definition: data.cc:2724
const_iterator end(void) const
Definition: oct-map.h:304
octave_fields xkeys
Definition: oct-map.h:250
dim_vector squeeze(void) const
Definition: dim-vector.cc:122
void permute_to_correct_order1(const octave_scalar_map &ref, const octave_scalar_map &src, octave_scalar_map &dest, Array< octave_idx_type > &perm)
Definition: oct-map.cc:615
void extract_scalar(octave_scalar_map &dest, octave_idx_type index) const
Definition: oct-map.cc:349
void orderfields(Array< octave_idx_type > &perm)
Definition: oct-map.cc:108
bool concat(const dim_vector &dvb, int dim)
This corresponds to cat().
Definition: dim-vector.cc:187
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:439
std::vector< octave_value > xvals
Definition: oct-map.h:251
octave_fields xkeys
Definition: oct-map.h:458
octave_idx_type nfields(void) const
Definition: oct-map.h:326
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
string_vector fieldnames(void) const
Definition: oct-map.cc:159
void rmfield(const std::string &key)
Definition: oct-map.cc:188
octave_map permute(const Array< int > &vec, bool inv=false) const
Definition: oct-map.cc:453
bool fast_elem_insert(octave_idx_type n, const octave_scalar_map &rhs)
Definition: oct-map.cc:401
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1028
dim_vector dims(void) const
Definition: oct-map.h:399
double tmp
Definition: data.cc:6300
octave_value retval
Definition: data.cc:6294
void rmfield(const std::string &key)
Definition: oct-map.cc:286
std::string key(const_iterator p) const
Definition: oct-map.h:308
fields_rep * rep
Definition: oct-map.h:54
octave_scalar_map fast_elem_extract(octave_idx_type n) const
Definition: oct-map.cc:391
Cell & insert(const Cell &a, octave_idx_type r, octave_idx_type c)
Definition: Cell.cc:311
Definition: dMatrix.h:37
const_iterator begin(void) const
Definition: oct-map.h:303
bool all_zero(void) const
Definition: dim-vector.h:333
octave_map(void)
Definition: oct-map.h:273
void make_unique(void)
Definition: oct-map.h:70
void setfield(const std::string &key, const Cell &val)
Definition: oct-map.cc:270
T & xelem(octave_idx_type n)
Definition: Array.h:455
octave_idx_type nfields(void) const
Definition: oct-map.h:113
void clear(void)
Definition: Array.cc:95
int ndims(void) const
Definition: oct-map.h:401
const_iterator iterator
Definition: oct-map.h:99
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
p
Definition: lu.cc:138
const_iterator begin(void) const
Definition: oct-map.h:101
octave_map map(dims)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:200
const_iterator seek(const std::string &k) const
Definition: oct-map.h:306
Array< T > reshape(octave_idx_type nr, octave_idx_type nc) const
Definition: Array.h:563
octave_map reshape(const dim_vector &dv) const
Definition: oct-map.cc:514
octave_scalar_map checkelem(octave_idx_type n) const
Definition: oct-map.cc:358
bool is_empty(void) const
Definition: oct-map.h:373
octave_value getfield(const std::string &key) const
Definition: oct-map.cc:171
octave_idx_type index(const_iterator p) const
Definition: oct-map.h:310
void resize(const dim_vector &dv, bool fill=false)
Definition: oct-map.cc:547
void optimize_dimensions(void)
Definition: oct-map.cc:1319
octave_map concat(const octave_map &rb, const Array< octave_idx_type > &ra_idx)
Definition: oct-map.cc:1291
const T * fortran_vec(void) const
Definition: Array.h:584
octave_fields::const_iterator const_iterator
Definition: oct-map.h:300
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
dim_vector dv
Definition: sub2ind.cc:263
static void do_cat(int dim, octave_idx_type n, const octave_scalar_map *map_list, octave_map &retval)
Definition: oct-map.cc:573
octave_idx_type getfield(const std::string &name) const
Definition: oct-map.cc:66
Array< T > index(const idx_vector &i) const
Indexing without resizing.
Definition: Array.cc:718
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
octave_map transpose(void) const
Definition: oct-map.cc:487
static fields_rep * nil_rep(void)
Definition: oct-map.cc:37