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