Mercurial > octave-nkf
annotate src/DLD-FUNCTIONS/cellfun.cc @ 8347:fa78cb8d8a5c
corrections for typos
Here is a patch with some corrections for typos and missing/extra
words in the manual.
changeset: 8347:34fd1d1c2294
user: Brian Gough <bjg@gnu.org>
date: Wed Nov 26 11:00:15 2008 -0500
summary: [docs] can not => cannot
author | Brian Gough<bjg@network-theory.co.uk> |
---|---|
date | Thu, 27 Nov 2008 10:28:24 +0100 |
parents | 6f2d95255911 |
children | 63fe023d7898 |
rev | line source |
---|---|
5205 | 1 /* |
2 | |
7017 | 3 Copyright (C) 2005, 2006, 2007 Mohamed Kamoun |
5205 | 4 |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
7016 | 9 Free Software Foundation; either version 3 of the License, or (at your |
10 option) any later version. | |
5205 | 11 |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
7016 | 18 along with Octave; see the file COPYING. If not, see |
19 <http://www.gnu.org/licenses/>. | |
5205 | 20 |
21 */ | |
22 | |
23 #ifdef HAVE_CONFIG_H | |
24 #include <config.h> | |
25 #endif | |
26 | |
27 #include <string> | |
5988 | 28 #include <vector> |
29 #include <list> | |
5205 | 30 |
31 #include "lo-mappers.h" | |
32 | |
33 #include "Cell.h" | |
5988 | 34 #include "oct-map.h" |
5205 | 35 #include "defun-dld.h" |
36 #include "parse.h" | |
37 #include "variables.h" | |
5451 | 38 #include "ov-colon.h" |
5988 | 39 #include "unwind-prot.h" |
5205 | 40 |
5988 | 41 DEFUN_DLD (cellfun, args, nargout, |
5205 | 42 " -*- texinfo -*-\n\ |
6854 | 43 @deftypefn {Loadable Function} {} cellfun (@var{name}, @var{c})\n\ |
44 @deftypefnx {Loadable Function} {} cellfun (\"size\", @var{c}, @var{k})\n\ | |
45 @deftypefnx {Loadable Function} {} cellfun (\"isclass\", @var{c}, @var{class})\n\ | |
46 @deftypefnx {Loadable Function} {} cellfun (@var{func}, @var{c})\n\ | |
47 @deftypefnx {Loadable Function} {} cellfun (@var{func}, @var{c}, @var{d})\n\ | |
48 @deftypefnx {Loadable Function} {[@var{a}, @var{b}] =} cellfun (@dots{})\n\ | |
49 @deftypefnx {Loadable Function} {} cellfun (@dots{}, 'ErrorHandler', @var{errfunc})\n\ | |
50 @deftypefnx {Loadable Function} {} cellfun (@dots{}, 'UniformOutput', @var{val})\n\ | |
5205 | 51 \n\ |
52 Evaluate the function named @var{name} on the elements of the cell array\n\ | |
5543 | 53 @var{c}. Elements in @var{c} are passed on to the named function\n\ |
5205 | 54 individually. The function @var{name} can be one of the functions\n\ |
55 \n\ | |
56 @table @code\n\ | |
57 @item isempty\n\ | |
5543 | 58 Return 1 for empty elements.\n\ |
5205 | 59 @item islogical\n\ |
60 Return 1 for logical elements.\n\ | |
61 @item isreal\n\ | |
62 Return 1 for real elements.\n\ | |
63 @item length\n\ | |
64 Return a vector of the lengths of cell elements.\n\ | |
5543 | 65 @item ndims\n\ |
5205 | 66 Return the number of dimensions of each element.\n\ |
67 @item prodofsize\n\ | |
68 Return the product of dimensions of each element.\n\ | |
69 @item size\n\ | |
70 Return the size along the @var{k}-th dimension.\n\ | |
71 @item isclass\n\ | |
72 Return 1 for elements of @var{class}.\n\ | |
73 @end table\n\ | |
74 \n\ | |
75 Additionally, @code{cellfun} accepts an arbitrary function @var{func}\n\ | |
76 in the form of an inline function, function handle, or the name of a\n\ | |
5988 | 77 function (in a character string). In the case of a character string\n\ |
78 argument, the function must accept a single argument named @var{x}, and\n\ | |
79 it must return a string value. The function can take one or more arguments,\n\ | |
80 with the inputs args given by @var{c}, @var{d}, etc. Equally the function\n\ | |
81 can return one or more output arguments. For example\n\ | |
5205 | 82 \n\ |
83 @example\n\ | |
84 @group\n\ | |
5988 | 85 cellfun (@@atan2, @{1, 0@}, @{0, 1@})\n\ |
86 @result{}ans = [1.57080 0.00000]\n\ | |
87 @end group\n\ | |
88 @end example\n\ | |
89 \n\ | |
90 Note that the default output argument is an array of the same size as the\n\ | |
91 input arguments.\n\ | |
92 \n\ | |
93 If the param 'UniformOutput' is set to true (the default), then the function\n\ | |
8347
fa78cb8d8a5c
corrections for typos
Brian Gough<bjg@network-theory.co.uk>
parents:
8286
diff
changeset
|
94 must return a single element which will be concatenated into the\n\ |
fa78cb8d8a5c
corrections for typos
Brian Gough<bjg@network-theory.co.uk>
parents:
8286
diff
changeset
|
95 return value. If 'UniformOutput' is false, the outputs are concatenated in\n\ |
5988 | 96 a cell array. For example\n\ |
97 \n\ | |
98 @example\n\ | |
99 @group\n\ | |
6623 | 100 cellfun (\"tolower(x)\", @{\"Foo\", \"Bar\", \"FooBar\"@},\n\ |
101 \"UniformOutput\",false)\n\ | |
5205 | 102 @result{} ans = @{\"foo\", \"bar\", \"foobar\"@}\n\ |
103 @end group\n\ | |
104 @end example\n\ | |
5988 | 105 \n\ |
106 Given the parameter 'ErrorHandler', then @var{errfunc} defines a function to\n\ | |
107 call in case @var{func} generates an error. The form of the function is\n\ | |
108 \n\ | |
109 @example\n\ | |
110 function [@dots{}] = errfunc (@var{s}, @dots{})\n\ | |
111 @end example\n\ | |
112 \n\ | |
113 where there is an additional input argument to @var{errfunc} relative to\n\ | |
114 @var{func}, given by @var{s}. This is a structure with the elements\n\ | |
115 'identifier', 'message' and 'index', giving respectively the error\n\ | |
116 identifier, the error message, and the index into the input arguments\n\ | |
117 of the element that caused the error. For example\n\ | |
118 \n\ | |
119 @example\n\ | |
120 @group\n\ | |
121 function y = foo (s, x), y = NaN; endfunction\n\ | |
122 cellfun (@@factorial, @{-1,2@},'ErrorHandler',@@foo)\n\ | |
123 @result{} ans = [NaN 2]\n\ | |
124 @end group\n\ | |
125 @end example\n\ | |
126 \n\ | |
8286
6f2d95255911
fix @seealso references to point to existing anchors
Thorsten Meyer <thorsten.meyier@gmx.de>
parents:
8096
diff
changeset
|
127 @seealso{isempty, islogical, isreal, length, ndims, numel, size}\n\ |
5642 | 128 @end deftypefn") |
5205 | 129 { |
5988 | 130 octave_value_list retval; |
5205 | 131 std::string name = "function"; |
132 octave_function *func = 0; | |
133 int nargin = args.length (); | |
5988 | 134 nargout = (nargout < 1 ? 1 : nargout); |
5205 | 135 |
136 if (nargin < 2) | |
137 { | |
138 error ("cellfun: you must supply at least 2 arguments"); | |
5823 | 139 print_usage (); |
5205 | 140 return retval; |
141 } | |
142 | |
143 if (args(0).is_function_handle () || args(0).is_inline_function ()) | |
144 { | |
145 func = args(0).function_value (); | |
146 | |
147 if (error_state) | |
148 return retval; | |
149 } | |
150 else if (args(0).is_string ()) | |
151 name = args(0).string_value (); | |
152 else | |
153 { | |
5543 | 154 error ("cellfun: first argument must be a string or function handle"); |
5205 | 155 return retval; |
156 } | |
157 | |
158 if (! args(1).is_cell ()) | |
159 { | |
5543 | 160 error ("cellfun: second argument must be a cell array"); |
5205 | 161 |
162 return retval; | |
163 } | |
164 | |
165 Cell f_args = args(1).cell_value (); | |
166 | |
5988 | 167 octave_idx_type k = f_args.numel (); |
5205 | 168 |
169 if (name == "isempty") | |
170 { | |
171 boolNDArray result (f_args.dims ()); | |
5988 | 172 for (octave_idx_type count = 0; count < k ; count++) |
5543 | 173 result(count) = f_args.elem(count).is_empty (); |
5988 | 174 retval(0) = result; |
5205 | 175 } |
176 else if (name == "islogical") | |
177 { | |
178 boolNDArray result (f_args.dims ()); | |
5988 | 179 for (octave_idx_type count= 0; count < k ; count++) |
5205 | 180 result(count) = f_args.elem(count).is_bool_type (); |
5988 | 181 retval(0) = result; |
5205 | 182 } |
183 else if (name == "isreal") | |
184 { | |
185 boolNDArray result (f_args.dims ()); | |
5988 | 186 for (octave_idx_type count= 0; count < k ; count++) |
5205 | 187 result(count) = f_args.elem(count).is_real_type (); |
5988 | 188 retval(0) = result; |
5205 | 189 } |
190 else if (name == "length") | |
191 { | |
192 NDArray result (f_args.dims ()); | |
5988 | 193 for (octave_idx_type count= 0; count < k ; count++) |
5544 | 194 result(count) = static_cast<double> (f_args.elem(count).length ()); |
5988 | 195 retval(0) = result; |
5205 | 196 } |
197 else if (name == "ndims") | |
198 { | |
199 NDArray result (f_args.dims ()); | |
5988 | 200 for (octave_idx_type count = 0; count < k ; count++) |
5544 | 201 result(count) = static_cast<double> (f_args.elem(count).ndims ()); |
5988 | 202 retval(0) = result; |
5205 | 203 } |
204 else if (name == "prodofsize") | |
205 { | |
206 NDArray result (f_args.dims ()); | |
5988 | 207 for (octave_idx_type count = 0; count < k ; count++) |
5544 | 208 result(count) = static_cast<double> (f_args.elem(count).numel ()); |
5988 | 209 retval(0) = result; |
5205 | 210 } |
211 else if (name == "size") | |
212 { | |
213 if (nargin == 3) | |
214 { | |
215 int d = args(2).nint_value () - 1; | |
216 | |
217 if (d < 0) | |
7001 | 218 error ("cellfun: third argument must be a positive integer"); |
5205 | 219 |
6484 | 220 if (! error_state) |
5205 | 221 { |
222 NDArray result (f_args.dims ()); | |
5988 | 223 for (octave_idx_type count = 0; count < k ; count++) |
5205 | 224 { |
225 dim_vector dv = f_args.elem(count).dims (); | |
226 if (d < dv.length ()) | |
5544 | 227 result(count) = static_cast<double> (dv(d)); |
5205 | 228 else |
229 result(count) = 1.0; | |
230 } | |
5988 | 231 retval(0) = result; |
5205 | 232 } |
233 } | |
234 else | |
5543 | 235 error ("not enough arguments for `size'"); |
5205 | 236 } |
237 else if (name == "isclass") | |
238 { | |
239 if (nargin == 3) | |
240 { | |
241 std::string class_name = args(2).string_value(); | |
242 boolNDArray result (f_args.dims ()); | |
5988 | 243 for (octave_idx_type count = 0; count < k ; count++) |
5205 | 244 result(count) = (f_args.elem(count).class_name() == class_name); |
245 | |
5988 | 246 retval(0) = result; |
5205 | 247 } |
248 else | |
5543 | 249 error ("not enough arguments for `isclass'"); |
5205 | 250 } |
251 else | |
252 { | |
5988 | 253 unwind_protect::begin_frame ("Fcellfun"); |
254 unwind_protect_int (buffer_error_messages); | |
255 | |
5205 | 256 std::string fcn_name; |
257 | |
258 if (! func) | |
259 { | |
260 fcn_name = unique_symbol_name ("__cellfun_fcn_"); | |
261 std::string fname = "function y = "; | |
262 fname.append (fcn_name); | |
263 fname.append ("(x) y = "); | |
264 func = extract_function (args(0), "cellfun", fcn_name, fname, | |
265 "; endfunction"); | |
266 } | |
267 | |
268 if (! func) | |
269 error ("unknown function"); | |
270 else | |
271 { | |
5988 | 272 octave_value_list idx; |
273 octave_value_list inputlist; | |
6484 | 274 bool uniform_output = true; |
275 bool have_error_handler = false; | |
5988 | 276 std::string err_name; |
6484 | 277 octave_function *error_handler = 0; |
5988 | 278 int offset = 1; |
279 int i = 1; | |
280 OCTAVE_LOCAL_BUFFER (Cell, inputs, nargin); | |
5205 | 281 |
5988 | 282 while (i < nargin) |
5205 | 283 { |
5988 | 284 if (args(i).is_string()) |
285 { | |
286 std::string arg = args(i++).string_value(); | |
287 if (i == nargin) | |
288 { | |
289 error ("cellfun: parameter value is missing"); | |
290 goto cellfun_err; | |
291 } | |
292 | |
293 std::transform (arg.begin (), arg.end (), | |
294 arg.begin (), tolower); | |
295 | |
296 if (arg == "uniformoutput") | |
6484 | 297 uniform_output = args(i++).bool_value(); |
5988 | 298 else if (arg == "errorhandler") |
299 { | |
300 if (args(i).is_function_handle () || | |
301 args(i).is_inline_function ()) | |
302 { | |
6484 | 303 error_handler = args(i).function_value (); |
5205 | 304 |
5988 | 305 if (error_state) |
306 goto cellfun_err; | |
307 } | |
308 else if (args(i).is_string ()) | |
309 { | |
310 err_name = unique_symbol_name ("__cellfun_fcn_"); | |
311 std::string fname = "function y = "; | |
312 fname.append (fcn_name); | |
313 fname.append ("(x) y = "); | |
6484 | 314 error_handler = extract_function (args(i), "cellfun", |
315 err_name, fname, | |
316 "; endfunction"); | |
5988 | 317 } |
318 | |
6484 | 319 if (! error_handler) |
5988 | 320 goto cellfun_err; |
321 | |
6484 | 322 have_error_handler = true; |
5988 | 323 i++; |
324 } | |
325 else | |
326 { | |
327 error ("cellfun: unrecognized parameter %s", | |
328 arg.c_str()); | |
329 goto cellfun_err; | |
330 } | |
331 offset += 2; | |
332 } | |
333 else | |
334 { | |
335 inputs[i-offset] = args(i).cell_value (); | |
336 if (f_args.dims() != inputs[i-offset].dims()) | |
337 { | |
338 error ("cellfun: Dimension mismatch"); | |
339 goto cellfun_err; | |
340 | |
341 } | |
342 i++; | |
343 } | |
5205 | 344 } |
345 | |
5988 | 346 inputlist.resize(nargin-offset); |
347 | |
6484 | 348 if (have_error_handler) |
5988 | 349 buffer_error_messages++; |
350 | |
6484 | 351 if (uniform_output) |
5988 | 352 { |
353 retval.resize(nargout); | |
354 | |
355 for (octave_idx_type count = 0; count < k ; count++) | |
356 { | |
5989 | 357 for (int j = 0; j < nargin-offset; j++) |
358 inputlist(j) = inputs[j](count); | |
5988 | 359 |
360 octave_value_list tmp = feval (func, inputlist, nargout); | |
361 | |
6484 | 362 if (error_state && have_error_handler) |
5988 | 363 { |
364 Octave_map msg; | |
7977
065c28e1c368
Modify Fcellfun to directly access the error message/id rather than use a call to Flasterr
David Bateman <dbateman@free.fr>
parents:
7038
diff
changeset
|
365 msg.assign ("identifier", last_error_id ()); |
065c28e1c368
Modify Fcellfun to directly access the error message/id rather than use a call to Flasterr
David Bateman <dbateman@free.fr>
parents:
7038
diff
changeset
|
366 msg.assign ("message", last_error_message ()); |
065c28e1c368
Modify Fcellfun to directly access the error message/id rather than use a call to Flasterr
David Bateman <dbateman@free.fr>
parents:
7038
diff
changeset
|
367 msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1)))); |
5988 | 368 octave_value_list errlist = inputlist; |
369 errlist.prepend (msg); | |
370 buffer_error_messages--; | |
371 error_state = 0; | |
6484 | 372 tmp = feval (error_handler, errlist, nargout); |
5988 | 373 buffer_error_messages++; |
374 | |
375 if (error_state) | |
376 goto cellfun_err; | |
377 } | |
378 | |
379 if (tmp.length() < nargout) | |
380 { | |
381 error ("cellfun: too many output arguments"); | |
382 goto cellfun_err; | |
383 } | |
384 | |
385 if (error_state) | |
386 break; | |
387 | |
388 if (count == 0) | |
389 { | |
5989 | 390 for (int j = 0; j < nargout; j++) |
5988 | 391 { |
392 octave_value val; | |
5989 | 393 val = tmp(j); |
5988 | 394 |
395 if (error_state) | |
396 goto cellfun_err; | |
397 | |
6422 | 398 retval(j) = val.resize(f_args.dims()); |
5988 | 399 } |
400 } | |
401 else | |
402 { | |
403 idx(0) = octave_value (static_cast<double>(count+1)); | |
5989 | 404 for (int j = 0; j < nargout; j++) |
405 { | |
406 // FIXME -- need an easier way to express | |
407 // this test. | |
408 octave_value val = tmp(j); | |
409 | |
410 if (val.ndims () == 2 | |
411 && val.rows () == 1 && val.columns () == 1) | |
412 retval(j) = | |
413 retval(j).subsasgn ("(", | |
414 std::list<octave_value_list> | |
415 (1, idx(0)), val); | |
416 else | |
417 error ("cellfun: expecting all values to be scalars for UniformOutput = true"); | |
418 } | |
5988 | 419 } |
420 | |
421 if (error_state) | |
422 break; | |
423 } | |
424 } | |
425 else | |
426 { | |
427 OCTAVE_LOCAL_BUFFER (Cell, results, nargout); | |
5989 | 428 for (int j = 0; j < nargout; j++) |
429 results[j].resize(f_args.dims()); | |
5988 | 430 |
431 for (octave_idx_type count = 0; count < k ; count++) | |
432 { | |
5989 | 433 for (int j = 0; j < nargin-offset; j++) |
434 inputlist(j) = inputs[j](count); | |
5988 | 435 |
436 octave_value_list tmp = feval (func, inputlist, nargout); | |
437 | |
6484 | 438 if (error_state && have_error_handler) |
5988 | 439 { |
440 Octave_map msg; | |
7977
065c28e1c368
Modify Fcellfun to directly access the error message/id rather than use a call to Flasterr
David Bateman <dbateman@free.fr>
parents:
7038
diff
changeset
|
441 msg.assign ("identifier", last_error_id ()); |
065c28e1c368
Modify Fcellfun to directly access the error message/id rather than use a call to Flasterr
David Bateman <dbateman@free.fr>
parents:
7038
diff
changeset
|
442 msg.assign ("message", last_error_message ()); |
065c28e1c368
Modify Fcellfun to directly access the error message/id rather than use a call to Flasterr
David Bateman <dbateman@free.fr>
parents:
7038
diff
changeset
|
443 msg.assign ("index", octave_value(double (count + static_cast<octave_idx_type>(1)))); |
5988 | 444 octave_value_list errlist = inputlist; |
445 errlist.prepend (msg); | |
446 buffer_error_messages--; | |
447 error_state = 0; | |
6484 | 448 tmp = feval (error_handler, errlist, nargout); |
5988 | 449 buffer_error_messages++; |
450 | |
451 if (error_state) | |
452 goto cellfun_err; | |
453 } | |
454 | |
455 if (tmp.length() < nargout) | |
456 { | |
457 error ("cellfun: too many output arguments"); | |
458 goto cellfun_err; | |
459 } | |
460 | |
461 if (error_state) | |
462 break; | |
463 | |
464 | |
5989 | 465 for (int j = 0; j < nargout; j++) |
466 results[j](count) = tmp(j); | |
5988 | 467 } |
468 | |
469 retval.resize(nargout); | |
5989 | 470 for (int j = 0; j < nargout; j++) |
471 retval(j) = results[j]; | |
5988 | 472 } |
473 | |
474 cellfun_err: | |
475 if (error_state) | |
476 retval = octave_value_list(); | |
5205 | 477 |
478 if (! fcn_name.empty ()) | |
479 clear_function (fcn_name); | |
5988 | 480 |
481 if (! err_name.empty ()) | |
482 clear_function (err_name); | |
5205 | 483 } |
5988 | 484 |
485 unwind_protect::run_frame ("Fcellfun"); | |
5205 | 486 } |
487 | |
488 return retval; | |
489 } | |
490 | |
5988 | 491 /* |
492 | |
493 %!error(cellfun(1)) | |
494 %!error(cellfun('isclass',1)) | |
495 %!error(cellfun('size',1)) | |
496 %!error(cellfun(@sin,{[]},'BadParam',false)) | |
497 %!error(cellfun(@sin,{[]},'UniformOuput')) | |
498 %!error(cellfun(@sin,{[]},'ErrorHandler')) | |
499 %!assert(cellfun(@sin,{0,1}),sin([0,1])) | |
500 %!assert(cellfun(inline('sin(x)'),{0,1}),sin([0,1])) | |
501 %!assert(cellfun('sin',{0,1}),sin([0,1])) | |
502 %!assert(cellfun('isempty',{1,[]}),[false,true]) | |
503 %!assert(cellfun('islogical',{false,pi}),[true,false]) | |
504 %!assert(cellfun('isreal',{1i,1}),[false,true]) | |
505 %!assert(cellfun('length',{zeros(2,2),1}),[2,1]) | |
506 %!assert(cellfun('prodofsize',{zeros(2,2),1}),[4,1]) | |
507 %!assert(cellfun('ndims',{zeros([2,2,2]),1}),[3,2]) | |
508 %!assert(cellfun('isclass',{zeros([2,2,2]),'test'},'double'),[true,false]) | |
509 %!assert(cellfun('size',{zeros([1,2,3]),1},1),[1,1]) | |
510 %!assert(cellfun('size',{zeros([1,2,3]),1},2),[2,1]) | |
511 %!assert(cellfun('size',{zeros([1,2,3]),1},3),[3,1]) | |
512 %!assert(cellfun(@atan2,{1,1},{1,2}),[atan2(1,1),atan2(1,2)]) | |
513 %!assert(cellfun(@atan2,{1,1},{1,2},'UniformOutput',false),{atan2(1,1),atan2(1,2)}) | |
6422 | 514 %!assert(cellfun(@sin,{1,2;3,4}),sin([1,2;3,4])) |
515 %!assert(cellfun(@atan2,{1,1;1,1},{1,2;1,2}),atan2([1,1;1,1],[1,2;1,2])) | |
5988 | 516 %!error(cellfun(@factorial,{-1,3})) |
517 %!assert(cellfun(@factorial,{-1,3},'ErrorHandler',@(x,y) NaN),[NaN,6]) | |
518 %!test | |
6704 | 519 %! [a,b,c]=cellfun(@fileparts,{fullfile("a","b","c.d"),fullfile("e","f","g.h")},'UniformOutput',false); |
520 %! assert(a,{fullfile("a","b"),fullfile("e","f")}) | |
5988 | 521 %! assert(b,{'c','g'}) |
522 %! assert(c,{'.d','.h'}) | |
523 | |
524 */ | |
525 | |
5451 | 526 DEFUN_DLD (num2cell, args, , |
527 "-*- texinfo -*-\n\ | |
528 @deftypefn {Loadable Function} {@var{c} =} num2cell (@var{m})\n\ | |
8095
d94a597c94a2
Typo in num2cell's description
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7977
diff
changeset
|
529 @deftypefnx {Loadable Function} {@var{c} =} num2cell (@var{m}, @var{dim})\n\ |
8096 | 530 Convert the matrix @var{m} into a cell array. If @var{dim} is defined, the\n\ |
5451 | 531 value @var{c} is of dimension 1 in this dimension and the elements of\n\ |
532 @var{m} are placed in slices in @var{c}.\n\ | |
5642 | 533 @seealso{mat2cell}\n\ |
534 @end deftypefn") | |
5451 | 535 { |
536 int nargin = args.length(); | |
537 octave_value retval; | |
538 | |
539 if (nargin < 1 || nargin > 2) | |
5823 | 540 print_usage (); |
5451 | 541 else |
542 { | |
543 dim_vector dv = args(0).dims (); | |
544 Array<int> sings; | |
545 | |
546 if (nargin == 2) | |
547 { | |
548 ColumnVector dsings = ColumnVector (args(1).vector_value | |
549 (false, true)); | |
550 sings.resize (dsings.length()); | |
551 | |
552 if (!error_state) | |
5988 | 553 for (octave_idx_type i = 0; i < dsings.length(); i++) |
5451 | 554 if (dsings(i) > dv.length() || dsings(i) < 1 || |
555 D_NINT(dsings(i)) != dsings(i)) | |
556 { | |
557 error ("invalid dimension specified"); | |
558 break; | |
559 } | |
560 else | |
561 sings(i) = NINT(dsings(i)) - 1; | |
562 } | |
563 | |
564 if (! error_state) | |
565 { | |
566 Array<bool> idx_colon (dv.length()); | |
567 dim_vector new_dv (dv); | |
568 octave_value_list lst (new_dv.length(), octave_value()); | |
569 | |
570 for (int i = 0; i < dv.length(); i++) | |
571 { | |
572 idx_colon(i) = false; | |
573 for (int j = 0; j < sings.length(); j++) | |
574 { | |
575 if (sings(j) == i) | |
576 { | |
577 new_dv(i) = 1; | |
578 idx_colon(i) = true; | |
579 lst(i) = octave_value (octave_value::magic_colon_t); | |
580 break; | |
581 } | |
582 } | |
583 } | |
584 | |
585 Cell ret (new_dv); | |
586 octave_idx_type nel = new_dv.numel(); | |
587 octave_idx_type ntot = 1; | |
588 | |
589 for (int j = 0; j < new_dv.length()-1; j++) | |
590 ntot *= new_dv(j); | |
591 | |
592 for (octave_idx_type i = 0; i < nel; i++) | |
593 { | |
594 octave_idx_type n = ntot; | |
595 octave_idx_type ii = i; | |
596 for (int j = new_dv.length() - 1; j >= 0 ; j--) | |
597 { | |
598 if (! idx_colon(j)) | |
599 lst (j) = ii/n + 1; | |
600 ii = ii % n; | |
601 if (j != 0) | |
602 n /= new_dv(j-1); | |
603 } | |
604 ret(i) = args(0).do_index_op(lst, 0); | |
605 } | |
606 | |
607 retval = ret; | |
608 } | |
609 } | |
610 | |
611 return retval; | |
612 } | |
613 | |
5988 | 614 /* |
615 | |
616 %!assert(num2cell([1,2;3,4]),{1,2;3,4}) | |
617 %!assert(num2cell([1,2;3,4],1),{[1;3],[2;4]}) | |
618 %!assert(num2cell([1,2;3,4],2),{[1,2];[3,4]}) | |
619 | |
620 */ | |
621 | |
5784 | 622 DEFUN_DLD (mat2cell, args, , |
623 "-*- texinfo -*-\n\ | |
624 @deftypefn {Loadable Function} {@var{b} =} mat2cell (@var{a}, @var{m}, @var{n})\n\ | |
625 @deftypefnx {Loadable Function} {@var{b} =} mat2cell (@var{a}, @var{d1}, @var{d2}, @dots{})\n\ | |
626 @deftypefnx {Loadable Function} {@var{b} =} mat2cell (@var{a}, @var{r})\n\ | |
8096 | 627 Convert the matrix @var{a} to a cell array. If @var{a} is 2-D, then\n\ |
5784 | 628 it is required that @code{sum (@var{m}) == size (@var{a}, 1)} and\n\ |
629 @code{sum (@var{n}) == size (@var{a}, 2)}. Similarly, if @var{a} is\n\ | |
630 a multi-dimensional and the number of dimensional arguments is equal\n\ | |
631 to the dimensions of @var{a}, then it is required that @code{sum (@var{di})\n\ | |
632 == size (@var{a}, i)}.\n\ | |
633 \n\ | |
634 Given a single dimensional argument @var{r}, the other dimensional\n\ | |
635 arguments are assumed to equal @code{size (@var{a},@var{i})}.\n\ | |
636 \n\ | |
637 An example of the use of mat2cell is\n\ | |
638 \n\ | |
639 @example\n\ | |
640 @group\n\ | |
641 mat2cell (reshape(1:16,4,4),[3,1],[3,1])\n\ | |
642 @result{} @{\n\ | |
643 [1,1] =\n\ | |
644 \n\ | |
645 1 5 9\n\ | |
646 2 6 10\n\ | |
647 3 7 11\n\ | |
648 \n\ | |
649 [2,1] =\n\ | |
650 \n\ | |
651 4 8 12\n\ | |
652 \n\ | |
653 [1,2] =\n\ | |
654 \n\ | |
655 13\n\ | |
656 14\n\ | |
657 15\n\ | |
658 \n\ | |
659 [2,2] = 16\n\ | |
660 @}\n\ | |
661 @end group\n\ | |
662 @end example\n\ | |
5829 | 663 @seealso{num2cell, cell2mat}\n\ |
5784 | 664 @end deftypefn") |
665 { | |
666 int nargin = args.length(); | |
667 octave_value retval; | |
668 | |
669 if (nargin < 2) | |
7038 | 670 print_usage (); |
5784 | 671 else |
672 { | |
673 dim_vector dv = args(0).dims(); | |
674 dim_vector new_dv; | |
675 new_dv.resize(dv.length()); | |
676 | |
677 if (nargin > 2) | |
678 { | |
679 octave_idx_type nmax = -1; | |
680 | |
681 if (nargin - 1 != dv.length()) | |
682 error ("mat2cell: Incorrect number of dimensions"); | |
683 else | |
684 { | |
685 for (octave_idx_type j = 0; j < dv.length(); j++) | |
686 { | |
687 ColumnVector d = ColumnVector (args(j+1).vector_value | |
688 (false, true)); | |
689 | |
690 if (d.length() < 1) | |
691 { | |
692 error ("mat2cell: dimension can not be empty"); | |
693 break; | |
694 } | |
695 else | |
696 { | |
697 if (nmax < d.length()) | |
698 nmax = d.length(); | |
699 | |
700 for (octave_idx_type i = 1; i < d.length(); i++) | |
701 { | |
702 OCTAVE_QUIT; | |
703 | |
704 if (d(i) >= 0) | |
705 d(i) += d(i-1); | |
706 else | |
707 { | |
708 error ("mat2cell: invalid dimensional argument"); | |
709 break; | |
710 } | |
711 } | |
712 | |
713 if (d(0) < 0) | |
714 error ("mat2cell: invalid dimensional argument"); | |
715 | |
716 if (d(d.length() - 1) != dv(j)) | |
717 error ("mat2cell: inconsistent dimensions"); | |
718 | |
719 if (error_state) | |
720 break; | |
721 | |
722 new_dv(j) = d.length(); | |
723 } | |
724 } | |
725 } | |
726 | |
727 if (! error_state) | |
728 { | |
729 // Construct a matrix with the index values | |
730 Matrix dimargs(nmax, new_dv.length()); | |
731 for (octave_idx_type j = 0; j < new_dv.length(); j++) | |
732 { | |
733 OCTAVE_QUIT; | |
734 | |
735 ColumnVector d = ColumnVector (args(j+1).vector_value | |
736 (false, true)); | |
737 | |
738 dimargs(0,j) = d(0); | |
739 for (octave_idx_type i = 1; i < d.length(); i++) | |
740 dimargs(i,j) = dimargs(i-1,j) + d(i); | |
741 } | |
742 | |
743 | |
744 octave_value_list lst (new_dv.length(), octave_value()); | |
745 Cell ret (new_dv); | |
746 octave_idx_type nel = new_dv.numel(); | |
747 octave_idx_type ntot = 1; | |
748 | |
749 for (int j = 0; j < new_dv.length()-1; j++) | |
750 ntot *= new_dv(j); | |
751 | |
752 for (octave_idx_type i = 0; i < nel; i++) | |
753 { | |
754 octave_idx_type n = ntot; | |
755 octave_idx_type ii = i; | |
756 for (octave_idx_type j = new_dv.length() - 1; j >= 0; j--) | |
757 { | |
758 OCTAVE_QUIT; | |
759 | |
760 octave_idx_type idx = ii / n; | |
761 lst (j) = Range((idx == 0 ? 1. : dimargs(idx-1,j)+1.), | |
762 dimargs(idx,j)); | |
763 ii = ii % n; | |
764 if (j != 0) | |
765 n /= new_dv(j-1); | |
766 } | |
767 ret(i) = args(0).do_index_op(lst, 0); | |
768 if (error_state) | |
769 break; | |
770 } | |
771 | |
772 if (!error_state) | |
773 retval = ret; | |
774 } | |
775 } | |
776 else | |
777 { | |
778 ColumnVector d = ColumnVector (args(1).vector_value | |
779 (false, true)); | |
780 | |
781 double sumd = 0.; | |
782 for (octave_idx_type i = 0; i < d.length(); i++) | |
783 { | |
784 OCTAVE_QUIT; | |
785 | |
786 if (d(i) >= 0) | |
787 sumd += d(i); | |
788 else | |
789 { | |
790 error ("mat2cell: invalid dimensional argument"); | |
791 break; | |
792 } | |
793 } | |
794 | |
795 if (sumd != dv(0)) | |
796 error ("mat2cell: inconsistent dimensions"); | |
797 | |
798 new_dv(0) = d.length(); | |
799 for (octave_idx_type i = 1; i < dv.length(); i++) | |
800 new_dv(i) = 1; | |
801 | |
802 if (! error_state) | |
803 { | |
804 octave_value_list lst (new_dv.length(), octave_value()); | |
805 Cell ret (new_dv); | |
806 | |
807 for (octave_idx_type i = 1; i < new_dv.length(); i++) | |
808 lst (i) = Range (1., static_cast<double>(dv(i))); | |
809 | |
810 double idx = 0.; | |
811 for (octave_idx_type i = 0; i < new_dv(0); i++) | |
812 { | |
813 OCTAVE_QUIT; | |
814 | |
815 lst(0) = Range(idx + 1., idx + d(i)); | |
816 ret(i) = args(0).do_index_op(lst, 0); | |
817 idx += d(i); | |
818 if (error_state) | |
819 break; | |
820 } | |
821 | |
822 if (!error_state) | |
823 retval = ret; | |
824 } | |
825 } | |
826 } | |
827 | |
828 return retval; | |
829 } | |
830 | |
831 /* | |
832 | |
833 %!test | |
834 %! x = reshape(1:20,5,4); | |
835 %! c = mat2cell(x,[3,2],[3,1]); | |
836 %! assert(c,{[1,6,11;2,7,12;3,8,13],[16;17;18];[4,9,14;5,10,15],[19;20]}) | |
837 | |
838 %!test | |
839 %! x = 'abcdefghij'; | |
840 %! c = mat2cell(x,1,[0,4,2,0,4,0]); | |
841 %! empty1by0str = resize('',1,0); | |
842 %! assert(c,{empty1by0str,'abcd','ef',empty1by0str,'ghij',empty1by0str}) | |
843 | |
844 */ | |
845 | |
5205 | 846 /* |
847 ;;; Local Variables: *** | |
848 ;;; mode: C++ *** | |
849 ;;; End: *** | |
850 */ |