GNU Octave 11.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
ov-cell.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1999-2026 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <istream>
31#include <ostream>
32#include <sstream>
33#include <vector>
34#include <queue>
35#include <iterator>
36
37#include "Array-util.h"
38#include "byte-swap.h"
39#include "lo-utils.h"
40#include "quit.h"
41#include "oct-locbuf.h"
42
43#include "builtin-defun-decls.h"
44#include "defun.h"
45#include "error.h"
46#include "mxarray.h"
47#include "ov-cell.h"
48#include "ovl.h"
49#include "oct-hdf5.h"
50#include "unwind-prot.h"
51#include "utils.h"
52#include "ov-fcn-handle.h"
53#include "ov-re-mat.h"
54#include "ov-scalar.h"
55#include "pr-output.h"
56#include "ov-scalar.h"
57#include "errwarn.h"
58
59#include "ls-oct-text.h"
60#include "ls-oct-binary.h"
61#include "ls-hdf5.h"
62#include "ls-utils.h"
63
64
66
67void
68octave_cell::break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)
69{
70 for (octave_idx_type i = 0; i < m_matrix.numel (); i++)
71 m_matrix(i).break_closure_cycles (frame);
72}
73
76{
77 octave_value_list retval;
78
79 switch (type)
80 {
81 case '(':
82 retval(0) = do_index_op (idx);
83 break;
84
85 case '{':
86 {
87 if (idx.empty ())
88 error ("invalid empty index expression {}, use {:} instead");
89
90 octave_value tmp = do_index_op (idx);
91
92 Cell tcell = tmp.cell_value ();
93
94 if (tcell.numel () == 1)
95 retval(0) = tcell(0, 0);
96 else
97 {
98 // Return a comma-separated list.
99 retval = octave_value (octave_value_list (tcell));
100 }
101 }
102 break;
103
104 case '.':
105 {
106 std::string nm = type_name ();
107 error ("%s cannot be indexed with %c", nm.c_str (), type);
108 }
109 break;
110
111 default:
112 error ("unexpected: index not '(', '{', or '.' in octave_cell::simple_subsref - please report this bug");
113 }
114
115 return retval;
116}
117
119octave_cell::subsref (const std::string& type,
120 const std::list<octave_value_list>& idx,
121 int nargout)
122{
123 octave_value_list retval;
124
125 switch (type[0])
126 {
127 case '(':
128 retval(0) = do_index_op (idx.front ());
129 break;
130
131 case '{':
132 {
133 if (idx.front ().empty ())
134 error ("invalid empty index expression {}, use {:} instead");
135
136 octave_value tmp = do_index_op (idx.front ());
137
138 Cell tcell = tmp.cell_value ();
139
140 if (tcell.numel () == 1)
141 retval(0) = tcell(0, 0);
142 else
143 {
144 // Return a comma-separated list.
145 retval = octave_value (octave_value_list (tcell));
146 }
147 }
148 break;
149
150 case '.':
151 {
152 std::string nm = type_name ();
153 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
154 }
155 break;
156
157 default:
158 error ("unexpected: index not '(', '{', or '.' in octave_cell::subsref - please report this bug");
159 }
160
161 // FIXME: perhaps there should be an
162 // octave_value_list::next_subsref member function? See also
163 // octave_user_function::subsref.
164
165 if (idx.size () > 1)
166 retval = retval(0).next_subsref (nargout, type, idx);
167
168 return retval;
169}
170
172octave_cell::subsref (const std::string& type,
173 const std::list<octave_value_list>& idx,
174 bool auto_add)
175{
176 octave_value retval;
177
178 switch (type[0])
179 {
180 case '(':
181 retval = do_index_op (idx.front (), auto_add);
182 break;
183
184 case '{':
185 {
186 octave_value tmp = do_index_op (idx.front (), auto_add);
187
188 const Cell tcell = tmp.cell_value ();
189
190 if (tcell.numel () == 1)
191 retval = tcell(0, 0);
192 else
193 {
194 // Return a comma-separated list.
195 retval = octave_value (octave_value_list (tcell));
196 }
197 }
198 break;
199
200 case '.':
201 {
202 std::string nm = type_name ();
203 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
204 }
205 break;
206
207 default:
208 error ("unexpected: index not '(', '{', or '.' in octave_cell::subsref - please report this bug");
209 }
210
211 // FIXME: perhaps there should be an
212 // octave_value_list::next_subsref member function? See also
213 // octave_user_function::subsref.
214
215 if (idx.size () > 1)
216 retval = retval.next_subsref (auto_add, type, idx);
217
218 return retval;
219}
220
222octave_cell::subsasgn (const std::string& type,
223 const std::list<octave_value_list>& idx,
224 const octave_value& rhs)
225{
226 octave_value retval;
227
228 int n = type.length ();
229
230 octave_value t_rhs = rhs;
231
232 clear_cellstr_cache ();
233
234 if (idx.front ().empty ())
235 error ("missing index in indexed assignment");
236
237 if (n > 1)
238 {
239 switch (type[0])
240 {
241 case '(':
242 {
243 if (isempty () && type[1] == '.')
244 {
245 // Allow conversion of empty cell array to some other
246 // type in cases like
247 //
248 // x = {}; x(i).f = rhs
249
250 octave_value tmp = octave_value::empty_conv (type, rhs);
251
252 return tmp.subsasgn (type, idx, rhs);
253 }
254 else
255 {
256 octave_value tmp = do_index_op (idx.front (), true);
257
258 if (! tmp.is_defined ())
259 tmp = octave_value::empty_conv (type.substr (1), rhs);
260
261 std::list<octave_value_list> next_idx (std::next (idx.begin ()), idx.end ());
262
263 tmp.make_unique ();
264
265 t_rhs = tmp.subsasgn (type.substr (1), next_idx, rhs);
266 }
267 }
268 break;
269
270 case '{':
271 {
273 Cell tmpc = m_matrix.index (idx.front (), true);
274
275 std::list<octave_value_list> next_idx (std::next (idx.begin ()), idx.end ());
276
277 std::string next_type = type.substr (1);
278
279 if (tmpc.numel () != 1)
281
282 octave_value tmp = tmpc(0);
283 tmpc = Cell ();
284
285 if (! tmp.is_defined () || tmp.is_zero_by_zero ())
286 {
287 tmp = octave_value::empty_conv (type.substr (1), rhs);
288 tmp.make_unique (); // probably a no-op.
289 }
290 else
291 // optimization: ignore copy still stored inside array.
292 tmp.make_unique (1);
293
294 t_rhs = tmp.subsasgn (next_type, next_idx, rhs);
295 }
296 break;
297
298 case '.':
299 {
300 if (! isempty ())
301 {
302 std::string nm = type_name ();
303 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
304 }
305
306 // Do nothing; the next branch will handle it.
307 }
308 break;
309
310 default:
311 error ("unexpected: index not '(', '{', or '.' in octave_cell::subsasgn - please report this bug");
312 }
313 }
314
315 switch (type[0])
316 {
317 case '(':
318 {
319 octave_value_list i = idx.front ();
320
321 if (t_rhs.iscell ())
323 else if (t_rhs.isnull ())
325 else
327
328 m_count++;
329 retval = octave_value (this);
330 }
331 break;
332
333 case '{':
334 {
335 octave_value_list idxf = idx.front ();
336
337 if (t_rhs.is_cs_list ())
338 {
339 Cell tmp_cell = Cell (t_rhs.list_value ());
340
341 // Inquire the proper shape of the RHS.
342
343 dim_vector didx = dims ().redim (idxf.length ());
344 for (octave_idx_type k = 0; k < idxf.length (); k++)
345 if (! idxf(k).is_magic_colon ()) didx(k) = idxf(k).numel ();
346
347 if (didx.numel () == tmp_cell.numel ())
348 tmp_cell = tmp_cell.reshape (didx);
349
350 octave_base_matrix<Cell>::assign (idxf, tmp_cell);
351 }
352 else if (idxf.all_scalars ()
353 || do_index_op (idxf, true).numel () == 1)
354 // Regularize a null matrix if stored into a cell.
356 Cell (t_rhs.storable_value ()));
357 else
359
360 m_count++;
361 retval = octave_value (this);
362 }
363 break;
364
365 case '.':
366 {
367 if (! isempty ())
368 {
369 std::string nm = type_name ();
370 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
371 }
372
373 // Allow conversion of empty cell array to some other
374 // type in cases like
375 //
376 // x = {}; x.f = rhs
377
378 octave_value tmp = octave_value::empty_conv (type, rhs);
379
380 return tmp.subsasgn (type, idx, rhs);
381 }
382 break;
383
384 default:
385 error ("unexpected: index not '(', '{', or '.' in octave_cell::subsasgn - please report this bug");
386 }
387
388 return retval;
389}
390
391bool
393{
394 bool retval;
395 if (m_cellstr_cache.get ())
396 retval = true;
397 else
398 {
399 retval = m_matrix.iscellstr ();
400 // Allocate empty cache to mark that this is indeed a cellstr.
401 if (retval)
402 m_cellstr_cache.reset (new Array<std::string> ());
403 }
404
405 return retval;
406}
407
408void
410{
411 clear_cellstr_cache ();
413}
414
415void
417{
418 clear_cellstr_cache ();
420}
421
422void
424{
425 clear_cellstr_cache ();
427}
428
429std::size_t
431{
432 std::size_t retval = 0;
433
434 for (octave_idx_type i = 0; i < numel (); i++)
435 retval += m_matrix(i).byte_size ();
436
437 return retval;
438}
439
442{
443 octave_value retval;
444
445 if (! iscellstr ())
446 error ("sort: only cell arrays of character strings may be sorted");
447
449
450 tmp = tmp.sort (dim, mode);
451
452 // We already have the cache.
453 retval = new octave_cell (tmp);
454
455 return retval;
456}
457
460 sortmode mode) const
461{
462 octave_value retval;
463
464 if (! iscellstr ())
465 error ("sort: only cell arrays of character strings may be sorted");
466
468
469 tmp = tmp.sort (sidx, dim, mode);
470
471 // We already have the cache.
472 retval = new octave_cell (tmp);
473
474 return retval;
475}
476
479{
480 sortmode retval = UNSORTED;
481
482 if (! iscellstr ())
483 error ("issorted: A is not a cell array of strings");
484
486
487 retval = tmp.issorted (mode);
488
489 return retval;
490}
491
494{
496
497 if (! iscellstr ())
498 error ("sortrows: only cell arrays of character strings may be sorted");
499
501
502 retval = tmp.sort_rows_idx (mode);
503
504 return retval;
505}
506
509{
510 sortmode retval = UNSORTED;
511
512 if (! iscellstr ())
513 error ("issorted: A is not a cell array of strings");
514
516
517 retval = tmp.is_sorted_rows (mode);
518
519 return retval;
520}
521
522bool
524{
525 error ("invalid conversion from cell array to logical value");
526}
527
530{
532}
533
536{
537 string_vector retval;
538
539 octave_idx_type nel = numel ();
540
541 int n_elts = 0;
542
543 octave_idx_type max_len = 0;
544
545 std::queue<string_vector> strvec_queue;
546
547 for (octave_idx_type i = 0; i < nel; i++)
548 {
550
551 octave_idx_type s_len = s.numel ();
552
553 n_elts += s_len ? s_len : 1;
554
555 octave_idx_type s_max_len = s.max_length ();
556
557 if (s_max_len > max_len)
558 max_len = s_max_len;
559
560 strvec_queue.push (s);
561 }
562
563 retval = string_vector (n_elts);
564
565 octave_idx_type k = 0;
566
567 for (octave_idx_type i = 0; i < nel; i++)
568 {
569 const string_vector s = strvec_queue.front ();
570 strvec_queue.pop ();
571
572 octave_idx_type s_len = s.numel ();
573
574 if (s_len)
575 {
576 for (octave_idx_type j = 0; j < s_len; j++)
577 {
578 std::string t = s[j];
579 int t_len = t.length ();
580
581 if (pad && max_len > t_len)
582 t += std::string (max_len - t_len, ' ');
583
584 retval[k++] = t;
585 }
586 }
587 else if (pad)
588 retval[k++] = std::string (max_len, ' ');
589 else
590 retval[k++] = "";
591 }
592
593 return retval;
594}
595
598{
599 if (! iscellstr ())
600 error ("invalid conversion from cell array to array of strings");
601
602 if (m_cellstr_cache->isempty ())
603 *m_cellstr_cache = m_matrix.cellstr_value ();
604
605 return *m_cellstr_cache;
606}
607
608bool
610{
611 return true;
612}
613
614void
615octave_cell::print (std::ostream& os, bool)
616{
617 print_raw (os);
618}
619
620void
621octave_cell::print_raw (std::ostream& os, bool) const
622{
623 int nd = m_matrix.ndims ();
624
625 if (nd == 2)
626 {
627 octave_idx_type nr = rows ();
628 octave_idx_type nc = columns ();
629
630 if (nr > 0 && nc > 0)
631 {
632 indent (os);
633 os << '{';
634 newline (os);
635
637
638 for (octave_idx_type j = 0; j < nc; j++)
639 {
640 for (octave_idx_type i = 0; i < nr; i++)
641 {
642 octave_quit ();
643
644 std::ostringstream buf;
645 buf << '[' << i+1 << ',' << j+1 << ']';
646
647 octave_value val = m_matrix(i, j);
648
649 val.print_with_name (os, buf.str ());
650 }
651 }
652
654
655 indent (os);
656 os << '}';
657 newline (os);
658 }
659 else
660 {
661 indent (os);
662 os << "{}";
664 os << '(' << nr << 'x' << nc << ')';
665 newline (os);
666 }
667 }
668 else
669 {
670 indent (os);
671 const dim_vector& dv = m_matrix.dims ();
672 os << '{' << dv.str () << " Cell Array}";
673 newline (os);
674 }
675}
676
677bool
678octave_cell::print_name_tag (std::ostream& os, const std::string& name) const
679{
680 bool retval = false;
681
682 indent (os);
683
684 if (isempty () || ndims () > 2)
685 os << name << " = ";
686 else
687 {
688 os << name << " =";
689 newline (os);
690 retval = true;
691 }
692
693 return retval;
694}
695
696void
697octave_cell::short_disp (std::ostream& os) const
698{
699 // octave_base_matrix<octave_value>::short_disp is not appropriate for
700 // cell arrays.
701
703}
704
705#define CELL_ELT_TAG "<cell-element>"
706
707bool
708octave_cell::save_ascii (std::ostream& os)
709{
710 const dim_vector& dv = dims ();
711 if (dv.ndims () > 2)
712 {
713 os << "# ndims: " << dv.ndims () << "\n";
714
715 for (int i = 0; i < dv.ndims (); i++)
716 os << ' ' << dv(i);
717 os << "\n";
718
719 Cell tmp = cell_value ();
720
721 for (octave_idx_type i = 0; i < dv.numel (); i++)
722 {
723 octave_value o_val = tmp.elem (i);
724
725 // Recurse to save sub-value.
726 bool b = save_text_data (os, o_val, CELL_ELT_TAG, false, 0);
727
728 if (! b)
729 return ! os.fail ();
730 }
731 }
732 else
733 {
734 // Keep this case, rather than use generic code above for backward
735 // compatibility. Makes load_ascii much more complex!!
736 os << "# rows: " << rows () << "\n"
737 << "# columns: " << columns () << "\n";
738
739 Cell tmp = cell_value ();
740
741 for (octave_idx_type j = 0; j < tmp.cols (); j++)
742 {
743 for (octave_idx_type i = 0; i < tmp.rows (); i++)
744 {
745 octave_value o_val = tmp.elem (i, j);
746
747 // Recurse to save sub-value.
748 bool b = save_text_data (os, o_val, CELL_ELT_TAG, false, 0);
749
750 if (! b)
751 return ! os.fail ();
752 }
753
754 os << "\n";
755 }
756 }
757
758 return true;
759}
760
761bool
762octave_cell::load_ascii (std::istream& is)
763{
764 clear_cellstr_cache ();
765
766 string_vector keywords(2);
767
768 keywords[0] = "ndims";
769 keywords[1] = "rows";
770
771 std::string kw;
772 octave_idx_type val = 0;
773
774 if (! extract_keyword (is, keywords, kw, val, true))
775 error ("load: failed to extract number of rows and columns");
776
777 if (kw == "ndims")
778 {
779 int mdims = static_cast<int> (val);
780
781 if (mdims < 0)
782 error ("load: failed to extract number of rows and columns");
783
784 dim_vector dv;
785 dv.resize (mdims);
786
787 for (int i = 0; i < mdims; i++)
788 is >> dv(i);
789
790 Cell tmp(dv);
791
792 for (octave_idx_type i = 0; i < dv.numel (); i++)
793 {
794 octave_value t2;
795 bool dummy;
796
797 // recurse to read cell elements
798 std::string nm = read_text_data (is, "",
799 dummy, t2, i);
800
801 if (nm != CELL_ELT_TAG)
802 error ("load: cell array element had unexpected name");
803
804 if (is)
805 tmp.elem (i) = t2;
806 }
807
808 if (! is)
809 error ("load: failed to load matrix constant");
810
811 m_matrix = tmp;
812 }
813 else if (kw == "rows")
814 {
815 octave_idx_type nr = val;
816 octave_idx_type nc = 0;
817
818 if (nr < 0 || ! extract_keyword (is, "columns", nc) || nc < 0)
819 error ("load: failed to extract number of rows and columns for cell array");
820
821 if (nr > 0 && nc > 0)
822 {
823 Cell tmp (nr, nc);
824
825 for (octave_idx_type j = 0; j < nc; j++)
826 {
827 for (octave_idx_type i = 0; i < nr; i++)
828 {
829 octave_value t2;
830 bool dummy;
831
832 // recurse to read cell elements
833 std::string nm = read_text_data (is, "",
834 dummy, t2, i);
835
836 if (nm != CELL_ELT_TAG)
837 error ("load: cell array element had unexpected name");
838
839 if (is)
840 tmp.elem (i, j) = t2;
841 }
842 }
843
844 if (! is)
845 error ("load: failed to load cell element");
846
847 m_matrix = tmp;
848 }
849 else if (nr == 0 || nc == 0)
850 m_matrix = Cell (nr, nc);
851 else
852 error ("unexpected dimensions in octave_cell::load_ascii - please report this bug");
853 }
854 else
855 error ("unexpected dimensions keyword (= '%s') octave_cell::load_ascii - please report this bug", kw.c_str ());
856
857 return true;
858}
859
860bool
861octave_cell::save_binary (std::ostream& os, bool save_as_floats)
862{
863 const dim_vector& dv = dims ();
864 if (dv.ndims () < 1)
865 return false;
866
867 // Use negative value for ndims
868 int32_t di = - dv.ndims ();
869 os.write (reinterpret_cast<char *> (&di), 4);
870 for (int i = 0; i < dv.ndims (); i++)
871 {
872 di = dv(i);
873 os.write (reinterpret_cast<char *> (&di), 4);
874 }
875
876 Cell tmp = cell_value ();
877
878 for (octave_idx_type i = 0; i < dv.numel (); i++)
879 {
880 octave_value o_val = tmp.elem (i);
881
882 // Recurse to save sub-value.
883 bool b = save_binary_data (os, o_val, CELL_ELT_TAG, "", 0,
884 save_as_floats);
885
886 if (! b)
887 return false;
888 }
889
890 return true;
891}
892
893bool
894octave_cell::load_binary (std::istream& is, bool swap,
895 octave::mach_info::float_format fmt)
896{
897 clear_cellstr_cache ();
898
899 int32_t mdims;
900 if (! is.read (reinterpret_cast<char *> (&mdims), 4))
901 return false;
902 if (swap)
903 swap_bytes<4> (&mdims);
904 if (mdims >= 0)
905 return false;
906
907 mdims = -mdims;
908 int32_t di;
909 dim_vector dv;
910 dv.resize (mdims);
911
912 for (int i = 0; i < mdims; i++)
913 {
914 if (! is.read (reinterpret_cast<char *> (&di), 4))
915 return false;
916 if (swap)
917 swap_bytes<4> (&di);
918 dv(i) = di;
919 }
920
921 // Convert an array with a single dimension to be a row vector.
922 // Octave should never write files like this, other software
923 // might.
924
925 if (mdims == 1)
926 {
927 mdims = 2;
928 dv.resize (mdims);
929 dv(1) = dv(0);
930 dv(0) = 1;
931 }
932
933 octave_idx_type nel = dv.numel ();
934 Cell tmp(dv);
935
936 for (octave_idx_type i = 0; i < nel; i++)
937 {
938 octave_value t2;
939 bool dummy;
940 std::string doc;
941
942 // recurse to read cell elements
943 std::string nm = read_binary_data (is, swap, fmt, "",
944 dummy, t2, doc);
945
946 if (nm != CELL_ELT_TAG)
947 error ("load: cell array element had unexpected name");
948
949 if (is)
950 tmp.elem (i) = t2;
951 }
952
953 if (! is)
954 error ("load: failed to load matrix constant");
955
956 m_matrix = tmp;
957
958 return true;
959}
960
961const void *
963{
964 clear_cellstr_cache ();
965 return m_matrix.data ();
966}
967
968bool
969octave_cell::save_hdf5 (octave_hdf5_id loc_id, const char *name,
970 bool save_as_floats)
971{
972#if defined (HAVE_HDF5)
973
974 const dim_vector& dv = dims ();
975 int empty = save_hdf5_empty (loc_id, name, dv);
976 if (empty)
977 return (empty > 0);
978
979 hsize_t rank = dv.ndims ();
980 hid_t space_hid, data_hid, size_hid;
981 space_hid = data_hid = size_hid = -1;
982
983#if defined (HAVE_HDF5_18)
984 data_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,
986#else
987 data_hid = H5Gcreate (loc_id, name, 0);
988#endif
989
990 if (data_hid < 0)
991 return false;
992
993 // Have to save cell array shape, since can't have a
994 // dataset of groups....
995
996 space_hid = H5Screate_simple (1, &rank, nullptr);
997
998 if (space_hid < 0)
999 {
1000 H5Gclose (data_hid);
1001 return false;
1002 }
1003
1004 OCTAVE_LOCAL_BUFFER (octave_idx_type, hdims, rank);
1005
1006 // Octave uses column-major, while HDF5 uses row-major ordering
1007 for (hsize_t i = 0; i < rank; i++)
1008 hdims[i] = dv(rank-i-1);
1009
1010#if defined (HAVE_HDF5_18)
1011 size_hid = H5Dcreate (data_hid, "dims", H5T_NATIVE_IDX, space_hid,
1014#else
1015 size_hid = H5Dcreate (data_hid, "dims", H5T_NATIVE_IDX, space_hid,
1017#endif
1018 if (size_hid < 0)
1019 {
1020 H5Sclose (space_hid);
1021 H5Gclose (data_hid);
1022 return false;
1023 }
1024
1025 if (H5Dwrite (size_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
1026 octave_H5P_DEFAULT, hdims) < 0)
1027 {
1028 H5Dclose (size_hid);
1029 H5Sclose (space_hid);
1030 H5Gclose (data_hid);
1031 return false;
1032 }
1033
1034 H5Dclose (size_hid);
1035 H5Sclose (space_hid);
1036
1037 // Recursively add each element of the cell to this group.
1038
1039 Cell tmp = cell_value ();
1040
1041 octave_idx_type nel = dv.numel ();
1042
1043 for (octave_idx_type i = 0; i < nel; i++)
1044 {
1045 std::ostringstream buf;
1046 int digits = static_cast<int> (std::floor (::log10 (static_cast<double>
1047 (nel)) + 1.0));
1048 buf << '_' << std::setw (digits) << std::setfill ('0') << i;
1049 std::string s = buf.str ();
1050
1051 if (! add_hdf5_data (data_hid, tmp.elem (i), s.c_str (), "", false,
1052 save_as_floats))
1053 {
1054 H5Gclose (data_hid);
1055 return false;
1056 }
1057 }
1058
1059 H5Gclose (data_hid);
1060
1061 return true;
1062
1063#else
1064 octave_unused_parameter (loc_id);
1065 octave_unused_parameter (name);
1066 octave_unused_parameter (save_as_floats);
1067
1068 warn_save ("hdf5");
1069
1070 return false;
1071#endif
1072}
1073
1074bool
1075octave_cell::load_hdf5 (octave_hdf5_id loc_id, const char *name)
1076{
1077 bool retval = false;
1078
1079#if defined (HAVE_HDF5)
1080
1081 clear_cellstr_cache ();
1082
1083 dim_vector dv;
1084 int empty = load_hdf5_empty (loc_id, name, dv);
1085 if (empty > 0)
1086 m_matrix.resize (dv);
1087 if (empty)
1088 return (empty > 0);
1089
1090#if defined (HAVE_HDF5_18)
1091 hid_t group_id = H5Gopen (loc_id, name, octave_H5P_DEFAULT);
1092#else
1093 hid_t group_id = H5Gopen (loc_id, name);
1094#endif
1095
1096 if (group_id < 0)
1097 return false;
1098
1099#if defined (HAVE_HDF5_18)
1100 hid_t data_hid = H5Dopen (group_id, "dims", octave_H5P_DEFAULT);
1101#else
1102 hid_t data_hid = H5Dopen (group_id, "dims");
1103#endif
1104 hid_t space_hid = H5Dget_space (data_hid);
1105 hsize_t rank = H5Sget_simple_extent_ndims (space_hid);
1106 if (rank != 1)
1107 {
1108 H5Dclose (data_hid);
1109 H5Gclose (group_id);
1110 return false;
1111 }
1112
1113 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
1114 OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
1115
1116 H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
1117
1118 // Octave uses column-major, while HDF5 uses row-major ordering.
1119
1120 dv.resize (hdims[0]);
1121
1122 OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, hdims[0]);
1123
1124 if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
1125 octave_H5P_DEFAULT, tmp) < 0)
1126 {
1127 H5Dclose (data_hid);
1128 H5Gclose (group_id);
1129 return false;
1130 }
1131
1132 H5Dclose (data_hid);
1133 H5Gclose (group_id);
1134
1135 for (hsize_t i = 0, j = hdims[0] - 1; i < hdims[0]; i++, j--)
1136 dv(j) = tmp[i];
1137
1138 hdf5_callback_data dsub;
1139
1140 herr_t retval2 = -1;
1141
1142 Cell m (dv);
1143
1144 int current_item = 0;
1145
1146 hsize_t num_obj = 0;
1147#if defined (HAVE_HDF5_18)
1148 group_id = H5Gopen (loc_id, name, octave_H5P_DEFAULT);
1149#else
1150 group_id = H5Gopen (loc_id, name);
1151#endif
1152 H5Gget_num_objs (group_id, &num_obj);
1153 H5Gclose (group_id);
1154
1155 for (octave_idx_type i = 0; i < dv.numel (); i++)
1156 {
1157
1158 if (current_item >= static_cast<int> (num_obj))
1159 retval2 = -1;
1160 else
1161 retval2 = hdf5_h5g_iterate (loc_id, name, &current_item, &dsub);
1162
1163 if (retval2 <= 0)
1164 break;
1165
1166 octave_value ov = dsub.tc;
1167 m.elem (i) = ov;
1168
1169 }
1170
1171 if (retval2 >= 0)
1172 {
1173 m_matrix = m;
1174 retval = true;
1175 }
1176
1177#else
1178 octave_unused_parameter (loc_id);
1179 octave_unused_parameter (name);
1180
1181 warn_load ("hdf5");
1182#endif
1183
1184 return retval;
1185}
1186
1188
1189DEFUN (iscell, args, ,
1190 doc: /* -*- texinfo -*-
1191@deftypefn {} {@var{tf} =} iscell (@var{x})
1192Return true if @var{x} is a cell array object.
1193@seealso{ismatrix, isstruct, iscellstr, isa}
1194@end deftypefn */)
1195{
1196 if (args.length () != 1)
1197 print_usage ();
1198
1199 return ovl (args(0).iscell ());
1200}
1201
1202DEFUN (cell, args, ,
1203 doc: /* -*- texinfo -*-
1204@deftypefn {} {@var{C} =} cell (@var{n})
1205@deftypefnx {} {@var{C} =} cell (@var{m}, @var{n})
1206@deftypefnx {} {@var{C} =} cell (@var{m}, @var{n}, @var{k}, @dots{})
1207@deftypefnx {} {@var{C} =} cell ([@var{m} @var{n} @dots{}])
1208Create a new cell array object.
1209
1210If invoked with a single scalar integer argument, return a square
1211@nospell{NxN} cell array. If invoked with two or more scalar integer
1212arguments, or a vector of integer values, return an array with the given
1213dimensions.
1214@seealso{cellstr, mat2cell, num2cell, struct2cell}
1215@end deftypefn */)
1216{
1217 int nargin = args.length ();
1218
1219 dim_vector dims;
1220
1221 switch (nargin)
1222 {
1223 case 0:
1224 dims = dim_vector (0, 0);
1225 break;
1226
1227 case 1:
1228 if (args(0).iscell ())
1229 return args(0); // shortcut path for input which is already a Cell
1230 else
1231 get_dimensions (args(0), "cell", dims);
1232 break;
1233
1234 default:
1235 {
1236 dims.resize (nargin);
1237
1238 for (int i = 0; i < nargin; i++)
1239 dims(i) = (args(i).isempty ()
1240 ? 0 : args(i).strict_idx_type_value ("cell: dimension must be a scalar integer"));
1241 }
1242 break;
1243 }
1244
1246
1247 check_dimensions (dims, "cell");
1248
1249 return ovl (Cell (dims));
1250}
1251
1252/*
1253## Note: Matlab compatibility requires using 0 for negative dimensions.
1254%!assert (size (cell (2, -3)), [2, 0])
1255
1256%!test <*63132>
1257%! x = {1, 3};
1258%! y = cell (x);
1259%! assert (x, y);
1260%! x = cell (0, 3);
1261%! y = cell (x);
1262%! assert (x, y);
1263
1264## This might work on some system someday, but for now, who has a system
1265## where a 16 yottabyte array can be allocated? See bug #50934.
1266%!error <out of memory> cell (1e24, 1)
1267*/
1268
1269DEFUN (iscellstr, args, ,
1270 doc: /* -*- texinfo -*-
1271@deftypefn {} {@var{tf} =} iscellstr (@var{cell})
1272Return true if every element of the cell array @var{cell} is a character
1273string.
1274@seealso{ischar, isstring}
1275@end deftypefn */)
1276{
1277 if (args.length () != 1)
1278 print_usage ();
1279
1280 return ovl (args(0).iscellstr ());
1281}
1282
1283DEFUN (cellstr, args, ,
1284 doc: /* -*- texinfo -*-
1285@deftypefn {} {@var{cstr} =} cellstr (@var{strmat})
1286Create a new cell array object from the elements of the string array
1287@var{strmat}.
1288
1289Each row of @var{strmat} becomes an element of @var{cstr}. Any trailing
1290spaces in a row are deleted before conversion.
1291
1292To convert back from a cellstr to a character array use @code{char}.
1293@seealso{cell, char}
1294@end deftypefn */)
1295{
1296 if (args.length () != 1)
1297 print_usage ();
1298
1299 octave_value_list tmp = Fiscellstr (args, 1);
1300
1301 if (tmp(0).is_true ())
1302 return ovl (args(0));
1303 else
1304 {
1305 string_vector s = args(0).xstring_vector_value ("cellstr: argument STRING must be a 2-D character array");
1306
1307 return ovl (s.isempty () ? Cell (octave_value (""))
1308 : Cell (s, true));
1309 }
1310}
1311
1312DEFUN (struct2cell, args, ,
1313 doc: /* -*- texinfo -*-
1314@deftypefn {} {@var{c} =} struct2cell (@var{s})
1315Create a new cell array from the objects stored in the struct object.
1316
1317If @var{f} is the number of fields in the structure, the resulting cell
1318array will have a dimension vector corresponding to
1319@code{[@var{f} size(@var{s})]}. For example:
1320
1321@example
1322@group
1323s = struct ("name", @{"Peter", "Hannah", "Robert"@},
1324 "age", @{23, 16, 3@});
1325c = struct2cell (s)
1326 @xresult{} c = @{2x1x3 Cell Array@}
1327c(1,1,:)(:)
1328 @xresult{}
1329 @{
1330 [1,1] = Peter
1331 [2,1] = Hannah
1332 [3,1] = Robert
1333 @}
1334c(2,1,:)(:)
1335 @xresult{}
1336 @{
1337 [1,1] = 23
1338 [2,1] = 16
1339 [3,1] = 3
1340 @}
1341@end group
1342@end example
1343
1344@seealso{cell2struct, namedargs2cell, fieldnames}
1345@end deftypefn */)
1346{
1347 if (args.length () != 1)
1348 print_usage ();
1349
1350 const octave_map m = args(0).xmap_value ("struct2cell: argument S must be a structure");
1351
1352 const dim_vector m_dv = m.dims ();
1353
1354 octave_idx_type num_fields = m.nfields ();
1355
1356 // The resulting dim_vector should have dimensions:
1357 // [numel(fields) size(struct)]
1358 // except if the struct is a column vector.
1359
1360 dim_vector result_dv;
1361 if (m_dv(m_dv.ndims () - 1) == 1)
1362 result_dv.resize (m_dv.ndims ());
1363 else
1364 result_dv.resize (m_dv.ndims () + 1); // Add 1 for the fields.
1365
1366 result_dv(0) = num_fields;
1367
1368 for (int i = 1; i < result_dv.ndims (); i++)
1369 result_dv(i) = m_dv(i-1);
1370
1371 Cell c (result_dv);
1372
1373 octave_idx_type n_elts = m.numel ();
1374
1375 // Fill c in one sweep. Note that thanks to octave_map structure,
1376 // we don't need a key lookup at all.
1377 for (octave_idx_type j = 0; j < n_elts; j++)
1378 for (octave_idx_type i = 0; i < num_fields; i++)
1379 c.xelem (i, j) = m.contents(i)(j);
1380
1381 return ovl (c);
1382}
1383
1384/*
1385%!test
1386%! keys = cellstr (char (floor (rand (11,10)*24+65)))';
1387%! vals = cellfun (@(x) mat2cell (rand (19,1), ones (19,1), 1), ...
1388%! mat2cell ([1:11]', ones (11,1), 1), "uniformoutput", false)';
1389%! s = struct ([keys; vals]{:});
1390%! t = cell2struct ([vals{:}], keys, 2);
1391%! assert (s, t);
1392%! assert (struct2cell (s), [vals{:}]');
1393%! assert (fieldnames (s), keys');
1394*/
1395
1396OCTAVE_END_NAMESPACE(octave)
1397
1398mxArray *
1399octave_cell::as_mxArray (bool interleaved) const
1400{
1401 mxArray *retval = new mxArray (interleaved, dims ());
1402
1403 mxArray **elts = static_cast<mxArray **> (retval->get_data ());
1404
1405 mwSize nel = numel ();
1406
1407 const octave_value *p = m_matrix.data ();
1408
1409 for (mwIndex i = 0; i < nel; i++)
1410 elts[i] = new mxArray (interleaved, p[i]);
1411
1412 return retval;
1413}
1414
1417{
1418 switch (umap)
1419 {
1420#define FORWARD_MAPPER(UMAP) \
1421 case umap_ ## UMAP: \
1422 return m_matrix.UMAP ()
1423
1424 FORWARD_MAPPER (xisalnum);
1425 FORWARD_MAPPER (xisalpha);
1426 FORWARD_MAPPER (xisascii);
1427 FORWARD_MAPPER (xiscntrl);
1428 FORWARD_MAPPER (xisdigit);
1429 FORWARD_MAPPER (xisgraph);
1430 FORWARD_MAPPER (xislower);
1431 FORWARD_MAPPER (xisprint);
1432 FORWARD_MAPPER (xispunct);
1433 FORWARD_MAPPER (xisspace);
1434 FORWARD_MAPPER (xisupper);
1435 FORWARD_MAPPER (xisxdigit);
1436 FORWARD_MAPPER (xtolower);
1437 FORWARD_MAPPER (xtoupper);
1438
1439 default:
1440 return octave_base_value::map (umap);
1441 }
1442}
void swap_bytes< 4 >(void *ptr)
Definition byte-swap.h:63
N Dimensional Array with copy-on-write semantics.
Definition Array-base.h:130
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Definition Array-base.h:529
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition Array-base.h:547
std::size_t byte_size() const
Size of the specified dimension.
Definition Array-base.h:525
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition Array-base.h:585
int ndims() const
Size of the specified dimension.
Definition Array-base.h:701
octave_idx_type rows() const
Definition Array-base.h:485
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Array< octave_idx_type > sort_rows_idx(sortmode mode=ASCENDING) const
Sort by rows returns only indices.
octave_idx_type cols() const
Definition Array-base.h:495
void make_unique()
Definition Array-base.h:232
Array< T, Alloc > sort(int dim=0, sortmode mode=ASCENDING) const
Size of the specified dimension.
const T * data() const
Size of the specified dimension.
Definition Array-base.h:687
sortmode issorted(sortmode mode=UNSORTED) const
Ordering is auto-detected or can be specified.
sortmode is_sorted_rows(sortmode mode=UNSORTED) const
Ordering is auto-detected or can be specified.
octave_idx_type numel() const
Number of elements in the array.
Definition Array-base.h:440
Definition Cell.h:41
Cell reshape(const dim_vector &new_dims) const
Definition Cell.h:117
Cell index(const octave_value_list &idx, bool resize_ok=false) const
Definition Cell.cc:171
Array< std::string > cellstr_value() const
Definition Cell.cc:145
string_vector string_vector_value() const
Definition Cell.cc:158
bool iscellstr() const
Definition Cell.cc:126
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:92
std::string str(char sep='x') const
Definition dim-vector.cc:58
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition dim-vector.h:341
void chop_trailing_singletons()
Definition dim-vector.h:162
void resize(int n, int fill_value=0)
Definition dim-vector.h:278
octave_idx_type ndims() const
Number of dimensions.
Definition dim-vector.h:263
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
void * get_data() const
Definition mxarray.h:482
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
void delete_elements(const octave_value_list &idx)
octave_idx_type numel() const
dim_vector dims() const
void assign(const octave_value_list &idx, const MT &rhs)
octave_idx_type rows() const
Definition ov-base.h:384
octave_idx_type columns() const
Definition ov-base.h:391
virtual void short_disp(std::ostream &os) const
Definition ov-base.h:761
void increment_indent_level() const
Definition ov-base.h:939
void indent(std::ostream &os) const
Definition ov-base.cc:1358
void newline(std::ostream &os) const
Definition ov-base.cc:1377
virtual octave_value map(unary_mapper_t) const
Definition ov-base.cc:1170
octave::refcount< octave_idx_type > m_count
Definition ov-base.h:958
void warn_load(const char *type) const
Definition ov-base.cc:1152
virtual bool is_magic_colon() const
Definition ov-base.h:477
void decrement_indent_level() const
Definition ov-base.h:942
bool isempty() const
Definition ov-base.h:429
friend class octave_value
Definition ov-base.h:278
void warn_save(const char *type) const
Definition ov-base.cc:1161
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition ov-cell.cc:222
void short_disp(std::ostream &os) const
Definition ov-cell.cc:697
bool is_true() const
Definition ov-cell.cc:523
octave_value map(unary_mapper_t umap) const
Definition ov-cell.cc:1416
std::size_t byte_size() const
Definition ov-cell.cc:430
sortmode is_sorted_rows(sortmode mode=UNSORTED) const
Definition ov-cell.cc:508
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition ov-cell.cc:615
bool print_as_scalar() const
Definition ov-cell.cc:609
octave_value sort(octave_idx_type dim=0, sortmode mode=ASCENDING) const
Definition ov-cell.cc:441
const void * mex_get_data() const
Definition ov-cell.cc:962
Array< std::string > cellstr_value() const
Definition ov-cell.cc:597
bool save_binary(std::ostream &os, bool save_as_floats)
Definition ov-cell.cc:861
bool print_name_tag(std::ostream &os, const std::string &name) const
Definition ov-cell.cc:678
bool save_ascii(std::ostream &os)
Definition ov-cell.cc:708
std::string type_name() const
Definition ov-cell.h:194
Cell cell_value() const
Definition ov-cell.h:138
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition ov-cell.cc:1075
octave_value_list simple_subsref(char type, octave_value_list &idx, int nargout)
Definition ov-cell.cc:75
void break_closure_cycles(const std::shared_ptr< octave::stack_frame > &frame)
Definition ov-cell.cc:68
void delete_elements(const octave_value_list &idx)
Definition ov-cell.cc:423
bool load_ascii(std::istream &is)
Definition ov-cell.cc:762
string_vector string_vector_value(bool pad=false) const
Definition ov-cell.cc:535
Array< octave_idx_type > sort_rows_idx(sortmode mode=ASCENDING) const
Definition ov-cell.cc:493
void assign(const octave_value_list &idx, const Cell &rhs)
Definition ov-cell.cc:409
bool iscellstr() const
Definition ov-cell.cc:392
sortmode issorted(sortmode mode=UNSORTED) const
Definition ov-cell.cc:478
mxArray * as_mxArray(bool interleaved) const
Definition ov-cell.cc:1399
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition ov-cell.h:75
octave_value_list list_value() const
Definition ov-cell.cc:529
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition ov-cell.cc:621
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition ov-cell.cc:969
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition ov-cell.cc:894
octave_cell()
Definition ov-cell.h:55
octave_idx_type nfields() const
Definition oct-map.h:323
dim_vector dims() const
Definition oct-map.h:409
const Cell & contents(const_iterator p) const
Definition oct-map.h:310
octave_idx_type numel() const
Definition oct-map.h:368
bool all_scalars() const
Definition ovl.cc:188
bool empty() const
Definition ovl.h:113
octave_idx_type length() const
Definition ovl.h:111
octave_value_list list_value() const
Cell cell_value() const
void print_with_name(std::ostream &os, const std::string &name) const
Definition ov.h:1343
void make_unique()
Definition ov.h:350
static octave_value empty_conv(const std::string &type, const octave_value &rhs=octave_value())
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, std::size_t skip=1)
bool is_defined() const
Definition ov.h:590
octave_value storable_value() const
bool is_zero_by_zero() const
Definition ov.h:554
bool iscell() const
Definition ov.h:602
bool isnull() const
Definition ov.h:677
octave_idx_type length() const
bool is_cs_list() const
Definition ov.h:668
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
octave_idx_type max_length() const
Definition str-vec.h:77
bool isempty() const
Definition str-vec.h:100
octave_idx_type numel() const
Definition str-vec.h:98
const octave_hdf5_id octave_H5P_DEFAULT
const octave_hdf5_id octave_H5S_ALL
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
Definition defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition defun.h:56
void error(const char *fmt,...)
Definition error.cc:1008
void err_indexed_cs_list()
Definition errwarn.cc:65
void err_nonbraced_cs_list_assignment()
Definition errwarn.cc:89
int save_hdf5_empty(octave_hdf5_id loc_id, const char *name, const dim_vector &d)
Definition ls-hdf5.cc:1255
int load_hdf5_empty(octave_hdf5_id loc_id, const char *name, dim_vector &d)
Definition ls-hdf5.cc:1312
bool add_hdf5_data(octave_hdf5_id loc_id, const octave_value &tc_in, const std::string &name, const std::string &doc, bool mark_global, bool save_as_floats)
Definition ls-hdf5.cc:1412
octave_hdf5_err hdf5_h5g_iterate(octave_hdf5_id loc_id, const char *name, int *idx, void *operator_data)
Definition ls-hdf5.cc:1065
std::string read_binary_data(std::istream &is, bool swap, octave::mach_info::float_format fmt, const std::string &filename, bool &global, octave_value &tc, std::string &doc)
bool save_binary_data(std::ostream &os, const octave_value &tc_in, const std::string &name, const std::string &doc, bool mark_global, bool save_as_floats)
std::string read_text_data(std::istream &is, const std::string &filename, bool &global, octave_value &tc, octave_idx_type count, const bool do_name_validation)
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
bool save_text_data(std::ostream &os, const octave_value &val_arg, const std::string &name, bool mark_global, int precision)
#define CELL_ELT_TAG
Definition ls-oct-text.h:42
bool is_true(const std::string &s)
int64_t octave_hdf5_id
#define H5T_NATIVE_IDX
Definition oct-hdf5.h:42
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition oct-locbuf.h:44
sortmode
Definition oct-sort.h:97
@ UNSORTED
Definition oct-sort.h:97
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition ov-base.h:246
octave_value_list Fiscellstr(const octave_value_list &args, int)
Definition ov-cell.cc:1275
#define FORWARD_MAPPER(UMAP)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition ovl.h:217
bool Vprint_empty_dimensions
Definition pr-output.cc:71
octave_value tc
Definition ls-hdf5.h:121
void get_dimensions(const octave_value &a, const char *warn_for, dim_vector &dim)
Definition utils.cc:1377
void check_dimensions(dim_vector &dim, const char *warnfor)
Definition utils.cc:1358