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