GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
data.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1994-2015 John W. Eaton
4 Copyright (C) 2009 Jaroslav Hajek
5 Copyright (C) 2009-2010 VZLU Prague
6 Copyright (C) 2012 Carlo de Falco
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 the
12 Free Software Foundation; either version 3 of the License, or (at your
13 option) any later version.
14 
15 Octave is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 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 <http://www.gnu.org/licenses/>.
23 
24 */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #include <sys/types.h>
31 #include <sys/times.h>
32 
33 #ifdef HAVE_SYS_RESOURCE_H
34 #include <sys/resource.h>
35 #endif
36 
37 #include <cfloat>
38 #include <ctime>
39 
40 #include <string>
41 
42 #include "lo-ieee.h"
43 #include "lo-math.h"
44 #include "oct-base64.h"
45 #include "oct-time.h"
46 #include "str-vec.h"
47 #include "quit.h"
48 #include "mx-base.h"
49 #include "oct-binmap.h"
50 
51 #include "Cell.h"
52 #include "defun.h"
53 #include "error.h"
54 #include "gripes.h"
55 #include "oct-map.h"
56 #include "oct-obj.h"
57 #include "ov.h"
58 #include "ov-class.h"
59 #include "ov-float.h"
60 #include "ov-complex.h"
61 #include "ov-flt-complex.h"
62 #include "ov-cx-mat.h"
63 #include "ov-flt-cx-mat.h"
64 #include "ov-cx-sparse.h"
65 #include "parse.h"
66 #include "pt-mat.h"
67 #include "utils.h"
68 #include "variables.h"
69 #include "pager.h"
70 #include "xnorm.h"
71 
72 #if ! defined (CLOCKS_PER_SEC)
73 #if defined (CLK_TCK)
74 #define CLOCKS_PER_SEC CLK_TCK
75 #else
76 #error "no definition for CLOCKS_PER_SEC!"
77 #endif
78 #endif
79 
80 #if ! defined (HAVE_HYPOTF) && defined (HAVE__HYPOTF)
81 #define hypotf _hypotf
82 #define HAVE_HYPOTF 1
83 #endif
84 
85 #define ANY_ALL(FCN) \
86  \
87  octave_value retval; \
88  \
89  int nargin = args.length (); \
90  \
91  if (nargin == 1 || nargin == 2) \
92  { \
93  int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
94  \
95  if (! error_state) \
96  { \
97  if (dim >= -1) \
98  retval = args(0).FCN (dim); \
99  else \
100  error (#FCN ": invalid dimension argument = %d", dim + 1); \
101  } \
102  else \
103  error (#FCN ": expecting dimension argument to be an integer"); \
104  } \
105  else \
106  print_usage (); \
107  \
108  return retval
109 
110 DEFUN (all, args, ,
111  "-*- texinfo -*-\n\
112 @deftypefn {Built-in Function} {} all (@var{x})\n\
113 @deftypefnx {Built-in Function} {} all (@var{x}, @var{dim})\n\
114 For a vector argument, return true (logical 1) if all elements of the vector\n\
115 are nonzero.\n\
116 \n\
117 For a matrix argument, return a row vector of logical ones and\n\
118 zeros with each element indicating whether all of the elements of the\n\
119 corresponding column of the matrix are nonzero. For example:\n\
120 \n\
121 @example\n\
122 @group\n\
123 all ([2, 3; 1, 0])\n\
124  @result{} [ 1, 0 ]\n\
125 @end group\n\
126 @end example\n\
127 \n\
128 If the optional argument @var{dim} is supplied, work along dimension\n\
129 @var{dim}.\n\
130 @seealso{any}\n\
131 @end deftypefn")
132 {
133  ANY_ALL (all);
134 }
135 
136 /*
137 %!test
138 %! x = ones (3);
139 %! x(1,1) = 0;
140 %! assert (all (all (rand (3) + 1) == [1, 1, 1]) == 1);
141 %! assert (all (all (x) == [0, 1, 1]) == 1);
142 %! assert (all (x, 1) == [0, 1, 1]);
143 %! assert (all (x, 2) == [0; 1; 1]);
144 
145 %!test
146 %! x = ones (3, "single");
147 %! x(1,1) = 0;
148 %! assert (all (all (single (rand (3) + 1)) == [1, 1, 1]) == 1);
149 %! assert (all (all (x) == [0, 1, 1]) == 1);
150 %! assert (all (x, 1) == [0, 1, 1]);
151 %! assert (all (x, 2) == [0; 1; 1]);
152 
153 %!error all ()
154 %!error all (1, 2, 3)
155 */
156 
157 DEFUN (any, args, ,
158  "-*- texinfo -*-\n\
159 @deftypefn {Built-in Function} {} any (@var{x})\n\
160 @deftypefnx {Built-in Function} {} any (@var{x}, @var{dim})\n\
161 For a vector argument, return true (logical 1) if any element of the vector\n\
162 is nonzero.\n\
163 \n\
164 For a matrix argument, return a row vector of logical ones and\n\
165 zeros with each element indicating whether any of the elements of the\n\
166 corresponding column of the matrix are nonzero. For example:\n\
167 \n\
168 @example\n\
169 @group\n\
170 any (eye (2, 4))\n\
171  @result{} [ 1, 1, 0, 0 ]\n\
172 @end group\n\
173 @end example\n\
174 \n\
175 If the optional argument @var{dim} is supplied, work along dimension\n\
176 @var{dim}. For example:\n\
177 \n\
178 @example\n\
179 @group\n\
180 any (eye (2, 4), 2)\n\
181  @result{} [ 1; 1 ]\n\
182 @end group\n\
183 @end example\n\
184 @seealso{all}\n\
185 @end deftypefn")
186 {
187  ANY_ALL (any);
188 }
189 
190 /*
191 %!test
192 %! x = zeros (3);
193 %! x(3,3) = 1;
194 %! assert (all (any (x) == [0, 0, 1]) == 1);
195 %! assert (all (any (ones (3)) == [1, 1, 1]) == 1);
196 %! assert (any (x, 1) == [0, 0, 1]);
197 %! assert (any (x, 2) == [0; 0; 1]);
198 
199 %!test
200 %! x = zeros (3, "single");
201 %! x(3,3) = 1;
202 %! assert (all (any (x) == [0, 0, 1]) == 1);
203 %! assert (all (any (ones (3, "single")) == [1, 1, 1]) == 1);
204 %! assert (any (x, 1) == [0, 0, 1]);
205 %! assert (any (x, 2) == [0; 0; 1]);
206 
207 %!error any ()
208 %!error any (1, 2, 3)
209 */
210 
211 // These mapping functions may also be useful in other places, eh?
212 
213 DEFUN (atan2, args, ,
214  "-*- texinfo -*-\n\
215 @deftypefn {Mapping Function} {} atan2 (@var{y}, @var{x})\n\
216 Compute atan (@var{y} / @var{x}) for corresponding elements of @var{y}\n\
217 and @var{x}.\n\
218 \n\
219 @var{y} and @var{x} must match in size and orientation.\n\
220 @seealso{tan, tand, tanh, atanh}\n\
221 @end deftypefn")
222 {
223  octave_value retval;
224 
225  int nargin = args.length ();
226 
227  if (nargin == 2)
228  {
229  if (! args(0).is_numeric_type ())
230  gripe_wrong_type_arg ("atan2", args(0));
231  else if (! args(1).is_numeric_type ())
232  gripe_wrong_type_arg ("atan2", args(1));
233  else if (args(0).is_complex_type () || args(1).is_complex_type ())
234  error ("atan2: not defined for complex numbers");
235  else if (args(0).is_single_type () || args(1).is_single_type ())
236  {
237  if (args(0).is_scalar_type () && args(1).is_scalar_type ())
238  retval = atan2f (args(0).float_value (), args(1).float_value ());
239  else
240  {
241  FloatNDArray a0 = args(0).float_array_value ();
242  FloatNDArray a1 = args(1).float_array_value ();
243  retval = binmap<float> (a0, a1, ::atan2f, "atan2");
244  }
245  }
246  else
247  {
248  if (args(0).is_scalar_type () && args(1).is_scalar_type ())
249  retval = atan2 (args(0).scalar_value (), args(1).scalar_value ());
250  else if (args(0).is_sparse_type ())
251  {
252  SparseMatrix m0 = args(0).sparse_matrix_value ();
253  SparseMatrix m1 = args(1).sparse_matrix_value ();
254  retval = binmap<double> (m0, m1, ::atan2, "atan2");
255  }
256  else
257  {
258  NDArray a0 = args(0).array_value ();
259  NDArray a1 = args(1).array_value ();
260  retval = binmap<double> (a0, a1, ::atan2, "atan2");
261  }
262  }
263  }
264  else
265  print_usage ();
266 
267  return retval;
268 }
269 
270 /*
271 %!assert (size (atan2 (zeros (0, 2), zeros (0, 2))), [0, 2])
272 %!assert (size (atan2 (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
273 %!assert (size (atan2 (rand (2, 3, 4), 1)), [2, 3, 4])
274 %!assert (size (atan2 (1, rand (2, 3, 4))), [2, 3, 4])
275 %!assert (size (atan2 (1, 2)), [1, 1])
276 
277 %!test
278 %! rt2 = sqrt (2);
279 %! rt3 = sqrt (3);
280 %! v = [0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0];
281 %! y = [0, rt3, 1, rt3, -rt3, -1, -rt3, 0];
282 %! x = [1, 3, 1, 1, 1, 1, 3, 1];
283 %! assert (atan2 (y, x), v, sqrt (eps));
284 
285 %!test
286 %! rt2 = sqrt (2);
287 %! rt3 = sqrt (3);
288 %! v = single ([0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0]);
289 %! y = single ([0, rt3, 1, rt3, -rt3, -1, -rt3, 0]);
290 %! x = single ([1, 3, 1, 1, 1, 1, 3, 1]);
291 %! assert (atan2 (y, x), v, sqrt (eps ("single")));
292 
293 ## Test sparse implementations
294 %!shared xs
295 %! xs = sparse (0:3);
296 %!test
297 %! y = atan2 (1, xs);
298 %! assert (issparse (y), false);
299 %! assert (nnz (y), 4);
300 %! assert (y, atan2 (1, 0:3));
301 %!test
302 %! y = atan2 (0, xs);
303 %! assert (issparse (y), false);
304 %! assert (nnz (y), 0);
305 %! assert (y, zeros (1,4));
306 %!test
307 %! y = atan2 (xs, 1);
308 %! assert (issparse (y));
309 %! assert (nnz (y), 3);
310 %! assert (y, sparse (atan2 (0:3, 1)));
311 %!test
312 %! y = atan2 (xs, 0);
313 %! assert (issparse (y));
314 %! assert (nnz (y), 3);
315 %! assert (y, sparse (atan2 (0:3, 0)));
316 %!test
317 %! y = atan2 (xs, sparse (ones (1, 4)));
318 %! assert (issparse (y));
319 %! assert (nnz (y), 3);
320 %! assert (y, sparse (atan2 (0:3, ones (1,4))));
321 %!test
322 %! y = atan2 (xs, sparse (zeros (1,4)));
323 %! assert (issparse (y));
324 %! assert (nnz (y), 3);
325 %! assert (y, sparse (atan2 (0:3, zeros (1,4))));
326 
327 %!error atan2 ()
328 %!error atan2 (1, 2, 3)
329 */
330 
331 
332 static octave_value
334 {
335  octave_value retval;
336 
337  octave_value arg0 = x;
338  octave_value arg1 = y;
339  if (! arg0.is_numeric_type ())
340  gripe_wrong_type_arg ("hypot", arg0);
341  else if (! arg1.is_numeric_type ())
342  gripe_wrong_type_arg ("hypot", arg1);
343  else
344  {
345  if (arg0.is_complex_type ())
346  arg0 = arg0.abs ();
347  if (arg1.is_complex_type ())
348  arg1 = arg1.abs ();
349 
350  if (arg0.is_single_type () || arg1.is_single_type ())
351  {
352  if (arg0.is_scalar_type () && arg1.is_scalar_type ())
353  retval = hypotf (arg0.float_value (), arg1.float_value ());
354  else
355  {
356  FloatNDArray a0 = arg0.float_array_value ();
357  FloatNDArray a1 = arg1.float_array_value ();
358  retval = binmap<float> (a0, a1, ::hypotf, "hypot");
359  }
360  }
361  else
362  {
363  if (arg0.is_scalar_type () && arg1.is_scalar_type ())
364  retval = hypot (arg0.scalar_value (), arg1.scalar_value ());
365  else if (arg0.is_sparse_type () || arg1.is_sparse_type ())
366  {
367  SparseMatrix m0 = arg0.sparse_matrix_value ();
368  SparseMatrix m1 = arg1.sparse_matrix_value ();
369  retval = binmap<double> (m0, m1, ::hypot, "hypot");
370  }
371  else
372  {
373  NDArray a0 = arg0.array_value ();
374  NDArray a1 = arg1.array_value ();
375  retval = binmap<double> (a0, a1, ::hypot, "hypot");
376  }
377  }
378  }
379 
380  return retval;
381 }
382 
383 DEFUN (hypot, args, ,
384  "-*- texinfo -*-\n\
385 @deftypefn {Built-in Function} {} hypot (@var{x}, @var{y})\n\
386 @deftypefnx {Built-in Function} {} hypot (@var{x}, @var{y}, @var{z}, @dots{})\n\
387 Compute the element-by-element square root of the sum of the squares of\n\
388 @var{x} and @var{y}.\n\
389 \n\
390 This is equivalent to\n\
391 @code{sqrt (@var{x}.^2 + @var{y}.^2)}, but is calculated in a manner that\n\
392 avoids overflows for large values of @var{x} or @var{y}.\n\
393 \n\
394 @code{hypot} can also be called with more than 2 arguments; in this case,\n\
395 the arguments are accumulated from left to right:\n\
396 \n\
397 @example\n\
398 @group\n\
399 hypot (hypot (@var{x}, @var{y}), @var{z})\n\
400 hypot (hypot (hypot (@var{x}, @var{y}), @var{z}), @var{w}), etc.\n\
401 @end group\n\
402 @end example\n\
403 @end deftypefn")
404 {
405  octave_value retval;
406 
407  int nargin = args.length ();
408 
409  if (nargin == 2)
410  {
411  retval = do_hypot (args(0), args(1));
412  }
413  else if (nargin >= 3)
414  {
415  retval = args(0);
416  for (int i = 1; i < nargin && ! error_state; i++)
417  retval = do_hypot (retval, args(i));
418  }
419  else
420  print_usage ();
421 
422  return retval;
423 }
424 
425 /*
426 %!assert (size (hypot (zeros (0, 2), zeros (0, 2))), [0, 2])
427 %!assert (size (hypot (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
428 %!assert (size (hypot (rand (2, 3, 4), 1)), [2, 3, 4])
429 %!assert (size (hypot (1, rand (2, 3, 4))), [2, 3, 4])
430 %!assert (size (hypot (1, 2)), [1, 1])
431 %!assert (hypot (1:10, 1:10), sqrt (2) * [1:10], 16*eps)
432 %!assert (hypot (single (1:10), single (1:10)), single (sqrt (2) * [1:10]))
433 
434 ## Test sparse implementations
435 %!shared xs
436 %! xs = sparse (0:3);
437 %!test
438 %! y = hypot (1, xs);
439 %! assert (nnz (y), 4);
440 %! assert (y, sparse (hypot (1, 0:3)));
441 %!test
442 %! y = hypot (0, xs);
443 %! assert (nnz (y), 3);
444 %! assert (y, xs);
445 %!test
446 %! y = hypot (xs, 1);
447 %! assert (nnz (y), 4);
448 %! assert (y, sparse (hypot (0:3, 1)));
449 %!test
450 %! y = hypot (xs, 0);
451 %! assert (nnz (y), 3);
452 %! assert (y, xs);
453 %!test
454 %! y = hypot (sparse ([0 0]), sparse ([0 1]));
455 %! assert (nnz (y), 1);
456 %! assert (y, sparse ([0 1]));
457 %!test
458 %! y = hypot (sparse ([0 1]), sparse ([0 0]));
459 %! assert (nnz (y), 1);
460 %! assert (y, sparse ([0 1]));
461 
462 */
463 
464 template<typename T, typename ET>
465 void
467 {
468  f = Array<T>(x.dims ());
469  e = Array<ET>(x.dims ());
470  for (octave_idx_type i = 0; i < x.numel (); i++)
471  {
472  int exp;
473  f.xelem (i) = xlog2 (x(i), exp);
474  e.xelem (i) = exp;
475  }
476 }
477 
478 DEFUN (log2, args, nargout,
479  "-*- texinfo -*-\n\
480 @deftypefn {Mapping Function} {} log2 (@var{x})\n\
481 @deftypefnx {Mapping Function} {[@var{f}, @var{e}] =} log2 (@var{x})\n\
482 Compute the base-2 logarithm of each element of @var{x}.\n\
483 \n\
484 If called with two output arguments, split @var{x} into\n\
485 binary mantissa and exponent so that\n\
486 @tex\n\
487 ${1 \\over 2} \\le \\left| f \\right| < 1$\n\
488 @end tex\n\
489 @ifnottex\n\
490 @code{1/2 <= abs(f) < 1}\n\
491 @end ifnottex\n\
492 and @var{e} is an integer. If\n\
493 @tex\n\
494 $x = 0$, $f = e = 0$.\n\
495 @end tex\n\
496 @ifnottex\n\
497 @code{x = 0}, @code{f = e = 0}.\n\
498 @end ifnottex\n\
499 @seealso{pow2, log, log10, exp}\n\
500 @end deftypefn")
501 {
502  octave_value_list retval;
503 
504  if (args.length () == 1)
505  {
506  if (nargout < 2)
507  retval(0) = args(0).log2 ();
508  else if (args(0).is_single_type ())
509  {
510  if (args(0).is_real_type ())
511  {
512  FloatNDArray f;
513  FloatNDArray x = args(0).float_array_value ();
514  // FIXME: should E be an int value?
515  FloatMatrix e;
516  map_2_xlog2 (x, f, e);
517  retval(1) = e;
518  retval(0) = f;
519  }
520  else if (args(0).is_complex_type ())
521  {
523  FloatComplexNDArray x = args(0).float_complex_array_value ();
524  // FIXME: should E be an int value?
525  FloatNDArray e;
526  map_2_xlog2 (x, f, e);
527  retval(1) = e;
528  retval(0) = f;
529  }
530  }
531  else if (args(0).is_real_type ())
532  {
533  NDArray f;
534  NDArray x = args(0).array_value ();
535  // FIXME: should E be an int value?
536  Matrix e;
537  map_2_xlog2 (x, f, e);
538  retval(1) = e;
539  retval(0) = f;
540  }
541  else if (args(0).is_complex_type ())
542  {
544  ComplexNDArray x = args(0).complex_array_value ();
545  // FIXME: should E be an int value?
546  NDArray e;
547  map_2_xlog2 (x, f, e);
548  retval(1) = e;
549  retval(0) = f;
550  }
551  else
552  gripe_wrong_type_arg ("log2", args(0));
553  }
554  else
555  print_usage ();
556 
557  return retval;
558 }
559 
560 /*
561 %!assert (log2 ([1/4, 1/2, 1, 2, 4]), [-2, -1, 0, 1, 2])
562 %!assert (log2 (Inf), Inf)
563 %!assert (isnan (log2 (NaN)))
564 %!assert (log2 (4*i), 2 + log2 (1*i))
565 %!assert (log2 (complex (0,Inf)), Inf + log2 (i))
566 
567 %!test
568 %! [f, e] = log2 ([0,-1; 2,-4; Inf,-Inf]);
569 %! assert (f, [0,-0.5; 0.5,-0.5; Inf,-Inf]);
570 %! assert (e(1:2,:), [0,1;2,3]);
571 
572 %!test
573 %! [f, e] = log2 (complex (zeros (3, 2), [0,-1; 2,-4; Inf,-Inf]));
574 %! assert (f, complex (zeros (3, 2), [0,-0.5; 0.5,-0.5; Inf,-Inf]));
575 %! assert (e(1:2,:), [0,1; 2,3]);
576 
577 # bug #42583
578 %!assert (all (log2 (pow2 (-1074:1023)) == -1074:1023))
579 */
580 
581 DEFUN (rem, args, ,
582  "-*- texinfo -*-\n\
583 @deftypefn {Mapping Function} {} rem (@var{x}, @var{y})\n\
584 Return the remainder of the division @code{@var{x} / @var{y}}.\n\
585 \n\
586 The remainder is computed using the expression\n\
587 \n\
588 @example\n\
589 x - y .* fix (x ./ y)\n\
590 @end example\n\
591 \n\
592 An error message is printed if the dimensions of the arguments do not agree,\n\
593 or if either of the arguments is complex.\n\
594 @seealso{mod}\n\
595 @end deftypefn")
596 {
597  octave_value retval;
598 
599  int nargin = args.length ();
600 
601  if (nargin == 2)
602  {
603  if (! args(0).is_numeric_type ())
604  gripe_wrong_type_arg ("rem", args(0));
605  else if (! args(1).is_numeric_type ())
606  gripe_wrong_type_arg ("rem", args(1));
607  else if (args(0).is_complex_type () || args(1).is_complex_type ())
608  error ("rem: not defined for complex numbers");
609  else if (args(0).is_integer_type () || args(1).is_integer_type ())
610  {
611  builtin_type_t btyp0 = args(0).builtin_type ();
612  builtin_type_t btyp1 = args(1).builtin_type ();
613  if (btyp0 == btyp_double || btyp0 == btyp_float)
614  btyp0 = btyp1;
615  if (btyp1 == btyp_double || btyp1 == btyp_float)
616  btyp1 = btyp0;
617 
618  if (btyp0 == btyp1)
619  {
620  switch (btyp0)
621  {
622 #define MAKE_INT_BRANCH(X) \
623  case btyp_ ## X: \
624  { \
625  X##NDArray a0 = args(0).X##_array_value (); \
626  X##NDArray a1 = args(1).X##_array_value (); \
627  retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, rem, "rem"); \
628  } \
629  break;
630  MAKE_INT_BRANCH (int8);
631  MAKE_INT_BRANCH (int16);
632  MAKE_INT_BRANCH (int32);
633  MAKE_INT_BRANCH (int64);
634  MAKE_INT_BRANCH (uint8);
635  MAKE_INT_BRANCH (uint16);
636  MAKE_INT_BRANCH (uint32);
637  MAKE_INT_BRANCH (uint64);
638 #undef MAKE_INT_BRANCH
639  default:
640  panic_impossible ();
641  }
642  }
643  else
644  error ("rem: cannot combine %s and %d",
645  args(0).class_name ().c_str (),
646  args(1).class_name ().c_str ());
647  }
648  else if (args(0).is_single_type () || args(1).is_single_type ())
649  {
650  if (args(0).is_scalar_type () && args(1).is_scalar_type ())
651  retval = xrem (args(0).float_value (), args(1).float_value ());
652  else
653  {
654  FloatNDArray a0 = args(0).float_array_value ();
655  FloatNDArray a1 = args(1).float_array_value ();
656  retval = binmap<float> (a0, a1, xrem<float>, "rem");
657  }
658  }
659  else
660  {
661  if (args(0).is_scalar_type () && args(1).is_scalar_type ())
662  retval = xrem (args(0).scalar_value (), args(1).scalar_value ());
663  else if (args(0).is_sparse_type () || args(1).is_sparse_type ())
664  {
665  SparseMatrix m0 = args(0).sparse_matrix_value ();
666  SparseMatrix m1 = args(1).sparse_matrix_value ();
667  retval = binmap<double> (m0, m1, xrem<double>, "rem");
668  }
669  else
670  {
671  NDArray a0 = args(0).array_value ();
672  NDArray a1 = args(1).array_value ();
673  retval = binmap<double> (a0, a1, xrem<double>, "rem");
674  }
675  }
676  }
677  else
678  print_usage ();
679 
680  return retval;
681 }
682 
683 /*
684 %!assert (size (rem (zeros (0, 2), zeros (0, 2))), [0, 2])
685 %!assert (size (rem (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
686 %!assert (size (rem (rand (2, 3, 4), 1)), [2, 3, 4])
687 %!assert (size (rem (1, rand (2, 3, 4))), [2, 3, 4])
688 %!assert (size (rem (1, 2)), [1, 1])
689 
690 %!assert (rem ([1, 2, 3; -1, -2, -3], 2), [1, 0, 1; -1, 0, -1])
691 %!assert (rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3)),[1, 0, 1; -1, 0, -1])
692 %!assert (rem (uint8 ([1, 2, 3; -1, -2, -3]), uint8 (2)), uint8 ([1, 0, 1; -1, 0, -1]))
693 %!assert (uint8 (rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3))),uint8 ([1, 0, 1; -1, 0, -1]))
694 
695 ## Test sparse implementations
696 %!shared xs
697 %! xs = sparse (0:3);
698 %!test
699 %! y = rem (11, xs);
700 %! assert (nnz (y), 3);
701 %! assert (y, sparse (rem (11, 0:3)));
702 %!test
703 %! y = rem (0, xs);
704 %! assert (nnz (y), 0);
705 %! assert (y, sparse (zeros (1,4)));
706 %!test
707 %! y = rem (xs, 2);
708 %! assert (nnz (y), 2);
709 %! assert (y, sparse (rem (0:3, 2)));
710 %!test
711 %! y = rem (xs, 1);
712 %! assert (nnz (y), 0);
713 %! assert (y, sparse (rem (0:3, 1)));
714 %!test
715 %! y = rem (sparse ([11 11 11 11]), xs);
716 %! assert (nnz (y), 3);
717 %! assert (y, sparse (rem (11, 0:3)));
718 %!test
719 %! y = rem (sparse ([0 0 0 0]), xs);
720 %! assert (nnz (y), 0);
721 %! assert (y, sparse (zeros (1,4)));
722 
723 %!error rem (uint (8), int8 (5))
724 %!error rem (uint8 ([1, 2]), uint8 ([3, 4, 5]))
725 %!error rem ()
726 %!error rem (1, 2, 3)
727 %!error rem ([1, 2], [3, 4, 5])
728 %!error rem (i, 1)
729 
730 # bug 42627
731 %!assert (rem (0.94, 0.01), 0.0);
732 */
733 
734 DEFUN (mod, args, ,
735  "-*- texinfo -*-\n\
736 @deftypefn {Mapping Function} {} mod (@var{x}, @var{y})\n\
737 Compute the modulo of @var{x} and @var{y}.\n\
738 \n\
739 Conceptually this is given by\n\
740 \n\
741 @example\n\
742 x - y .* floor (x ./ y)\n\
743 @end example\n\
744 \n\
745 @noindent\n\
746 and is written such that the correct modulus is returned for integer types.\n\
747 This function handles negative values correctly. That is,\n\
748 @code{mod (-1, 3)} is 2, not -1, as @code{rem (-1, 3)} returns.\n\
749 @code{mod (@var{x}, 0)} returns @var{x}.\n\
750 \n\
751 An error results if the dimensions of the arguments do not agree, or if\n\
752 either of the arguments is complex.\n\
753 @seealso{rem}\n\
754 @end deftypefn")
755 {
756  octave_value retval;
757 
758  int nargin = args.length ();
759 
760  if (nargin == 2)
761  {
762  if (! args(0).is_numeric_type ())
763  gripe_wrong_type_arg ("mod", args(0));
764  else if (! args(1).is_numeric_type ())
765  gripe_wrong_type_arg ("mod", args(1));
766  else if (args(0).is_complex_type () || args(1).is_complex_type ())
767  error ("mod: not defined for complex numbers");
768  else if (args(0).is_integer_type () || args(1).is_integer_type ())
769  {
770  builtin_type_t btyp0 = args(0).builtin_type ();
771  builtin_type_t btyp1 = args(1).builtin_type ();
772  if (btyp0 == btyp_double || btyp0 == btyp_float)
773  btyp0 = btyp1;
774  if (btyp1 == btyp_double || btyp1 == btyp_float)
775  btyp1 = btyp0;
776 
777  if (btyp0 == btyp1)
778  {
779  switch (btyp0)
780  {
781 #define MAKE_INT_BRANCH(X) \
782  case btyp_ ## X: \
783  { \
784  X##NDArray a0 = args(0).X##_array_value (); \
785  X##NDArray a1 = args(1).X##_array_value (); \
786  retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, mod, "mod"); \
787  } \
788  break;
789  MAKE_INT_BRANCH (int8);
790  MAKE_INT_BRANCH (int16);
791  MAKE_INT_BRANCH (int32);
792  MAKE_INT_BRANCH (int64);
793  MAKE_INT_BRANCH (uint8);
794  MAKE_INT_BRANCH (uint16);
795  MAKE_INT_BRANCH (uint32);
796  MAKE_INT_BRANCH (uint64);
797 #undef MAKE_INT_BRANCH
798  default:
799  panic_impossible ();
800  }
801  }
802  else
803  error ("mod: cannot combine %s and %d",
804  args(0).class_name ().c_str (),
805  args(1).class_name ().c_str ());
806  }
807  else if (args(0).is_single_type () || args(1).is_single_type ())
808  {
809  if (args(0).is_scalar_type () && args(1).is_scalar_type ())
810  retval = xmod (args(0).float_value (), args(1).float_value ());
811  else
812  {
813  FloatNDArray a0 = args(0).float_array_value ();
814  FloatNDArray a1 = args(1).float_array_value ();
815  retval = binmap<float> (a0, a1, xmod<float>, "mod");
816  }
817  }
818  else
819  {
820  if (args(0).is_scalar_type () && args(1).is_scalar_type ())
821  retval = xmod (args(0).scalar_value (), args(1).scalar_value ());
822  else if (args(0).is_sparse_type () || args(1).is_sparse_type ())
823  {
824  SparseMatrix m0 = args(0).sparse_matrix_value ();
825  SparseMatrix m1 = args(1).sparse_matrix_value ();
826  retval = binmap<double> (m0, m1, xmod<double>, "mod");
827  }
828  else
829  {
830  NDArray a0 = args(0).array_value ();
831  NDArray a1 = args(1).array_value ();
832  retval = binmap<double> (a0, a1, xmod<double>, "mod");
833  }
834  }
835  }
836  else
837  print_usage ();
838 
839  return retval;
840 }
841 
842 /*
843 ## empty input test
844 %!assert (isempty (mod ([], [])))
845 
846 ## x mod y, y != 0 tests
847 %!assert (mod (5, 3), 2)
848 %!assert (mod (-5, 3), 1)
849 %!assert (mod (0, 3), 0)
850 %!assert (mod ([-5, 5, 0], [3, 3, 3]), [1, 2, 0])
851 %!assert (mod ([-5; 5; 0], [3; 3; 3]), [1; 2; 0])
852 %!assert (mod ([-5, 5; 0, 3], [3, 3 ; 3, 1]), [1, 2 ; 0, 0])
853 
854 ## x mod 0 tests
855 %!assert (mod (5, 0), 5)
856 %!assert (mod (-5, 0), -5)
857 %!assert (mod ([-5, 5, 0], [3, 0, 3]), [1, 5, 0])
858 %!assert (mod ([-5; 5; 0], [3; 0; 3]), [1; 5; 0])
859 %!assert (mod ([-5, 5; 0, 3], [3, 0 ; 3, 1]), [1, 5 ; 0, 0])
860 %!assert (mod ([-5, 5; 0, 3], [0, 0 ; 0, 0]), [-5, 5; 0, 3])
861 
862 ## mixed scalar/matrix tests
863 %!assert (mod ([-5, 5; 0, 3], 0), [-5, 5; 0, 3])
864 %!assert (mod ([-5, 5; 0, 3], 3), [1, 2; 0, 0])
865 %!assert (mod (-5, [0,0; 0,0]), [-5, -5; -5, -5])
866 %!assert (mod (-5, [3,0; 3,1]), [1, -5; 1, 0])
867 %!assert (mod (-5, [3,2; 3,1]), [1, 1; 1, 0])
868 
869 ## integer types
870 %!assert (mod (uint8 (5), uint8 (4)), uint8 (1))
871 %!assert (mod (uint8 ([1:5]), uint8 (4)), uint8 ([1,2,3,0,1]))
872 %!assert (mod (uint8 ([1:5]), uint8 (0)), uint8 ([1:5]))
873 %!error (mod (uint8 (5), int8 (4)))
874 
875 ## mixed integer/real types
876 %!assert (mod (uint8 (5), 4), uint8 (1))
877 %!assert (mod (5, uint8 (4)), uint8 (1))
878 %!assert (mod (uint8 ([1:5]), 4), uint8 ([1,2,3,0,1]))
879 
880 ## non-integer real numbers
881 %!assert (mod (2.1, 0.1), 0)
882 %!assert (mod (2.1, 0.2), 0.1, eps)
883 
884 # bug 42627
885 %!assert (mod (0.94, 0.01), 0.0);
886 */
887 
888 // FIXME: Need to convert reduction functions of this file for single precision
889 
890 #define NATIVE_REDUCTION_1(FCN, TYPE, DIM) \
891  (arg.is_ ## TYPE ## _type ()) \
892  { \
893  TYPE ## NDArray tmp = arg. TYPE ##_array_value (); \
894  \
895  if (! error_state) \
896  { \
897  retval = tmp.FCN (DIM); \
898  } \
899  }
900 
901 #define NATIVE_REDUCTION(FCN, BOOL_FCN) \
902  \
903  octave_value retval; \
904  \
905  int nargin = args.length (); \
906  \
907  bool isnative = false; \
908  bool isdouble = false; \
909  \
910  if (nargin > 1 && args(nargin - 1).is_string ()) \
911  { \
912  std::string str = args(nargin - 1).string_value (); \
913  \
914  if (str == "native") \
915  isnative = true; \
916  else if (str == "double") \
917  isdouble = true; \
918  else \
919  error ("sum: unrecognized string argument"); \
920  nargin --; \
921  } \
922  \
923  if (nargin == 1 || nargin == 2) \
924  { \
925  octave_value arg = args(0); \
926  \
927  int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
928  \
929  if (! error_state) \
930  { \
931  if (dim >= -1) \
932  { \
933  if (arg.is_sparse_type ()) \
934  { \
935  if (arg.is_real_type ()) \
936  { \
937  SparseMatrix tmp = arg.sparse_matrix_value (); \
938  \
939  if (! error_state) \
940  retval = tmp.FCN (dim); \
941  } \
942  else \
943  { \
944  SparseComplexMatrix tmp \
945  = arg.sparse_complex_matrix_value (); \
946  \
947  if (! error_state) \
948  retval = tmp.FCN (dim); \
949  } \
950  } \
951  else \
952  { \
953  if (isnative) \
954  { \
955  if NATIVE_REDUCTION_1 (FCN, uint8, dim) \
956  else if NATIVE_REDUCTION_1 (FCN, uint16, dim) \
957  else if NATIVE_REDUCTION_1 (FCN, uint32, dim) \
958  else if NATIVE_REDUCTION_1 (FCN, uint64, dim) \
959  else if NATIVE_REDUCTION_1 (FCN, int8, dim) \
960  else if NATIVE_REDUCTION_1 (FCN, int16, dim) \
961  else if NATIVE_REDUCTION_1 (FCN, int32, dim) \
962  else if NATIVE_REDUCTION_1 (FCN, int64, dim) \
963  else if (arg.is_bool_type ()) \
964  { \
965  boolNDArray tmp = arg.bool_array_value (); \
966  if (! error_state) \
967  retval = boolNDArray (tmp.BOOL_FCN (dim)); \
968  } \
969  else if (arg.is_char_matrix ()) \
970  { \
971  error (#FCN, ": invalid char type"); \
972  } \
973  else if (!isdouble && arg.is_single_type ()) \
974  { \
975  if (arg.is_complex_type ()) \
976  { \
977  FloatComplexNDArray tmp = \
978  arg.float_complex_array_value (); \
979  \
980  if (! error_state) \
981  retval = tmp.FCN (dim); \
982  } \
983  else if (arg.is_real_type ()) \
984  { \
985  FloatNDArray tmp = arg.float_array_value (); \
986  \
987  if (! error_state) \
988  retval = tmp.FCN (dim); \
989  } \
990  } \
991  else if (arg.is_complex_type ()) \
992  { \
993  ComplexNDArray tmp = arg.complex_array_value (); \
994  \
995  if (! error_state) \
996  retval = tmp.FCN (dim); \
997  } \
998  else if (arg.is_real_type ()) \
999  { \
1000  NDArray tmp = arg.array_value (); \
1001  \
1002  if (! error_state) \
1003  retval = tmp.FCN (dim); \
1004  } \
1005  else \
1006  { \
1007  gripe_wrong_type_arg (#FCN, arg); \
1008  return retval; \
1009  } \
1010  } \
1011  else if (arg.is_bool_type ()) \
1012  { \
1013  boolNDArray tmp = arg.bool_array_value (); \
1014  if (! error_state) \
1015  retval = tmp.FCN (dim); \
1016  } \
1017  else if (!isdouble && arg.is_single_type ()) \
1018  { \
1019  if (arg.is_real_type ()) \
1020  { \
1021  FloatNDArray tmp = arg.float_array_value (); \
1022  \
1023  if (! error_state) \
1024  retval = tmp.FCN (dim); \
1025  } \
1026  else if (arg.is_complex_type ()) \
1027  { \
1028  FloatComplexNDArray tmp = \
1029  arg.float_complex_array_value (); \
1030  \
1031  if (! error_state) \
1032  retval = tmp.FCN (dim); \
1033  } \
1034  } \
1035  else if (arg.is_real_type ()) \
1036  { \
1037  NDArray tmp = arg.array_value (); \
1038  \
1039  if (! error_state) \
1040  retval = tmp.FCN (dim); \
1041  } \
1042  else if (arg.is_complex_type ()) \
1043  { \
1044  ComplexNDArray tmp = arg.complex_array_value (); \
1045  \
1046  if (! error_state) \
1047  retval = tmp.FCN (dim); \
1048  } \
1049  else \
1050  { \
1051  gripe_wrong_type_arg (#FCN, arg); \
1052  return retval; \
1053  } \
1054  } \
1055  } \
1056  else \
1057  error (#FCN ": invalid dimension argument = %d", dim + 1); \
1058  } \
1059  \
1060  } \
1061  else \
1062  print_usage (); \
1063  \
1064  return retval
1065 
1066 #define DATA_REDUCTION(FCN) \
1067  \
1068  octave_value retval; \
1069  \
1070  int nargin = args.length (); \
1071  \
1072  if (nargin == 1 || nargin == 2) \
1073  { \
1074  octave_value arg = args(0); \
1075  \
1076  int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
1077  \
1078  if (! error_state) \
1079  { \
1080  if (dim >= -1) \
1081  { \
1082  if (arg.is_real_type ()) \
1083  { \
1084  if (arg.is_sparse_type ()) \
1085  { \
1086  SparseMatrix tmp = arg.sparse_matrix_value (); \
1087  \
1088  if (! error_state) \
1089  retval = tmp.FCN (dim); \
1090  } \
1091  else if (arg.is_single_type ()) \
1092  { \
1093  FloatNDArray tmp = arg.float_array_value (); \
1094  \
1095  if (! error_state) \
1096  retval = tmp.FCN (dim); \
1097  } \
1098  else \
1099  { \
1100  NDArray tmp = arg.array_value (); \
1101  \
1102  if (! error_state) \
1103  retval = tmp.FCN (dim); \
1104  } \
1105  } \
1106  else if (arg.is_complex_type ()) \
1107  { \
1108  if (arg.is_sparse_type ()) \
1109  { \
1110  SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \
1111  \
1112  if (! error_state) \
1113  retval = tmp.FCN (dim); \
1114  } \
1115  else if (arg.is_single_type ()) \
1116  { \
1117  FloatComplexNDArray tmp \
1118  = arg.float_complex_array_value (); \
1119  \
1120  if (! error_state) \
1121  retval = tmp.FCN (dim); \
1122  } \
1123  else \
1124  { \
1125  ComplexNDArray tmp = arg.complex_array_value (); \
1126  \
1127  if (! error_state) \
1128  retval = tmp.FCN (dim); \
1129  } \
1130  } \
1131  else \
1132  { \
1133  gripe_wrong_type_arg (#FCN, arg); \
1134  return retval; \
1135  } \
1136  } \
1137  else \
1138  error (#FCN ": invalid dimension argument = %d", dim + 1); \
1139  } \
1140  } \
1141  else \
1142  print_usage (); \
1143  \
1144  return retval
1145 
1146 DEFUN (cumprod, args, ,
1147  "-*- texinfo -*-\n\
1148 @deftypefn {Built-in Function} {} cumprod (@var{x})\n\
1149 @deftypefnx {Built-in Function} {} cumprod (@var{x}, @var{dim})\n\
1150 Cumulative product of elements along dimension @var{dim}.\n\
1151 \n\
1152 If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
1153 @seealso{prod, cumsum}\n\
1154 @end deftypefn")
1155 {
1156  DATA_REDUCTION (cumprod);
1157 }
1158 
1159 /*
1160 %!assert (cumprod ([1, 2, 3]), [1, 2, 6])
1161 %!assert (cumprod ([-1; -2; -3]), [-1; 2; -6])
1162 %!assert (cumprod ([i, 2+i, -3+2i, 4]), [i, -1+2i, -1-8i, -4-32i])
1163 %!assert (cumprod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [1, 2, 3; i, 4i, 9i; -1+i, -8+8i, -27+27i])
1164 
1165 %!assert (cumprod (single ([1, 2, 3])), single ([1, 2, 6]))
1166 %!assert (cumprod (single ([-1; -2; -3])), single ([-1; 2; -6]))
1167 %!assert (cumprod (single ([i, 2+i, -3+2i, 4])), single ([i, -1+2i, -1-8i, -4-32i]))
1168 %!assert (cumprod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single ([1, 2, 3; i, 4i, 9i; -1+i, -8+8i, -27+27i]))
1169 
1170 %!assert (cumprod ([2, 3; 4, 5], 1), [2, 3; 8, 15])
1171 %!assert (cumprod ([2, 3; 4, 5], 2), [2, 6; 4, 20])
1172 
1173 %!assert (cumprod (single ([2, 3; 4, 5]), 1), single ([2, 3; 8, 15]))
1174 %!assert (cumprod (single ([2, 3; 4, 5]), 2), single ([2, 6; 4, 20]))
1175 
1176 %!error cumprod ()
1177 */
1178 
1179 DEFUN (cumsum, args, ,
1180  "-*- texinfo -*-\n\
1181 @deftypefn {Built-in Function} {} cumsum (@var{x})\n\
1182 @deftypefnx {Built-in Function} {} cumsum (@var{x}, @var{dim})\n\
1183 @deftypefnx {Built-in Function} {} cumsum (@dots{}, \"native\")\n\
1184 @deftypefnx {Built-in Function} {} cumsum (@dots{}, \"double\")\n\
1185 @deftypefnx {Built-in Function} {} cumsum (@dots{}, \"extra\")\n\
1186 Cumulative sum of elements along dimension @var{dim}.\n\
1187 \n\
1188 If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
1189 \n\
1190 See @code{sum} for an explanation of the optional parameters\n\
1191 @qcode{\"native\"}, @qcode{\"double\"}, and @qcode{\"extra\"}.\n\
1192 @seealso{sum, cumprod}\n\
1193 @end deftypefn")
1194 {
1195  octave_value retval;
1196 
1197  int nargin = args.length ();
1198 
1199  bool isnative = false;
1200  bool isdouble = false;
1201 
1202  if (nargin > 1 && args(nargin - 1).is_string ())
1203  {
1204  std::string str = args(nargin - 1).string_value ();
1205 
1206  if (str == "native")
1207  isnative = true;
1208  else if (str == "double")
1209  isdouble = true;
1210  else
1211  error ("cumsum: unrecognized string argument");
1212  nargin --;
1213  }
1214 
1215  if (error_state)
1216  return retval;
1217 
1218  if (nargin == 1 || nargin == 2)
1219  {
1220  octave_value arg = args(0);
1221 
1222  int dim = -1;
1223  if (nargin == 2)
1224  {
1225  dim = args(1).int_value () - 1;
1226  if (dim < 0)
1227  error ("cumsum: invalid dimension argument = %d", dim + 1);
1228  }
1229 
1230  if (! error_state)
1231  {
1232  switch (arg.builtin_type ())
1233  {
1234  case btyp_double:
1235  if (arg.is_sparse_type ())
1236  retval = arg.sparse_matrix_value ().cumsum (dim);
1237  else
1238  retval = arg.array_value ().cumsum (dim);
1239  break;
1240  case btyp_complex:
1241  if (arg.is_sparse_type ())
1242  retval = arg.sparse_complex_matrix_value ().cumsum (dim);
1243  else
1244  retval = arg.complex_array_value ().cumsum (dim);
1245  break;
1246  case btyp_float:
1247  if (isdouble)
1248  retval = arg.array_value ().cumsum (dim);
1249  else
1250  retval = arg.float_array_value ().cumsum (dim);
1251  break;
1252  case btyp_float_complex:
1253  if (isdouble)
1254  retval = arg.complex_array_value ().cumsum (dim);
1255  else
1256  retval = arg.float_complex_array_value ().cumsum (dim);
1257  break;
1258 
1259 #define MAKE_INT_BRANCH(X) \
1260  case btyp_ ## X: \
1261  if (isnative) \
1262  retval = arg.X ## _array_value ().cumsum (dim); \
1263  else \
1264  retval = arg.array_value ().cumsum (dim); \
1265  break;
1266  MAKE_INT_BRANCH (int8);
1267  MAKE_INT_BRANCH (int16);
1268  MAKE_INT_BRANCH (int32);
1269  MAKE_INT_BRANCH (int64);
1270  MAKE_INT_BRANCH (uint8);
1271  MAKE_INT_BRANCH (uint16);
1272  MAKE_INT_BRANCH (uint32);
1273  MAKE_INT_BRANCH (uint64);
1274 #undef MAKE_INT_BRANCH
1275 
1276  case btyp_bool:
1277  if (arg.is_sparse_type ())
1278  {
1279  SparseMatrix cs = arg.sparse_matrix_value ().cumsum (dim);
1280  if (isnative)
1281  retval = cs != 0.0;
1282  else
1283  retval = cs;
1284  }
1285  else
1286  {
1287  NDArray cs = arg.bool_array_value ().cumsum (dim);
1288  if (isnative)
1289  retval = cs != 0.0;
1290  else
1291  retval = cs;
1292  }
1293  break;
1294 
1295  default:
1296  gripe_wrong_type_arg ("cumsum", arg);
1297  }
1298  }
1299  }
1300  else
1301  print_usage ();
1302 
1303  return retval;
1304 }
1305 
1306 /*
1307 %!assert (cumsum ([1, 2, 3]), [1, 3, 6])
1308 %!assert (cumsum ([-1; -2; -3]), [-1; -3; -6])
1309 %!assert (cumsum ([i, 2+i, -3+2i, 4]), [i, 2+2i, -1+4i, 3+4i])
1310 %!assert (cumsum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [1, 2, 3; 1+i, 2+2i, 3+3i; 2+2i, 4+4i, 6+6i])
1311 
1312 %!assert (cumsum (single ([1, 2, 3])), single ([1, 3, 6]))
1313 %!assert (cumsum (single ([-1; -2; -3])), single ([-1; -3; -6]))
1314 %!assert (cumsum (single ([i, 2+i, -3+2i, 4])), single ([i, 2+2i, -1+4i, 3+4i]))
1315 %!assert (cumsum (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single ([1, 2, 3; 1+i, 2+2i, 3+3i; 2+2i, 4+4i, 6+6i]))
1316 
1317 %!assert (cumsum ([1, 2; 3, 4], 1), [1, 2; 4, 6])
1318 %!assert (cumsum ([1, 2; 3, 4], 2), [1, 3; 3, 7])
1319 
1320 %!assert (cumsum (single ([1, 2; 3, 4]), 1), single ([1, 2; 4, 6]))
1321 %!assert (cumsum (single ([1, 2; 3, 4]), 2), single ([1, 3; 3, 7]))
1322 
1323 %!error cumsum ()
1324 */
1325 
1326 DEFUN (diag, args, ,
1327  "-*- texinfo -*-\n\
1328 @deftypefn {Built-in Function} {@var{M} =} diag (@var{v})\n\
1329 @deftypefnx {Built-in Function} {@var{M} =} diag (@var{v}, @var{k})\n\
1330 @deftypefnx {Built-in Function} {@var{M} =} diag (@var{v}, @var{m}, @var{n})\n\
1331 @deftypefnx {Built-in Function} {@var{v} =} diag (@var{M})\n\
1332 @deftypefnx {Built-in Function} {@var{v} =} diag (@var{M}, @var{k})\n\
1333 Return a diagonal matrix with vector @var{v} on diagonal @var{k}.\n\
1334 \n\
1335 The second argument is optional. If it is positive, the vector is placed on\n\
1336 the @var{k}-th superdiagonal. If it is negative, it is placed on the\n\
1337 @var{-k}-th subdiagonal. The default value of @var{k} is 0, and the vector\n\
1338 is placed on the main diagonal. For example:\n\
1339 \n\
1340 @example\n\
1341 @group\n\
1342 diag ([1, 2, 3], 1)\n\
1343  @result{} 0 1 0 0\n\
1344  0 0 2 0\n\
1345  0 0 0 3\n\
1346  0 0 0 0\n\
1347 @end group\n\
1348 @end example\n\
1349 \n\
1350 @noindent\n\
1351 The 3-input form returns a diagonal matrix with vector @var{v} on the main\n\
1352 diagonal and the resulting matrix being of size @var{m} rows x @var{n}\n\
1353 columns.\n\
1354 \n\
1355 Given a matrix argument, instead of a vector, @code{diag} extracts the\n\
1356 @var{k}-th diagonal of the matrix.\n\
1357 @end deftypefn")
1358 {
1359  octave_value retval;
1360 
1361  int nargin = args.length ();
1362 
1363  if (nargin == 1 && args(0).is_defined ())
1364  retval = args(0).diag ();
1365  else if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
1366  {
1367  octave_idx_type k = args(1).int_value ();
1368 
1369  if (error_state)
1370  error ("diag: invalid argument K");
1371  else
1372  retval = args(0).diag (k);
1373  }
1374  else if (nargin == 3)
1375  {
1376  octave_value arg0 = args(0);
1377 
1378  if (arg0.ndims () == 2 && (arg0.rows () == 1 || arg0.columns () == 1))
1379  {
1380  octave_idx_type m = args(1).int_value ();
1381  octave_idx_type n = args(2).int_value ();
1382 
1383  if (! error_state)
1384  retval = arg0.diag (m, n);
1385  else
1386  error ("diag: invalid dimensions");
1387  }
1388  else
1389  error ("diag: V must be a vector");
1390  }
1391  else
1392  print_usage ();
1393 
1394  return retval;
1395 }
1396 
1397 /*
1398 
1399 %!assert (full (diag ([1; 2; 3])), [1, 0, 0; 0, 2, 0; 0, 0, 3])
1400 %!assert (diag ([1; 2; 3], 1), [0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0])
1401 %!assert (diag ([1; 2; 3], 2), [0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0])
1402 %!assert (diag ([1; 2; 3],-1), [0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0])
1403 %!assert (diag ([1; 2; 3],-2), [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0])
1404 
1405 %!assert (diag ([1, 0, 0; 0, 2, 0; 0, 0, 3]), [1; 2; 3])
1406 %!assert (diag ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0], 1), [1; 2; 3])
1407 %!assert (diag ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0], -1), [1; 2; 3])
1408 %!assert (diag (ones (1, 0), 2), zeros (2))
1409 %!assert (diag (1:3, 4, 2), [1, 0; 0, 2; 0, 0; 0, 0])
1410 
1411 %!assert (full (diag (single ([1; 2; 3]))), single ([1, 0, 0; 0, 2, 0; 0, 0, 3]))
1412 %!assert (diag (single ([1; 2; 3]), 1), single ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]))
1413 %!assert (diag (single ([1; 2; 3]), 2), single ([0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]))
1414 %!assert (diag (single ([1; 2; 3]),-1), single ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]))
1415 %!assert (diag (single ([1; 2; 3]),-2), single ([0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0]))
1416 
1417 %!assert (diag (single ([1, 0, 0; 0, 2, 0; 0, 0, 3])), single ([1; 2; 3]))
1418 %!assert (diag (single ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), single ([1; 2; 3]))
1419 %!assert (diag (single ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), single ([1; 2; 3]))
1420 
1421 %!assert (diag (int8 ([1; 2; 3])), int8 ([1, 0, 0; 0, 2, 0; 0, 0, 3]))
1422 %!assert (diag (int8 ([1; 2; 3]), 1), int8 ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]))
1423 %!assert (diag (int8 ([1; 2; 3]), 2), int8 ([0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]))
1424 %!assert (diag (int8 ([1; 2; 3]),-1), int8 ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]))
1425 %!assert (diag (int8 ([1; 2; 3]),-2), int8 ([0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0]))
1426 
1427 %!assert (diag (int8 ([1, 0, 0; 0, 2, 0; 0, 0, 3])), int8 ([1; 2; 3]))
1428 %!assert (diag (int8 ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), int8 ([1; 2; 3]))
1429 %!assert (diag (int8 ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), int8 ([1; 2; 3]))
1430 
1431 ## bug #37411
1432 %!assert (diag (diag ([5, 2, 3])(:,1)), diag([5 0 0 ]))
1433 %!assert (diag (diag ([5, 2, 3])(:,1), 2), [0 0 5 0 0; zeros(4, 5)])
1434 %!assert (diag (diag ([5, 2, 3])(:,1), -2), [[0 0 5 0 0]', zeros(5, 4)])
1435 
1436 ## Test non-square size
1437 %!assert (diag ([1,2,3], 6, 3), [1 0 0; 0 2 0; 0 0 3; 0 0 0; 0 0 0; 0 0 0])
1438 %!assert (diag (1, 2, 3), [1,0,0; 0,0,0]);
1439 %!assert (diag ({1}, 2, 3), {1,[],[]; [],[],[]});
1440 %!assert (diag ({1,2}, 3, 4), {1,[],[],[]; [],2,[],[]; [],[],[],[]});
1441 
1442 ## Test out-of-range diagonals
1443 %!assert (diag (ones (3,3), 4), zeros (0, 1))
1444 %!assert (diag (cell (3,3), 4), cell (0, 1))
1445 %!assert (diag (sparse (ones (3,3)), 4), sparse (zeros (0, 1)))
1446 
1447 %% Test input validation
1448 %!error <Invalid call to diag> diag ()
1449 %!error <Invalid call to diag> diag (1,2,3,4)
1450 %!error diag (ones (2), 3, 3)
1451 %!error diag (1:3, -4, 3)
1452 
1453 %!assert (diag (1, 3, 3), diag ([1, 0, 0]))
1454 %!assert (diag (i, 3, 3), diag ([i, 0, 0]))
1455 %!assert (diag (single (1), 3, 3), diag ([single(1), 0, 0]))
1456 %!assert (diag (single (i), 3, 3), diag ([single(i), 0, 0]))
1457 %!assert (diag ([1, 2], 3, 3), diag ([1, 2, 0]))
1458 %!assert (diag ([1, 2]*i, 3, 3), diag ([1, 2, 0]*i))
1459 %!assert (diag (single ([1, 2]), 3, 3), diag (single ([1, 2, 0])))
1460 %!assert (diag (single ([1, 2]*i), 3, 3), diag (single ([1, 2, 0]*i)))
1461 */
1462 
1463 DEFUN (prod, args, ,
1464  "-*- texinfo -*-\n\
1465 @deftypefn {Built-in Function} {} prod (@var{x})\n\
1466 @deftypefnx {Built-in Function} {} prod (@var{x}, @var{dim})\n\
1467 @deftypefnx {Built-in Function} {} prod (@dots{}, \"native\")\n\
1468 @deftypefnx {Built-in Function} {} prod (@dots{}, \"double\")\n\
1469 Product of elements along dimension @var{dim}.\n\
1470 \n\
1471 If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
1472 \n\
1473 The optional @qcode{\"type\"} input determines the class of the variable\n\
1474 used for calculations. If the argument @qcode{\"native\"} is given, then\n\
1475 the operation is performed in the same type as the original argument, rather\n\
1476 than the default double type.\n\
1477 \n\
1478 For example:\n\
1479 \n\
1480 @example\n\
1481 @group\n\
1482 prod ([true, true])\n\
1483  @result{} 1\n\
1484 prod ([true, true], \"native\")\n\
1485  @result{} true\n\
1486 @end group\n\
1487 @end example\n\
1488 \n\
1489 On the contrary, if @qcode{\"double\"} is given, the operation is performed\n\
1490 in double precision even for single precision inputs.\n\
1491 @seealso{cumprod, sum}\n\
1492 @end deftypefn")
1493 {
1494  octave_value retval;
1495 
1496  int nargin = args.length ();
1497 
1498  bool isnative = false;
1499  bool isdouble = false;
1500 
1501  if (nargin > 1 && args(nargin - 1).is_string ())
1502  {
1503  std::string str = args(nargin - 1).string_value ();
1504 
1505  if (str == "native")
1506  isnative = true;
1507  else if (str == "double")
1508  isdouble = true;
1509  else
1510  error ("prod: unrecognized type argument '%s'", str.c_str ());
1511  nargin --;
1512  }
1513 
1514  if (error_state)
1515  return retval;
1516 
1517  if (nargin == 1 || nargin == 2)
1518  {
1519  octave_value arg = args(0);
1520 
1521  int dim = -1;
1522  if (nargin == 2)
1523  {
1524  dim = args(1).int_value () - 1;
1525  if (dim < 0)
1526  error ("prod: invalid dimension DIM = %d", dim + 1);
1527  }
1528 
1529  if (! error_state)
1530  {
1531  switch (arg.builtin_type ())
1532  {
1533  case btyp_double:
1534  if (arg.is_sparse_type ())
1535  retval = arg.sparse_matrix_value ().prod (dim);
1536  else
1537  retval = arg.array_value ().prod (dim);
1538  break;
1539  case btyp_complex:
1540  if (arg.is_sparse_type ())
1541  retval = arg.sparse_complex_matrix_value ().prod (dim);
1542  else
1543  retval = arg.complex_array_value ().prod (dim);
1544  break;
1545  case btyp_float:
1546  if (isdouble)
1547  retval = arg.float_array_value ().dprod (dim);
1548  else
1549  retval = arg.float_array_value ().prod (dim);
1550  break;
1551  case btyp_float_complex:
1552  if (isdouble)
1553  retval = arg.float_complex_array_value ().dprod (dim);
1554  else
1555  retval = arg.float_complex_array_value ().prod (dim);
1556  break;
1557 
1558 #define MAKE_INT_BRANCH(X) \
1559  case btyp_ ## X: \
1560  if (isnative) \
1561  retval = arg.X ## _array_value ().prod (dim); \
1562  else \
1563  retval = arg.array_value ().prod (dim); \
1564  break;
1565  MAKE_INT_BRANCH (int8);
1566  MAKE_INT_BRANCH (int16);
1567  MAKE_INT_BRANCH (int32);
1568  MAKE_INT_BRANCH (int64);
1569  MAKE_INT_BRANCH (uint8);
1570  MAKE_INT_BRANCH (uint16);
1571  MAKE_INT_BRANCH (uint32);
1572  MAKE_INT_BRANCH (uint64);
1573 #undef MAKE_INT_BRANCH
1574 
1575  // GAGME: Accursed Matlab compatibility...
1576  case btyp_char:
1577  retval = arg.array_value (true).prod (dim);
1578  break;
1579  case btyp_bool:
1580  if (arg.is_sparse_type ())
1581  {
1582  if (isnative)
1583  retval = arg.sparse_bool_matrix_value ().all (dim);
1584  else
1585  retval = arg.sparse_matrix_value ().prod (dim);
1586  }
1587  else if (isnative)
1588  retval = arg.bool_array_value ().all (dim);
1589  else
1590  retval = NDArray (arg.bool_array_value ().all (dim));
1591  break;
1592 
1593  default:
1594  gripe_wrong_type_arg ("prod", arg);
1595  }
1596  }
1597  }
1598  else
1599  print_usage ();
1600 
1601  return retval;
1602 }
1603 
1604 /*
1605 %!assert (prod ([1, 2, 3]), 6)
1606 %!assert (prod ([-1; -2; -3]), -6)
1607 %!assert (prod ([i, 2+i, -3+2i, 4]), -4 - 32i)
1608 %!assert (prod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [-1+i, -8+8i, -27+27i])
1609 
1610 %!assert (prod (single ([1, 2, 3])), single (6))
1611 %!assert (prod (single ([-1; -2; -3])), single (-6))
1612 %!assert (prod (single ([i, 2+i, -3+2i, 4])), single (-4 - 32i))
1613 %!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single ([-1+i, -8+8i, -27+27i]))
1614 
1615 %% Test sparse
1616 %!assert (prod (sparse ([1, 2, 3])), sparse (6))
1617 %!assert (prod (sparse ([-1; -2; -3])), sparse (-6))
1618 ## Commented out until bug #42290 is fixed
1619 #%!assert (prod (sparse ([i, 2+i, -3+2i, 4])), sparse (-4 - 32i))
1620 #%!assert (prod (sparse ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), sparse ([-1+i, -8+8i, -27+27i]))
1621 
1622 %!assert (prod ([1, 2; 3, 4], 1), [3, 8])
1623 %!assert (prod ([1, 2; 3, 4], 2), [2; 12])
1624 %!assert (prod (zeros (1, 0)), 1)
1625 %!assert (prod (zeros (1, 0), 1), zeros (1, 0))
1626 %!assert (prod (zeros (1, 0), 2), 1)
1627 %!assert (prod (zeros (0, 1)), 1)
1628 %!assert (prod (zeros (0, 1), 1), 1)
1629 %!assert (prod (zeros (0, 1), 2), zeros (0, 1))
1630 %!assert (prod (zeros (2, 0)), zeros (1, 0))
1631 %!assert (prod (zeros (2, 0), 1), zeros (1, 0))
1632 %!assert (prod (zeros (2, 0), 2), [1; 1])
1633 %!assert (prod (zeros (0, 2)), [1, 1])
1634 %!assert (prod (zeros (0, 2), 1), [1, 1])
1635 %!assert (prod (zeros (0, 2), 2), zeros (0, 1))
1636 
1637 %!assert (prod (single ([1, 2; 3, 4]), 1), single ([3, 8]))
1638 %!assert (prod (single ([1, 2; 3, 4]), 2), single ([2; 12]))
1639 %!assert (prod (zeros (1, 0, "single")), single (1))
1640 %!assert (prod (zeros (1, 0, "single"), 1), zeros (1, 0, "single"))
1641 %!assert (prod (zeros (1, 0, "single"), 2), single (1))
1642 %!assert (prod (zeros (0, 1, "single")), single (1))
1643 %!assert (prod (zeros (0, 1, "single"), 1), single (1))
1644 %!assert (prod (zeros (0, 1, "single"), 2), zeros (0, 1, "single"))
1645 %!assert (prod (zeros (2, 0, "single")), zeros (1, 0, "single"))
1646 %!assert (prod (zeros (2, 0, "single"), 1), zeros (1, 0, "single"))
1647 %!assert (prod (zeros (2, 0, "single"), 2), single ([1; 1]))
1648 %!assert (prod (zeros (0, 2, "single")), single ([1, 1]))
1649 %!assert (prod (zeros (0, 2, "single"), 1), single ([1, 1]))
1650 %!assert (prod (zeros (0, 2, "single"), 2), zeros (0, 1, "single"))
1651 
1652 %% Test "double" type argument
1653 %!assert (prod (single ([1, 2, 3]), "double"), 6)
1654 %!assert (prod (single ([-1; -2; -3]), "double"), -6)
1655 %!assert (prod (single ([i, 2+i, -3+2i, 4]), "double"), -4 - 32i)
1656 %!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), "double"), [-1+i, -8+8i, -27+27i])
1657 
1658 %% Test "native" type argument
1659 %!assert (prod (uint8 ([1, 2, 3]), "native"), uint8 (6))
1660 %!assert (prod (uint8 ([-1; -2; -3]), "native"), uint8 (0))
1661 %!assert (prod (int8 ([1, 2, 3]), "native"), int8 (6))
1662 %!assert (prod (int8 ([-1; -2; -3]), "native"), int8 (-6))
1663 %!assert (prod ([true false; true true], "native"), [true false])
1664 %!assert (prod ([true false; true true], 2, "native"), [false; true])
1665 
1666 %% Test input validation
1667 %!error prod ()
1668 %!error prod (1,2,3)
1669 %!error <unrecognized type argument 'foobar'> prod (1, "foobar")
1670 */
1671 
1672 static bool
1674 {
1675  int n_args = args.length ();
1676  for (int i = 0; i < n_args; i++)
1677  if (args(i).numel () != 1)
1678  return false;
1679 
1680  return true;
1681 }
1682 
1683 template <class TYPE, class T>
1684 static void
1686  const octave_value_list& args,
1687  int dim)
1688 {
1689  int n_args = args.length ();
1692  && all_scalar_1x1 (args))
1693  {
1694  // Optimize all scalars case.
1695  dim_vector dv (1, 1);
1696  if (dim == -1 || dim == -2)
1697  dim = -dim - 1;
1698  else if (dim >= 2)
1699  dv.resize (dim+1, 1);
1700  dv(dim) = n_args;
1701 
1702  result.clear (dv);
1703 
1704  for (int j = 0; j < n_args && ! error_state; j++)
1705  {
1706  octave_quit ();
1707 
1708  result(j) = octave_value_extract<T> (args(j));
1709  }
1710  }
1711  else
1712  {
1713  OCTAVE_LOCAL_BUFFER (Array<T>, array_list, n_args);
1714 
1715  for (int j = 0; j < n_args && ! error_state; j++)
1716  {
1717  octave_quit ();
1718 
1719  array_list[j] = octave_value_extract<TYPE> (args(j));
1720  }
1721 
1722  if (! error_state)
1723  result = Array<T>::cat (dim, n_args, array_list);
1724  }
1725 }
1726 
1727 template <class TYPE, class T>
1728 static void
1730  const octave_value_list& args,
1731  int dim)
1732 {
1733  int n_args = args.length ();
1734  OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_list, n_args);
1735 
1736  for (int j = 0; j < n_args && ! error_state; j++)
1737  {
1738  octave_quit ();
1739 
1740  sparse_list[j] = octave_value_extract<TYPE> (args(j));
1741  }
1742 
1743  if (! error_state)
1744  result = Sparse<T>::cat (dim, n_args, sparse_list);
1745 }
1746 
1747 // Dispatcher.
1748 template<class TYPE>
1749 static TYPE
1751 {
1752  TYPE result;
1753 
1754  single_type_concat<TYPE, typename TYPE::element_type> (result, args, dim);
1755 
1756  return result;
1757 }
1758 
1759 template<class MAP>
1760 static void
1762  const octave_value_list& args,
1763  int dim)
1764 {
1765  int n_args = args.length ();
1766  OCTAVE_LOCAL_BUFFER (MAP, map_list, n_args);
1767 
1768  for (int j = 0; j < n_args && ! error_state; j++)
1769  {
1770  octave_quit ();
1771 
1772  map_list[j] = octave_value_extract<MAP> (args(j));
1773  }
1774 
1775  if (! error_state)
1776  result = octave_map::cat (dim, n_args, map_list);
1777 }
1778 
1779 static octave_map
1781  int dim)
1782 {
1783  octave_map result;
1784  if (all_scalar_1x1 (args)) // optimize all scalars case.
1785  single_type_concat_map<octave_scalar_map> (result, args, dim);
1786  else
1787  single_type_concat_map<octave_map> (result, args, dim);
1788 
1789  return result;
1790 }
1791 
1792 static octave_value
1793 attempt_type_conversion (const octave_value& ov, std::string dtype)
1794 {
1795  octave_value retval;
1796 
1797  // First try to find function in the class of OV that can convert to
1798  // the dispatch type dtype. It will have the name of the dispatch
1799  // type.
1800 
1801  std::string cname = ov.class_name ();
1802 
1803  octave_value fcn = symbol_table::find_method (dtype, cname);
1804 
1805  if (fcn.is_defined ())
1806  {
1807  octave_value_list result
1808  = fcn.do_multi_index_op (1, octave_value_list (1, ov));
1809 
1810  if (! error_state && result.length () > 0)
1811  retval = result(0);
1812  else
1813  error ("conversion from %s to %s failed", dtype.c_str (),
1814  cname.c_str ());
1815  }
1816  else
1817  {
1818  // No conversion function available. Try the constructor for the
1819  // dispatch type.
1820 
1821  fcn = symbol_table::find_method (dtype, dtype);
1822 
1823  if (fcn.is_defined ())
1824  {
1825  octave_value_list result
1826  = fcn.do_multi_index_op (1, octave_value_list (1, ov));
1827 
1828  if (! error_state && result.length () > 0)
1829  retval = result(0);
1830  else
1831  error ("%s constructor failed for %s argument", dtype.c_str (),
1832  cname.c_str ());
1833  }
1834  else
1835  error ("no constructor for %s!", dtype.c_str ());
1836  }
1837 
1838  return retval;
1839 }
1840 
1842 do_class_concat (const octave_value_list& ovl, std::string cattype, int dim)
1843 {
1844  octave_value retval;
1845 
1846  // Get dominant type for list
1847 
1848  std::string dtype = get_dispatch_type (ovl);
1849 
1850  octave_value fcn = symbol_table::find_method (cattype, dtype);
1851 
1852  if (fcn.is_defined ())
1853  {
1854  // Have method for dominant type, so call it and let it handle
1855  // conversions.
1856 
1857  octave_value_list tmp2 = fcn.do_multi_index_op (1, ovl);
1858 
1859  if (! error_state)
1860  {
1861  if (tmp2.length () > 0)
1862  retval = tmp2(0);
1863  else
1864  {
1865  error ("%s/%s method did not return a value",
1866  dtype.c_str (), cattype.c_str ());
1867  goto done;
1868  }
1869  }
1870  else
1871  goto done;
1872  }
1873  else
1874  {
1875  // No method for dominant type, so attempt type conversions for
1876  // all elements that are not of the dominant type, then do the
1877  // default operation for octave_class values.
1878 
1879  octave_idx_type j = 0;
1880  octave_idx_type len = ovl.length ();
1881  octave_value_list tmp (len, octave_value ());
1882  for (octave_idx_type k = 0; k < len; k++)
1883  {
1884  octave_value elt = ovl(k);
1885 
1886  std::string t1_type = elt.class_name ();
1887 
1888  if (t1_type == dtype)
1889  tmp(j++) = elt;
1890  else if (elt.is_object () || ! elt.is_empty ())
1891  {
1892  tmp(j++) = attempt_type_conversion (elt, dtype);
1893 
1894  if (error_state)
1895  goto done;
1896  }
1897  }
1898 
1899  tmp.resize (j);
1900 
1901  octave_map m = do_single_type_concat_map (tmp, dim);
1902 
1903  std::string cname = tmp(0).class_name ();
1904  std::list<std::string> parents = tmp(0).parent_class_name_list ();
1905 
1906  retval = octave_value (new octave_class (m, cname, parents));
1907  }
1908 
1909 done:
1910  return retval;
1911 }
1912 
1913 static octave_value
1914 do_cat (const octave_value_list& xargs, int dim, std::string fname)
1915 {
1916  octave_value retval;
1917 
1918  // We may need to convert elements of the list to cells, so make a
1919  // copy. This should be efficient, it is done mostly by incrementing
1920  // reference counts.
1921  octave_value_list args = xargs;
1922 
1923  int n_args = args.length ();
1924 
1925  if (n_args == 0)
1926  retval = Matrix ();
1927  else if (n_args == 1)
1928  retval = args(0);
1929  else if (n_args > 1)
1930  {
1931  std::string result_type;
1932 
1933  bool all_strings_p = true;
1934  bool all_sq_strings_p = true;
1935  bool all_dq_strings_p = true;
1936  bool all_real_p = true;
1937  bool all_cmplx_p = true;
1938  bool any_sparse_p = false;
1939  bool any_cell_p = false;
1940  bool any_class_p = false;
1941 
1942  bool first_elem_is_struct = false;
1943 
1944  for (int i = 0; i < n_args; i++)
1945  {
1946  if (i == 0)
1947  {
1948  result_type = args(i).class_name ();
1949 
1950  first_elem_is_struct = args(i).is_map ();
1951  }
1952  else
1953  result_type = get_concat_class (result_type, args(i).class_name ());
1954 
1955  if (all_strings_p && ! args(i).is_string ())
1956  all_strings_p = false;
1957  if (all_sq_strings_p && ! args(i).is_sq_string ())
1958  all_sq_strings_p = false;
1959  if (all_dq_strings_p && ! args(i).is_dq_string ())
1960  all_dq_strings_p = false;
1961  if (all_real_p && ! args(i).is_real_type ())
1962  all_real_p = false;
1963  if (all_cmplx_p && ! (args(i).is_complex_type ()
1964  || args(i).is_real_type ()))
1965  all_cmplx_p = false;
1966  if (!any_sparse_p && args(i).is_sparse_type ())
1967  any_sparse_p = true;
1968  if (!any_cell_p && args(i).is_cell ())
1969  any_cell_p = true;
1970  if (!any_class_p && args(i).is_object ())
1971  any_class_p = true;
1972  }
1973 
1974  if (any_cell_p && ! any_class_p && ! first_elem_is_struct)
1975  {
1976  for (int i = 0; i < n_args; i++)
1977  {
1978  if (! args(i).is_cell ())
1979  args(i) = Cell (args(i));
1980  }
1981  }
1982 
1983  if (any_class_p)
1984  {
1985  retval = do_class_concat (args, fname, dim);
1986  }
1987  else if (result_type == "double")
1988  {
1989  if (any_sparse_p)
1990  {
1991  if (all_real_p)
1992  retval = do_single_type_concat<SparseMatrix> (args, dim);
1993  else
1994  retval = do_single_type_concat<SparseComplexMatrix> (args, dim);
1995  }
1996  else
1997  {
1998  if (all_real_p)
1999  retval = do_single_type_concat<NDArray> (args, dim);
2000  else
2001  retval = do_single_type_concat<ComplexNDArray> (args, dim);
2002  }
2003  }
2004  else if (result_type == "single")
2005  {
2006  if (all_real_p)
2007  retval = do_single_type_concat<FloatNDArray> (args, dim);
2008  else
2009  retval = do_single_type_concat<FloatComplexNDArray> (args, dim);
2010  }
2011  else if (result_type == "char")
2012  {
2013  char type = all_dq_strings_p ? '"' : '\'';
2014 
2015  if (! all_strings_p)
2016  gripe_implicit_conversion ("Octave:num-to-str",
2017  "numeric", result_type);
2018  else
2019  maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
2020 
2021  charNDArray result = do_single_type_concat<charNDArray> (args, dim);
2022 
2023  retval = octave_value (result, type);
2024  }
2025  else if (result_type == "logical")
2026  {
2027  if (any_sparse_p)
2028  retval = do_single_type_concat<SparseBoolMatrix> (args, dim);
2029  else
2030  retval = do_single_type_concat<boolNDArray> (args, dim);
2031  }
2032  else if (result_type == "int8")
2033  retval = do_single_type_concat<int8NDArray> (args, dim);
2034  else if (result_type == "int16")
2035  retval = do_single_type_concat<int16NDArray> (args, dim);
2036  else if (result_type == "int32")
2037  retval = do_single_type_concat<int32NDArray> (args, dim);
2038  else if (result_type == "int64")
2039  retval = do_single_type_concat<int64NDArray> (args, dim);
2040  else if (result_type == "uint8")
2041  retval = do_single_type_concat<uint8NDArray> (args, dim);
2042  else if (result_type == "uint16")
2043  retval = do_single_type_concat<uint16NDArray> (args, dim);
2044  else if (result_type == "uint32")
2045  retval = do_single_type_concat<uint32NDArray> (args, dim);
2046  else if (result_type == "uint64")
2047  retval = do_single_type_concat<uint64NDArray> (args, dim);
2048  else if (result_type == "cell")
2049  retval = do_single_type_concat<Cell> (args, dim);
2050  else if (result_type == "struct")
2051  retval = do_single_type_concat_map (args, dim);
2052  else
2053  {
2054  dim_vector dv = args(0).dims ();
2055 
2056  // Default concatenation.
2057  bool (dim_vector::*concat_rule) (const dim_vector&, int)
2058  = &dim_vector::concat;
2059 
2060  if (dim == -1 || dim == -2)
2061  {
2062  concat_rule = &dim_vector::hvcat;
2063  dim = -dim - 1;
2064  }
2065 
2066  for (int i = 1; i < args.length (); i++)
2067  {
2068  if (! (dv.*concat_rule) (args(i).dims (), dim))
2069  {
2070  // Dimensions do not match.
2071  error ("cat: dimension mismatch");
2072  return retval;
2073  }
2074  }
2075 
2076  // The lines below might seem crazy, since we take a copy
2077  // of the first argument, resize it to be empty and then resize
2078  // it to be full. This is done since it means that there is no
2079  // recopying of data, as would happen if we used a single resize.
2080  // It should be noted that resize operation is also significantly
2081  // slower than the do_cat_op function, so it makes sense to have
2082  // an empty matrix and copy all data.
2083  //
2084  // We might also start with a empty octave_value using
2085  // tmp = octave_value_typeinfo::lookup_type
2086  // (args(1).type_name());
2087  // and then directly resize. However, for some types there might
2088  // be some additional setup needed, and so this should be avoided.
2089 
2090  octave_value tmp = args(0);
2091  tmp = tmp.resize (dim_vector (0,0)).resize (dv);
2092 
2093  if (error_state)
2094  return retval;
2095 
2096  int dv_len = dv.length ();
2097  Array<octave_idx_type> ra_idx (dim_vector (dv_len, 1), 0);
2098 
2099  for (int j = 0; j < n_args; j++)
2100  {
2101  // Can't fast return here to skip empty matrices as something
2102  // like cat (1,[],single ([])) must return an empty matrix of
2103  // the right type.
2104  tmp = do_cat_op (tmp, args(j), ra_idx);
2105 
2106  if (error_state)
2107  return retval;
2108 
2109  dim_vector dv_tmp = args(j).dims ();
2110 
2111  if (dim >= dv_len)
2112  {
2113  if (j > 1)
2114  error ("%s: indexing error", fname.c_str ());
2115  break;
2116  }
2117  else
2118  ra_idx (dim) += (dim < dv_tmp.length () ?
2119  dv_tmp (dim) : 1);
2120  }
2121  retval = tmp;
2122  }
2123  }
2124  else
2125  print_usage ();
2126 
2127  return retval;
2128 }
2129 
2130 DEFUN (horzcat, args, ,
2131  "-*- texinfo -*-\n\
2132 @deftypefn {Built-in Function} {} horzcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2133 Return the horizontal concatenation of N-D array objects, @var{array1},\n\
2134 @var{array2}, @dots{}, @var{arrayN} along dimension 2.\n\
2135 \n\
2136 Arrays may also be concatenated horizontally using the syntax for creating\n\
2137 new matrices. For example:\n\
2138 \n\
2139 @example\n\
2140 @var{hcat} = [ @var{array1}, @var{array2}, @dots{} ]\n\
2141 @end example\n\
2142 @seealso{cat, vertcat}\n\
2143 @end deftypefn")
2144 {
2145  return do_cat (args, -2, "horzcat");
2146 }
2147 
2148 /*
2149 ## Test concatenation with all zero matrices
2150 %!assert (horzcat ("", 65*ones (1,10)), "AAAAAAAAAA");
2151 %!assert (horzcat (65*ones (1,10), ""), "AAAAAAAAAA");
2152 
2153 %!assert (class (horzcat (int64 (1), int64 (1))), "int64")
2154 %!assert (class (horzcat (int64 (1), int32 (1))), "int64")
2155 %!assert (class (horzcat (int64 (1), int16 (1))), "int64")
2156 %!assert (class (horzcat (int64 (1), int8 (1))), "int64")
2157 %!assert (class (horzcat (int64 (1), uint64 (1))), "int64")
2158 %!assert (class (horzcat (int64 (1), uint32 (1))), "int64")
2159 %!assert (class (horzcat (int64 (1), uint16 (1))), "int64")
2160 %!assert (class (horzcat (int64 (1), uint8 (1))), "int64")
2161 %!assert (class (horzcat (int64 (1), single (1))), "int64")
2162 %!assert (class (horzcat (int64 (1), double (1))), "int64")
2163 %!assert (class (horzcat (int64 (1), cell (1))), "cell")
2164 %!assert (class (horzcat (int64 (1), true)), "int64")
2165 %!assert (class (horzcat (int64 (1), "a")), "char")
2166 
2167 %!assert (class (horzcat (int32 (1), int64 (1))), "int32")
2168 %!assert (class (horzcat (int32 (1), int32 (1))), "int32")
2169 %!assert (class (horzcat (int32 (1), int16 (1))), "int32")
2170 %!assert (class (horzcat (int32 (1), int8 (1))), "int32")
2171 %!assert (class (horzcat (int32 (1), uint64 (1))), "int32")
2172 %!assert (class (horzcat (int32 (1), uint32 (1))), "int32")
2173 %!assert (class (horzcat (int32 (1), uint16 (1))), "int32")
2174 %!assert (class (horzcat (int32 (1), uint8 (1))), "int32")
2175 %!assert (class (horzcat (int32 (1), single (1))), "int32")
2176 %!assert (class (horzcat (int32 (1), double (1))), "int32")
2177 %!assert (class (horzcat (int32 (1), cell (1))), "cell")
2178 %!assert (class (horzcat (int32 (1), true)), "int32")
2179 %!assert (class (horzcat (int32 (1), "a")), "char")
2180 
2181 %!assert (class (horzcat (int16 (1), int64 (1))), "int16")
2182 %!assert (class (horzcat (int16 (1), int32 (1))), "int16")
2183 %!assert (class (horzcat (int16 (1), int16 (1))), "int16")
2184 %!assert (class (horzcat (int16 (1), int8 (1))), "int16")
2185 %!assert (class (horzcat (int16 (1), uint64 (1))), "int16")
2186 %!assert (class (horzcat (int16 (1), uint32 (1))), "int16")
2187 %!assert (class (horzcat (int16 (1), uint16 (1))), "int16")
2188 %!assert (class (horzcat (int16 (1), uint8 (1))), "int16")
2189 %!assert (class (horzcat (int16 (1), single (1))), "int16")
2190 %!assert (class (horzcat (int16 (1), double (1))), "int16")
2191 %!assert (class (horzcat (int16 (1), cell (1))), "cell")
2192 %!assert (class (horzcat (int16 (1), true)), "int16")
2193 %!assert (class (horzcat (int16 (1), "a")), "char")
2194 
2195 %!assert (class (horzcat (int8 (1), int64 (1))), "int8")
2196 %!assert (class (horzcat (int8 (1), int32 (1))), "int8")
2197 %!assert (class (horzcat (int8 (1), int16 (1))), "int8")
2198 %!assert (class (horzcat (int8 (1), int8 (1))), "int8")
2199 %!assert (class (horzcat (int8 (1), uint64 (1))), "int8")
2200 %!assert (class (horzcat (int8 (1), uint32 (1))), "int8")
2201 %!assert (class (horzcat (int8 (1), uint16 (1))), "int8")
2202 %!assert (class (horzcat (int8 (1), uint8 (1))), "int8")
2203 %!assert (class (horzcat (int8 (1), single (1))), "int8")
2204 %!assert (class (horzcat (int8 (1), double (1))), "int8")
2205 %!assert (class (horzcat (int8 (1), cell (1))), "cell")
2206 %!assert (class (horzcat (int8 (1), true)), "int8")
2207 %!assert (class (horzcat (int8 (1), "a")), "char")
2208 
2209 %!assert (class (horzcat (uint64 (1), int64 (1))), "uint64")
2210 %!assert (class (horzcat (uint64 (1), int32 (1))), "uint64")
2211 %!assert (class (horzcat (uint64 (1), int16 (1))), "uint64")
2212 %!assert (class (horzcat (uint64 (1), int8 (1))), "uint64")
2213 %!assert (class (horzcat (uint64 (1), uint64 (1))), "uint64")
2214 %!assert (class (horzcat (uint64 (1), uint32 (1))), "uint64")
2215 %!assert (class (horzcat (uint64 (1), uint16 (1))), "uint64")
2216 %!assert (class (horzcat (uint64 (1), uint8 (1))), "uint64")
2217 %!assert (class (horzcat (uint64 (1), single (1))), "uint64")
2218 %!assert (class (horzcat (uint64 (1), double (1))), "uint64")
2219 %!assert (class (horzcat (uint64 (1), cell (1))), "cell")
2220 %!assert (class (horzcat (uint64 (1), true)), "uint64")
2221 %!assert (class (horzcat (uint64 (1), "a")), "char")
2222 
2223 %!assert (class (horzcat (uint32 (1), int64 (1))), "uint32")
2224 %!assert (class (horzcat (uint32 (1), int32 (1))), "uint32")
2225 %!assert (class (horzcat (uint32 (1), int16 (1))), "uint32")
2226 %!assert (class (horzcat (uint32 (1), int8 (1))), "uint32")
2227 %!assert (class (horzcat (uint32 (1), uint64 (1))), "uint32")
2228 %!assert (class (horzcat (uint32 (1), uint32 (1))), "uint32")
2229 %!assert (class (horzcat (uint32 (1), uint16 (1))), "uint32")
2230 %!assert (class (horzcat (uint32 (1), uint8 (1))), "uint32")
2231 %!assert (class (horzcat (uint32 (1), single (1))), "uint32")
2232 %!assert (class (horzcat (uint32 (1), double (1))), "uint32")
2233 %!assert (class (horzcat (uint32 (1), cell (1))), "cell")
2234 %!assert (class (horzcat (uint32 (1), true)), "uint32")
2235 %!assert (class (horzcat (uint32 (1), "a")), "char")
2236 
2237 %!assert (class (horzcat (uint16 (1), int64 (1))), "uint16")
2238 %!assert (class (horzcat (uint16 (1), int32 (1))), "uint16")
2239 %!assert (class (horzcat (uint16 (1), int16 (1))), "uint16")
2240 %!assert (class (horzcat (uint16 (1), int8 (1))), "uint16")
2241 %!assert (class (horzcat (uint16 (1), uint64 (1))), "uint16")
2242 %!assert (class (horzcat (uint16 (1), uint32 (1))), "uint16")
2243 %!assert (class (horzcat (uint16 (1), uint16 (1))), "uint16")
2244 %!assert (class (horzcat (uint16 (1), uint8 (1))), "uint16")
2245 %!assert (class (horzcat (uint16 (1), single (1))), "uint16")
2246 %!assert (class (horzcat (uint16 (1), double (1))), "uint16")
2247 %!assert (class (horzcat (uint16 (1), cell (1))), "cell")
2248 %!assert (class (horzcat (uint16 (1), true)), "uint16")
2249 %!assert (class (horzcat (uint16 (1), "a")), "char")
2250 
2251 %!assert (class (horzcat (uint8 (1), int64 (1))), "uint8")
2252 %!assert (class (horzcat (uint8 (1), int32 (1))), "uint8")
2253 %!assert (class (horzcat (uint8 (1), int16 (1))), "uint8")
2254 %!assert (class (horzcat (uint8 (1), int8 (1))), "uint8")
2255 %!assert (class (horzcat (uint8 (1), uint64 (1))), "uint8")
2256 %!assert (class (horzcat (uint8 (1), uint32 (1))), "uint8")
2257 %!assert (class (horzcat (uint8 (1), uint16 (1))), "uint8")
2258 %!assert (class (horzcat (uint8 (1), uint8 (1))), "uint8")
2259 %!assert (class (horzcat (uint8 (1), single (1))), "uint8")
2260 %!assert (class (horzcat (uint8 (1), double (1))), "uint8")
2261 %!assert (class (horzcat (uint8 (1), cell (1))), "cell")
2262 %!assert (class (horzcat (uint8 (1), true)), "uint8")
2263 %!assert (class (horzcat (uint8 (1), "a")), "char")
2264 
2265 %!assert (class (horzcat (single (1), int64 (1))), "int64")
2266 %!assert (class (horzcat (single (1), int32 (1))), "int32")
2267 %!assert (class (horzcat (single (1), int16 (1))), "int16")
2268 %!assert (class (horzcat (single (1), int8 (1))), "int8")
2269 %!assert (class (horzcat (single (1), uint64 (1))), "uint64")
2270 %!assert (class (horzcat (single (1), uint32 (1))), "uint32")
2271 %!assert (class (horzcat (single (1), uint16 (1))), "uint16")
2272 %!assert (class (horzcat (single (1), uint8 (1))), "uint8")
2273 %!assert (class (horzcat (single (1), single (1))), "single")
2274 %!assert (class (horzcat (single (1), double (1))), "single")
2275 %!assert (class (horzcat (single (1), cell (1))), "cell")
2276 %!assert (class (horzcat (single (1), true)), "single")
2277 %!assert (class (horzcat (single (1), "a")), "char")
2278 
2279 %!assert (class (horzcat (double (1), int64 (1))), "int64")
2280 %!assert (class (horzcat (double (1), int32 (1))), "int32")
2281 %!assert (class (horzcat (double (1), int16 (1))), "int16")
2282 %!assert (class (horzcat (double (1), int8 (1))), "int8")
2283 %!assert (class (horzcat (double (1), uint64 (1))), "uint64")
2284 %!assert (class (horzcat (double (1), uint32 (1))), "uint32")
2285 %!assert (class (horzcat (double (1), uint16 (1))), "uint16")
2286 %!assert (class (horzcat (double (1), uint8 (1))), "uint8")
2287 %!assert (class (horzcat (double (1), single (1))), "single")
2288 %!assert (class (horzcat (double (1), double (1))), "double")
2289 %!assert (class (horzcat (double (1), cell (1))), "cell")
2290 %!assert (class (horzcat (double (1), true)), "double")
2291 %!assert (class (horzcat (double (1), "a")), "char")
2292 
2293 %!assert (class (horzcat (cell (1), int64 (1))), "cell")
2294 %!assert (class (horzcat (cell (1), int32 (1))), "cell")
2295 %!assert (class (horzcat (cell (1), int16 (1))), "cell")
2296 %!assert (class (horzcat (cell (1), int8 (1))), "cell")
2297 %!assert (class (horzcat (cell (1), uint64 (1))), "cell")
2298 %!assert (class (horzcat (cell (1), uint32 (1))), "cell")
2299 %!assert (class (horzcat (cell (1), uint16 (1))), "cell")
2300 %!assert (class (horzcat (cell (1), uint8 (1))), "cell")
2301 %!assert (class (horzcat (cell (1), single (1))), "cell")
2302 %!assert (class (horzcat (cell (1), double (1))), "cell")
2303 %!assert (class (horzcat (cell (1), cell (1))), "cell")
2304 %!assert (class (horzcat (cell (1), true)), "cell")
2305 %!assert (class (horzcat (cell (1), "a")), "cell")
2306 
2307 %!assert (class (horzcat (true, int64 (1))), "int64")
2308 %!assert (class (horzcat (true, int32 (1))), "int32")
2309 %!assert (class (horzcat (true, int16 (1))), "int16")
2310 %!assert (class (horzcat (true, int8 (1))), "int8")
2311 %!assert (class (horzcat (true, uint64 (1))), "uint64")
2312 %!assert (class (horzcat (true, uint32 (1))), "uint32")
2313 %!assert (class (horzcat (true, uint16 (1))), "uint16")
2314 %!assert (class (horzcat (true, uint8 (1))), "uint8")
2315 %!assert (class (horzcat (true, single (1))), "single")
2316 %!assert (class (horzcat (true, double (1))), "double")
2317 %!assert (class (horzcat (true, cell (1))), "cell")
2318 %!assert (class (horzcat (true, true)), "logical")
2319 %!assert (class (horzcat (true, "a")), "char")
2320 
2321 %!assert (class (horzcat ("a", int64 (1))), "char")
2322 %!assert (class (horzcat ("a", int32 (1))), "char")
2323 %!assert (class (horzcat ("a", int16 (1))), "char")
2324 %!assert (class (horzcat ("a", int8 (1))), "char")
2325 %!assert (class (horzcat ("a", int64 (1))), "char")
2326 %!assert (class (horzcat ("a", int32 (1))), "char")
2327 %!assert (class (horzcat ("a", int16 (1))), "char")
2328 %!assert (class (horzcat ("a", int8 (1))), "char")
2329 %!assert (class (horzcat ("a", single (1))), "char")
2330 %!assert (class (horzcat ("a", double (1))), "char")
2331 %!assert (class (horzcat ("a", cell (1))), "cell")
2332 %!assert (class (horzcat ("a", true)), "char")
2333 %!assert (class (horzcat ("a", "a")), "char")
2334 
2335 %!assert (class (horzcat (cell (1), struct ("foo", "bar"))), "cell")
2336 
2337 %!error horzcat (struct ("foo", "bar"), cell (1))
2338 */
2339 
2340 DEFUN (vertcat, args, ,
2341  "-*- texinfo -*-\n\
2342 @deftypefn {Built-in Function} {} vertcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2343 Return the vertical concatenation of N-D array objects, @var{array1},\n\
2344 @var{array2}, @dots{}, @var{arrayN} along dimension 1.\n\
2345 \n\
2346 Arrays may also be concatenated vertically using the syntax for creating\n\
2347 new matrices. For example:\n\
2348 \n\
2349 @example\n\
2350 @var{vcat} = [ @var{array1}; @var{array2}; @dots{} ]\n\
2351 @end example\n\
2352 @seealso{cat, horzcat}\n\
2353 @end deftypefn")
2354 {
2355  return do_cat (args, -1, "vertcat");
2356 }
2357 
2358 /*
2359 %!test
2360 %! c = {"foo"; "bar"; "bazoloa"};
2361 %! assert (vertcat (c, "a", "bc", "def"), {"foo"; "bar"; "bazoloa"; "a"; "bc"; "def"});
2362 */
2363 
2364 DEFUN (cat, args, ,
2365  "-*- texinfo -*-\n\
2366 @deftypefn {Built-in Function} {} cat (@var{dim}, @var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2367 Return the concatenation of N-D array objects, @var{array1},\n\
2368 @var{array2}, @dots{}, @var{arrayN} along dimension @var{dim}.\n\
2369 \n\
2370 @example\n\
2371 @group\n\
2372 A = ones (2, 2);\n\
2373 B = zeros (2, 2);\n\
2374 cat (2, A, B)\n\
2375  @result{} 1 1 0 0\n\
2376  1 1 0 0\n\
2377 @end group\n\
2378 @end example\n\
2379 \n\
2380 Alternatively, we can concatenate @var{A} and @var{B} along the\n\
2381 second dimension in the following way:\n\
2382 \n\
2383 @example\n\
2384 @group\n\
2385 [A, B]\n\
2386 @end group\n\
2387 @end example\n\
2388 \n\
2389 @var{dim} can be larger than the dimensions of the N-D array objects\n\
2390 and the result will thus have @var{dim} dimensions as the\n\
2391 following example shows:\n\
2392 \n\
2393 @example\n\
2394 @group\n\
2395 cat (4, ones (2, 2), zeros (2, 2))\n\
2396  @result{} ans(:,:,1,1) =\n\
2397 \n\
2398  1 1\n\
2399  1 1\n\
2400 \n\
2401  ans(:,:,1,2) =\n\
2402 \n\
2403  0 0\n\
2404  0 0\n\
2405 @end group\n\
2406 @end example\n\
2407 @seealso{horzcat, vertcat}\n\
2408 @end deftypefn")
2409 {
2410  octave_value retval;
2411 
2412  if (args.length () > 0)
2413  {
2414  int dim = args(0).int_value () - 1;
2415 
2416  if (! error_state)
2417  {
2418  if (dim >= 0)
2419  retval = do_cat (args.slice (1, args.length () - 1), dim, "cat");
2420  else
2421  error ("cat: DIM must be a valid dimension");
2422  }
2423  else
2424  error ("cat: DIM must be an integer");
2425  }
2426  else
2427  print_usage ();
2428 
2429  return retval;
2430 }
2431 
2432 /*
2433 %!function ret = __testcat (t1, t2, tr, cmplx)
2434 %! assert (cat (1, cast ([], t1), cast ([], t2)), cast ([], tr));
2435 %!
2436 %! assert (cat (1, cast (1, t1), cast (2, t2)), cast ([1; 2], tr));
2437 %! assert (cat (1, cast (1, t1), cast ([2; 3], t2)), cast ([1; 2; 3], tr));
2438 %! assert (cat (1, cast ([1; 2], t1), cast (3, t2)), cast ([1; 2; 3], tr));
2439 %! assert (cat (1, cast ([1; 2], t1), cast ([3; 4], t2)), cast ([1; 2; 3; 4], tr));
2440 %! assert (cat (2, cast (1, t1), cast (2, t2)), cast ([1, 2], tr));
2441 %! assert (cat (2, cast (1, t1), cast ([2, 3], t2)), cast ([1, 2, 3], tr));
2442 %! assert (cat (2, cast ([1, 2], t1), cast (3, t2)), cast ([1, 2, 3], tr));
2443 %! assert (cat (2, cast ([1, 2], t1), cast ([3, 4], t2)), cast ([1, 2, 3, 4], tr));
2444 %!
2445 %! assert ([cast(1, t1); cast(2, t2)], cast ([1; 2], tr));
2446 %! assert ([cast(1, t1); cast([2; 3], t2)], cast ([1; 2; 3], tr));
2447 %! assert ([cast([1; 2], t1); cast(3, t2)], cast ([1; 2; 3], tr));
2448 %! assert ([cast([1; 2], t1); cast([3; 4], t2)], cast ([1; 2; 3; 4], tr));
2449 %! assert ([cast(1, t1), cast(2, t2)], cast ([1, 2], tr));
2450 %! assert ([cast(1, t1), cast([2, 3], t2)], cast ([1, 2, 3], tr));
2451 %! assert ([cast([1, 2], t1), cast(3, t2)], cast ([1, 2, 3], tr));
2452 %! assert ([cast([1, 2], t1), cast([3, 4], t2)], cast ([1, 2, 3, 4], tr));
2453 %!
2454 %! if (nargin == 3 || cmplx)
2455 %! assert (cat (1, cast (1i, t1), cast (2, t2)), cast ([1i; 2], tr));
2456 %! assert (cat (1, cast (1i, t1), cast ([2; 3], t2)), cast ([1i; 2; 3], tr));
2457 %! assert (cat (1, cast ([1i; 2], t1), cast (3, t2)), cast ([1i; 2; 3], tr));
2458 %! assert (cat (1, cast ([1i; 2], t1), cast ([3; 4], t2)), cast ([1i; 2; 3; 4], tr));
2459 %! assert (cat (2, cast (1i, t1), cast (2, t2)), cast ([1i, 2], tr));
2460 %! assert (cat (2, cast (1i, t1), cast ([2, 3], t2)), cast ([1i, 2, 3], tr));
2461 %! assert (cat (2, cast ([1i, 2], t1), cast (3, t2)), cast ([1i, 2, 3], tr));
2462 %! assert (cat (2, cast ([1i, 2], t1), cast ([3, 4], t2)), cast ([1i, 2, 3, 4], tr));
2463 %!
2464 %! assert ([cast(1i, t1); cast(2, t2)], cast ([1i; 2], tr));
2465 %! assert ([cast(1i, t1); cast([2; 3], t2)], cast ([1i; 2; 3], tr));
2466 %! assert ([cast([1i; 2], t1); cast(3, t2)], cast ([1i; 2; 3], tr));
2467 %! assert ([cast([1i; 2], t1); cast([3; 4], t2)], cast ([1i; 2; 3; 4], tr));
2468 %! assert ([cast(1i, t1), cast(2, t2)], cast ([1i, 2], tr));
2469 %! assert ([cast(1i, t1), cast([2, 3], t2)], cast ([1i, 2, 3], tr));
2470 %! assert ([cast([1i, 2], t1), cast(3, t2)], cast ([1i, 2, 3], tr));
2471 %! assert ([cast([1i, 2], t1), cast([3, 4], t2)], cast ([1i, 2, 3, 4], tr));
2472 %!
2473 %! assert (cat (1, cast (1, t1), cast (2i, t2)), cast ([1; 2i], tr));
2474 %! assert (cat (1, cast (1, t1), cast ([2i; 3], t2)), cast ([1; 2i; 3], tr));
2475 %! assert (cat (1, cast ([1; 2], t1), cast (3i, t2)), cast ([1; 2; 3i], tr));
2476 %! assert (cat (1, cast ([1; 2], t1), cast ([3i; 4], t2)), cast ([1; 2; 3i; 4], tr));
2477 %! assert (cat (2, cast (1, t1), cast (2i, t2)), cast ([1, 2i], tr));
2478 %! assert (cat (2, cast (1, t1), cast ([2i, 3], t2)), cast ([1, 2i, 3], tr));
2479 %! assert (cat (2, cast ([1, 2], t1), cast (3i, t2)), cast ([1, 2, 3i], tr));
2480 %! assert (cat (2, cast ([1, 2], t1), cast ([3i, 4], t2)), cast ([1, 2, 3i, 4], tr));
2481 %!
2482 %! assert ([cast(1, t1); cast(2i, t2)], cast ([1; 2i], tr));
2483 %! assert ([cast(1, t1); cast([2i; 3], t2)], cast ([1; 2i; 3], tr));
2484 %! assert ([cast([1; 2], t1); cast(3i, t2)], cast ([1; 2; 3i], tr));
2485 %! assert ([cast([1; 2], t1); cast([3i; 4], t2)], cast ([1; 2; 3i; 4], tr));
2486 %! assert ([cast(1, t1), cast(2i, t2)], cast ([1, 2i], tr));
2487 %! assert ([cast(1, t1), cast([2i, 3], t2)], cast ([1, 2i, 3], tr));
2488 %! assert ([cast([1, 2], t1), cast(3i, t2)], cast ([1, 2, 3i], tr));
2489 %! assert ([cast([1, 2], t1), cast([3i, 4], t2)], cast ([1, 2, 3i, 4], tr));
2490 %!
2491 %! assert (cat (1, cast (1i, t1), cast (2i, t2)), cast ([1i; 2i], tr));
2492 %! assert (cat (1, cast (1i, t1), cast ([2i; 3], t2)), cast ([1i; 2i; 3], tr));
2493 %! assert (cat (1, cast ([1i; 2], t1), cast (3i, t2)), cast ([1i; 2; 3i], tr));
2494 %! assert (cat (1, cast ([1i; 2], t1), cast ([3i; 4], t2)), cast ([1i; 2; 3i; 4], tr));
2495 %! assert (cat (2, cast (1i, t1), cast (2i, t2)), cast ([1i, 2i], tr));
2496 %! assert (cat (2, cast (1i, t1), cast ([2i, 3], t2)), cast ([1i, 2i, 3], tr));
2497 %! assert (cat (2, cast ([1i, 2], t1), cast (3i, t2)), cast ([1i, 2, 3i], tr));
2498 %! assert (cat (2, cast ([1i, 2], t1), cast ([3i, 4], t2)), cast ([1i, 2, 3i, 4], tr));
2499 %!
2500 %! assert ([cast(1i, t1); cast(2i, t2)], cast ([1i; 2i], tr));
2501 %! assert ([cast(1i, t1); cast([2i; 3], t2)], cast ([1i; 2i; 3], tr));
2502 %! assert ([cast([1i; 2], t1); cast(3i, t2)], cast ([1i; 2; 3i], tr));
2503 %! assert ([cast([1i; 2], t1); cast([3i; 4], t2)], cast ([1i; 2; 3i; 4], tr));
2504 %! assert ([cast(1i, t1), cast(2i, t2)], cast ([1i, 2i], tr));
2505 %! assert ([cast(1i, t1), cast([2i, 3], t2)], cast ([1i, 2i, 3], tr));
2506 %! assert ([cast([1i, 2], t1), cast(3i, t2)], cast ([1i, 2, 3i], tr));
2507 %! assert ([cast([1i, 2], t1), cast([3i, 4], t2)], cast ([1i, 2, 3i, 4], tr));
2508 %! endif
2509 %! ret = true;
2510 %!endfunction
2511 
2512 %!assert (__testcat ("double", "double", "double"))
2513 %!assert (__testcat ("single", "double", "single"))
2514 %!assert (__testcat ("double", "single", "single"))
2515 %!assert (__testcat ("single", "single", "single"))
2516 
2517 %!assert (__testcat ("double", "int8", "int8", false))
2518 %!assert (__testcat ("int8", "double", "int8", false))
2519 %!assert (__testcat ("single", "int8", "int8", false))
2520 %!assert (__testcat ("int8", "single", "int8", false))
2521 %!assert (__testcat ("int8", "int8", "int8", false))
2522 %!assert (__testcat ("double", "int16", "int16", false))
2523 %!assert (__testcat ("int16", "double", "int16", false))
2524 %!assert (__testcat ("single", "int16", "int16", false))
2525 %!assert (__testcat ("int16", "single", "int16", false))
2526 %!assert (__testcat ("int16", "int16", "int16", false))
2527 %!assert (__testcat ("double", "int32", "int32", false))
2528 %!assert (__testcat ("int32", "double", "int32", false))
2529 %!assert (__testcat ("single", "int32", "int32", false))
2530 %!assert (__testcat ("int32", "single", "int32", false))
2531 %!assert (__testcat ("int32", "int32", "int32", false))
2532 %!assert (__testcat ("double", "int64", "int64", false))
2533 %!assert (__testcat ("int64", "double", "int64", false))
2534 %!assert (__testcat ("single", "int64", "int64", false))
2535 %!assert (__testcat ("int64", "single", "int64", false))
2536 %!assert (__testcat ("int64", "int64", "int64", false))
2537 
2538 %!assert (__testcat ("double", "uint8", "uint8", false))
2539 %!assert (__testcat ("uint8", "double", "uint8", false))
2540 %!assert (__testcat ("single", "uint8", "uint8", false))
2541 %!assert (__testcat ("uint8", "single", "uint8", false))
2542 %!assert (__testcat ("uint8", "uint8", "uint8", false))
2543 %!assert (__testcat ("double", "uint16", "uint16", false))
2544 %!assert (__testcat ("uint16", "double", "uint16", false))
2545 %!assert (__testcat ("single", "uint16", "uint16", false))
2546 %!assert (__testcat ("uint16", "single", "uint16", false))
2547 %!assert (__testcat ("uint16", "uint16", "uint16", false))
2548 %!assert (__testcat ("double", "uint32", "uint32", false))
2549 %!assert (__testcat ("uint32", "double", "uint32", false))
2550 %!assert (__testcat ("single", "uint32", "uint32", false))
2551 %!assert (__testcat ("uint32", "single", "uint32", false))
2552 %!assert (__testcat ("uint32", "uint32", "uint32", false))
2553 %!assert (__testcat ("double", "uint64", "uint64", false))
2554 %!assert (__testcat ("uint64", "double", "uint64", false))
2555 %!assert (__testcat ("single", "uint64", "uint64", false))
2556 %!assert (__testcat ("uint64", "single", "uint64", false))
2557 %!assert (__testcat ("uint64", "uint64", "uint64", false))
2558 
2559 %!assert (cat (3, [], [1,2;3,4]), [1,2;3,4])
2560 %!assert (cat (3, [1,2;3,4], []), [1,2;3,4])
2561 %!assert (cat (3, [], [1,2;3,4], []), [1,2;3,4])
2562 %!assert (cat (3, [], [], []), zeros (0, 0, 3))
2563 
2564 %!assert (cat (3, [], [], 1, 2), cat (3, 1, 2))
2565 %!assert (cat (3, [], [], [1,2;3,4]), [1,2;3,4])
2566 %!assert (cat (4, [], [], [1,2;3,4]), [1,2;3,4])
2567 
2568 %!assert ([zeros(3,2,2); ones(1,2,2)], repmat ([0;0;0;1],[1,2,2]))
2569 %!assert ([zeros(3,2,2); ones(1,2,2)], vertcat (zeros (3,2,2), ones (1,2,2)))
2570 
2571 %!error <dimension mismatch> cat (3, cat (3, [], []), [1,2;3,4])
2572 %!error <dimension mismatch> cat (3, zeros (0, 0, 2), [1,2;3,4])
2573 */
2574 
2575 static octave_value
2576 do_permute (const octave_value_list& args, bool inv)
2577 {
2578  octave_value retval;
2579 
2580  if (args.length () == 2 && args(1).length () >= args(1).ndims ())
2581  {
2582  Array<int> vec = args(1).int_vector_value ();
2583 
2584  // FIXME: maybe we should create an idx_vector object
2585  // here and pass that to permute?
2586 
2587  int n = vec.length ();
2588 
2589  for (int i = 0; i < n; i++)
2590  vec(i)--;
2591 
2592  octave_value ret = args(0).permute (vec, inv);
2593 
2594  if (! error_state)
2595  retval = ret;
2596  }
2597  else
2598  print_usage ();
2599 
2600  return retval;
2601 }
2602 
2603 DEFUN (permute, args, ,
2604  "-*- texinfo -*-\n\
2605 @deftypefn {Built-in Function} {} permute (@var{A}, @var{perm})\n\
2606 Return the generalized transpose for an N-D array object @var{A}.\n\
2607 \n\
2608 The permutation vector @var{perm} must contain the elements\n\
2609 @code{1:ndims (A)} (in any order, but each element must appear only once).\n\
2610 \n\
2611 The @var{N}th dimension of @var{A} gets remapped to dimension\n\
2612 @code{@var{PERM}(@var{N})}. For example:\n\
2613 \n\
2614 @example\n\
2615 @group\n\
2616 @var{x} = zeros ([2, 3, 5, 7]);\n\
2617 size (@var{x})\n\
2618  @result{} 2 3 5 7\n\
2619 \n\
2620 size (permute (@var{x}, [2, 1, 3, 4]))\n\
2621  @result{} 3 2 5 7\n\
2622 \n\
2623 size (permute (@var{x}, [1, 3, 4, 2]))\n\
2624  @result{} 2 5 7 3\n\
2625 \n\
2626 ## The identity permutation\n\
2627 size (permute (@var{x}, [1, 2, 3, 4]))\n\
2628  @result{} 2 3 5 7\n\
2629 @end group\n\
2630 @end example\n\
2631 @seealso{ipermute}\n\
2632 @end deftypefn")
2633 {
2634  return do_permute (args, false);
2635 }
2636 
2637 DEFUN (ipermute, args, ,
2638  "-*- texinfo -*-\n\
2639 @deftypefn {Built-in Function} {} ipermute (@var{A}, @var{iperm})\n\
2640 The inverse of the @code{permute} function.\n\
2641 \n\
2642 The expression\n\
2643 \n\
2644 @example\n\
2645 ipermute (permute (A, perm), perm)\n\
2646 @end example\n\
2647 \n\
2648 @noindent\n\
2649 returns the original array @var{A}.\n\
2650 @seealso{permute}\n\
2651 @end deftypefn")
2652 {
2653  return do_permute (args, true);
2654 }
2655 
2656 DEFUN (length, args, ,
2657  "-*- texinfo -*-\n\
2658 @deftypefn {Built-in Function} {} length (@var{a})\n\
2659 Return the length of the object @var{a}.\n\
2660 \n\
2661 The length is 0 for empty objects, 1 for scalars, and the number of elements\n\
2662 for vectors. For matrix objects, the length is the number of rows or\n\
2663 columns, whichever is greater (this odd definition is used for compatibility\n\
2664 with @sc{matlab}).\n\
2665 @seealso{numel, size}\n\
2666 @end deftypefn")
2667 {
2668  octave_value retval;
2669 
2670  if (args.length () == 1)
2671  retval = args(0).length ();
2672  else
2673  print_usage ();
2674 
2675  return retval;
2676 }
2677 
2678 DEFUN (ndims, args, ,
2679  "-*- texinfo -*-\n\
2680 @deftypefn {Built-in Function} {} ndims (@var{a})\n\
2681 Return the number of dimensions of @var{a}.\n\
2682 \n\
2683 For any array, the result will always be greater than or equal to 2.\n\
2684 Trailing singleton dimensions are not counted.\n\
2685 \n\
2686 @example\n\
2687 @group\n\
2688 ndims (ones (4, 1, 2, 1))\n\
2689  @result{} 3\n\
2690 @end group\n\
2691 @end example\n\
2692 @seealso{size}\n\
2693 @end deftypefn")
2694 {
2695  octave_value retval;
2696 
2697  if (args.length () == 1)
2698  retval = args(0).ndims ();
2699  else
2700  print_usage ();
2701 
2702  return retval;
2703 }
2704 
2705 DEFUN (numel, args, ,
2706  "-*- texinfo -*-\n\
2707 @deftypefn {Built-in Function} {} numel (@var{a})\n\
2708 @deftypefnx {Built-in Function} {} numel (@var{a}, @var{idx1}, @var{idx2}, @dots{})\n\
2709 Return the number of elements in the object @var{a}.\n\
2710 \n\
2711 Optionally, if indices @var{idx1}, @var{idx2}, @dots{} are supplied,\n\
2712 return the number of elements that would result from the indexing\n\
2713 \n\
2714 @example\n\
2715 @var{a}(@var{idx1}, @var{idx2}, @dots{})\n\
2716 @end example\n\
2717 \n\
2718 Note that the indices do not have to be numerical. For example,\n\
2719 \n\
2720 @example\n\
2721 @group\n\
2722 @var{a} = 1;\n\
2723 @var{b} = ones (2, 3);\n\
2724 numel (@var{a}, @var{b})\n\
2725 @end group\n\
2726 @end example\n\
2727 \n\
2728 @noindent\n\
2729 will return 6, as this is the number of ways to index with @var{b}.\n\
2730 \n\
2731 This method is also called when an object appears as lvalue with cs-list\n\
2732 indexing, i.e., @code{object@{@dots{}@}} or @code{object(@dots{}).field}.\n\
2733 @seealso{size}\n\
2734 @end deftypefn")
2735 {
2736  octave_value retval;
2737  octave_idx_type nargin = args.length ();
2738 
2739  if (nargin == 1)
2740  retval = args(0).numel ();
2741  else if (nargin > 1)
2742  {
2743  // Don't use numel (const octave_value_list&) here as that corresponds to
2744  // an overloaded call, not to builtin!
2745  retval = dims_to_numel (args(0).dims (), args.slice (1, nargin-1));
2746  }
2747  else
2748  print_usage ();
2749 
2750  return retval;
2751 }
2752 
2753 DEFUN (size, args, nargout,
2754  "-*- texinfo -*-\n\
2755 @deftypefn {Built-in Function} {} size (@var{a})\n\
2756 @deftypefnx {Built-in Function} {} size (@var{a}, @var{dim})\n\
2757 Return the number of rows and columns of @var{a}.\n\
2758 \n\
2759 With one input argument and one output argument, the result is returned\n\
2760 in a row vector. If there are multiple output arguments, the number of\n\
2761 rows is assigned to the first, and the number of columns to the second,\n\
2762 etc. For example:\n\
2763 \n\
2764 @example\n\
2765 @group\n\
2766 size ([1, 2; 3, 4; 5, 6])\n\
2767  @result{} [ 3, 2 ]\n\
2768 \n\
2769 [nr, nc] = size ([1, 2; 3, 4; 5, 6])\n\
2770  @result{} nr = 3\n\
2771  @result{} nc = 2\n\
2772 @end group\n\
2773 @end example\n\
2774 \n\
2775 If given a second argument, @code{size} will return the size of the\n\
2776 corresponding dimension. For example,\n\
2777 \n\
2778 @example\n\
2779 @group\n\
2780 size ([1, 2; 3, 4; 5, 6], 2)\n\
2781  @result{} 2\n\
2782 @end group\n\
2783 @end example\n\
2784 \n\
2785 @noindent\n\
2786 returns the number of columns in the given matrix.\n\
2787 @seealso{numel, ndims, length, rows, columns}\n\
2788 @end deftypefn")
2789 {
2790  octave_value_list retval;
2791 
2792  int nargin = args.length ();
2793 
2794  if (nargin == 1)
2795  {
2796  const dim_vector dimensions = args(0).dims ();
2797 
2798  if (nargout > 1)
2799  {
2800  const dim_vector rdims = dimensions.redim (nargout);
2801  retval.resize (nargout);
2802  for (int i = 0; i < nargout; i++)
2803  retval(i) = rdims(i);
2804  }
2805  else
2806  {
2807  int ndims = dimensions.length ();
2808 
2809  NoAlias<Matrix> m (1, ndims);
2810 
2811  for (int i = 0; i < ndims; i++)
2812  m(i) = dimensions(i);
2813 
2814  retval(0) = m;
2815  }
2816  }
2817  else if (nargin == 2 && nargout < 2)
2818  {
2819  octave_idx_type nd = args(1).int_value (true);
2820 
2821  if (error_state)
2822  error ("size: DIM must be a scalar");
2823  else
2824  {
2825  const dim_vector dv = args(0).dims ();
2826 
2827  if (nd > 0)
2828  {
2829  if (nd <= dv.length ())
2830  retval(0) = dv(nd-1);
2831  else
2832  retval(0) = 1;
2833  }
2834  else
2835  error ("size: requested dimension DIM (= %d) out of range", nd);
2836  }
2837  }
2838  else
2839  print_usage ();
2840 
2841  return retval;
2842 }
2843 
2844 DEFUN (size_equal, args, ,
2845  "-*- texinfo -*-\n\
2846 @deftypefn {Built-in Function} {} size_equal (@var{a}, @var{b}, @dots{})\n\
2847 Return true if the dimensions of all arguments agree.\n\
2848 \n\
2849 Trailing singleton dimensions are ignored.\n\
2850 When called with a single or no argument @code{size_equal} returns true.\n\
2851 @seealso{size, numel, ndims}\n\
2852 @end deftypefn")
2853 {
2854  octave_value retval;
2855 
2856  int nargin = args.length ();
2857 
2858  retval = true;
2859 
2860  if (nargin >= 1)
2861  {
2862  dim_vector a_dims = args(0).dims ();
2863 
2864  for (int i = 1; i < nargin; ++i)
2865  {
2866  dim_vector b_dims = args(i).dims ();
2867 
2868  if (a_dims != b_dims)
2869  {
2870  retval = false;
2871  break;
2872  }
2873  }
2874  }
2875 
2876  return retval;
2877 }
2878 
2879 DEFUN (nnz, args, ,
2880  "-*- texinfo -*-\n\
2881 @deftypefn {Built-in Function} {@var{n} =} nnz (@var{a})\n\
2882 Return the number of nonzero elements in @var{a}.\n\
2883 @seealso{nzmax, nonzeros, find}\n\
2884 @end deftypefn")
2885 {
2886  octave_value retval;
2887 
2888  if (args.length () == 1)
2889  retval = args(0).nnz ();
2890  else
2891  print_usage ();
2892 
2893  return retval;
2894 }
2895 
2896 DEFUN (nzmax, args, ,
2897  "-*- texinfo -*-\n\
2898 @deftypefn {Built-in Function} {@var{n} =} nzmax (@var{SM})\n\
2899 Return the amount of storage allocated to the sparse matrix @var{SM}.\n\
2900 \n\
2901 Note that Octave tends to crop unused memory at the first opportunity\n\
2902 for sparse objects. Thus, in general the value of @code{nzmax} will be the\n\
2903 same as @code{nnz} except for some cases of user-created sparse objects.\n\
2904 @seealso{nnz, spalloc, sparse}\n\
2905 @end deftypefn")
2906 {
2907  octave_value retval;
2908 
2909  if (args.length () == 1)
2910  retval = args(0).nzmax ();
2911  else
2912  print_usage ();
2913 
2914  return retval;
2915 }
2916 
2917 DEFUN (rows, args, ,
2918  "-*- texinfo -*-\n\
2919 @deftypefn {Built-in Function} {} rows (@var{a})\n\
2920 Return the number of rows of @var{a}.\n\
2921 @seealso{columns, size, length, numel, isscalar, isvector, ismatrix}\n\
2922 @end deftypefn")
2923 {
2924  octave_value retval;
2925 
2926  if (args.length () == 1)
2927  retval = args(0).rows ();
2928  else
2929  print_usage ();
2930 
2931  return retval;
2932 }
2933 
2934 DEFUN (columns, args, ,
2935  "-*- texinfo -*-\n\
2936 @deftypefn {Built-in Function} {} columns (@var{a})\n\
2937 Return the number of columns of @var{a}.\n\
2938 @seealso{rows, size, length, numel, isscalar, isvector, ismatrix}\n\
2939 @end deftypefn")
2940 {
2941  octave_value retval;
2942 
2943  if (args.length () == 1)
2944  retval = args(0).columns ();
2945  else
2946  print_usage ();
2947 
2948  return retval;
2949 }
2950 
2951 DEFUN (sum, args, ,
2952  "-*- texinfo -*-\n\
2953 @deftypefn {Built-in Function} {} sum (@var{x})\n\
2954 @deftypefnx {Built-in Function} {} sum (@var{x}, @var{dim})\n\
2955 @deftypefnx {Built-in Function} {} sum (@dots{}, \"native\")\n\
2956 @deftypefnx {Built-in Function} {} sum (@dots{}, \"double\")\n\
2957 @deftypefnx {Built-in Function} {} sum (@dots{}, \"extra\")\n\
2958 Sum of elements along dimension @var{dim}.\n\
2959 \n\
2960 If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
2961 \n\
2962 The optional @qcode{\"type\"} input determines the class of the variable\n\
2963 used for calculations. If the argument @qcode{\"native\"} is given, then\n\
2964 the operation is performed in the same type as the original argument, rather\n\
2965 than the default double type.\n\
2966 \n\
2967 For example:\n\
2968 \n\
2969 @example\n\
2970 @group\n\
2971 sum ([true, true])\n\
2972  @result{} 2\n\
2973 sum ([true, true], \"native\")\n\
2974  @result{} true\n\
2975 @end group\n\
2976 @end example\n\
2977 \n\
2978 On the contrary, if @qcode{\"double\"} is given, the sum is performed in\n\
2979 double precision even for single precision inputs.\n\
2980 \n\
2981 For double precision inputs, the @qcode{\"extra\"} option will use a more\n\
2982 accurate algorithm than straightforward summation. For single precision\n\
2983 inputs, @qcode{\"extra\"} is the same as @qcode{\"double\"}. Otherwise,\n\
2984 @qcode{\"extra\"} has no effect.\n\
2985 @seealso{cumsum, sumsq, prod}\n\
2986 @end deftypefn")
2987 {
2988  octave_value retval;
2989 
2990  int nargin = args.length ();
2991 
2992  bool isnative = false;
2993  bool isdouble = false;
2994  bool isextra = false;
2995 
2996  if (nargin > 1 && args(nargin - 1).is_string ())
2997  {
2998  std::string str = args(nargin - 1).string_value ();
2999 
3000  if (str == "native")
3001  isnative = true;
3002  else if (str == "double")
3003  isdouble = true;
3004  else if (str == "extra")
3005  isextra = true;
3006  else
3007  error ("sum: unrecognized type argument '%s'", str.c_str ());
3008  nargin --;
3009  }
3010 
3011  if (error_state)
3012  return retval;
3013 
3014  if (nargin == 1 || nargin == 2)
3015  {
3016  octave_value arg = args(0);
3017 
3018  int dim = -1;
3019  if (nargin == 2)
3020  {
3021  dim = args(1).int_value () - 1;
3022  if (dim < 0)
3023  error ("sum: invalid dimension DIM = %d", dim + 1);
3024  }
3025 
3026  if (! error_state)
3027  {
3028  switch (arg.builtin_type ())
3029  {
3030  case btyp_double:
3031  if (arg.is_sparse_type ())
3032  {
3033  if (isextra)
3034  warning ("sum: 'extra' not yet implemented for sparse matrices");
3035  retval = arg.sparse_matrix_value ().sum (dim);
3036  }
3037  else if (isextra)
3038  retval = arg.array_value ().xsum (dim);
3039  else
3040  retval = arg.array_value ().sum (dim);
3041  break;
3042  case btyp_complex:
3043  if (arg.is_sparse_type ())
3044  {
3045  if (isextra)
3046  warning ("sum: 'extra' not yet implemented for sparse matrices");
3047  retval = arg.sparse_complex_matrix_value ().sum (dim);
3048  }
3049  else if (isextra)
3050  retval = arg.complex_array_value ().xsum (dim);
3051  else
3052  retval = arg.complex_array_value ().sum (dim);
3053  break;
3054  case btyp_float:
3055  if (isdouble || isextra)
3056  retval = arg.float_array_value ().dsum (dim);
3057  else
3058  retval = arg.float_array_value ().sum (dim);
3059  break;
3060  case btyp_float_complex:
3061  if (isdouble || isextra)
3062  retval = arg.float_complex_array_value ().dsum (dim);
3063  else
3064  retval = arg.float_complex_array_value ().sum (dim);
3065  break;
3066 
3067 #define MAKE_INT_BRANCH(X) \
3068  case btyp_ ## X: \
3069  if (isnative) \
3070  retval = arg.X ## _array_value ().sum (dim); \
3071  else \
3072  retval = arg.X ## _array_value ().dsum (dim); \
3073  break;
3074  MAKE_INT_BRANCH (int8);
3075  MAKE_INT_BRANCH (int16);
3076  MAKE_INT_BRANCH (int32);
3077  MAKE_INT_BRANCH (int64);
3078  MAKE_INT_BRANCH (uint8);
3079  MAKE_INT_BRANCH (uint16);
3080  MAKE_INT_BRANCH (uint32);
3081  MAKE_INT_BRANCH (uint64);
3082 #undef MAKE_INT_BRANCH
3083 
3084  // GAGME: Accursed Matlab compatibility...
3085  case btyp_char:
3086  if (isextra)
3087  retval = arg.array_value (true).xsum (dim);
3088  else
3089  retval = arg.array_value (true).sum (dim);
3090  break;
3091  case btyp_bool:
3092  if (arg.is_sparse_type ())
3093  {
3094  if (isnative)
3095  retval = arg.sparse_bool_matrix_value ().any (dim);
3096  else
3097  retval = arg.sparse_bool_matrix_value ().sum (dim);
3098  }
3099  else if (isnative)
3100  retval = arg.bool_array_value ().any (dim);
3101  else
3102  retval = arg.bool_array_value ().sum (dim);
3103  break;
3104 
3105  default:
3106  gripe_wrong_type_arg ("sum", arg);
3107  }
3108  }
3109  }
3110  else
3111  print_usage ();
3112 
3113  return retval;
3114 }
3115 
3116 /*
3117 %!assert (sum ([1, 2, 3]), 6)
3118 %!assert (sum ([-1; -2; -3]), -6)
3119 %!assert (sum ([i, 2+i, -3+2i, 4]), 3+4i)
3120 %!assert (sum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [2+2i, 4+4i, 6+6i])
3121 
3122 %!assert (sum (single ([1, 2, 3])), single (6))
3123 %!assert (sum (single ([-1; -2; -3])), single (-6))
3124 %!assert (sum (single ([i, 2+i, -3+2i, 4])), single (3+4i))
3125 %!assert (sum (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single ([2+2i, 4+4i, 6+6i]))
3126 
3127 %!assert (sum ([1, 2; 3, 4], 1), [4, 6])
3128 %!assert (sum ([1, 2; 3, 4], 2), [3; 7])
3129 %!assert (sum (zeros (1, 0)), 0)
3130 %!assert (sum (zeros (1, 0), 1), zeros (1, 0))
3131 %!assert (sum (zeros (1, 0), 2), 0)
3132 %!assert (sum (zeros (0, 1)), 0)
3133 %!assert (sum (zeros (0, 1), 1), 0)
3134 %!assert (sum (zeros (0, 1), 2), zeros (0, 1))
3135 %!assert (sum (zeros (2, 0)), zeros (1, 0))
3136 %!assert (sum (zeros (2, 0), 1), zeros (1, 0))
3137 %!assert (sum (zeros (2, 0), 2), [0; 0])
3138 %!assert (sum (zeros (0, 2)), [0, 0])
3139 %!assert (sum (zeros (0, 2), 1), [0, 0])
3140 %!assert (sum (zeros (0, 2), 2), zeros (0, 1))
3141 %!assert (sum (zeros (2, 2, 0, 3)), zeros (1, 2, 0, 3))
3142 %!assert (sum (zeros (2, 2, 0, 3), 2), zeros (2, 1, 0, 3))
3143 %!assert (sum (zeros (2, 2, 0, 3), 3), zeros (2, 2, 1, 3))
3144 %!assert (sum (zeros (2, 2, 0, 3), 4), zeros (2, 2, 0))
3145 %!assert (sum (zeros (2, 2, 0, 3), 7), zeros (2, 2, 0, 3))
3146 
3147 %!assert (sum (single ([1, 2; 3, 4]), 1), single ([4, 6]))
3148 %!assert (sum (single ([1, 2; 3, 4]), 2), single ([3; 7]))
3149 %!assert (sum (zeros (1, 0, "single")), single (0))
3150 %!assert (sum (zeros (1, 0, "single"), 1), zeros (1, 0, "single"))
3151 %!assert (sum (zeros (1, 0, "single"), 2), single (0))
3152 %!assert (sum (zeros (0, 1, "single")), single (0))
3153 %!assert (sum (zeros (0, 1, "single"), 1), single (0))
3154 %!assert (sum (zeros (0, 1, "single"), 2), zeros (0, 1, "single"))
3155 %!assert (sum (zeros (2, 0, "single")), zeros (1, 0, "single"))
3156 %!assert (sum (zeros (2, 0, "single"), 1), zeros (1, 0, "single"))
3157 %!assert (sum (zeros (2, 0, "single"), 2), single ([0; 0]))
3158 %!assert (sum (zeros (0, 2, "single")), single ([0, 0]))
3159 %!assert (sum (zeros (0, 2, "single"), 1), single ([0, 0]))
3160 %!assert (sum (zeros (0, 2, "single"), 2), zeros (0, 1, "single"))
3161 %!assert (sum (zeros (2, 2, 0, 3, "single")), zeros (1, 2, 0, 3, "single"))
3162 %!assert (sum (zeros (2, 2, 0, 3, "single"), 2), zeros (2, 1, 0, 3, "single"))
3163 %!assert (sum (zeros (2, 2, 0, 3, "single"), 3), zeros (2, 2, 1, 3, "single"))
3164 %!assert (sum (zeros (2, 2, 0, 3, "single"), 4), zeros (2, 2, 0, "single"))
3165 %!assert (sum (zeros (2, 2, 0, 3, "single"), 7), zeros (2, 2, 0, 3, "single"))
3166 
3167 ## Test "native"
3168 %!assert (sum ([true,true]), 2)
3169 %!assert (sum ([true,true], "native"), true)
3170 %!assert (sum (int8 ([127,10,-20])), 117)
3171 %!assert (sum (int8 ([127,10,-20]), "native"), int8 (107))
3172 
3173 ;-)
3174 %!assert (sum ("Octave") + "8", sumsq (primes (17)))
3175 
3176 %!error sum ()
3177 %!error sum (1,2,3)
3178 %!error <unrecognized type argument 'foobar'> sum (1, "foobar")
3179 */
3180 
3181 DEFUN (sumsq, args, ,
3182  "-*- texinfo -*-\n\
3183 @deftypefn {Built-in Function} {} sumsq (@var{x})\n\
3184 @deftypefnx {Built-in Function} {} sumsq (@var{x}, @var{dim})\n\
3185 Sum of squares of elements along dimension @var{dim}.\n\
3186 \n\
3187 If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
3188 \n\
3189 This function is conceptually equivalent to computing\n\
3190 \n\
3191 @example\n\
3192 sum (x .* conj (x), dim)\n\
3193 @end example\n\
3194 \n\
3195 @noindent\n\
3196 but it uses less memory and avoids calling @code{conj} if @var{x} is real.\n\
3197 @seealso{sum, prod}\n\
3198 @end deftypefn")
3199 {
3200  DATA_REDUCTION (sumsq);
3201 }
3202 
3203 /*
3204 %!assert (sumsq ([1, 2, 3]), 14)
3205 %!assert (sumsq ([-1; -2; 4i]), 21)
3206 %!assert (sumsq ([1, 2, 3; 2, 3, 4; 4i, 6i, 2]), [21, 49, 29])
3207 
3208 %!assert (sumsq (single ([1, 2, 3])), single (14))
3209 %!assert (sumsq (single ([-1; -2; 4i])), single (21))
3210 %!assert (sumsq (single ([1, 2, 3; 2, 3, 4; 4i, 6i, 2])), single ([21, 49, 29]))
3211 
3212 %!assert (sumsq ([1, 2; 3, 4], 1), [10, 20])
3213 %!assert (sumsq ([1, 2; 3, 4], 2), [5; 25])
3214 
3215 %!assert (sumsq (single ([1, 2; 3, 4]), 1), single ([10, 20]))
3216 %!assert (sumsq (single ([1, 2; 3, 4]), 2), single ([5; 25]))
3217 
3218 %!error sumsq ()
3219 */
3220 
3221 DEFUN (islogical, args, ,
3222  "-*- texinfo -*-\n\
3223 @deftypefn {Built-in Function} {} islogical (@var{x})\n\
3224 @deftypefnx {Built-in Function} {} isbool (@var{x})\n\
3225 Return true if @var{x} is a logical object.\n\
3226 @seealso{isfloat, isinteger, ischar, isnumeric, isa}\n\
3227 @end deftypefn")
3228 {
3229  octave_value retval;
3230 
3231  if (args.length () == 1)
3232  retval = args(0).is_bool_type ();
3233  else
3234  print_usage ();
3235 
3236  return retval;
3237 }
3238 
3239 DEFALIAS (isbool, islogical);
3240 
3241 /*
3242 %!assert (islogical (true), true)
3243 %!assert (islogical (false), true)
3244 %!assert (islogical ([true, false]), true)
3245 %!assert (islogical (1), false)
3246 %!assert (islogical (1i), false)
3247 %!assert (islogical ([1,1]), false)
3248 %!assert (islogical (single (1)), false)
3249 %!assert (islogical (single (1i)), false)
3250 %!assert (islogical (single ([1,1])), false)
3251 %!assert (islogical (sparse ([true, false])), true)
3252 %!assert (islogical (sparse ([1, 0])), false)
3253 */
3254 
3255 DEFUN (isinteger, args, ,
3256  "-*- texinfo -*-\n\
3257 @deftypefn {Built-in Function} {} isinteger (@var{x})\n\
3258 Return true if @var{x} is an integer object (int8, uint8, int16, etc.).\n\
3259 \n\
3260 Note that @w{@code{isinteger (14)}} is false because numeric constants in\n\
3261 Octave are double precision floating point values.\n\
3262 @seealso{isfloat, ischar, islogical, isnumeric, isa}\n\
3263 @end deftypefn")
3264 {
3265  octave_value retval;
3266 
3267  if (args.length () == 1)
3268  retval = args(0).is_integer_type ();
3269  else
3270  print_usage ();
3271 
3272  return retval;
3273 }
3274 
3275 DEFUN (iscomplex, args, ,
3276  "-*- texinfo -*-\n\
3277 @deftypefn {Built-in Function} {} iscomplex (@var{x})\n\
3278 Return true if @var{x} is a complex-valued numeric object.\n\
3279 @seealso{isreal, isnumeric, islogical, ischar, isfloat, isa}\n\
3280 @end deftypefn")
3281 {
3282  octave_value retval;
3283 
3284  if (args.length () == 1)
3285  retval = args(0).is_complex_type ();
3286  else
3287  print_usage ();
3288 
3289  return retval;
3290 }
3291 
3292 DEFUN (isfloat, args, ,
3293  "-*- texinfo -*-\n\
3294 @deftypefn {Built-in Function} {} isfloat (@var{x})\n\
3295 Return true if @var{x} is a floating-point numeric object.\n\
3296 \n\
3297 Objects of class double or single are floating-point objects.\n\
3298 @seealso{isinteger, ischar, islogical, isnumeric, isa}\n\
3299 @end deftypefn")
3300 {
3301  octave_value retval;
3302 
3303  if (args.length () == 1)
3304  retval = args(0).is_float_type ();
3305  else
3306  print_usage ();
3307 
3308  return retval;
3309 }
3310 
3311 // FIXME: perhaps this should be implemented with an
3312 // octave_value member function?
3313 
3314 DEFUN (complex, args, ,
3315  "-*- texinfo -*-\n\
3316 @deftypefn {Built-in Function} {} complex (@var{x})\n\
3317 @deftypefnx {Built-in Function} {} complex (@var{re}, @var{im})\n\
3318 Return a complex value from real arguments.\n\
3319 \n\
3320 With 1 real argument @var{x}, return the complex result @code{@var{x} + 0i}.\n\
3321 \n\
3322 With 2 real arguments, return the complex result @code{@var{re} + @var{im}}.\n\
3323 @code{complex} can often be more convenient than expressions such as\n\
3324 @code{a + i*b}.\n\
3325 For example:\n\
3326 \n\
3327 @example\n\
3328 @group\n\
3329 complex ([1, 2], [3, 4])\n\
3330  @result{} [ 1 + 3i 2 + 4i ]\n\
3331 @end group\n\
3332 @end example\n\
3333 @seealso{real, imag, iscomplex, abs, arg}\n\
3334 @end deftypefn")
3335 {
3336  octave_value retval;
3337 
3338  int nargin = args.length ();
3339 
3340  if (nargin == 1)
3341  {
3342  octave_value arg = args(0);
3343 
3344  if (arg.is_complex_type ())
3345  retval = arg;
3346  else
3347  {
3348  if (arg.is_sparse_type ())
3349  {
3351 
3352  if (! error_state)
3353  retval = octave_value (new octave_sparse_complex_matrix (val));
3354  }
3355  else if (arg.is_single_type ())
3356  {
3357  if (arg.numel () == 1)
3358  {
3359  FloatComplex val = arg.float_complex_value ();
3360 
3361  if (! error_state)
3362  retval = octave_value (new octave_float_complex (val));
3363  }
3364  else
3365  {
3367 
3368  if (! error_state)
3369  retval = octave_value (new octave_float_complex_matrix (val));
3370  }
3371  }
3372  else
3373  {
3374  if (arg.numel () == 1)
3375  {
3376  Complex val = arg.complex_value ();
3377 
3378  if (! error_state)
3379  retval = octave_value (new octave_complex (val));
3380  }
3381  else
3382  {
3383  ComplexNDArray val = arg.complex_array_value ();
3384 
3385  if (! error_state)
3386  retval = octave_value (new octave_complex_matrix (val));
3387  }
3388  }
3389 
3390  if (error_state)
3391  error ("complex: invalid conversion");
3392  }
3393  }
3394  else if (nargin == 2)
3395  {
3396  octave_value re = args(0);
3397  octave_value im = args(1);
3398 
3399  if (re.is_sparse_type () && im.is_sparse_type ())
3400  {
3401  const SparseMatrix re_val = re.sparse_matrix_value ();
3402  const SparseMatrix im_val = im.sparse_matrix_value ();
3403 
3404  if (!error_state)
3405  {
3406  if (re.numel () == 1)
3407  {
3408  SparseComplexMatrix result;
3409  if (re_val.nnz () == 0)
3410  result = Complex (0, 1) * SparseComplexMatrix (im_val);
3411  else
3412  {
3413  octave_idx_type nr = im_val.rows ();
3414  octave_idx_type nc = im_val.cols ();
3415  result = SparseComplexMatrix (nr, nc, re_val(0));
3416 
3417  for (octave_idx_type j = 0; j < nc; j++)
3418  {
3419  octave_idx_type off = j * nr;
3420  for (octave_idx_type i = im_val.cidx (j);
3421  i < im_val.cidx (j + 1); i++)
3422  result.data (im_val.ridx (i) + off) +=
3423  Complex (0, im_val.data (i));
3424  }
3425  }
3426  retval = octave_value (new octave_sparse_complex_matrix (result));
3427  }
3428  else if (im.numel () == 1)
3429  {
3430  SparseComplexMatrix result;
3431  if (im_val.nnz () == 0)
3432  result = SparseComplexMatrix (re_val);
3433  else
3434  {
3435  octave_idx_type nr = re_val.rows ();
3436  octave_idx_type nc = re_val.cols ();
3437  result = SparseComplexMatrix (nr, nc,
3438  Complex (0, im_val(0)));
3439 
3440  for (octave_idx_type j = 0; j < nc; j++)
3441  {
3442  octave_idx_type off = j * nr;
3443  for (octave_idx_type i = re_val.cidx (j);
3444  i < re_val.cidx (j + 1); i++)
3445  result.data (re_val.ridx (i) + off) +=
3446  re_val.data (i);
3447  }
3448  }
3449  retval = octave_value (new octave_sparse_complex_matrix (result));
3450  }
3451  else
3452  {
3453  if (re_val.dims () == im_val.dims ())
3454  {
3455  SparseComplexMatrix result;
3456  result = SparseComplexMatrix (re_val)
3457  + Complex (0, 1) * SparseComplexMatrix (im_val);
3458  retval = octave_value (
3459  new octave_sparse_complex_matrix (result));
3460  }
3461  else
3462  error ("complex: dimension mismatch");
3463  }
3464  }
3465  }
3466  else if (re.is_single_type () || im.is_single_type ())
3467  {
3468  if (re.numel () == 1)
3469  {
3470  float re_val = re.float_value ();
3471 
3472  if (im.numel () == 1)
3473  {
3474  float im_val = im.double_value ();
3475 
3476  if (! error_state)
3477  retval = octave_value (
3478  new octave_float_complex (FloatComplex (re_val,
3479  im_val)));
3480  }
3481  else
3482  {
3483  const FloatNDArray im_val = im.float_array_value ();
3484 
3485  if (! error_state)
3486  {
3487  FloatComplexNDArray result (im_val.dims (),
3488  FloatComplex ());
3489 
3490  for (octave_idx_type i = 0; i < im_val.numel (); i++)
3491  result.xelem (i) = FloatComplex (re_val, im_val(i));
3492 
3493  retval = octave_value (
3494  new octave_float_complex_matrix (result));
3495  }
3496  }
3497  }
3498  else
3499  {
3500  const FloatNDArray re_val = re.float_array_value ();
3501 
3502  if (im.numel () == 1)
3503  {
3504  float im_val = im.float_value ();
3505 
3506  if (! error_state)
3507  {
3508  FloatComplexNDArray result (re_val.dims (),
3509  FloatComplex ());
3510 
3511  for (octave_idx_type i = 0; i < re_val.numel (); i++)
3512  result.xelem (i) = FloatComplex (re_val(i), im_val);
3513 
3514  retval = octave_value (
3515  new octave_float_complex_matrix (result));
3516  }
3517  }
3518  else
3519  {
3520  const FloatNDArray im_val = im.float_array_value ();
3521 
3522  if (! error_state)
3523  {
3524  if (re_val.dims () == im_val.dims ())
3525  {
3526  FloatComplexNDArray result (re_val.dims (),
3527  FloatComplex ());
3528 
3529  for (octave_idx_type i = 0; i < re_val.numel (); i++)
3530  result.xelem (i) = FloatComplex (re_val(i),
3531  im_val(i));
3532 
3533  retval = octave_value (
3534  new octave_float_complex_matrix (result));
3535  }
3536  else
3537  error ("complex: dimension mismatch");
3538  }
3539  }
3540  }
3541  }
3542  else if (re.numel () == 1)
3543  {
3544  double re_val = re.double_value ();
3545 
3546  if (im.numel () == 1)
3547  {
3548  double im_val = im.double_value ();
3549 
3550  if (! error_state)
3551  retval = octave_value (new octave_complex (Complex (re_val,
3552  im_val)));
3553  }
3554  else
3555  {
3556  const NDArray im_val = im.array_value ();
3557 
3558  if (! error_state)
3559  {
3560  ComplexNDArray result (im_val.dims (), Complex ());
3561 
3562  for (octave_idx_type i = 0; i < im_val.numel (); i++)
3563  result.xelem (i) = Complex (re_val, im_val(i));
3564 
3565  retval = octave_value (new octave_complex_matrix (result));
3566  }
3567  }
3568  }
3569  else
3570  {
3571  const NDArray re_val = re.array_value ();
3572 
3573  if (im.numel () == 1)
3574  {
3575  double im_val = im.double_value ();
3576 
3577  if (! error_state)
3578  {
3579  ComplexNDArray result (re_val.dims (), Complex ());
3580 
3581  for (octave_idx_type i = 0; i < re_val.numel (); i++)
3582  result.xelem (i) = Complex (re_val(i), im_val);
3583 
3584  retval = octave_value (new octave_complex_matrix (result));
3585  }
3586  }
3587  else
3588  {
3589  const NDArray im_val = im.array_value ();
3590 
3591  if (! error_state)
3592  {
3593  if (re_val.dims () == im_val.dims ())
3594  {
3595  ComplexNDArray result (re_val.dims (), Complex ());
3596 
3597  for (octave_idx_type i = 0; i < re_val.numel (); i++)
3598  result.xelem (i) = Complex (re_val(i), im_val(i));
3599 
3600  retval = octave_value (
3601  new octave_complex_matrix (result));
3602  }
3603  else
3604  error ("complex: dimension mismatch");
3605  }
3606  }
3607  }
3608 
3609  if (error_state)
3610  error ("complex: invalid conversion");
3611  }
3612  else
3613  print_usage ();
3614 
3615  return retval;
3616 }
3617 
3618 DEFUN (isreal, args, ,
3619  "-*- texinfo -*-\n\
3620 @deftypefn {Built-in Function} {} isreal (@var{x})\n\
3621 Return true if @var{x} is a non-complex matrix or scalar.\n\
3622 \n\
3623 For compatibility with @sc{matlab}, this includes logical and character\n\
3624 matrices.\n\
3625 @seealso{iscomplex, isnumeric, isa}\n\
3626 @end deftypefn")
3627 {
3628  octave_value retval;
3629 
3630  if (args.length () == 1)
3631  retval = args(0).is_real_type ();
3632  else
3633  print_usage ();
3634 
3635  return retval;
3636 }
3637 
3638 DEFUN (isempty, args, ,
3639  "-*- texinfo -*-\n\
3640 @deftypefn {Built-in Function} {} isempty (@var{a})\n\
3641 Return true if @var{a} is an empty matrix (any one of its dimensions is\n\
3642 zero).\n\
3643 @seealso{isnull, isa}\n\
3644 @end deftypefn")
3645 {
3646  octave_value retval = false;
3647 
3648  if (args.length () == 1)
3649  retval = args(0).is_empty ();
3650  else
3651  print_usage ();
3652 
3653  return retval;
3654 }
3655 
3656 /*
3657 %% Debian bug #706376
3658 %!assert (isempty (speye(2^16)), false)
3659 */
3660 
3661 DEFUN (isnumeric, args, ,
3662  "-*- texinfo -*-\n\
3663 @deftypefn {Built-in Function} {} isnumeric (@var{x})\n\
3664 Return true if @var{x} is a numeric object, i.e., an integer, real, or\n\
3665 complex array.\n\
3666 \n\
3667 Logical and character arrays are not considered to be numeric.\n\
3668 @seealso{isinteger, isfloat, isreal, iscomplex, islogical, ischar, iscell, isstruct, isa}\n\
3669 @end deftypefn")
3670 {
3671  octave_value retval;
3672 
3673  if (args.length () == 1)
3674  retval = args(0).is_numeric_type ();
3675  else
3676  print_usage ();
3677 
3678  return retval;
3679 }
3680 
3681 /*
3682 %!assert (isnumeric (1), true)
3683 %!assert (isnumeric (1i), true)
3684 %!assert (isnumeric ([1,1]), true)
3685 %!assert (isnumeric (single (1)), true)
3686 %!assert (isnumeric (single (1i)), true)
3687 %!assert (isnumeric (single ([1,1])), true)
3688 %!assert (isnumeric (int8 (1)), true)
3689 %!assert (isnumeric (uint8 ([1,1])), true)
3690 %!assert (isnumeric ("Hello World"), false)
3691 %!assert (isnumeric (true), false)
3692 %!assert (isnumeric (false), false)
3693 %!assert (isnumeric ([true, false]), false)
3694 %!assert (isnumeric (sparse ([true, false])), false)
3695 */
3696 
3697 DEFUN (isscalar, args, ,
3698  "-*- texinfo -*-\n\
3699 @deftypefn {Built-in Function} {} isscalar (@var{x})\n\
3700 Return true if @var{x} is a scalar.\n\
3701 @seealso{isvector, ismatrix}\n\
3702 @end deftypefn")
3703 {
3704  octave_value retval;
3705 
3706  if (args.length () == 1)
3707  retval = args(0).numel () == 1;
3708  else
3709  print_usage ();
3710 
3711  return retval;
3712 }
3713 
3714 /*
3715 %!assert (isscalar (1))
3716 %!assert (isscalar ([1, 2]), false)
3717 %!assert (isscalar ([]), false)
3718 %!assert (isscalar ([1, 2; 3, 4]), false)
3719 
3720 %!assert (isscalar ("t"))
3721 %!assert (isscalar ("test"), false)
3722 %!assert (isscalar (["test"; "ing"]), false)
3723 
3724 %!test
3725 %! s.a = 1;
3726 %! assert (isscalar (s));
3727 
3728 %% Test input validation
3729 %!error isscalar ()
3730 %!error isscalar (1, 2)
3731 */
3732 
3733 DEFUN (isvector, args, ,
3734  "-*- texinfo -*-\n\
3735 @deftypefn {Function File} {} isvector (@var{x})\n\
3736 Return true if @var{x} is a vector.\n\
3737 \n\
3738 A vector is a 2-D array where one of the dimensions is equal to 1. As a\n\
3739 consequence a 1x1 array, or scalar, is also a vector.\n\
3740 @seealso{isscalar, ismatrix, size, rows, columns, length}\n\
3741 @end deftypefn")
3742 {
3743  octave_value retval;
3744 
3745  if (args.length () == 1)
3746  {
3747  dim_vector sz = args(0).dims ();
3748  retval = sz.length () == 2 && (sz(0) == 1 || sz(1) == 1);
3749  }
3750  else
3751  print_usage ();
3752 
3753  return retval;
3754 }
3755 
3756 /*
3757 %!assert (isvector (1), true)
3758 %!assert (isvector ([1; 2; 3]), true)
3759 %!assert (isvector ([1, 2, 3]), true)
3760 %!assert (isvector ([]), false)
3761 %!assert (isvector ([1, 2; 3, 4]), false)
3762 
3763 %!assert (isvector ("t"), true)
3764 %!assert (isvector ("test"), true)
3765 %!assert (isvector (["test"; "ing"]), false)
3766 
3767 %!test
3768 %! s.a = 1;
3769 %! assert (isvector (s), true);
3770 
3771 %% Test input validation
3772 %!error isvector ()
3773 %!error isvector ([1, 2], 2)
3774 */
3775 
3776 DEFUN (isrow, args, ,
3777  "-*- texinfo -*-\n\
3778 @deftypefn {Function File} {} isrow (@var{x})\n\
3779 Return true if @var{x} is a row vector 1xN with non-negative N.\n\
3780 @seealso{iscolumn, isscalar, isvector, ismatrix}\n\
3781 @end deftypefn")
3782 {
3783  octave_value retval;
3784 
3785  if (args.length () == 1)
3786  {
3787  dim_vector sz = args(0).dims ();
3788  retval = sz.length () == 2 && sz(0) == 1;
3789  }
3790  else
3791  print_usage ();
3792 
3793  return retval;
3794 }
3795 
3796 /*
3797 %!assert (isrow ([1, 2, 3]))
3798 %!assert (isrow ([1; 2; 3]), false)
3799 %!assert (isrow (1))
3800 %!assert (isrow ([]), false)
3801 %!assert (isrow ([1, 2; 3, 4]), false)
3802 
3803 %!assert (isrow (ones (1, 0)), true)
3804 %!assert (isrow (ones (1, 1)), true)
3805 %!assert (isrow (ones (1, 2)), true)
3806 %!assert (isrow (ones (1, 1, 1)), true)
3807 %!assert (isrow (ones (1, 1, 1, 1)), true)
3808 
3809 %!assert (isrow (ones (0, 0)), false)
3810 %!assert (isrow (ones (1, 1, 0)), false)
3811 
3812 
3813 %!assert (isrow ("t"), true)
3814 %!assert (isrow ("test"), true)
3815 %!assert (isrow (["test"; "ing"]), false)
3816 
3817 %!test
3818 %! s.a = 1;
3819 %! assert (isrow (s), true);
3820 
3821 %% Test input validation
3822 %!error isrow ()
3823 %!error isrow ([1, 2], 2)
3824 */
3825 
3826 DEFUN (iscolumn, args, ,
3827  "-*- texinfo -*-\n\
3828 @deftypefn {Function File} {} iscolumn (@var{x})\n\
3829 Return true if @var{x} is a column vector Nx1 with non-negative N.\n\
3830 @seealso{isrow, isscalar, isvector, ismatrix}\n\
3831 @end deftypefn")
3832 {
3833  octave_value retval;
3834 
3835  if (args.length () == 1)
3836  {
3837  dim_vector sz = args(0).dims ();
3838  retval = sz.length () == 2 && sz(1) == 1;
3839  }
3840  else
3841  print_usage ();
3842 
3843  return retval;
3844 }
3845 
3846 /*
3847 %!assert (iscolumn ([1, 2, 3]), false)
3848 %!assert (iscolumn ([1; 2; 3]), true)
3849 %!assert (iscolumn (1), true)
3850 %!assert (iscolumn ([]), false)
3851 %!assert (iscolumn ([1, 2; 3, 4]), false)
3852 
3853 %!assert (iscolumn ("t"), true)
3854 %!assert (iscolumn ("test"), false)
3855 %!assert (iscolumn (["test"; "ing"]), false)
3856 
3857 %!assert (iscolumn (ones (0, 1)), true)
3858 %!assert (iscolumn (ones (1, 1)), true)
3859 %!assert (iscolumn (ones (2, 1)), true)
3860 %!assert (iscolumn (ones (1, 1, 1)), true)
3861 %!assert (iscolumn (ones (1, 1, 1, 1)), true)
3862 
3863 %!assert (iscolumn (ones (0, 0)), false)
3864 %!assert (iscolumn (ones (0, 1, 0)), false)
3865 
3866 %!test
3867 %! s.a = 1;
3868 %! assert (iscolumn (s));
3869 
3870 %% Test input validation
3871 %!error iscolumn ()
3872 %!error iscolumn ([1, 2], 2)
3873 */
3874 
3875 DEFUN (ismatrix, args, ,
3876  "-*- texinfo -*-\n\
3877 @deftypefn {Built-in Function} {} ismatrix (@var{a})\n\
3878 Return true if @var{a} is a 2-D array.\n\
3879 @seealso{isscalar, isvector, iscell, isstruct, issparse, isa}\n\
3880 @end deftypefn")
3881 {
3882  octave_value retval = false;
3883 
3884  if (args.length () == 1)
3885  {
3886  dim_vector sz = args(0).dims ();
3887  retval = (sz.length () == 2) && (sz(0) >= 0) && (sz(1) >= 0);
3888  }
3889  else
3890  print_usage ();
3891 
3892  return retval;
3893 }
3894 
3895 /*
3896 %!assert (ismatrix ([]), true)
3897 %!assert (ismatrix (1), true)
3898 %!assert (ismatrix ([1, 2, 3]), true)
3899 %!assert (ismatrix ([1, 2; 3, 4]), true)
3900 
3901 %!assert (ismatrix (zeros (0)), true)
3902 %!assert (ismatrix (zeros (0, 0)), true)
3903 %!assert (ismatrix (zeros (0, 0, 0)), false)
3904 %!assert (ismatrix (zeros (3, 2, 4)), false)
3905 
3906 %!assert (ismatrix (single ([])), true)
3907 %!assert (ismatrix (single (1)), true)
3908 %!assert (ismatrix (single ([1, 2, 3])), true)
3909 %!assert (ismatrix (single ([1, 2; 3, 4])), true)
3910 
3911 %!assert (ismatrix ("t"), true)
3912 %!assert (ismatrix ("test"), true)
3913 %!assert (ismatrix (["test"; "ing"]), true)
3914 
3915 %!test
3916 %! s.a = 1;
3917 %! assert (ismatrix (s), true);
3918 
3919 %!error ismatrix ()
3920 %!error ismatrix ([1, 2; 3, 4], 2)
3921 */
3922 
3923 DEFUN (issquare, args, ,
3924  "-*- texinfo -*-\n\
3925 @deftypefn {Function File} {} issquare (@var{x})\n\
3926 Return true if @var{x} is a square matrix.\n\
3927 @seealso{isscalar, isvector, ismatrix, size}\n\
3928 @end deftypefn")
3929 {
3930  octave_value retval;
3931 
3932  if (args.length () == 1)
3933  {
3934  dim_vector sz = args(0).dims ();
3935  retval = sz.length () == 2 && sz(0) == sz(1);
3936  }
3937  else
3938  print_usage ();
3939 
3940  return retval;
3941 }
3942 
3943 /*
3944 %!assert (issquare ([]))
3945 %!assert (issquare (1))
3946 %!assert (! issquare ([1, 2]))
3947 %!assert (issquare ([1, 2; 3, 4]))
3948 %!assert (! issquare ([1, 2; 3, 4; 5, 6]))
3949 %!assert (! issquare (ones (3,3,3)))
3950 %!assert (issquare ("t"))
3951 %!assert (! issquare ("test"))
3952 %!assert (issquare (["test"; "ing"; "1"; "2"]))
3953 %!test
3954 %! s.a = 1;
3955 %! assert (issquare (s));
3956 %!assert (issquare ({1, 2; 3, 4}))
3957 %!assert (sparse (([1, 2; 3, 4])))
3958 
3959 %% Test input validation
3960 %!error issquare ()
3961 %!error issquare ([1, 2; 3, 4], 2)
3962 */
3963 
3964 static octave_value
3965 fill_matrix (const octave_value_list& args, int val, const char *fcn)
3966 {
3967  octave_value retval;
3968 
3969  int nargin = args.length ();
3970 
3972 
3973  dim_vector dims (1, 1);
3974 
3975  if (nargin > 0 && args(nargin-1).is_string ())
3976  {
3977  std::string nm = args(nargin-1).string_value ();
3978  nargin--;
3979 
3981 
3982  if (error_state)
3983  return retval;
3984  }
3985 
3986  switch (nargin)
3987  {
3988  case 0:
3989  break;
3990 
3991  case 1:
3992  get_dimensions (args(0), fcn, dims);
3993  break;
3994 
3995  default:
3996  {
3997  dims.resize (nargin);
3998 
3999  for (int i = 0; i < nargin; i++)
4000  {
4001  dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
4002 
4003  if (error_state)
4004  {
4005  error ("%s: expecting scalar integer arguments", fcn);
4006  break;
4007  }
4008  }
4009  }
4010  break;
4011  }
4012 
4013  if (! error_state)
4014  {
4015  dims.chop_trailing_singletons ();
4016 
4017  check_dimensions (dims, fcn);
4018 
4019  // FIXME: perhaps this should be made extensible by
4020  // using the class name to lookup a function to call to create
4021  // the new value.
4022 
4023  // Note that automatic narrowing will handle conversion from
4024  // NDArray to scalar.
4025 
4026  if (! error_state)
4027  {
4028  switch (dt)
4029  {
4031  retval = int8NDArray (dims, val);
4032  break;
4033 
4035  retval = uint8NDArray (dims, val);
4036  break;
4037 
4039  retval = int16NDArray (dims, val);
4040  break;
4041 
4043  retval = uint16NDArray (dims, val);
4044  break;
4045 
4047  retval = int32NDArray (dims, val);
4048  break;
4049 
4051  retval = uint32NDArray (dims, val);
4052  break;
4053 
4055  retval = int64NDArray (dims, val);
4056  break;
4057 
4059  retval = uint64NDArray (dims, val);
4060  break;
4061 
4063  retval = FloatNDArray (dims, val);
4064  break;
4065 
4067  {
4068  if (val == 1 && dims.length () == 2 && dims (0) == 1)
4069  retval = Range (1.0, 0.0, dims (1)); // packed form
4070  else
4071  retval = NDArray (dims, val);
4072  }
4073  break;
4074 
4076  retval = boolNDArray (dims, val);
4077  break;
4078 
4079  default:
4080  error ("%s: invalid class name", fcn);
4081  break;
4082  }
4083  }
4084  }
4085 
4086  return retval;
4087 }
4088 
4089 static octave_value
4090 fill_matrix (const octave_value_list& args, double val, float fval,
4091  const char *fcn)
4092 {
4093  octave_value retval;
4094 
4095  int nargin = args.length ();
4096 
4098 
4099  dim_vector dims (1, 1);
4100 
4101  if (nargin > 0 && args(nargin-1).is_string ())
4102  {
4103  std::string nm = args(nargin-1).string_value ();
4104  nargin--;
4105 
4107 
4108  if (error_state)
4109  return retval;
4110  }
4111 
4112  switch (nargin)
4113  {
4114  case 0:
4115  break;
4116 
4117  case 1:
4118  get_dimensions (args(0), fcn, dims);
4119  break;
4120 
4121  default:
4122  {
4123  dims.resize (nargin);
4124 
4125  for (int i = 0; i < nargin; i++)
4126  {
4127  dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
4128 
4129  if (error_state)
4130  {
4131  error ("%s: expecting scalar integer arguments", fcn);
4132  break;
4133  }
4134  }
4135  }
4136  break;
4137  }
4138 
4139  if (! error_state)
4140  {
4141  dims.chop_trailing_singletons ();
4142 
4143  check_dimensions (dims, fcn);
4144 
4145  // Note that automatic narrowing will handle conversion from
4146  // NDArray to scalar.
4147 
4148  if (! error_state)
4149  {
4150  switch (dt)
4151  {
4153  retval = FloatNDArray (dims, fval);
4154  break;
4155 
4157  retval = NDArray (dims, val);
4158  break;
4159 
4160  default:
4161  error ("%s: invalid class name", fcn);
4162  break;
4163  }
4164  }
4165  }
4166 
4167  return retval;
4168 }
4169 
4170 static octave_value
4171 fill_matrix (const octave_value_list& args, double val, const char *fcn)
4172 {
4173  octave_value retval;
4174 
4175  int nargin = args.length ();
4176 
4178 
4179  dim_vector dims (1, 1);
4180 
4181  if (nargin > 0 && args(nargin-1).is_string ())
4182  {
4183  std::string nm = args(nargin-1).string_value ();
4184  nargin--;
4185 
4187 
4188  if (error_state)
4189  return retval;
4190  }
4191 
4192  switch (nargin)
4193  {
4194  case 0:
4195  break;
4196 
4197  case 1:
4198  get_dimensions (args(0), fcn, dims);
4199  break;
4200 
4201  default:
4202  {
4203  dims.resize (nargin);
4204 
4205  for (int i = 0; i < nargin; i++)
4206  {
4207  dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
4208 
4209  if (error_state)
4210  {
4211  error ("%s: expecting scalar integer arguments", fcn);
4212  break;
4213  }
4214  }
4215  }
4216  break;
4217  }
4218 
4219  if (! error_state)
4220  {
4221  dims.chop_trailing_singletons ();
4222 
4223  check_dimensions (dims, fcn);
4224 
4225  // Note that automatic narrowing will handle conversion from
4226  // NDArray to scalar.
4227 
4228  if (! error_state)
4229  {
4230  switch (dt)
4231  {
4233  retval = FloatNDArray (dims, static_cast<float> (val));
4234  break;
4235 
4237  retval = NDArray (dims, val);
4238  break;
4239 
4240  default:
4241  error ("%s: invalid class name", fcn);
4242  break;
4243  }
4244  }
4245  }
4246 
4247  return retval;
4248 }
4249 
4250 static octave_value
4251 fill_matrix (const octave_value_list& args, const Complex& val,
4252  const char *fcn)
4253 {
4254  octave_value retval;
4255 
4256  int nargin = args.length ();
4257 
4259 
4260  dim_vector dims (1, 1);
4261 
4262  if (nargin > 0 && args(nargin-1).is_string ())
4263  {
4264  std::string nm = args(nargin-1).string_value ();
4265  nargin--;
4266 
4268 
4269  if (error_state)
4270  return retval;
4271  }
4272 
4273  switch (nargin)
4274  {
4275  case 0:
4276  break;
4277 
4278  case 1:
4279  get_dimensions (args(0), fcn, dims);
4280  break;
4281 
4282  default:
4283  {
4284  dims.resize (nargin);
4285 
4286  for (int i = 0; i < nargin; i++)
4287  {
4288  dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
4289 
4290  if (error_state)
4291  {
4292  error ("%s: expecting scalar integer arguments", fcn);
4293  break;
4294  }
4295  }
4296  }
4297  break;
4298  }
4299 
4300  if (! error_state)
4301  {
4302  dims.chop_trailing_singletons ();
4303 
4304  check_dimensions (dims, fcn);
4305 
4306  // Note that automatic narrowing will handle conversion from
4307  // NDArray to scalar.
4308 
4309  if (! error_state)
4310  {
4311  switch (dt)
4312  {
4314  retval = FloatComplexNDArray (dims,
4315  static_cast<FloatComplex> (val));
4316  break;
4317 
4319  retval = ComplexNDArray (dims, val);
4320  break;
4321 
4322  default:
4323  error ("%s: invalid class name", fcn);
4324  break;
4325  }
4326  }
4327  }
4328 
4329  return retval;
4330 }
4331 
4332 static octave_value
4333 fill_matrix (const octave_value_list& args, bool val, const char *fcn)
4334 {
4335  octave_value retval;
4336 
4337  int nargin = args.length ();
4338 
4339  dim_vector dims (1, 1);
4340 
4341  switch (nargin)
4342  {
4343  case 0:
4344  break;
4345 
4346  case 1:
4347  get_dimensions (args(0), fcn, dims);
4348  break;
4349 
4350  default:
4351  {
4352  dims.resize (nargin);
4353 
4354  for (int i = 0; i < nargin; i++)
4355  {
4356  dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
4357 
4358  if (error_state)
4359  {
4360  error ("%s: expecting scalar integer arguments", fcn);
4361  break;
4362  }
4363  }
4364  }
4365  break;
4366  }
4367 
4368  if (! error_state)
4369  {
4370  dims.chop_trailing_singletons ();
4371 
4372  check_dimensions (dims, fcn);
4373 
4374  // Note that automatic narrowing will handle conversion from
4375  // NDArray to scalar.
4376 
4377  if (! error_state)
4378  retval = boolNDArray (dims, val);
4379  }
4380 
4381  return retval;
4382 }
4383 
4384 DEFUN (ones, args, ,
4385  "-*- texinfo -*-\n\
4386 @deftypefn {Built-in Function} {} ones (@var{n})\n\
4387 @deftypefnx {Built-in Function} {} ones (@var{m}, @var{n})\n\
4388 @deftypefnx {Built-in Function} {} ones (@var{m}, @var{n}, @var{k}, @dots{})\n\
4389 @deftypefnx {Built-in Function} {} ones ([@var{m} @var{n} @dots{}])\n\
4390 @deftypefnx {Built-in Function} {} ones (@dots{}, @var{class})\n\
4391 Return a matrix or N-dimensional array whose elements are all 1.\n\
4392 \n\
4393 If invoked with a single scalar integer argument @var{n}, return a square\n\
4394 @nospell{NxN} matrix.\n\
4395 \n\
4396 If invoked with two or more scalar integer arguments, or a vector of integer\n\
4397 values, return an array with the given dimensions.\n\
4398 \n\
4399 To create a constant matrix whose values are all the same use an expression\n\
4400 such as\n\
4401 \n\
4402 @example\n\
4403 val_matrix = val * ones (m, n)\n\
4404 @end example\n\
4405 \n\
4406 The optional argument @var{class} specifies the class of the return array\n\
4407 and defaults to double. For example:\n\
4408 \n\
4409 @example\n\
4410 val = ones (m,n, \"uint8\")\n\
4411 @end example\n\
4412 @seealso{zeros}\n\
4413 @end deftypefn")
4414 {
4415  return fill_matrix (args, 1, "ones");
4416 }
4417 
4418 /*
4419 %!assert (ones (3), [1, 1, 1; 1, 1, 1; 1, 1, 1])
4420 %!assert (ones (2, 3), [1, 1, 1; 1, 1, 1])
4421 %!assert (ones (3, 2), [1, 1; 1, 1; 1, 1])
4422 %!assert (size (ones (3, 4, 5)), [3, 4, 5])
4423 
4424 %!assert (ones (3, "single"), single ([1, 1, 1; 1, 1, 1; 1, 1, 1]))
4425 %!assert (ones (2, 3, "single"), single ([1, 1, 1; 1, 1, 1]))
4426 %!assert (ones (3, 2, "single"), single ([1, 1; 1, 1; 1, 1]))
4427 %!assert (size (ones (3, 4, 5, "single")), [3, 4, 5])
4428 
4429 %!assert (ones (3, "int8"), int8 ([1, 1, 1; 1, 1, 1; 1, 1, 1]))
4430 %!assert (ones (2, 3, "int8"), int8 ([1, 1, 1; 1, 1, 1]))
4431 %!assert (ones (3, 2, "int8"), int8 ([1, 1; 1, 1; 1, 1]))
4432 %!assert (size (ones (3, 4, 5, "int8")), [3, 4, 5])
4433 */
4434 
4435 DEFUN (zeros, args, ,
4436  "-*- texinfo -*-\n\
4437 @deftypefn {Built-in Function} {} zeros (@var{n})\n\
4438 @deftypefnx {Built-in Function} {} zeros (@var{m}, @var{n})\n\
4439 @deftypefnx {Built-in Function} {} zeros (@var{m}, @var{n}, @var{k}, @dots{})\n\
4440 @deftypefnx {Built-in Function} {} zeros ([@var{m} @var{n} @dots{}])\n\
4441 @deftypefnx {Built-in Function} {} zeros (@dots{}, @var{class})\n\
4442 Return a matrix or N-dimensional array whose elements are all 0.\n\
4443 \n\
4444 If invoked with a single scalar integer argument, return a square\n\
4445 @nospell{NxN} matrix.\n\
4446 \n\
4447 If invoked with two or more scalar integer arguments, or a vector of integer\n\
4448 values, return an array with the given dimensions.\n\
4449 \n\
4450 The optional argument @var{class} specifies the class of the return array\n\
4451 and defaults to double. For example:\n\
4452 \n\
4453 @example\n\
4454 val = zeros (m,n, \"uint8\")\n\
4455 @end example\n\
4456 @seealso{ones}\n\
4457 @end deftypefn")
4458 {
4459  return fill_matrix (args, 0, "zeros");
4460 }
4461 
4462 /*
4463 %!assert (zeros (3), [0, 0, 0; 0, 0, 0; 0, 0, 0])
4464 %!assert (zeros (2, 3), [0, 0, 0; 0, 0, 0])
4465 %!assert (zeros (3, 2), [0, 0; 0, 0; 0, 0])
4466 %!assert (size (zeros (3, 4, 5)), [3, 4, 5])
4467 
4468 %!assert (zeros (3, "single"), single ([0, 0, 0; 0, 0, 0; 0, 0, 0]))
4469 %!assert (zeros (2, 3, "single"), single ([0, 0, 0; 0, 0, 0]))
4470 %!assert (zeros (3, 2, "single"), single ([0, 0; 0, 0; 0, 0]))
4471 %!assert (size (zeros (3, 4, 5, "single")), [3, 4, 5])
4472 
4473 %!assert (zeros (3, "int8"), int8 ([0, 0, 0; 0, 0, 0; 0, 0, 0]))
4474 %!assert (zeros (2, 3, "int8"), int8 ([0, 0, 0; 0, 0, 0]))
4475 %!assert (zeros (3, 2, "int8"), int8 ([0, 0; 0, 0; 0, 0]))
4476 %!assert (size (zeros (3, 4, 5, "int8")), [3, 4, 5])
4477 */
4478 
4479 DEFUN (Inf, args, ,
4480  "-*- texinfo -*-\n\
4481 @c List other form of function in documentation index\n\
4482 @findex inf\n\
4483 \n\
4484 @deftypefn {Built-in Function} {} Inf\n\
4485 @deftypefnx {Built-in Function} {} Inf (@var{n})\n\
4486 @deftypefnx {Built-in Function} {} Inf (@var{n}, @var{m})\n\
4487 @deftypefnx {Built-in Function} {} Inf (@var{n}, @var{m}, @var{k}, @dots{})\n\
4488 @deftypefnx {Built-in Function} {} Inf (@dots{}, @var{class})\n\
4489 Return a scalar, matrix or N-dimensional array whose elements are all equal\n\
4490 to the IEEE representation for positive infinity.\n\
4491 \n\
4492 Infinity is produced when results are too large to be represented using the\n\
4493 IEEE floating point format for numbers. Two common examples which produce\n\
4494 infinity are division by zero and overflow.\n\
4495 \n\
4496 @example\n\
4497 @group\n\
4498 [ 1/0 e^800 ]\n\
4499 @result{} Inf Inf\n\
4500 @end group\n\
4501 @end example\n\
4502 \n\
4503 When called with no arguments, return a scalar with the value @samp{Inf}.\n\
4504 \n\
4505 When called with a single argument, return a square matrix with the dimension\n\
4506 specified.\n\
4507 \n\
4508 When called with more than one scalar argument the first two arguments are\n\
4509 taken as the number of rows and columns and any further arguments specify\n\
4510 additional matrix dimensions.\n\
4511 \n\
4512 The optional argument @var{class} specifies the return type and may be\n\
4513 either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4514 @seealso{isinf, NaN}\n\
4515 @end deftypefn")
4516 {
4517  return fill_matrix (args, lo_ieee_inf_value (),
4518  lo_ieee_float_inf_value (), "Inf");
4519 }
4520 
4521 DEFALIAS (inf, Inf);
4522 
4523 /*
4524 %!assert (inf (3), [Inf, Inf, Inf; Inf, Inf, Inf; Inf, Inf, Inf])
4525 %!assert (inf (2, 3), [Inf, Inf, Inf; Inf, Inf, Inf])
4526 %!assert (inf (3, 2), [Inf, Inf; Inf, Inf; Inf, Inf])
4527 %!assert (size (inf (3, 4, 5)), [3, 4, 5])
4528 
4529 %!assert (inf (3, "single"), single ([Inf, Inf, Inf; Inf, Inf, Inf; Inf, Inf, Inf]))
4530 %!assert (inf (2, 3, "single"), single ([Inf, Inf, Inf; Inf, Inf, Inf]))
4531 %!assert (inf (3, 2, "single"), single ([Inf, Inf; Inf, Inf; Inf, Inf]))
4532 %!assert (size (inf (3, 4, 5, "single")), [3, 4, 5])
4533 
4534 %!error (inf (3, "int8"))
4535 %!error (inf (2, 3, "int8"))
4536 %!error (inf (3, 2, "int8"))
4537 %!error (inf (3, 4, 5, "int8"))
4538 */
4539 
4540 DEFUN (NaN, args, ,
4541  "-*- texinfo -*-\n\
4542 @c List other form of function in documentation index\n\
4543 @findex nan\n\
4544 \n\
4545 @deftypefn {Built-in Function} {} NaN\n\
4546 @deftypefnx {Built-in Function} {} NaN (@var{n})\n\
4547 @deftypefnx {Built-in Function} {} NaN (@var{n}, @var{m})\n\
4548 @deftypefnx {Built-in Function} {} NaN (@var{n}, @var{m}, @var{k}, @dots{})\n\
4549 @deftypefnx {Built-in Function} {} NaN (@dots{}, @var{class})\n\
4550 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
4551 to the IEEE symbol NaN (Not a Number).\n\
4552 \n\
4553 NaN is the result of operations which do not produce a well defined numerical\n\
4554 result. Common operations which produce a NaN are arithmetic with infinity\n\
4555 @tex\n\
4556 ($\\infty - \\infty$), zero divided by zero ($0/0$),\n\
4557 @end tex\n\
4558 @ifnottex\n\
4559 (Inf - Inf), zero divided by zero (0/0),\n\
4560 @end ifnottex\n\
4561 and any operation involving another NaN value (5 + NaN).\n\
4562 \n\
4563 Note that NaN always compares not equal to NaN (NaN != NaN). This behavior\n\
4564 is specified by the IEEE standard for floating point arithmetic. To find\n\
4565 NaN values, use the @code{isnan} function.\n\
4566 \n\
4567 When called with no arguments, return a scalar with the value @samp{NaN}.\n\
4568 \n\
4569 When called with a single argument, return a square matrix with the dimension\n\
4570 specified.\n\
4571 \n\
4572 When called with more than one scalar argument the first two arguments are\n\
4573 taken as the number of rows and columns and any further arguments specify\n\
4574 additional matrix dimensions.\n\
4575 \n\
4576 \n\
4577 The optional argument @var{class} specifies the return type and may be\n\
4578 either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4579 @seealso{isnan, Inf}\n\
4580 @end deftypefn")
4581 {
4582  return fill_matrix (args, lo_ieee_nan_value (),
4583  lo_ieee_float_nan_value (), "NaN");
4584 }
4585 
4586 DEFALIAS (nan, NaN);
4587 
4588 /*
4589 %!assert (NaN (3), [NaN, NaN, NaN; NaN, NaN, NaN; NaN, NaN, NaN])
4590 %!assert (NaN (2, 3), [NaN, NaN, NaN; NaN, NaN, NaN])
4591 %!assert (NaN (3, 2), [NaN, NaN; NaN, NaN; NaN, NaN])
4592 %!assert (size (NaN (3, 4, 5)), [3, 4, 5])
4593 
4594 %!assert (NaN (3, "single"), single ([NaN, NaN, NaN; NaN, NaN, NaN; NaN, NaN, NaN]))
4595 %!assert (NaN (2, 3, "single"), single ([NaN, NaN, NaN; NaN, NaN, NaN]))
4596 %!assert (NaN (3, 2, "single"), single ([NaN, NaN; NaN, NaN; NaN, NaN]))
4597 %!assert (size (NaN (3, 4, 5, "single")), [3, 4, 5])
4598 
4599 %!error (NaN (3, "int8"))
4600 %!error (NaN (2, 3, "int8"))
4601 %!error (NaN (3, 2, "int8"))
4602 %!error (NaN (3, 4, 5, "int8"))
4603 */
4604 
4605 DEFUN (e, args, ,
4606  "-*- texinfo -*-\n\
4607 @deftypefn {Built-in Function} {} e\n\
4608 @deftypefnx {Built-in Function} {} e (@var{n})\n\
4609 @deftypefnx {Built-in Function} {} e (@var{n}, @var{m})\n\
4610 @deftypefnx {Built-in Function} {} e (@var{n}, @var{m}, @var{k}, @dots{})\n\
4611 @deftypefnx {Built-in Function} {} e (@dots{}, @var{class})\n\
4612 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
4613 to the base of natural logarithms.\n\
4614 \n\
4615 The constant\n\
4616 @tex\n\
4617 $e$ satisfies the equation $\\log (e) = 1$.\n\
4618 @end tex\n\
4619 @ifnottex\n\
4620 @samp{e} satisfies the equation @code{log} (e) = 1.\n\
4621 @end ifnottex\n\
4622 \n\
4623 When called with no arguments, return a scalar with the value @math{e}.\n\
4624 \n\
4625 When called with a single argument, return a square matrix with the dimension\n\
4626 specified.\n\
4627 \n\
4628 When called with more than one scalar argument the first two arguments are\n\
4629 taken as the number of rows and columns and any further arguments specify\n\
4630 additional matrix dimensions.\n\
4631 \n\
4632 The optional argument @var{class} specifies the return type and may be\n\
4633 either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4634 @seealso{log, exp, pi, I}\n\
4635 @end deftypefn")
4636 {
4637 #if defined (M_E)
4638  double e_val = M_E;
4639 #else
4640  double e_val = exp (1.0);
4641 #endif
4642 
4643  return fill_matrix (args, e_val, "e");
4644 }
4645 
4646 DEFUN (eps, args, ,
4647  "-*- texinfo -*-\n\
4648 @deftypefn {Built-in Function} {} eps\n\
4649 @deftypefnx {Built-in Function} {} eps (@var{x})\n\
4650 @deftypefnx {Built-in Function} {} eps (@var{n}, @var{m})\n\
4651 @deftypefnx {Built-in Function} {} eps (@var{n}, @var{m}, @var{k}, @dots{})\n\
4652 @deftypefnx {Built-in Function} {} eps (@dots{}, @var{class})\n\
4653 Return a scalar, matrix or N-dimensional array whose elements are all eps,\n\
4654 the machine precision.\n\
4655 \n\
4656 More precisely, @code{eps} is the relative spacing between any two adjacent\n\
4657 numbers in the machine's floating point system. This number is obviously\n\
4658 system dependent. On machines that support IEEE floating point arithmetic,\n\
4659 @code{eps} is approximately\n\
4660 @tex\n\
4661 $2.2204\\times10^{-16}$ for double precision and $1.1921\\times10^{-7}$\n\
4662 @end tex\n\
4663 @ifnottex\n\
4664 2.2204e-16 for double precision and 1.1921e-07\n\
4665 @end ifnottex\n\
4666 for single precision.\n\
4667 \n\
4668 When called with no arguments, return a scalar with the value\n\
4669 @code{eps (1.0)}.\n\
4670 \n\
4671 Given a single argument @var{x}, return the distance between @var{x} and the\n\
4672 next largest value.\n\
4673 \n\
4674 When called with more than one argument the first two arguments are taken as\n\
4675 the number of rows and columns and any further arguments specify additional\n\
4676 matrix dimensions. The optional argument @var{class} specifies the return\n\
4677 type and may be either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4678 @seealso{realmax, realmin, intmax, bitmax}\n\
4679 @end deftypefn")
4680 {
4681  int nargin = args.length ();
4682  octave_value retval;
4683 
4684  if (nargin == 1 && ! args(0).is_string ())
4685  {
4686  if (args(0).is_single_type ())
4687  {
4688  Array<float> x = args(0).float_array_value ();
4689 
4690  if (! error_state)
4691  {
4692  Array<float> epsval (x.dims ());
4693 
4694  for (octave_idx_type i = 0; i < x.numel (); i++)
4695  {
4696  float val = ::fabsf (x(i));
4697  if (xisnan (val) || xisinf (val))
4698  epsval(i) = lo_ieee_nan_value ();
4699  else if (val < std::numeric_limits<float>::min ())
4700  epsval(i) = powf (2.0, -149e0);
4701  else
4702  {
4703  int expon;
4704  gnulib::frexpf (val, &expon);
4705  epsval(i) = std::pow (2.0f,
4706  static_cast<float> (expon - 24));
4707  }
4708  }
4709  retval = epsval;
4710  }
4711  }
4712  else
4713  {
4714  Array<double> x = args(0).array_value ();
4715 
4716  if (! error_state)
4717  {
4718  Array<double> epsval (x.dims ());
4719 
4720  for (octave_idx_type i = 0; i < x.numel (); i++)
4721  {
4722  double val = ::fabs (x(i));
4723  if (xisnan (val) || xisinf (val))
4724  epsval(i) = lo_ieee_nan_value ();
4725  else if (val < std::numeric_limits<double>::min ())
4726  epsval(i) = pow (2.0, -1074e0);
4727  else
4728  {
4729  int expon;
4730  gnulib::frexp (val, &expon);
4731  epsval(i) = std::pow (2.0,
4732  static_cast<double> (expon - 53));
4733  }
4734  retval = epsval;
4735  }
4736  }
4737  }
4738  }
4739  else
4740  retval = fill_matrix (args, std::numeric_limits<double>::epsilon (),
4741  std::numeric_limits<float>::epsilon (), "eps");
4742 
4743  return retval;
4744 }
4745 
4746 /*
4747 %!assert (eps (1/2), 2^(-53))
4748 %!assert (eps (1), 2^(-52))
4749 %!assert (eps (2), 2^(-51))
4750 %!assert (eps (realmax), 2^971)
4751 %!assert (eps (0), 2^(-1074))
4752 %!assert (eps (realmin/2), 2^(-1074))
4753 %!assert (eps (realmin/16), 2^(-1074))
4754 %!assert (eps (Inf), NaN)
4755 %!assert (eps (NaN), NaN)
4756 %!assert (eps ([1/2 1 2 realmax 0 realmin/2 realmin/16 Inf NaN]),
4757 %! [2^(-53) 2^(-52) 2^(-51) 2^971 2^(-1074) 2^(-1074) 2^(-1074) NaN NaN])
4758 %!assert (eps (single (1/2)), single (2^(-24)))
4759 %!assert (eps (single (1)), single (2^(-23)))
4760 %!assert (eps (single (2)), single (2^(-22)))
4761 %!assert (eps (realmax ("single")), single (2^104))
4762 %!assert (eps (single (0)), single (2^(-149)))
4763 %!assert (eps (realmin ("single")/2), single (2^(-149)))
4764 %!assert (eps (realmin ("single")/16), single (2^(-149)))
4765 %!assert (eps (single (Inf)), single (NaN))
4766 %!assert (eps (single (NaN)), single (NaN))
4767 %!assert (eps (single ([1/2 1 2 realmax("single") 0 realmin("single")/2 realmin("single")/16 Inf NaN])),
4768 %! single ([2^(-24) 2^(-23) 2^(-22) 2^104 2^(-149) 2^(-149) 2^(-149) NaN NaN]))
4769 
4770 */
4771 
4772 DEFUN (pi, args, ,
4773  "-*- texinfo -*-\n\
4774 @deftypefn {Built-in Function} {} pi\n\
4775 @deftypefnx {Built-in Function} {} pi (@var{n})\n\
4776 @deftypefnx {Built-in Function} {} pi (@var{n}, @var{m})\n\
4777 @deftypefnx {Built-in Function} {} pi (@var{n}, @var{m}, @var{k}, @dots{})\n\
4778 @deftypefnx {Built-in Function} {} pi (@dots{}, @var{class})\n\
4779 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
4780 to the ratio of the circumference of a circle to its\n\
4781 @tex\n\
4782 diameter($\\pi$).\n\
4783 @end tex\n\
4784 @ifnottex\n\
4785 diameter.\n\
4786 @end ifnottex\n\
4787 \n\
4788 Internally, @code{pi} is computed as @samp{4.0 * atan (1.0)}.\n\
4789 \n\
4790 When called with no arguments, return a scalar with the value of\n\
4791 @tex\n\
4792 $\\pi$.\n\
4793 @end tex\n\
4794 @ifnottex\n\
4795 pi.\n\
4796 @end ifnottex\n\
4797 \n\
4798 When called with a single argument, return a square matrix with the dimension\n\
4799 specified.\n\
4800 \n\
4801 When called with more than one scalar argument the first two arguments are\n\
4802 taken as the number of rows and columns and any further arguments specify\n\
4803 additional matrix dimensions.\n\
4804 \n\
4805 The optional argument @var{class} specifies the return type and may be\n\
4806 either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4807 @seealso{e, I}\n\
4808 @end deftypefn")
4809 {
4810 #if defined (M_PI)
4811  double pi_val = M_PI;
4812 #else
4813  double pi_val = 4.0 * atan (1.0);
4814 #endif
4815 
4816  return fill_matrix (args, pi_val, "pi");
4817 }
4818 
4819 DEFUN (realmax, args, ,
4820  "-*- texinfo -*-\n\
4821 @deftypefn {Built-in Function} {} realmax\n\
4822 @deftypefnx {Built-in Function} {} realmax (@var{n})\n\
4823 @deftypefnx {Built-in Function} {} realmax (@var{n}, @var{m})\n\
4824 @deftypefnx {Built-in Function} {} realmax (@var{n}, @var{m}, @var{k}, @dots{})\n\
4825 @deftypefnx {Built-in Function} {} realmax (@dots{}, @var{class})\n\
4826 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
4827 to the largest floating point number that is representable.\n\
4828 \n\
4829 The actual value is system dependent. On machines that support IEEE\n\
4830 floating point arithmetic, @code{realmax} is approximately\n\
4831 @tex\n\
4832 $1.7977\\times10^{308}$ for double precision and $3.4028\\times10^{38}$\n\
4833 @end tex\n\
4834 @ifnottex\n\
4835 1.7977e+308 for double precision and 3.4028e+38\n\
4836 @end ifnottex\n\
4837 for single precision.\n\
4838 \n\
4839 When called with no arguments, return a scalar with the value\n\
4840 @code{realmax (@qcode{\"double\"})}.\n\
4841 \n\
4842 When called with a single argument, return a square matrix with the dimension\n\
4843 specified.\n\
4844 \n\
4845 When called with more than one scalar argument the first two arguments are\n\
4846 taken as the number of rows and columns and any further arguments specify\n\
4847 additional matrix dimensions.\n\
4848 \n\
4849 The optional argument @var{class} specifies the return type and may be\n\
4850 either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4851 @seealso{realmin, intmax, bitmax, eps}\n\
4852 @end deftypefn")
4853 {
4855  std::numeric_limits<float>::max (), "realmax");
4856 }
4857 
4858 DEFUN (realmin, args, ,
4859  "-*- texinfo -*-\n\
4860 @deftypefn {Built-in Function} {} realmin\n\
4861 @deftypefnx {Built-in Function} {} realmin (@var{n})\n\
4862 @deftypefnx {Built-in Function} {} realmin (@var{n}, @var{m})\n\
4863 @deftypefnx {Built-in Function} {} realmin (@var{n}, @var{m}, @var{k}, @dots{})\n\
4864 @deftypefnx {Built-in Function} {} realmin (@dots{}, @var{class})\n\
4865 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
4866 to the smallest normalized floating point number that is representable.\n\
4867 \n\
4868 The actual value is system dependent. On machines that support\n\
4869 IEEE floating point arithmetic, @code{realmin} is approximately\n\
4870 @tex\n\
4871 $2.2251\\times10^{-308}$ for double precision and $1.1755\\times10^{-38}$\n\
4872 @end tex\n\
4873 @ifnottex\n\
4874 2.2251e-308 for double precision and 1.1755e-38\n\
4875 @end ifnottex\n\
4876 for single precision.\n\
4877 \n\
4878 When called with no arguments, return a scalar with the value\n\
4879 @code{realmin (@qcode{\"double\"})}.\n\
4880 \n\
4881 When called with a single argument, return a square matrix with the dimension\n\
4882 specified.\n\
4883 \n\
4884 When called with more than one scalar argument the first two arguments are\n\
4885 taken as the number of rows and columns and any further arguments specify\n\
4886 additional matrix dimensions.\n\
4887 \n\
4888 The optional argument @var{class} specifies the return type and may be\n\
4889 either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4890 @seealso{realmax, intmin, eps}\n\
4891 @end deftypefn")
4892 {
4894  std::numeric_limits<float>::min (), "realmin");
4895 }
4896 
4897 DEFUN (I, args, ,
4898  "-*- texinfo -*-\n\
4899 @c List other forms of function in documentation index\n\
4900 @findex i\n\
4901 @findex j\n\
4902 @findex J\n\
4903 \n\
4904 @deftypefn {Built-in Function} {} I\n\
4905 @deftypefnx {Built-in Function} {} I (@var{n})\n\
4906 @deftypefnx {Built-in Function} {} I (@var{n}, @var{m})\n\
4907 @deftypefnx {Built-in Function} {} I (@var{n}, @var{m}, @var{k}, @dots{})\n\
4908 @deftypefnx {Built-in Function} {} I (@dots{}, @var{class})\n\
4909 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
4910 to the pure imaginary unit, defined as\n\
4911 @tex\n\
4912 $\\sqrt{-1}$.\n\
4913 @end tex\n\
4914 @ifnottex\n\
4915 @code{sqrt (-1)}.\n\
4916 @end ifnottex\n\
4917 \n\
4918 I, and its equivalents i, j, and J, are functions so any of the names may\n\
4919 be reused for other purposes (such as i for a counter variable).\n\
4920 \n\
4921 When called with no arguments, return a scalar with the value @math{i}.\n\
4922 \n\
4923 When called with a single argument, return a square matrix with the dimension\n\
4924 specified.\n\
4925 \n\
4926 When called with more than one scalar argument the first two arguments are\n\
4927 taken as the number of rows and columns and any further arguments specify\n\
4928 additional matrix dimensions.\n\
4929 \n\
4930 The optional argument @var{class} specifies the return type and may be\n\
4931 either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4932 @seealso{e, pi, log, exp}\n\
4933 @end deftypefn")
4934 {
4935  return fill_matrix (args, Complex (0.0, 1.0), "I");
4936 }
4937 
4938 DEFALIAS (i, I);
4939 DEFALIAS (J, I);
4940 DEFALIAS (j, I);
4941 
4942 DEFUN (NA, args, ,
4943  "-*- texinfo -*-\n\
4944 @deftypefn {Built-in Function} {} NA\n\
4945 @deftypefnx {Built-in Function} {} NA (@var{n})\n\
4946 @deftypefnx {Built-in Function} {} NA (@var{n}, @var{m})\n\
4947 @deftypefnx {Built-in Function} {} NA (@var{n}, @var{m}, @var{k}, @dots{})\n\
4948 @deftypefnx {Built-in Function} {} NA (@dots{}, @var{class})\n\
4949 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
4950 to the special constant used to designate missing values.\n\
4951 \n\
4952 Note that NA always compares not equal to NA (NA != NA).\n\
4953 To find NA values, use the @code{isna} function.\n\
4954 \n\
4955 When called with no arguments, return a scalar with the value @samp{NA}.\n\
4956 \n\
4957 When called with a single argument, return a square matrix with the dimension\n\
4958 specified.\n\
4959 \n\
4960 When called with more than one scalar argument the first two arguments are\n\
4961 taken as the number of rows and columns and any further arguments specify\n\
4962 additional matrix dimensions.\n\
4963 \n\
4964 The optional argument @var{class} specifies the return type and may be\n\
4965 either @qcode{\"double\"} or @qcode{\"single\"}.\n\
4966 @seealso{isna}\n\
4967 @end deftypefn")
4968 {
4969  return fill_matrix (args, lo_ieee_na_value (),
4970  lo_ieee_float_na_value (), "NA");
4971 }
4972 
4973 /*
4974 %!assert (single (NA ("double")), NA ("single"))
4975 %!assert (double (NA ("single")), NA ("double"))
4976 */
4977 
4978 DEFUN (false, args, ,
4979  "-*- texinfo -*-\n\
4980 @deftypefn {Built-in Function} {} false (@var{x})\n\
4981 @deftypefnx {Built-in Function} {} false (@var{n}, @var{m})\n\
4982 @deftypefnx {Built-in Function} {} false (@var{n}, @var{m}, @var{k}, @dots{})\n\
4983 Return a matrix or N-dimensional array whose elements are all logical 0.\n\
4984 \n\
4985 If invoked with a single scalar integer argument, return a square\n\
4986 matrix of the specified size.\n\
4987 \n\
4988 If invoked with two or more scalar integer arguments, or a vector of integer\n\
4989 values, return an array with given dimensions.\n\
4990 @seealso{true}\n\
4991 @end deftypefn")
4992 {
4993  return fill_matrix (args, false, "false");
4994 }
4995 
4996 DEFUN (true, args, ,
4997  "-*- texinfo -*-\n\
4998 @deftypefn {Built-in Function} {} true (@var{x})\n\
4999 @deftypefnx {Built-in Function} {} true (@var{n}, @var{m})\n\
5000 @deftypefnx {Built-in Function} {} true (@var{n}, @var{m}, @var{k}, @dots{})\n\
5001 Return a matrix or N-dimensional array whose elements are all logical 1.\n\
5002 \n\
5003 If invoked with a single scalar integer argument, return a square\n\
5004 matrix of the specified size.\n\
5005 \n\
5006 If invoked with two or more scalar integer arguments, or a vector of integer\n\
5007 values, return an array with given dimensions.\n\
5008 @seealso{false}\n\
5009 @end deftypefn")
5010 {
5011  return fill_matrix (args, true, "true");
5012 }
5013 
5014 template <class MT>
5016 identity_matrix (int nr, int nc)
5017 {
5018  octave_value retval;
5019 
5020  typename MT::element_type one (1);
5021 
5022  if (nr == 1 && nc == 1)
5023  retval = one;
5024  else
5025  {
5026  dim_vector dims (nr, nc);
5027 
5028  typename MT::element_type zero (0);
5029 
5030  MT m (dims, zero);
5031 
5032  if (nr > 0 && nc > 0)
5033  {
5034  int n = std::min (nr, nc);
5035 
5036  for (int i = 0; i < n; i++)
5037  m(i,i) = one;
5038  }
5039 
5040  retval = m;
5041  }
5042 
5043  return retval;
5044 }
5045 
5046 #define INSTANTIATE_EYE(T) \
5047  template octave_value identity_matrix<T> (int, int)
5048 
5060 
5061 static octave_value
5063 {
5064  octave_value retval;
5065 
5066  // FIXME: perhaps this should be made extensible by using
5067  // the class name to lookup a function to call to create the new
5068  // value.
5069 
5070  if (! error_state)
5071  {
5072  switch (dt)
5073  {
5075  retval = identity_matrix<int8NDArray> (nr, nc);
5076  break;
5077 
5079  retval = identity_matrix<uint8NDArray> (nr, nc);
5080  break;
5081 
5083  retval = identity_matrix<int16NDArray> (nr, nc);
5084  break;
5085 
5087  retval = identity_matrix<uint16NDArray> (nr, nc);
5088  break;
5089 
5091  retval = identity_matrix<int32NDArray> (nr, nc);
5092  break;
5093 
5095  retval = identity_matrix<uint32NDArray> (nr, nc);
5096  break;
5097 
5099  retval = identity_matrix<int64NDArray> (nr, nc);
5100  break;
5101 
5103  retval = identity_matrix<uint64NDArray> (nr, nc);
5104  break;
5105 
5107  retval = FloatDiagMatrix (nr, nc, 1.0f);
5108  break;
5109 
5111  retval = DiagMatrix (nr, nc, 1.0);
5112  break;
5113 
5115  retval = identity_matrix<boolNDArray> (nr, nc);
5116  break;
5117 
5118  default:
5119  error ("eye: invalid class name");
5120  break;
5121  }
5122  }
5123 
5124  return retval;
5125 }
5126 
5127 #undef INT_EYE_MATRIX
5128 
5129 DEFUN (eye, args, ,
5130  "-*- texinfo -*-\n\
5131 @deftypefn {Built-in Function} {} eye (@var{n})\n\
5132 @deftypefnx {Built-in Function} {} eye (@var{m}, @var{n})\n\
5133 @deftypefnx {Built-in Function} {} eye ([@var{m} @var{n}])\n\
5134 @deftypefnx {Built-in Function} {} eye (@dots{}, @var{class})\n\
5135 Return an identity matrix.\n\
5136 \n\
5137 If invoked with a single scalar argument @var{n}, return a square\n\
5138 @nospell{NxN} identity matrix.\n\
5139 \n\
5140 If supplied two scalar arguments (@var{m}, @var{n}), @code{eye} takes them\n\
5141 to be the number of rows and columns. If given a vector with two elements,\n\
5142 @code{eye} uses the values of the elements as the number of rows and\n\
5143 columns, respectively. For example:\n\
5144 \n\
5145 @example\n\
5146 @group\n\
5147 eye (3)\n\
5148  @result{} 1 0 0\n\
5149  0 1 0\n\
5150  0 0 1\n\
5151 @end group\n\
5152 @end example\n\
5153 \n\
5154 The following expressions all produce the same result:\n\
5155 \n\
5156 @example\n\
5157 @group\n\
5158 eye (2)\n\
5159 @equiv{}\n\
5160 eye (2, 2)\n\
5161 @equiv{}\n\
5162 eye (size ([1, 2; 3, 4]))\n\
5163 @end group\n\
5164 @end example\n\
5165 \n\
5166 The optional argument @var{class}, allows @code{eye} to return an array of\n\
5167 the specified type, like\n\
5168 \n\
5169 @example\n\
5170 val = zeros (n,m, \"uint8\")\n\
5171 @end example\n\
5172 \n\
5173 Calling @code{eye} with no arguments is equivalent to calling it with an\n\
5174 argument of 1. Any negative dimensions are treated as zero. These odd\n\
5175 definitions are for compatibility with @sc{matlab}.\n\
5176 @seealso{speye, ones, zeros}\n\
5177 @end deftypefn")
5178 {
5179  octave_value retval;
5180 
5181  int nargin = args.length ();
5182 
5184 
5185  // Check for type information.
5186 
5187  if (nargin > 0 && args(nargin-1).is_string ())
5188  {
5189  std::string nm = args(nargin-1).string_value ();
5190  nargin--;
5191 
5193 
5194  if (error_state)
5195  return retval;
5196  }
5197 
5198  switch (nargin)
5199  {
5200  case 0:
5201  retval = identity_matrix (1, 1, dt);
5202  break;
5203 
5204  case 1:
5205  {
5206  octave_idx_type nr, nc;
5207  get_dimensions (args(0), "eye", nr, nc);
5208 
5209  if (! error_state)
5210  retval = identity_matrix (nr, nc, dt);
5211  }
5212  break;
5213 
5214  case 2:
5215  {
5216  octave_idx_type nr, nc;
5217  get_dimensions (args(0), args(1), "eye", nr, nc);
5218 
5219  if (! error_state)
5220  retval = identity_matrix (nr, nc, dt);
5221  }
5222  break;
5223 
5224  default:
5225  print_usage ();
5226  break;
5227  }
5228 
5229  return retval;
5230 }
5231 
5232 /*
5233 %!assert (full (eye (3)), [1, 0, 0; 0, 1, 0; 0, 0, 1])
5234 %!assert (full (eye (2, 3)), [1, 0, 0; 0, 1, 0])
5235 
5236 %!assert (full (eye (3,"single")), single ([1, 0, 0; 0, 1, 0; 0, 0, 1]))
5237 %!assert (full (eye (2, 3,"single")), single ([1, 0, 0; 0, 1, 0]))
5238 
5239 %!assert (eye (3, "int8"), int8 ([1, 0, 0; 0, 1, 0; 0, 0, 1]))
5240 %!assert (eye (2, 3, "int8"), int8 ([1, 0, 0; 0, 1, 0]))
5241 
5242 %!error eye (1, 2, 3)
5243 */
5244 
5245 template <class MT>
5246 static octave_value
5247 do_linspace (const octave_value& base, const octave_value& limit,
5248  octave_idx_type n)
5249 {
5250  typedef typename MT::column_vector_type CVT;
5251  typedef typename MT::element_type T;
5252 
5253  octave_value retval;
5254 
5255  if (base.is_scalar_type ())
5256  {
5257  T bs = octave_value_extract<T> (base);
5258  if (limit.is_scalar_type ())
5259  {
5260  T ls = octave_value_extract<T> (limit);
5261  retval = linspace (bs, ls, n);
5262  }
5263  else
5264  {
5265  CVT lv = octave_value_extract<CVT> (limit);
5266  CVT bv (lv.length (), bs);
5267  retval = linspace (bv, lv, n);
5268  }
5269  }
5270  else
5271  {
5272  CVT bv = octave_value_extract<CVT> (base);
5273  if (limit.is_scalar_type ())
5274  {
5275  T ls = octave_value_extract<T> (limit);
5276  CVT lv (bv.length (), ls);
5277  retval = linspace (bv, lv, n);
5278  }
5279  else
5280  {
5281  CVT lv = octave_value_extract<CVT> (limit);
5282  retval = linspace (bv, lv, n);
5283  }
5284  }
5285 
5286  return retval;
5287 }
5288 
5289 DEFUN (linspace, args, ,
5290  "-*- texinfo -*-\n\
5291 @deftypefn {Built-in Function} {} linspace (@var{base}, @var{limit})\n\
5292 @deftypefnx {Built-in Function} {} linspace (@var{base}, @var{limit}, @var{n})\n\
5293 Return a row vector with @var{n} linearly spaced elements between\n\
5294 @var{base} and @var{limit}.\n\
5295 \n\
5296 If the number of elements is greater than one, then the endpoints @var{base}\n\
5297 and @var{limit} are always included in the range. If @var{base} is greater\n\
5298 than @var{limit}, the elements are stored in decreasing order. If the\n\
5299 number of points is not specified, a value of 100 is used.\n\
5300 \n\
5301 The @code{linspace} function always returns a row vector if both @var{base}\n\
5302 and @var{limit} are scalars. If one, or both, of them are column vectors,\n\
5303 @code{linspace} returns a matrix.\n\
5304 \n\
5305 For compatibility with @sc{matlab}, return the second argument (@var{limit})\n\
5306 if fewer than two values are requested.\n\
5307 @seealso{logspace}\n\
5308 @end deftypefn")
5309 {
5310  octave_value retval;
5311 
5312  int nargin = args.length ();
5313 
5314  octave_idx_type npoints = 100;
5315 
5316  if (nargin != 2 && nargin != 3)
5317  {
5318  print_usage ();
5319  return retval;
5320  }
5321 
5322  if (nargin == 3)
5323  {
5324  // Apparently undocumented Matlab. If the third arg is an empty
5325  // numeric value, the number of points defaults to 1.
5326 
5327  octave_value arg_3 = args(2);
5328 
5329  if (arg_3.is_numeric_type () && arg_3.is_empty ())
5330  npoints = 1;
5331  else
5332  npoints = arg_3.idx_type_value ();
5333  }
5334 
5335  if (! error_state)
5336  {
5337  octave_value arg_1 = args(0);
5338  octave_value arg_2 = args(1);
5339 
5340  if (arg_1.is_single_type () || arg_2.is_single_type ())
5341  {
5342  if (arg_1.is_complex_type () || arg_2.is_complex_type ())
5343  retval = do_linspace<FloatComplexMatrix> (arg_1, arg_2, npoints);
5344  else
5345  retval = do_linspace<FloatMatrix> (arg_1, arg_2, npoints);
5346 
5347  }
5348  else
5349  {
5350  if (arg_1.is_complex_type () || arg_2.is_complex_type ())
5351  retval = do_linspace<ComplexMatrix> (arg_1, arg_2, npoints);
5352  else
5353  retval = do_linspace<Matrix> (arg_1, arg_2, npoints);
5354  }
5355  }
5356  else
5357  error ("linspace: N must be an integer");
5358 
5359  return retval;
5360 }
5361 
5362 
5363 /*
5364 %!test
5365 %! x1 = linspace (1, 2);
5366 %! x2 = linspace (1, 2, 10);
5367 %! x3 = linspace (1, -2, 10);
5368 %! assert (size (x1) == [1, 100] && x1(1) == 1 && x1(100) == 2);
5369 %! assert (size (x2) == [1, 10] && x2(1) == 1 && x2(10) == 2);
5370 %! assert (size (x3) == [1, 10] && x3(1) == 1 && x3(10) == -2);
5371 
5372 %! ##assert (linspace ([1, 2; 3, 4], 5, 6), linspace (1, 5, 6))
5373 
5374 %!assert (linspace (0, 1, []), 1)
5375 
5376 %!error linspace ()
5377 %!error linspace (1, 2, 3, 4)
5378 */
5379 
5380 // FIXME: should accept dimensions as separate args for N-d
5381 // arrays as well as 1-d and 2-d arrays.
5382 
5383 DEFUN (resize, args, ,
5384  "-*- texinfo -*-\n\
5385 @deftypefn {Built-in Function} {} resize (@var{x}, @var{m})\n\
5386 @deftypefnx {Built-in Function} {} resize (@var{x}, @var{m}, @var{n}, @dots{})\n\
5387 @deftypefnx {Built-in Function} {} resize (@var{x}, [@var{m} @var{n} @dots{}])\n\
5388 Resize @var{x} cutting off elements as necessary.\n\
5389 \n\
5390 In the result, element with certain indices is equal to the corresponding\n\
5391 element of @var{x} if the indices are within the bounds of @var{x};\n\
5392 otherwise, the element is set to zero.\n\
5393 \n\
5394 In other words, the statement\n\
5395 \n\
5396 @example\n\
5397 y = resize (x, dv)\n\
5398 @end example\n\
5399 \n\
5400 @noindent\n\
5401 is equivalent to the following code:\n\
5402 \n\
5403 @example\n\
5404 @group\n\
5405 y = zeros (dv, class (x));\n\
5406 sz = min (dv, size (x));\n\
5407 for i = 1:length (sz)\n\
5408  idx@{i@} = 1:sz(i);\n\
5409 endfor\n\
5410 y(idx@{:@}) = x(idx@{:@});\n\
5411 @end group\n\
5412 @end example\n\
5413 \n\
5414 @noindent\n\
5415 but is performed more efficiently.\n\
5416 \n\
5417 If only @var{m} is supplied, and it is a scalar, the dimension of the\n\
5418 result is @var{m}-by-@var{m}.\n\
5419 If @var{m}, @var{n}, @dots{} are all scalars, then the dimensions of\n\
5420 the result are @var{m}-by-@var{n}-by-@dots{}.\n\
5421 If given a vector as input, then the\n\
5422 dimensions of the result are given by the elements of that vector.\n\
5423 \n\
5424 An object can be resized to more dimensions than it has;\n\
5425 in such case the missing dimensions are assumed to be 1.\n\
5426 Resizing an object to fewer dimensions is not possible.\n\
5427 @seealso{reshape, postpad, prepad, cat}\n\
5428 @end deftypefn")
5429 {
5430  octave_value retval;
5431  int nargin = args.length ();
5432 
5433  if (nargin == 2)
5434  {
5435  Array<double> vec = args(1).vector_value ();
5436  int ndim = vec.length ();
5437  if (ndim == 1)
5438  {
5439  octave_idx_type m = static_cast<octave_idx_type> (vec(0));
5440  retval = args(0);
5441  retval = retval.resize (dim_vector (m, m), true);
5442  }
5443  else
5444  {
5445  dim_vector dv;
5446  dv.resize (ndim);
5447  for (int i = 0; i < ndim; i++)
5448  dv(i) = static_cast<octave_idx_type> (vec(i));
5449  retval = args(0);
5450  retval = retval.resize (dv, true);
5451  }
5452  }
5453  else if (nargin > 2)
5454  {
5455  dim_vector dv;
5456  dv.resize (nargin - 1);
5457  for (octave_idx_type i = 1; i < nargin; i++)
5458  dv(i-1) = static_cast<octave_idx_type> (args(i).scalar_value ());
5459  if (!error_state)
5460  {
5461  retval = args(0);
5462  retval = retval.resize (dv, true);
5463  }
5464 
5465  }
5466  else
5467  print_usage ();
5468  return retval;
5469 }
5470 
5471 // FIXME: should use octave_idx_type for dimensions.
5472 
5473 DEFUN (reshape, args, ,
5474  "-*- texinfo -*-\n\
5475 @deftypefn {Built-in Function} {} reshape (@var{A}, @var{m}, @var{n}, @dots{})\n\
5476 @deftypefnx {Built-in Function} {} reshape (@var{A}, [@var{m} @var{n} @dots{}])\n\
5477 @deftypefnx {Built-in Function} {} reshape (@var{A}, @dots{}, [], @dots{})\n\
5478 @deftypefnx {Built-in Function} {} reshape (@var{A}, @var{size})\n\
5479 Return a matrix with the specified dimensions (@var{m}, @var{n}, @dots{})\n\
5480 whose elements are taken from the matrix @var{A}.\n\
5481 \n\
5482 The elements of the matrix are accessed in column-major order (like Fortran\n\
5483 arrays are stored).\n\
5484 \n\
5485 The following code demonstrates reshaping a 1x4 row vector into a 2x2 square\n\
5486 matrix.\n\
5487 \n\
5488 @example\n\
5489 @group\n\
5490 reshape ([1, 2, 3, 4], 2, 2)\n\
5491  @result{} 1 3\n\
5492  2 4\n\
5493 @end group\n\
5494 @end example\n\
5495 \n\
5496 @noindent\n\
5497 Note that the total number of elements in the original matrix\n\
5498 (@code{prod (size (@var{A}))}) must match the total number of elements\n\
5499 in the new matrix (@code{prod ([@var{m} @var{n} @dots{}])}).\n\
5500 \n\
5501 A single dimension of the return matrix may be left unspecified and Octave\n\
5502 will determine its size automatically. An empty matrix ([]) is used to flag\n\
5503 the unspecified dimension.\n\
5504 @seealso{resize, vec, postpad, cat, squeeze}\n\
5505 @end deftypefn")
5506 {
5507  octave_value retval;
5508 
5509  int nargin = args.length ();
5510 
5511  dim_vector new_dims;
5512 
5513  if (nargin == 2)
5514  {
5515  Array<octave_idx_type> new_size = args(1).octave_idx_type_vector_value ();
5516 
5517  if (new_size.length () < 2)
5518  {
5519  error ("reshape: SIZE must have 2 or more dimensions");
5520  return retval;
5521  }
5522 
5523  new_dims = dim_vector::alloc (new_size.length ());
5524 
5525  for (octave_idx_type i = 0; i < new_size.length (); i++)
5526  {
5527  if (new_size(i) < 0)
5528  {
5529  error ("reshape: SIZE must be non-negative");
5530  break;
5531  }
5532  else
5533  new_dims(i) = new_size(i);
5534  }
5535  }
5536  else if (nargin > 2)
5537  {
5538  new_dims = dim_vector::alloc (nargin-1);
5539  int empty_dim = -1;
5540 
5541  for (int i = 1; i < nargin; i++)
5542  {
5543  if (args(i).is_empty ())
5544  {
5545  if (empty_dim > 0)
5546  {
5547  error ("reshape: only a single dimension can be unknown");
5548  break;
5549  }
5550  else
5551  {
5552  empty_dim = i;
5553  new_dims(i-1) = 1;
5554  }
5555  }
5556  else
5557  {
5558  new_dims(i-1) = args(i).idx_type_value ();
5559 
5560  if (error_state)
5561  break;
5562  else if (new_dims(i-1) < 0)
5563  {
5564  error ("reshape: SIZE must be non-negative");
5565  break;
5566  }
5567  }
5568  }
5569 
5570  if (! error_state && (empty_dim > 0))
5571  {
5572  octave_idx_type nel = new_dims.numel ();
5573 
5574  if (nel == 0)
5575  new_dims(empty_dim-1) = 0;
5576  else
5577  {
5578  octave_idx_type a_nel = args(0).numel ();
5579  octave_idx_type size_empty_dim = a_nel / nel;
5580 
5581  if (a_nel != size_empty_dim * nel)
5582  error ("reshape: SIZE is not divisible by the product of known dimensions (= %d)",
5583  nel);
5584  else
5585  new_dims(empty_dim-1) = size_empty_dim;
5586  }
5587  }
5588  }
5589  else
5590  {
5591  print_usage ();
5592  return retval;
5593  }
5594 
5595  if (! error_state)
5596  retval = args(0).reshape (new_dims);
5597 
5598  return retval;
5599 }
5600 
5601 /*
5602 %!assert (size (reshape (ones (4, 4), 2, 8)), [2, 8])
5603 %!assert (size (reshape (ones (4, 4), 8, 2)), [8, 2])
5604 %!assert (size (reshape (ones (15, 4), 1, 60)), [1, 60])
5605 %!assert (size (reshape (ones (15, 4), 60, 1)), [60, 1])
5606 
5607 %!assert (size (reshape (ones (4, 4, "single"), 2, 8)), [2, 8])
5608 %!assert (size (reshape (ones (4, 4, "single"), 8, 2)), [8, 2])
5609 %!assert (size (reshape (ones (15, 4, "single"), 1, 60)), [1, 60])
5610 %!assert (size (reshape (ones (15, 4, "single"), 60, 1)), [60, 1])
5611 
5612 %!test
5613 %! s.a = 1;
5614 %! fail ("reshape (s, 2, 3)", "can't reshape 1x1 array to 2x3 array");
5615 
5616 %!error reshape ()
5617 %!error reshape (1, 2, 3, 4)
5618 %!error <SIZE must have 2 or more dimensions> reshape (1:3, 3)
5619 %!error <SIZE must be non-negative> reshape (1:3, [3 -1])
5620 %!error <only a single dimension can be unknown> reshape (1:3, 1,[],[],3)
5621 %!error <SIZE must be non-negative> reshape (1:3, 3, -1)
5622 %!error <SIZE is not divisible> reshape (1:3, 3, [], 2)
5623 */
5624 
5625 DEFUN (vec, args, ,
5626  "-*- texinfo -*-\n\
5627 @deftypefn {Built-in Function} {@var{v} =} vec (@var{x})\n\
5628 @deftypefnx {Built-in Function} {@var{v} =} vec (@var{x}, @var{dim})\n\
5629 Return the vector obtained by stacking the columns of the matrix @var{x}\n\
5630 one above the other.\n\
5631 \n\
5632 Without @var{dim} this is equivalent to @code{@var{x}(:)}.\n\
5633 \n\
5634 If @var{dim} is supplied, the dimensions of @var{v} are set to @var{dim}\n\
5635 with all elements along the last dimension. This is equivalent to\n\
5636 @code{shiftdim (@var{x}(:), 1-@var{dim})}.\n\
5637 @seealso{vech, resize, cat}\n\
5638 @end deftypefn")
5639 {
5640  octave_value retval;
5641  int dim = 1;
5642 
5643  int nargin = args.length ();
5644 
5645  if (nargin < 1 || nargin > 2)
5646  print_usage () ;
5647 
5648  if (! error_state && nargin == 2)
5649  {
5650  dim = args(1).idx_type_value ();
5651 
5652  if (dim < 1)
5653  error ("vec: DIM must be greater than zero");
5654  }
5655 
5656  if (! error_state)
5657  {
5659  octave_value arg = args(0);
5660  retval = arg.single_subsref ("(", colon);
5661 
5662 
5663  if (! error_state && dim > 1)
5664  {
5665  dim_vector new_dims = dim_vector::alloc (dim);
5666 
5667  for (int i = 0; i < dim-1; i++)
5668  new_dims(i) = 1;
5669 
5670  new_dims(dim-1) = retval.numel ();
5671 
5672  retval = retval.reshape (new_dims);
5673  }
5674  }
5675 
5676  return retval;
5677 }
5678 
5679 /*
5680 %!assert (vec ([1, 2; 3, 4]), [1; 3; 2; 4])
5681 %!assert (vec ([1, 3, 2, 4]), [1; 3; 2; 4])
5682 %!assert (vec ([1, 2, 3, 4], 2), [1, 2, 3, 4])
5683 %!assert (vec ([1, 2; 3, 4]), vec ([1, 2; 3, 4], 1))
5684 %!assert (vec ([1, 2; 3, 4], 1), [1; 3; 2; 4])
5685 %!assert (vec ([1, 2; 3, 4], 2), [1, 3, 2, 4])
5686 %!assert (vec ([1, 3; 2, 4], 3), reshape ([1, 2, 3, 4], 1, 1, 4))
5687 %!assert (vec ([1, 3; 2, 4], 3), shiftdim (vec ([1, 3; 2, 4]), -2))
5688 
5689 %!error vec ()
5690 %!error vec (1, 2, 3)
5691 %!error vec ([1, 2; 3, 4], 0)
5692 */
5693 
5694 DEFUN (squeeze, args, ,
5695  "-*- texinfo -*-\n\
5696 @deftypefn {Built-in Function} {} squeeze (@var{x})\n\
5697 Remove singleton dimensions from @var{x} and return the result.\n\
5698 \n\
5699 Note that for compatibility with @sc{matlab}, all objects have\n\
5700 a minimum of two dimensions and row vectors are left unchanged.\n\
5701 @seealso{reshape}\n\
5702 @end deftypefn")
5703 {
5704  octave_value retval;
5705 
5706  if (args.length () == 1)
5707  retval = args(0).squeeze ();
5708  else
5709  print_usage ();
5710 
5711  return retval;
5712 }
5713 
5714 DEFUN (full, args, ,
5715  "-*- texinfo -*-\n\
5716 @deftypefn {Built-in Function} {@var{FM} =} full (@var{SM})\n\
5717 Return a full storage matrix from a sparse, diagonal, or permutation matrix,\n\
5718 or a range.\n\
5719 @seealso{sparse, issparse}\n\
5720 @end deftypefn")
5721 {
5722  octave_value retval;
5723 
5724  if (args.length () == 1)
5725  retval = args(0).full_value ();
5726  else
5727  print_usage ();
5728 
5729  return retval;
5730 }
5731 
5732 // Compute various norms of the vector X.
5733 
5734 DEFUN (norm, args, ,
5735  "-*- texinfo -*-\n\
5736 @deftypefn {Built-in Function} {} norm (@var{A})\n\
5737 @deftypefnx {Built-in Function} {} norm (@var{A}, @var{p})\n\
5738 @deftypefnx {Built-in Function} {} norm (@var{A}, @var{p}, @var{opt})\n\
5739 Compute the p-norm of the matrix @var{A}.\n\
5740 \n\
5741 If the second argument is missing, @code{p = 2} is assumed.\n\
5742 \n\
5743 If @var{A} is a matrix (or sparse matrix):\n\
5744 \n\
5745 @table @asis\n\
5746 @item @var{p} = @code{1}\n\
5747 1-norm, the largest column sum of the absolute values of @var{A}.\n\
5748 \n\
5749 @item @var{p} = @code{2}\n\
5750 Largest singular value of @var{A}.\n\
5751 \n\
5752 @item @var{p} = @code{Inf} or @qcode{\"inf\"}\n\
5753 @cindex infinity norm\n\
5754 Infinity norm, the largest row sum of the absolute values of @var{A}.\n\
5755 \n\
5756 @item @var{p} = @qcode{\"fro\"}\n\
5757 @cindex Frobenius norm\n\
5758 Frobenius norm of @var{A}, @code{sqrt (sum (diag (@var{A}' * @var{A})))}.\n\
5759 \n\
5760 @item other @var{p}, @code{@var{p} > 1}\n\
5761 @cindex general p-norm\n\
5762 maximum @code{norm (A*x, p)} such that @code{norm (x, p) == 1}\n\
5763 @end table\n\
5764 \n\
5765 If @var{A} is a vector or a scalar:\n\
5766 \n\
5767 @table @asis\n\
5768 @item @var{p} = @code{Inf} or @qcode{\"inf\"}\n\
5769 @code{max (abs (@var{A}))}.\n\
5770 \n\
5771 @item @var{p} = @code{-Inf}\n\
5772 @code{min (abs (@var{A}))}.\n\
5773 \n\
5774 @item @var{p} = @qcode{\"fro\"}\n\
5775 Frobenius norm of @var{A}, @code{sqrt (sumsq (abs (A)))}.\n\
5776 \n\
5777 @item @var{p} = 0\n\
5778 Hamming norm - the number of nonzero elements.\n\
5779 \n\
5780 @item other @var{p}, @code{@var{p} > 1}\n\
5781 p-norm of @var{A}, @code{(sum (abs (@var{A}) .^ @var{p})) ^ (1/@var{p})}.\n\
5782 \n\
5783 @item other @var{p} @code{@var{p} < 1}\n\
5784 the p-pseudonorm defined as above.\n\
5785 @end table\n\
5786 \n\
5787 If @var{opt} is the value @qcode{\"rows\"}, treat each row as a vector and\n\
5788 compute its norm. The result is returned as a column vector.\n\
5789 Similarly, if @var{opt} is @qcode{\"columns\"} or @qcode{\"cols\"} then\n\
5790 compute the norms of each column and return a row vector.\n\
5791 @seealso{cond, svd}\n\
5792 @end deftypefn")
5793 {
5794  octave_value_list retval;
5795 
5796  int nargin = args.length ();
5797 
5798  if (nargin >= 1 && nargin <= 3)
5799  {
5800  octave_value x_arg = args(0);
5801 
5802  if (x_arg.ndims () == 2)
5803  {
5804  enum { sfmatrix, sfcols, sfrows, sffrob, sfinf } strflag = sfmatrix;
5805  if (nargin > 1 && args(nargin-1).is_string ())
5806  {
5807  std::string str = args(nargin-1).string_value ();
5808  if (str == "cols" || str == "columns")
5809  strflag = sfcols;
5810  else if (str == "rows")
5811  strflag = sfrows;
5812  else if (str == "fro")
5813  strflag = sffrob;
5814  else if (str == "inf")
5815  strflag = sfinf;
5816  else
5817  error ("norm: unrecognized option: %s", str.c_str ());
5818  // we've handled the last parameter, so act as if it was removed
5819  nargin --;
5820  }
5821 
5822  if (! error_state)
5823  {
5824  octave_value p_arg = (nargin > 1) ? args(1) : octave_value (2);
5825 
5826  if (p_arg.is_empty ())
5827  p_arg = octave_value (2);
5828  else if (p_arg.is_string ())
5829  {
5830  std::string str = p_arg.string_value ();
5831  if ((strflag == sfcols || strflag == sfrows))
5832  {
5833  if (str == "cols" || str == "columns" || str == "rows")
5834  error ("norm: invalid combination of options");
5835  else if (str == "fro")
5836  p_arg = octave_value (2);
5837  else if (str == "inf")
5838  p_arg = octave_Inf;
5839  else
5840  error ("norm: unrecognized option: %s", str.c_str ());
5841  }
5842  else
5843  error ("norm: invalid combination of options");
5844  }
5845  else if (! p_arg.is_scalar_type ())
5846  gripe_wrong_type_arg ("norm", p_arg, true);
5847 
5848  if (! error_state)
5849  {
5850  switch (strflag)
5851  {
5852  case sfmatrix:
5853  retval(0) = xnorm (x_arg, p_arg);
5854  break;
5855  case sfcols:
5856  retval(0) = xcolnorms (x_arg, p_arg);
5857  break;
5858  case sfrows:
5859  retval(0) = xrownorms (x_arg, p_arg);
5860  break;
5861  case sffrob:
5862  retval(0) = xfrobnorm (x_arg);
5863  break;
5864  case sfinf:
5865  retval(0) = xnorm (x_arg, octave_Inf);
5866  break;
5867  }
5868  }
5869  }
5870  }
5871  else
5872  error ("norm: only valid for 2-D objects");
5873  }
5874  else
5875  print_usage ();
5876 
5877  return retval;
5878 }
5879 
5880 /*
5881 %!shared x
5882 %! x = [1, -3, 4, 5, -7];
5883 %!assert (norm (x,1), 20)
5884 %!assert (norm (x,2), 10)
5885 %!assert (norm (x,3), 8.24257059961711, -4*eps)
5886 %!assert (norm (x,Inf), 7)
5887 %!assert (norm (x,-Inf), 1)
5888 %!assert (norm (x,"inf"), 7)
5889 %!assert (norm (x,"fro"), 10, -eps)
5890 %!assert (norm (x), 10)
5891 %!assert (norm ([1e200, 1]), 1e200)
5892 %!assert (norm ([3+4i, 3-4i, sqrt(31)]), 9, -4*eps)
5893 %!shared m
5894 %! m = magic (4);
5895 %!assert (norm (m,1), 34)
5896 %!assert (norm (m,2), 34, -eps)
5897 %!assert (norm (m,Inf), 34)
5898 %!assert (norm (m,"inf"), 34)
5899 %!shared m2, flo, fhi
5900 %! m2 = [1,2;3,4];
5901 %! flo = 1e-300;
5902 %! fhi = 1e+300;
5903 %!assert (norm (flo*m2,"fro"), sqrt (30)*flo, -eps)
5904 %!assert (norm (fhi*m2,"fro"), sqrt (30)*fhi, -eps)
5905 
5906 %!shared x
5907 %! x = single ([1, -3, 4, 5, -7]);
5908 %!assert (norm (x,1), single (20))
5909 %!assert (norm (x,2), single (10))
5910 %!assert (norm (x,3), single (8.24257059961711), -4*eps ("single"))
5911 %!assert (norm (x,Inf), single (7))
5912 %!assert (norm (x,-Inf), single (1))
5913 %!assert (norm (x,"inf"), single (7))
5914 %!assert (norm (x,"fro"), single (10), -eps ("single"))
5915 %!assert (norm (x), single (10))
5916 %!assert (norm (single ([1e38, 1])), single (1e38))
5917 %!assert (norm (single ([3+4i, 3-4i, sqrt(31)])), single (9), -4*eps ("single"))
5918 %!shared m
5919 %! m = single (magic (4));
5920 %!assert (norm (m,1), single (34))
5921 %!assert (norm (m,2), single (34), -eps ("single"))
5922 %!assert (norm (m,Inf), single (34))
5923 %!assert (norm (m,"inf"), single (34))
5924 %!shared m2, flo, fhi
5925 %! m2 = single ([1,2;3,4]);
5926 %! flo = single (1e-300);
5927 %! fhi = single (1e+300);
5928 %!assert (norm (flo*m2,"fro"), single (sqrt (30)*flo), -eps ("single"))
5929 %!assert (norm (fhi*m2,"fro"), single (sqrt (30)*fhi), -eps ("single"))
5930 
5931 %!shared q
5932 %! q = rand (1e3, 3);
5933 %!assert (norm (q, 3, "rows"), sum (q.^3, 2).^(1/3), sqrt (eps));
5934 %!assert (norm (q, "fro", "rows"), sum (q.^2, 2).^(1/2), sqrt (eps));
5935 %!assert (norm (q, "fro", "rows"), sqrt (sumsq (q, 2)), sqrt (eps));
5936 %!assert (norm (q, "fro", "cols"), sqrt (sumsq (q, 1)), sqrt (eps));
5937 %!assert (norm (q, 3, "cols"), sum (q.^3, 1).^(1/3), sqrt (eps));
5938 %!assert (norm (q, "inf", "rows"), norm (q, Inf, "rows"));
5939 %!assert (norm (q, "inf", "cols"), norm (q, Inf, "cols"));
5940 %!assert (norm (q, [], "rows"), norm (q, 2, "rows"));
5941 %!assert (norm (q, [], "cols"), norm (q, 2, "cols"));
5942 
5943 %!test
5944 %! ## Test for norm returning NaN on sparse matrix (bug #30631)
5945 %! A = sparse (2,2);
5946 %! A(2,1) = 1;
5947 %! assert (norm (A), 1);
5948 */
5949 
5950 static octave_value
5952  const octave_value_list& args)
5953 {
5954  octave_value retval;
5955  if (args.length () == 1)
5956  retval = do_unary_op (op, args(0));
5957  else
5958  print_usage ();
5959 
5960  return retval;
5961 }
5962 
5963 DEFUN (not, args, ,
5964  "-*- texinfo -*-\n\
5965 @deftypefn {Built-in Function} {@var{z} =} not (@var{x})\n\
5966 Return the logical NOT of @var{x}.\n\
5967 \n\
5968 This function is equivalent to the operator syntax @w{@code{! x}}.\n\
5969 @seealso{and, or, xor}\n\
5970 @end deftypefn")
5971 {
5973 }
5974 
5975 DEFUN (uplus, args, ,
5976  "-*- texinfo -*-\n\
5977 @deftypefn {Built-in Function} {} uplus (@var{x})\n\
5978 This function and @w{@tcode{+ x}} are equivalent.\n\
5979 @seealso{uminus, plus, minus}\n\
5980 @end deftypefn")
5981 {
5983 }
5984 
5985 DEFUN (uminus, args, ,
5986  "-*- texinfo -*-\n\
5987 @deftypefn {Built-in Function} {} uminus (@var{x})\n\
5988 This function and @w{@tcode{- x}} are equivalent.\n\
5989 @seealso{uplus, minus}\n\
5990 @end deftypefn")
5991 {
5993 }
5994 
5995 DEFUN (transpose, args, ,
5996  "-*- texinfo -*-\n\
5997 @deftypefn {Built-in Function} {} transpose (@var{x})\n\
5998 Return the transpose of @var{x}.\n\
5999 \n\
6000 This function and @tcode{x.'} are equivalent.\n\
6001 @seealso{ctranspose}\n\
6002 @end deftypefn")
6003 {
6005 }
6006 
6007 /*
6008 %!assert (2.', 2)
6009 %!assert (2i.', 2i)
6010 %!assert ([1:4].', [1;2;3;4])
6011 %!assert ([1;2;3;4].', [1:4])
6012 %!assert ([1,2;3,4].', [1,3;2,4])
6013 %!assert ([1,2i;3,4].', [1,3;2i,4])
6014 
6015 %!assert (transpose ([1,2;3,4]), [1,3;2,4])
6016 
6017 %!assert (single (2).', single (2))
6018 %!assert (single (2i).', single (2i))
6019 %!assert (single ([1:4]).', single ([1;2;3;4]))
6020 %!assert (single ([1;2;3;4]).', single ([1:4]))
6021 %!assert (single ([1,2;3,4]).', single ([1,3;2,4]))
6022 %!assert (single ([1,2i;3,4]).', single ([1,3;2i,4]))
6023 
6024 %!assert (transpose (single ([1,2;3,4])), single ([1,3;2,4]))
6025 */
6026 
6027 DEFUN (ctranspose, args, ,
6028  "-*- texinfo -*-\n\
6029 @deftypefn {Built-in Function} {} ctranspose (@var{x})\n\
6030 Return the complex conjugate transpose of @var{x}.\n\
6031 \n\
6032 This function and @tcode{x'} are equivalent.\n\
6033 @seealso{transpose}\n\
6034 @end deftypefn")
6035 {
6037 }
6038 
6039 /*
6040 %!assert (2', 2)
6041 %!assert (2i', -2i)
6042 %!assert ([1:4]', [1;2;3;4])
6043 %!assert ([1;2;3;4]', [1:4])
6044 %!assert ([1,2;3,4]', [1,3;2,4])
6045 %!assert ([1,2i;3,4]', [1,3;-2i,4])
6046 
6047 %!assert (ctranspose ([1,2i;3,4]), [1,3;-2i,4])
6048 
6049 %!assert (single (2)', single (2))
6050 %!assert (single (2i)', single (-2i))
6051 %!assert (single ([1:4])', single ([1;2;3;4]))
6052 %!assert (single ([1;2;3;4])', single ([1:4]))
6053 %!assert (single ([1,2;3,4])', single ([1,3;2,4]))
6054 %!assert (single ([1,2i;3,4])', single ([1,3;-2i,4]))
6055 
6056 %!assert (ctranspose (single ([1,2i;3,4])), single ([1,3;-2i,4]))
6057 */
6058 
6059 static octave_value
6061  const octave_value_list& args)
6062 {
6063  octave_value retval;
6064 
6065  if (args.length () == 2)
6066  retval = do_binary_op (op, args(0), args(1));
6067  else
6068  print_usage ();
6069 
6070  return retval;
6071 }
6072 
6073 static octave_value
6076  const octave_value_list& args)
6077 {
6078  octave_value retval;
6079  int nargin = args.length ();
6080 
6081  switch (nargin)
6082  {
6083  case 0:
6084  print_usage ();
6085  break;
6086  case 1:
6087  retval = args(0);
6088  break;
6089  case 2:
6090  retval = do_binary_op (op, args(0), args(1));
6091  break;
6092  default:
6093  retval = do_binary_op (op, args(0), args(1));
6094  for (int i = 2; i < nargin; i++)
6095  retval.assign (aop, args(i));
6096  break;
6097  }
6098 
6099  return retval;
6100 }
6101 
6102 DEFUN (plus, args, ,
6103  "-*- texinfo -*-\n\
6104 @deftypefn {Built-in Function} {} plus (@var{x}, @var{y})\n\
6105 @deftypefnx {Built-in Function} {} plus (@var{x1}, @var{x2}, @dots{})\n\
6106 This function and @w{@tcode{x + y}} are equivalent.\n\
6107 \n\
6108 If more arguments are given, the summation is applied\n\
6109 cumulatively from left to right:\n\
6110 \n\
6111 @example\n\
6112 (@dots{}((x1 + x2) + x3) + @dots{})\n\
6113 @end example\n\
6114 \n\
6115 At least one argument is required.\n\
6116 @seealso{minus, uplus}\n\
6117 @end deftypefn")
6118 {
6120  octave_value::op_add_eq, args);
6121 }
6122 
6123 DEFUN (minus, args, ,
6124  "-*- texinfo -*-\n\
6125 @deftypefn {Built-in Function} {} minus (@var{x}, @var{y})\n\
6126 This function and @w{@tcode{x - y}} are equivalent.\n\
6127 @seealso{plus, uminus}\n\
6128 @end deftypefn")
6129 {
6131 }
6132 
6133 DEFUN (mtimes, args, ,
6134  "-*- texinfo -*-\n\
6135 @deftypefn {Built-in Function} {} mtimes (@var{x}, @var{y})\n\
6136 @deftypefnx {Built-in Function} {} mtimes (@var{x1}, @var{x2}, @dots{})\n\
6137 Return the matrix multiplication product of inputs.\n\
6138 \n\
6139 This function and @w{@tcode{x * y}} are equivalent.\n\
6140 If more arguments are given, the multiplication is applied\n\
6141 cumulatively from left to right:\n\
6142 \n\
6143 @example\n\
6144 (@dots{}((x1 * x2) * x3) * @dots{})\n\
6145 @end example\n\
6146 \n\
6147 At least one argument is required.\n\
6148 @seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower}\n\
6149 @end deftypefn")
6150 {
6152  octave_value::op_mul_eq, args);
6153 }
6154 
6155 DEFUN (mrdivide, args, ,
6156  "-*- texinfo -*-\n\
6157 @deftypefn {Built-in Function} {} mrdivide (@var{x}, @var{y})\n\
6158 Return the matrix right division of @var{x} and @var{y}.\n\
6159 \n\
6160 This function and @w{@tcode{x / y}} are equivalent.\n\
6161 @seealso{mldivide, rdivide, plus, minus}\n\
6162 @end deftypefn")
6163 {
6165 }
6166 
6167 DEFUN (mpower, args, ,
6168  "-*- texinfo -*-\n\
6169 @deftypefn {Built-in Function} {} mpower (@var{x}, @var{y})\n\
6170 Return the matrix power operation of @var{x} raised to the @var{y} power.\n\
6171 \n\
6172 This function and @w{@tcode{x ^ y}} are equivalent.\n\
6173 @seealso{power, mtimes, plus, minus}\n\
6174 @end deftypefn")
6175 {
6177 }
6178 
6179 DEFUN (mldivide, args, ,
6180  "-*- texinfo -*-\n\
6181 @deftypefn {Built-in Function} {} mldivide (@var{x}, @var{y})\n\
6182 Return the matrix left division of @var{x} and @var{y}.\n\
6183 \n\
6184 This function and @w{@tcode{x @xbackslashchar{} y}} are equivalent.\n\
6185 @seealso{mrdivide, ldivide, rdivide}\n\
6186 @end deftypefn")
6187 {
6189 }
6190 
6191 DEFUN (lt, args, ,
6192  "-*- texinfo -*-\n\
6193 @deftypefn {Built-in Function} {} lt (@var{x}, @var{y})\n\
6194 This function is equivalent to @w{@code{x < y}}.\n\
6195 @seealso{le, eq, ge, gt, ne}\n\
6196 @end deftypefn")
6197 {
6199 }
6200 
6201 DEFUN (le, args, ,
6202  "-*- texinfo -*-\n\
6203 @deftypefn {Built-in Function} {} le (@var{x}, @var{y})\n\
6204 This function is equivalent to @w{@code{x <= y}}.\n\
6205 @seealso{eq, ge, gt, ne, lt}\n\
6206 @end deftypefn")
6207 {
6209 }
6210 
6211 DEFUN (eq, args, ,
6212  "-*- texinfo -*-\n\
6213 @deftypefn {Built-in Function} {} eq (@var{x}, @var{y})\n\
6214 Return true if the two inputs are equal.\n\
6215 \n\
6216 This function is equivalent to @w{@code{x == y}}.\n\
6217 @seealso{ne, isequal, le, ge, gt, ne, lt}\n\
6218 @end deftypefn")
6219 {
6221 }
6222 
6223 DEFUN (ge, args, ,
6224  "-*- texinfo -*-\n\
6225 @deftypefn {Built-in Function} {} ge (@var{x}, @var{y})\n\
6226 This function is equivalent to @w{@code{x >= y}}.\n\
6227 @seealso{le, eq, gt, ne, lt}\n\
6228 @end deftypefn")
6229 {
6231 }
6232 
6233 DEFUN (gt, args, ,
6234  "-*- texinfo -*-\n\
6235 @deftypefn {Built-in Function} {} gt (@var{x}, @var{y})\n\
6236 This function is equivalent to @w{@code{x > y}}.\n\
6237 @seealso{le, eq, ge, ne, lt}\n\
6238 @end deftypefn")
6239 {
6241 }
6242 
6243 DEFUN (ne, args, ,
6244  "-*- texinfo -*-\n\
6245 @deftypefn {Built-in Function} {} ne (@var{x}, @var{y})\n\
6246 Return true if the two inputs are not equal.\n\
6247 \n\
6248 This function is equivalent to @w{@code{x != y}}.\n\
6249 @seealso{eq, isequal, le, ge, lt}\n\
6250 @end deftypefn")
6251 {
6253 }
6254 
6255 DEFUN (times, args, ,
6256  "-*- texinfo -*-\n\
6257 @deftypefn {Built-in Function} {} times (@var{x}, @var{y})\n\
6258 @deftypefnx {Built-in Function} {} times (@var{x1}, @var{x2}, @dots{})\n\
6259 Return the element-by-element multiplication product of inputs.\n\
6260 \n\
6261 This function and @w{@tcode{x .* y}} are equivalent.\n\
6262 If more arguments are given, the multiplication is applied\n\
6263 cumulatively from left to right:\n\
6264 \n\
6265 @example\n\
6266 (@dots{}((x1 .* x2) .* x3) .* @dots{})\n\
6267 @end example\n\
6268 \n\
6269 At least one argument is required.\n\
6270 @seealso{mtimes, rdivide}\n\
6271 @end deftypefn")
6272 {
6275 }
6276 
6277 DEFUN (rdivide, args, ,
6278  "-*- texinfo -*-\n\
6279 @deftypefn {Built-in Function} {} rdivide (@var{x}, @var{y})\n\
6280 Return the element-by-element right division of @var{x} and @var{y}.\n\
6281 \n\
6282 This function and @w{@tcode{x ./ y}} are equivalent.\n\
6283 @seealso{ldivide, mrdivide, times, plus}\n\
6284 @end deftypefn")
6285 {
6287 }
6288 
6289 DEFUN (power, args, ,
6290  "-*- texinfo -*-\n\
6291 @deftypefn {Built-in Function} {} power (@var{x}, @var{y})\n\
6292 Return the element-by-element operation of @var{x} raised to the\n\
6293 @var{y} power.\n\
6294 \n\
6295 This function and @w{@tcode{x .^ y}} are equivalent.\n\
6296 \n\
6297 If several complex results are possible, returns the one with smallest\n\
6298 non-negative argument (angle). Use @code{realpow}, @code{realsqrt},\n\
6299 @code{cbrt}, or @code{nthroot} if a real result is preferred.\n\
6300 \n\
6301 @seealso{mpower, realpow, realsqrt, cbrt, nthroot}\n\
6302 @end deftypefn")
6303 {
6305 }
6306 
6307 DEFUN (ldivide, args, ,
6308  "-*- texinfo -*-\n\
6309 @deftypefn {Built-in Function} {} ldivide (@var{x}, @var{y})\n\
6310 Return the element-by-element left division of @var{x} and @var{y}.\n\
6311 \n\
6312 This function and @w{@tcode{x .@xbackslashchar{} y}} are equivalent.\n\
6313 @seealso{rdivide, mldivide, times, plus}\n\
6314 @end deftypefn")
6315 {
6317 }
6318 
6319 DEFUN (and, args, ,
6320  "-*- texinfo -*-\n\
6321 @deftypefn {Built-in Function} {@var{z} =} and (@var{x}, @var{y})\n\
6322 @deftypefnx {Built-in Function} {@var{z} =} and (@var{x1}, @var{x2}, @dots{})\n\
6323 Return the logical AND of @var{x} and @var{y}.\n\
6324 \n\
6325 This function is equivalent to the operator syntax @w{@code{x & y}}. If\n\
6326 more than two arguments are given, the logical AND is applied cumulatively\n\
6327 from left to right:\n\
6328 \n\
6329 @example\n\
6330 (@dots{}((x1 & x2) & x3) & @dots{})\n\
6331 @end example\n\
6332 \n\
6333 At least one argument is required.\n\
6334 @seealso{or, not, xor}\n\
6335 @end deftypefn")
6336 {
6339 }
6340 
6341 DEFUN (or, args, ,
6342  "-*- texinfo -*-\n\
6343 @deftypefn {Built-in Function} {@var{z} =} or (@var{x}, @var{y})\n\
6344 @deftypefnx {Built-in Function} {@var{z} =} or (@var{x1}, @var{x2}, @dots{})\n\
6345 Return the logical OR of @var{x} and @var{y}.\n\
6346 \n\
6347 This function is equivalent to the operator syntax @w{@code{x | y}}. If\n\
6348 more than two arguments are given, the logical OR is applied cumulatively\n\
6349 from left to right:\n\
6350 \n\
6351 @example\n\
6352 (@dots{}((x1 | x2) | x3) | @dots{})\n\
6353 @end example\n\
6354 \n\
6355 At least one argument is required.\n\
6356 @seealso{and, not, xor}\n\
6357 @end deftypefn")
6358 {
6361 }
6362 
6363 DEFUN (colon, args, ,
6364  "-*- texinfo -*-\n\
6365 @deftypefn {Built-in Function} {@var{r} =} colon (@var{base}, @var{limit})\n\
6366 @deftypefnx {Built-in Function} {@var{r} =} colon (@var{base}, @var{increment}, @var{limit})\n\
6367 Return the result of the colon expression corresponding to @var{base},\n\
6368 @var{limit}, and optionally, @var{increment}.\n\
6369 \n\
6370 This function is equivalent to the operator syntax @w{@code{base : limit}}\n\
6371 or @w{@code{base : increment : limit}}.\n\
6372 @end deftypefn")
6373 {
6374  octave_value retval;
6375  int nargin = args.length ();
6376 
6377  switch (nargin)
6378  {
6379  case 2:
6380  retval = do_colon_op (args(0), args(1));
6381  break;
6382 
6383  case 3:
6384  retval = do_colon_op (args(0), args(1), args (2));
6385  break;
6386 
6387  default:
6388  print_usage ();
6389  break;
6390  }
6391 
6392  return retval;
6393 }
6394 
6395 static double tic_toc_timestamp = -1.0;
6396 
6397 DEFUN (tic, args, nargout,
6398  "-*- texinfo -*-\n\
6399 @deftypefn {Built-in Function} {} tic ()\n\
6400 @deftypefnx {Built-in Function} {@var{id} =} tic ()\n\
6401 @deftypefnx {Built-in Function} {} toc ()\n\
6402 @deftypefnx {Built-in Function} {} toc (@var{id})\n\
6403 @deftypefnx {Built-in Function} {@var{val} =} toc (@dots{})\n\
6404 Set or check a wall-clock timer.\n\
6405 \n\
6406 Calling @code{tic} without an output argument sets the internal timer state.\n\
6407 Subsequent calls to @code{toc} return the number of seconds since the timer\n\
6408 was set.\n\
6409 For example,\n\
6410 \n\
6411 @example\n\
6412 @group\n\
6413 tic ();\n\
6414 # many computations later@dots{}\n\
6415 elapsed_time = toc ();\n\
6416 @end group\n\
6417 @end example\n\
6418 \n\
6419 @noindent\n\
6420 will set the variable @code{elapsed_time} to the number of seconds since\n\
6421 the most recent call to the function @code{tic}.\n\
6422 \n\
6423 If called with one output argument, @code{tic} returns a scalar\n\
6424 of type @code{uint64} that may be later passed to @code{toc}.\n\
6425 \n\
6426 @example\n\
6427 @group\n\
6428 id = tic; sleep (5); toc (id)\n\
6429  @result{} 5.0010\n\
6430 @end group\n\
6431 @end example\n\
6432 \n\
6433 Calling @code{tic} and @code{toc} this way allows nested timing calls.\n\
6434 \n\
6435 If you are more interested in the CPU time that your process used, you\n\
6436 should use the @code{cputime} function instead. The @code{tic} and\n\
6437 @code{toc} functions report the actual wall clock time that elapsed\n\
6438 between the calls. This may include time spent processing other jobs or\n\
6439 doing nothing at all.\n\
6440 @seealso{toc, cputime}\n\
6441 @end deftypefn")
6442 {
6443  octave_value retval;
6444 
6445  int nargin = args.length ();
6446 
6447  if (nargin != 0)
6448  warning ("tic: ignoring extra arguments");
6449 
6450  octave_time now;
6451 
6452  double tmp = now.double_value ();
6453 
6454  if (nargout > 0)
6455  {
6456  double ip = 0.0;
6457  double frac = modf (tmp, &ip);
6458  uint64_t microsecs = static_cast<uint64_t> (CLOCKS_PER_SEC * frac);
6459  microsecs += CLOCKS_PER_SEC * static_cast<uint64_t> (ip);
6460  retval = octave_uint64 (microsecs);
6461  }
6462  else
6463  tic_toc_timestamp = tmp;
6464 
6465  return retval;
6466 }
6467 
6468 DEFUN (toc, args, nargout,
6469  "-*- texinfo -*-\n\
6470 @deftypefn {Built-in Function} {} toc ()\n\
6471 @deftypefnx {Built-in Function} {} toc (@var{id})\n\
6472 @deftypefnx {Built-in Function} {@var{val} =} toc (@dots{})\n\
6473 @seealso{tic, cputime}\n\
6474 @end deftypefn")
6475 {
6476  octave_value retval;
6477 
6478  int nargin = args.length ();
6479 
6480  double start_time = tic_toc_timestamp;
6481 
6482  if (nargin > 1)
6483  print_usage ();
6484  else
6485  {
6486  if (nargin == 1)
6487  {
6488  octave_uint64 id = args(0).uint64_scalar_value ();
6489 
6490  if (! error_state)
6491  {
6492  uint64_t val = id.value ();
6493 
6494  start_time
6495  = (static_cast<double> (val / CLOCKS_PER_SEC)
6496  + static_cast<double> (val % CLOCKS_PER_SEC)
6497  / CLOCKS_PER_SEC);
6498 
6499  // FIXME: should we also check to see whether the start
6500  // time is after the beginning of this Octave session?
6501  }
6502  else
6503  error ("toc: invalid ID");
6504  }
6505 
6506  if (! error_state)
6507  {
6508  if (start_time < 0)
6509  error ("toc called before timer set");
6510  else
6511  {
6512  octave_time now;
6513 
6514  double tmp = now.double_value () - start_time;
6515 
6516  if (nargout > 0)
6517  retval = tmp;
6518  else
6519  octave_stdout << "Elapsed time is " << tmp << " seconds.\n";
6520  }
6521  }
6522  }
6523 
6524  return retval;
6525 }
6526 
6527 /*
6528 %!shared id
6529 %! id = tic ();
6530 %!assert (isa (id, "uint64"))
6531 %!assert (isa (toc (id), "double"))
6532 */
6533 
6534 DEFUN (cputime, args, ,
6535  "-*- texinfo -*-\n\
6536 @deftypefn {Built-in Function} {[@var{total}, @var{user}, @var{system}] =} cputime ();\n\
6537 Return the CPU time used by your Octave session.\n\
6538 \n\
6539 The first output is the total time spent executing your process and is equal\n\
6540 to the sum of second and third outputs, which are the number of CPU seconds\n\
6541 spent executing in user mode and the number of CPU seconds spent executing\n\
6542 in system mode, respectively.\n\
6543 \n\
6544 If your system does not have a way to report CPU time usage, @code{cputime}\n\
6545 returns 0 for each of its output values.\n\
6546 \n\
6547 Note that because Octave used some CPU time to start, it is reasonable\n\
6548 to check to see if @code{cputime} works by checking to see if the total\n\
6549 CPU time used is nonzero.\n\
6550 @seealso{tic, toc}\n\
6551 @end deftypefn")
6552 {
6553  octave_value_list retval;
6554  int nargin = args.length ();
6555  double usr = 0.0;
6556  double sys = 0.0;
6557 
6558  if (nargin != 0)
6559  warning ("tic: ignoring extra arguments");
6560 
6561 #if defined (HAVE_GETRUSAGE)
6562 
6563  struct rusage ru;
6564 
6565  getrusage (RUSAGE_SELF, &ru);
6566 
6567  usr = static_cast<double> (ru.ru_utime.tv_sec) +
6568  static_cast<double> (ru.ru_utime.tv_usec) * 1e-6;
6569 
6570  sys = static_cast<double> (ru.ru_stime.tv_sec) +
6571  static_cast<double> (ru.ru_stime.tv_usec) * 1e-6;
6572 
6573 #else
6574 
6575  struct tms t;
6576 
6577  times (&t);
6578 
6579  unsigned long ticks;
6580  unsigned long seconds;
6581  unsigned long fraction;
6582 
6583  ticks = t.tms_utime + t.tms_cutime;
6584  fraction = ticks % CLOCKS_PER_SEC;
6585  seconds = ticks / CLOCKS_PER_SEC;
6586 
6587  usr = static_cast<double> (seconds) + static_cast<double>(fraction) /
6588  static_cast<double>(CLOCKS_PER_SEC);
6589 
6590  ticks = t.tms_stime + t.tms_cstime;
6591  fraction = ticks % CLOCKS_PER_SEC;
6592  seconds = ticks / CLOCKS_PER_SEC;
6593 
6594  sys = static_cast<double> (seconds) + static_cast<double>(fraction) /
6595  static_cast<double>(CLOCKS_PER_SEC);
6596 
6597 #endif
6598 
6599  retval(2) = sys;
6600  retval(1) = usr;
6601  retval(0) = sys + usr;
6602 
6603  return retval;
6604 }
6605 
6606 DEFUN (sort, args, nargout,
6607  "-*- texinfo -*-\n\
6608 @deftypefn {Built-in Function} {[@var{s}, @var{i}] =} sort (@var{x})\n\
6609 @deftypefnx {Built-in Function} {[@var{s}, @var{i}] =} sort (@var{x}, @var{dim})\n\
6610 @deftypefnx {Built-in Function} {[@var{s}, @var{i}] =} sort (@var{x}, @var{mode})\n\
6611 @deftypefnx {Built-in Function} {[@var{s}, @var{i}] =} sort (@var{x}, @var{dim}, @var{mode})\n\
6612 Return a copy of @var{x} with the elements arranged in increasing order.\n\
6613 \n\
6614 For matrices, @code{sort} orders the elements within columns\n\
6615 \n\
6616 For example:\n\
6617 \n\
6618 @example\n\
6619 @group\n\
6620 sort ([1, 2; 2, 3; 3, 1])\n\
6621  @result{} 1 1\n\
6622  2 2\n\
6623  3 3\n\
6624 @end group\n\
6625 @end example\n\
6626 \n\
6627 If the optional argument @var{dim} is given, then the matrix is sorted\n\
6628 along the dimension defined by @var{dim}. The optional argument @code{mode}\n\
6629 defines the order in which the values will be sorted. Valid values of\n\
6630 @code{mode} are @qcode{\"ascend\"} or @qcode{\"descend\"}.\n\
6631 \n\
6632 The @code{sort} function may also be used to produce a matrix\n\
6633 containing the original row indices of the elements in the sorted\n\
6634 matrix. For example:\n\
6635 \n\
6636 @example\n\
6637 @group\n\
6638 [s, i] = sort ([1, 2; 2, 3; 3, 1])\n\
6639  @result{} s = 1 1\n\
6640  2 2\n\
6641  3 3\n\
6642  @result{} i = 1 3\n\
6643  2 1\n\
6644  3 2\n\
6645 @end group\n\
6646 @end example\n\
6647 \n\
6648 For equal elements, the indices are such that equal elements are listed\n\
6649 in the order in which they appeared in the original list.\n\
6650 \n\
6651 Sorting of complex entries is done first by magnitude (@code{abs (@var{z})})\n\
6652 and for any ties by phase angle (@code{angle (z)}). For example:\n\
6653 \n\
6654 @example\n\
6655 @group\n\
6656 sort ([1+i; 1; 1-i])\n\
6657  @result{} 1 + 0i\n\
6658  1 - 1i\n\
6659  1 + 1i\n\
6660 @end group\n\
6661 @end example\n\
6662 \n\
6663 NaN values are treated as being greater than any other value and are sorted\n\
6664 to the end of the list.\n\
6665 \n\
6666 The @code{sort} function may also be used to sort strings and cell arrays\n\
6667 of strings, in which case ASCII dictionary order (uppercase 'A' precedes\n\
6668 lowercase 'a') of the strings is used.\n\
6669 \n\
6670 The algorithm used in @code{sort} is optimized for the sorting of partially\n\
6671 ordered lists.\n\
6672 @seealso{sortrows, issorted}\n\
6673 @end deftypefn")
6674 {
6675  octave_value_list retval;
6676 
6677  int nargin = args.length ();
6678  sortmode smode = ASCENDING;
6679 
6680  if (nargin < 1 || nargin > 3)
6681  {
6682  print_usage ();
6683  return retval;
6684  }
6685 
6686  bool return_idx = nargout > 1;
6687 
6688  octave_value arg = args(0);
6689 
6690  int dim = 0;
6691  if (nargin > 1)
6692  {
6693  if (args(1).is_string ())
6694  {
6695  std::string mode = args(1).string_value ();
6696  if (mode == "ascend")
6697  smode = ASCENDING;
6698  else if (mode == "descend")
6699  smode = DESCENDING;
6700  else
6701  {
6702  error ("sort: MODE must be either \"ascend\" or \"descend\"");
6703  return retval;
6704  }
6705  }
6706  else
6707  dim = args(1).nint_value () - 1;
6708  }
6709 
6710  if (nargin > 2)
6711  {
6712  if (args(1).is_string ())
6713  {
6714  print_usage ();
6715  return retval;
6716  }
6717 
6718  if (! args(2).is_string ())
6719  {
6720  error ("sort: MODE must be a string");
6721  return retval;
6722  }
6723  std::string mode = args(2).string_value ();
6724  if (mode == "ascend")
6725  smode = ASCENDING;
6726  else if (mode == "descend")
6727  smode = DESCENDING;
6728  else
6729  {
6730  error ("sort: MODE must be either \"ascend\" or \"descend\"");
6731  return retval;
6732  }
6733  }
6734 
6735  const dim_vector dv = arg.dims ();
6736  if (nargin == 1 || args(1).is_string ())
6737  {
6738  // Find first non singleton dimension
6739  dim = dv.first_non_singleton ();
6740  }
6741  else
6742  {
6743  if (dim < 0)
6744  {
6745  error ("sort: DIM must be a valid dimension");
6746  return retval;
6747  }
6748  }
6749 
6750  if (return_idx)
6751  {
6752  retval.resize (2);
6753 
6755 
6756  retval(0) = arg.sort (sidx, dim, smode);
6757  retval(1) = idx_vector (sidx, dv(dim)); // No checking, extent is known.
6758  }
6759  else
6760  retval(0) = arg.sort (dim, smode);
6761 
6762  return retval;
6763 }
6764 
6765 /*
6766 ## Double
6767 %!assert (sort ([NaN, 1, -1, 2, Inf]), [-1, 1, 2, Inf, NaN])
6768 %!assert (sort ([NaN, 1, -1, 2, Inf], 1), [NaN, 1, -1, 2, Inf])
6769 %!assert (sort ([NaN, 1, -1, 2, Inf], 2), [-1, 1, 2, Inf, NaN])
6770 %!assert (sort ([NaN, 1, -1, 2, Inf], 3), [NaN, 1, -1, 2, Inf])
6771 %!assert (sort ([NaN, 1, -1, 2, Inf], "ascend"), [-1, 1, 2, Inf, NaN])
6772 %!assert (sort ([NaN, 1, -1, 2, Inf], 2, "ascend"), [-1, 1, 2, Inf, NaN])
6773 %!assert (sort ([NaN, 1, -1, 2, Inf], "descend"), [NaN, Inf, 2, 1, -1])
6774 %!assert (sort ([NaN, 1, -1, 2, Inf], 2, "descend"), [NaN, Inf, 2, 1, -1])
6775 %!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4]), [3, 1, 6, 4; 8, 2, 7, 5])
6776 %!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4], 1), [3, 1, 6, 4; 8, 2, 7, 5])
6777 %!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4], 2), [1, 3, 5, 7; 2, 4, 6, 8])
6778 %!assert (sort (1), 1)
6779 
6780 %!test
6781 %! [v, i] = sort ([NaN, 1, -1, Inf, 1]);
6782 %! assert (v, [-1, 1, 1, Inf, NaN]);
6783 %! assert (i, [3, 2, 5, 4, 1]);
6784 
6785 ## Complex
6786 %!assert (sort ([NaN, 1i, -1, 2, Inf]), [1i, -1, 2, Inf, NaN])
6787 %!assert (sort ([NaN, 1i, -1, 2, Inf], 1), [NaN, 1i, -1, 2, Inf])
6788 %!assert (sort ([NaN, 1i, -1, 2, Inf], 2), [1i, -1, 2, Inf, NaN])
6789 %!assert (sort ([NaN, 1i, -1, 2, Inf], 3), [NaN, 1i, -1, 2, Inf])
6790 %!assert (sort ([NaN, 1i, -1, 2, Inf], "ascend"), [1i, -1, 2, Inf, NaN])
6791 %!assert (sort ([NaN, 1i, -1, 2, Inf], 2, "ascend"), [1i, -1, 2, Inf, NaN])
6792 %!assert (sort ([NaN, 1i, -1, 2, Inf], "descend"), [NaN, Inf, 2, -1, 1i])
6793 %!assert (sort ([NaN, 1i, -1, 2, Inf], 2, "descend"), [NaN, Inf, 2, -1, 1i])
6794 %!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4]), [3, 1i, 6, 4; 8, 2, 7, 5])
6795 %!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4], 1), [3, 1i, 6, 4; 8, 2, 7, 5])
6796 %!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4], 2), [1i, 3, 5, 7; 2, 4, 6, 8])
6797 %!assert (sort (1i), 1i)
6798 
6799 %!test
6800 %! [v, i] = sort ([NaN, 1i, -1, Inf, 1, 1i]);
6801 %! assert (v, [1, 1i, 1i, -1, Inf, NaN]);
6802 %! assert (i, [5, 2, 6, 3, 4, 1]);
6803 
6804 ## Single
6805 %!assert (sort (single ([NaN, 1, -1, 2, Inf])), single ([-1, 1, 2, Inf, NaN]))
6806 %!assert (sort (single ([NaN, 1, -1, 2, Inf]), 1), single ([NaN, 1, -1, 2, Inf]))
6807 %!assert (sort (single ([NaN, 1, -1, 2, Inf]), 2), single ([-1, 1, 2, Inf, NaN]))
6808 %!assert (sort (single ([NaN, 1, -1, 2, Inf]), 3), single ([NaN, 1, -1, 2, Inf]))
6809 %!assert (sort (single ([NaN, 1, -1, 2, Inf]), "ascend"), single ([-1, 1, 2, Inf, NaN]))
6810 %!assert (sort (single ([NaN, 1, -1, 2, Inf]), 2, "ascend"), single ([-1, 1, 2, Inf, NaN]))
6811 %!assert (sort (single ([NaN, 1, -1, 2, Inf]), "descend"), single ([NaN, Inf, 2, 1, -1]))
6812 %!assert (sort (single ([NaN, 1, -1, 2, Inf]), 2, "descend"), single ([NaN, Inf, 2, 1, -1]))
6813 %!assert (sort (single ([3, 1, 7, 5; 8, 2, 6, 4])), single ([3, 1, 6, 4; 8, 2, 7, 5]))
6814 %!assert (sort (single ([3, 1, 7, 5; 8, 2, 6, 4]), 1), single ([3, 1, 6, 4; 8, 2, 7, 5]))
6815 %!assert (sort (single ([3, 1, 7, 5; 8, 2, 6, 4]), 2), single ([1, 3, 5, 7; 2, 4, 6, 8]))
6816 %!assert (sort (single (1)), single (1))
6817 
6818 %!test
6819 %! [v, i] = sort (single ([NaN, 1, -1, Inf, 1]));
6820 %! assert (v, single ([-1, 1, 1, Inf, NaN]));
6821 %! assert (i, [3, 2, 5, 4, 1]);
6822 
6823 ## Single Complex
6824 %!assert (sort (single ([NaN, 1i, -1, 2, Inf])), single ([1i, -1, 2, Inf, NaN]))
6825 %!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 1), single ([NaN, 1i, -1, 2, Inf]))
6826 %!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 2), single ([1i, -1, 2, Inf, NaN]))
6827 %!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 3), single ([NaN, 1i, -1, 2, Inf]))
6828 %!assert (sort (single ([NaN, 1i, -1, 2, Inf]), "ascend"), single ([1i, -1, 2, Inf, NaN]))
6829 %!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 2, "ascend"), single ([1i, -1, 2, Inf, NaN]))
6830 %!assert (sort (single ([NaN, 1i, -1, 2, Inf]), "descend"), single ([NaN, Inf, 2, -1, 1i]))
6831 %!assert (sort (single ([NaN, 1i, -1, 2, Inf]), 2, "descend"), single ([NaN, Inf, 2, -1, 1i]))
6832 %!assert (sort (single ([3, 1i, 7, 5; 8, 2, 6, 4])), single ([3, 1i, 6, 4; 8, 2, 7, 5]))
6833 %!assert (sort (single ([3, 1i, 7, 5; 8, 2, 6, 4]), 1), single ([3, 1i, 6, 4; 8, 2, 7, 5]))
6834 %!assert (sort (single ([3, 1i, 7, 5; 8, 2, 6, 4]), 2), single ([1i, 3, 5, 7; 2, 4, 6, 8]))
6835 %!assert (sort (single (1i)), single (1i))
6836 
6837 %!test
6838 %! [v, i] = sort (single ([NaN, 1i, -1, Inf, 1, 1i]));
6839 %! assert (v, single ([1, 1i, 1i, -1, Inf, NaN]));
6840 %! assert (i, [5, 2, 6, 3, 4, 1]);
6841 
6842 ## Bool
6843 %!assert (sort ([true, false, true, false]), [false, false, true, true])
6844 %!assert (sort ([true, false, true, false], 1), [true, false, true, false])
6845 %!assert (sort ([true, false, true, false], 2), [false, false, true, true])
6846 %!assert (sort ([true, false, true, false], 3), [true, false, true, false])
6847 %!assert (sort ([true, false, true, false], "ascend"), [false, false, true, true])
6848 %!assert (sort ([true, false, true, false], 2, "ascend"), [false, false, true, true])
6849 %!assert (sort ([true, false, true, false], "descend"), [true, true, false, false])
6850 %!assert (sort ([true, false, true, false], 2, "descend"), [true, true, false, false])
6851 %!assert (sort (true), true)
6852 
6853 %!test
6854 %! [v, i] = sort ([true, false, true, false]);
6855 %! assert (v, [false, false, true, true]);
6856 %! assert (i, [2, 4, 1, 3]);
6857 
6858 ## Sparse Double
6859 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf])), sparse ([-1, 0, 0, 1, 2, Inf, NaN]))
6860 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 1), sparse ([0, NaN, 1, 0, -1, 2, Inf]))
6861 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2), sparse ([-1, 0, 0, 1, 2, Inf, NaN]))
6862 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 3), sparse ([0, NaN, 1, 0, -1, 2, Inf]))
6863 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), "ascend"), sparse ([-1, 0, 0, 1, 2, Inf, NaN]))
6864 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2, "ascend"), sparse ([-1, 0, 0, 1, 2, Inf, NaN]))
6865 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), "descend"), sparse ([NaN, Inf, 2, 1, 0, 0, -1]))
6866 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2, "descend"), sparse ([NaN, Inf, 2, 1, 0, 0, -1]))
6867 
6868 %!shared a
6869 %! a = randn (10, 10);
6870 %! a(a < 0) = 0;
6871 %!assert (sort (sparse (a)), sparse (sort (a)))
6872 %!assert (sort (sparse (a), 1), sparse (sort (a, 1)))
6873 %!assert (sort (sparse (a), 2), sparse (sort (a, 2)))
6874 %!test
6875 %! [v, i] = sort (a);
6876 %! [vs, is] = sort (sparse (a));
6877 %! assert (vs, sparse (v));
6878 %! assert (is, i);
6879 
6880 ## Sparse Complex
6881 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf])), sparse ([0, 0, 1i, -1, 2, Inf, NaN]))
6882 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 1), sparse ([0, NaN, 1i, 0, -1, 2, Inf]))
6883 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2), sparse ([0, 0, 1i, -1, 2, Inf, NaN]))
6884 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 3), sparse ([0, NaN, 1i, 0, -1, 2, Inf]))
6885 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), "ascend"), sparse ([0, 0, 1i, -1, 2, Inf, NaN]))
6886 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2, "ascend"), sparse ([0, 0, 1i, -1, 2, Inf, NaN]))
6887 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), "descend"), sparse ([NaN, Inf, 2, -1, 1i, 0, 0]))
6888 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2, "descend"), sparse ([NaN, Inf, 2, -1, 1i, 0, 0]))
6889 
6890 %!shared a
6891 %! a = randn (10, 10);
6892 %! a(a < 0) = 0;
6893 %! a = 1i * a;
6894 %!assert (sort (sparse (a)), sparse (sort (a)))
6895 %!assert (sort (sparse (a), 1), sparse (sort (a, 1)))
6896 %!assert (sort (sparse (a), 2), sparse (sort (a, 2)))
6897 %!test
6898 %! [v, i] = sort (a);
6899 %! [vs, is] = sort (sparse (a));
6900 %! assert (vs, sparse (v));
6901 %! assert (is, i);
6902 
6903 ## Sparse Bool
6904 %!assert (sort (sparse ([true, false, true, false])), sparse ([false, false, true, true]))
6905 %!assert (sort (sparse ([true, false, true, false]), 1), sparse ([true, false, true, false]))
6906 %!assert (sort (sparse ([true, false, true, false]), 2), sparse ([false, false, true, true]))
6907 %!assert (sort (sparse ([true, false, true, false]), 3), sparse ([true, false, true, false]))
6908 %!assert (sort (sparse ([true, false, true, false]), "ascend"), sparse ([false, false, true, true]))
6909 %!assert (sort (sparse ([true, false, true, false]), 2, "ascend"), sparse ([false, false, true, true]))
6910 %!assert (sort (sparse ([true, false, true, false]), "descend"), sparse ([true, true, false, false]))
6911 %!assert (sort (sparse ([true, false, true, false]), 2, "descend"), sparse ([true, true, false, false]))
6912 
6913 %!test
6914 %! [v, i] = sort (sparse ([true, false, true, false]));
6915 %! assert (v, sparse ([false, false, true, true]));
6916 %! assert (i, [2, 4, 1, 3]);
6917 
6918 ## Cell string array
6919 %!shared a, b, c
6920 %! a = {"Alice", "Cecile", "Eric", "Barry", "David"};
6921 %! b = {"Alice", "Barry", "Cecile", "David", "Eric"};
6922 %! c = {"Eric", "David", "Cecile", "Barry", "Alice"};
6923 %!assert (sort (a), b)
6924 %!assert (sort (a, 1), a)
6925 %!assert (sort (a, 2), b)
6926 %!assert (sort (a, 3), a)
6927 %!assert (sort (a, "ascend"), b)
6928 %!assert (sort (a, 2, "ascend"), b)
6929 %!assert (sort (a, "descend"), c)
6930 %!assert (sort (a, 2, "descend"), c)
6931 
6932 %!test
6933 %! [v, i] = sort (a);
6934 %! assert (i, [1, 4, 2, 5, 3]);
6935 
6936 %!error sort ()
6937 %!error sort (1, 2, 3, 4)
6938 */
6939 
6940 // Sort the rows of the matrix @var{a} according to the order
6941 // specified by @var{mode}, which can either be 'ascend' or 'descend'
6942 // and return the index vector corresponding to the sort order.
6943 //
6944 // This function does not yet support sparse matrices.
6945 
6946 DEFUN (__sort_rows_idx__, args, ,
6947  "-*- texinfo -*-\n\
6948 @deftypefn {Built-in Function} {} __sort_rows_idx__ (@var{a}, @var{mode})\n\
6949 Undocumented internal function.\n\
6950 @end deftypefn\n")
6951 {
6952  octave_value retval;
6953 
6954  int nargin = args.length ();
6955  sortmode smode = ASCENDING;
6956 
6957  if (nargin < 1 || nargin > 2 || (nargin == 2 && ! args(1).is_string ()))
6958  {
6959  print_usage ();
6960  return retval;
6961  }
6962 
6963  if (nargin > 1)
6964  {
6965  std::string mode = args(1).string_value ();
6966  if (mode == "ascend")
6967  smode = ASCENDING;
6968  else if (mode == "descend")
6969  smode = DESCENDING;
6970  else
6971  {
6972  error ("__sort_rows_idx__: MODE must be either \"ascend\" or \"descend\"");
6973  return retval;
6974  }
6975  }
6976 
6977  octave_value arg = args(0);
6978 
6979  if (arg.is_sparse_type ())
6980  error ("__sort_rows_idx__: sparse matrices not yet supported");
6981  if (arg.ndims () == 2)
6982  {
6983  Array<octave_idx_type> idx = arg.sort_rows_idx (smode);
6984 
6985  retval = octave_value (idx, true, true);
6986  }
6987  else
6988  error ("__sort_rows_idx__: needs a 2-dimensional object");
6989 
6990  return retval;
6991 }
6992 
6993 static sortmode
6994 get_sort_mode_option (const octave_value& arg, const char *argn)
6995 {
6996  // FIXME: we initialize to UNSORTED here to avoid a GCC warning
6997  // about possibly using sortmode uninitialized.
6998  // FIXME: shouldn't these modes be scoped inside a class?
6999  sortmode smode = UNSORTED;
7000 
7001  if (arg.is_string ())
7002  {
7003  std::string mode = arg.string_value ();
7004  if (mode == "ascending")
7005  smode = ASCENDING;
7006  else if (mode == "descending")
7007  smode = DESCENDING;
7008  else if (mode == "either")
7009  smode = UNSORTED;
7010  else
7011  error ("issorted: MODE must be \"ascending\", \"descending\", or \"either\"");
7012  }
7013  else
7014  error ("issorted: expecting %s argument to be a string", argn);
7015 
7016  return smode;
7017 }
7018 
7019 DEFUN (issorted, args, ,
7020  "-*- texinfo -*-\n\
7021 @deftypefn {Built-in Function} {} issorted (@var{a})\n\
7022 @deftypefnx {Built-in Function} {} issorted (@var{a}, @var{mode})\n\
7023 @deftypefnx {Built-in Function} {} issorted (@var{a}, \"rows\", @var{mode})\n\
7024 Return true if the array is sorted according to @var{mode}, which\n\
7025 may be either @qcode{\"ascending\"}, @qcode{\"descending\"}, or\n\
7026 @qcode{\"either\"}.\n\
7027 \n\
7028 By default, @var{mode} is @qcode{\"ascending\"}. NaNs are treated in the\n\
7029 same manner as @code{sort}.\n\
7030 \n\
7031 If the optional argument @qcode{\"rows\"} is supplied, check whether\n\
7032 the array is sorted by rows as output by the function @code{sortrows}\n\
7033 (with no options).\n\
7034 \n\
7035 This function does not support sparse matrices.\n\
7036 @seealso{sort, sortrows}\n\
7037 @end deftypefn\n")
7038 {
7039  octave_value retval;
7040 
7041  int nargin = args.length ();
7042 
7043  if (nargin < 1 || nargin > 3)
7044  {
7045  print_usage ();
7046  return retval;
7047  }
7048 
7049  bool by_rows = false;
7050 
7051  sortmode smode = ASCENDING;
7052 
7053  if (nargin > 1)
7054  {
7055  octave_value mode_arg;
7056 
7057  if (nargin == 3)
7058  smode = get_sort_mode_option (args(2), "third");
7059 
7060  if (args(1).is_string ())
7061  {
7062  std::string tmp = args(1).string_value ();
7063  if (tmp == "rows")
7064  by_rows = true;
7065  else
7066  smode = get_sort_mode_option (args(1), "second");
7067  }
7068  else
7069  error ("issorted: second argument must be a string");
7070 
7071  if (error_state)
7072  return retval;
7073  }
7074 
7075  octave_value arg = args(0);
7076 
7077  if (by_rows)
7078  {
7079  if (arg.is_sparse_type ())
7080  error ("issorted: sparse matrices not yet supported");
7081  if (arg.ndims () == 2)
7082  retval = arg.is_sorted_rows (smode) != UNSORTED;
7083  else
7084  error ("issorted: A must be a 2-dimensional object");
7085  }
7086  else
7087  {
7088  if (arg.dims ().is_vector ())
7089  retval = args(0).is_sorted (smode) != UNSORTED;
7090  else
7091  error ("issorted: needs a vector");
7092  }
7093 
7094  return retval;
7095 }
7096 
7097 /*
7098 %!shared sm, um, sv, uv
7099 %! sm = [1, 2; 3, 4];
7100 %! um = [3, 1; 2, 4];
7101 %! sv = [1, 2, 3, 4];
7102 %! uv = [2, 1, 4, 3];
7103 %!assert (issorted (sm, "rows"))
7104 %!assert (!issorted (um, "rows"))
7105 %!assert (issorted (sv))
7106 %!assert (!issorted (uv))
7107 %!assert (issorted (sv'))
7108 %!assert (!issorted (uv'))
7109 %!assert (issorted (sm, "rows", "ascending"))
7110 %!assert (!issorted (um, "rows", "ascending"))
7111 %!assert (issorted (sv, "ascending"))
7112 %!assert (!issorted (uv, "ascending"))
7113 %!assert (issorted (sv', "ascending"))
7114 %!assert (!issorted (uv', "ascending"))
7115 %!assert (!issorted (sm, "rows", "descending"))
7116 %!assert (issorted (flipud (sm), "rows", "descending"))
7117 %!assert (!issorted (sv, "descending"))
7118 %!assert (issorted (fliplr (sv), "descending"))
7119 %!assert (!issorted (sv', "descending"))
7120 %!assert (issorted (fliplr (sv)', "descending"))
7121 %!assert (!issorted (um, "rows", "either"))
7122 %!assert (!issorted (uv, "either"))
7123 %!assert (issorted (sm, "rows", "either"))
7124 %!assert (issorted (flipud (sm), "rows", "either"))
7125 %!assert (issorted (sv, "either"))
7126 %!assert (issorted (fliplr (sv), "either"))
7127 %!assert (issorted (sv', "either"))
7128 %!assert (issorted (fliplr (sv)', "either"))
7129 */
7130 
7131 DEFUN (nth_element, args, ,
7132  "-*- texinfo -*-\n\
7133 @deftypefn {Built-in Function} {} nth_element (@var{x}, @var{n})\n\
7134 @deftypefnx {Built-in Function} {} nth_element (@var{x}, @var{n}, @var{dim})\n\
7135 Select the n-th smallest element of a vector, using the ordering defined by\n\
7136 @code{sort}.\n\
7137 \n\
7138 The result is equivalent to @code{sort(@var{x})(@var{n})}.\n\
7139 \n\
7140 @var{n} can also be a contiguous range, either ascending @code{l:u}\n\
7141 or descending @code{u:-1:l}, in which case a range of elements is returned.\n\
7142 \n\
7143 If @var{x} is an array, @code{nth_element} operates along the dimension\n\
7144 defined by @var{dim}, or the first non-singleton dimension if @var{dim} is\n\
7145 not given.\n\
7146 \n\
7147 Programming Note: nth_element encapsulates the C++ standard library\n\
7148 algorithms nth_element and partial_sort. On average, the complexity of the\n\
7149 operation is O(M*log(K)), where @w{@code{M = size (@var{x}, @var{dim})}} and\n\
7150 @w{@code{K = length (@var{n})}}. This function is intended for cases where\n\
7151 the ratio K/M is small; otherwise, it may be better to use @code{sort}.\n\
7152 @seealso{sort, min, max}\n\
7153 @end deftypefn")
7154 {
7155  octave_value retval;
7156  int nargin = args.length ();
7157 
7158  if (nargin == 2 || nargin == 3)
7159  {
7160  octave_value argx = args(0);
7161 
7162  int dim = -1;
7163  if (nargin == 3)
7164  {
7165  dim = args(2).int_value (true) - 1;
7166  if (dim < 0)
7167  error ("nth_element: DIM must be a valid dimension");
7168  }
7169  if (dim < 0)
7170  dim = argx.dims ().first_non_singleton ();
7171 
7172  idx_vector n = args(1).index_vector ();
7173 
7174  if (error_state)
7175  return retval;
7176 
7177  switch (argx.builtin_type ())
7178  {
7179  case btyp_double:
7180  retval = argx.array_value ().nth_element (n, dim);
7181  break;
7182  case btyp_float:
7183  retval = argx.float_array_value ().nth_element (n, dim);
7184  break;
7185  case btyp_complex:
7186  retval = argx.complex_array_value ().nth_element (n, dim);
7187  break;
7188  case btyp_float_complex:
7189  retval = argx.float_complex_array_value ().nth_element (n, dim);
7190  break;
7191 #define MAKE_INT_BRANCH(X) \
7192  case btyp_ ## X: \
7193  retval = argx.X ## _array_value ().nth_element (n, dim); \
7194  break;
7195 
7196  MAKE_INT_BRANCH (int8);
7197  MAKE_INT_BRANCH (int16);
7198  MAKE_INT_BRANCH (int32);
7199  MAKE_INT_BRANCH (int64);
7200  MAKE_INT_BRANCH (uint8);
7201  MAKE_INT_BRANCH (uint16);
7202  MAKE_INT_BRANCH (uint32);
7203  MAKE_INT_BRANCH (uint64);
7204 #undef MAKE_INT_BRANCH
7205  default:
7206  if (argx.is_cellstr ())
7207  retval = argx.cellstr_value ().nth_element (n, dim);
7208  else
7209  gripe_wrong_type_arg ("nth_element", argx);
7210  }
7211  }
7212  else
7213  print_usage ();
7214 
7215  return retval;
7216 }
7217 
7218 template <class NDT>
7219 static NDT
7220 do_accumarray_sum (const idx_vector& idx, const NDT& vals,
7221  octave_idx_type n = -1)
7222 {
7223  typedef typename NDT::element_type T;
7224  if (n < 0)
7225  n = idx.extent (0);
7226  else if (idx.extent (n) > n)
7227  error ("accumarray: index out of range");
7228 
7229  NDT retval (dim_vector (n, 1), T ());
7230 
7231  if (vals.numel () == 1)
7232  retval.idx_add (idx, vals (0));
7233  else if (vals.numel () == idx.length (n))
7234  retval.idx_add (idx, vals);
7235  else
7236  error ("accumarray: dimensions mismatch");
7237 
7238  return retval;
7239 }
7240 
7241 DEFUN (__accumarray_sum__, args, ,
7242  "-*- texinfo -*-\n\
7243 @deftypefn {Built-in Function} {} __accumarray_sum__ (@var{idx}, @var{vals}, @var{n})\n\
7244 Undocumented internal function.\n\
7245 @end deftypefn")
7246 {
7247  octave_value retval;
7248  int nargin = args.length ();
7249  if (nargin >= 2 && nargin <= 3 && args(0).is_numeric_type ())
7250  {
7251  idx_vector idx = args(0).index_vector ();
7252  octave_idx_type n = -1;
7253  if (nargin == 3)
7254  n = args(2).idx_type_value (true);
7255 
7256  if (! error_state)
7257  {
7258  octave_value vals = args(1);
7259  if (vals.is_range ())
7260  {
7261  Range r = vals.range_value ();
7262  if (r.inc () == 0)
7263  vals = r.base ();
7264  }
7265 
7266  if (vals.is_single_type ())
7267  {
7268  if (vals.is_complex_type ())
7269  retval = do_accumarray_sum (idx,
7270  vals.float_complex_array_value (),
7271  n);
7272  else
7273  retval = do_accumarray_sum (idx, vals.float_array_value (), n);
7274  }
7275  else if (vals.is_numeric_type () || vals.is_bool_type ())
7276  {
7277  if (vals.is_complex_type ())
7278  retval = do_accumarray_sum (idx,
7279  vals.complex_array_value (),
7280  n);
7281  else
7282  retval = do_accumarray_sum (idx, vals.array_value (), n);
7283  }
7284  else
7285  gripe_wrong_type_arg ("accumarray", vals);
7286  }
7287  }
7288  else
7289  print_usage ();
7290 
7291  return retval;
7292 }
7293 
7294 template <class NDT>
7295 static NDT
7296 do_accumarray_minmax (const idx_vector& idx, const NDT& vals,
7297  octave_idx_type n, bool ismin,
7298  const typename NDT::element_type& zero_val)
7299 {
7300  typedef typename NDT::element_type T;
7301  if (n < 0)
7302  n = idx.extent (0);
7303  else if (idx.extent (n) > n)
7304  error ("accumarray: index out of range");
7305 
7306  NDT retval (dim_vector (n, 1), zero_val);
7307 
7308  // Pick minimizer or maximizer.
7309  void (MArray<T>::*op) (const idx_vector&, const MArray<T>&) =
7310  ismin ? (&MArray<T>::idx_min) : (&MArray<T>::idx_max);
7311 
7312  octave_idx_type l = idx.length (n);
7313  if (vals.numel () == 1)
7314  (retval.*op) (idx, NDT (dim_vector (l, 1), vals(0)));
7315  else if (vals.numel () == l)
7316  (retval.*op) (idx, vals);
7317  else
7318  error ("accumarray: dimensions mismatch");
7319 
7320  return retval;
7321 }
7322 
7323 static octave_value_list
7325  bool ismin)
7326 {
7327  octave_value retval;
7328  int nargin = args.length ();
7329  if (nargin >= 3 && nargin <= 4 && args(0).is_numeric_type ())
7330  {
7331  idx_vector idx = args(0).index_vector ();
7332  octave_idx_type n = -1;
7333  if (nargin == 4)
7334  n = args(3).idx_type_value (true);
7335 
7336  if (! error_state)
7337  {
7338  octave_value vals = args(1);
7339  octave_value zero = args(2);
7340 
7341  switch (vals.builtin_type ())
7342  {
7343  case btyp_double:
7344  retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin,
7345  zero.double_value ());
7346  break;
7347  case btyp_float:
7348  retval = do_accumarray_minmax (idx, vals.float_array_value (), n,
7349  ismin, zero.float_value ());
7350  break;
7351  case btyp_complex:
7352  retval = do_accumarray_minmax (idx, vals.complex_array_value (),
7353  n, ismin, zero.complex_value ());
7354  break;
7355  case btyp_float_complex:
7356  retval = do_accumarray_minmax (idx,
7357  vals.float_complex_array_value (),
7358  n, ismin,
7359  zero.float_complex_value ());
7360  break;
7361 #define MAKE_INT_BRANCH(X) \
7362  case btyp_ ## X: \
7363  retval = do_accumarray_minmax (idx, vals.X ## _array_value (), \
7364  n, ismin, \
7365  zero.X ## _scalar_value ()); \
7366  break;
7367 
7368  MAKE_INT_BRANCH (int8);
7369  MAKE_INT_BRANCH (int16);
7370  MAKE_INT_BRANCH (int32);
7371  MAKE_INT_BRANCH (int64);
7372  MAKE_INT_BRANCH (uint8);
7373  MAKE_INT_BRANCH (uint16);
7374  MAKE_INT_BRANCH (uint32);
7375  MAKE_INT_BRANCH (uint64);
7376 #undef MAKE_INT_BRANCH
7377  case btyp_bool:
7378  retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin,
7379  zero.bool_value ());
7380  break;
7381  default:
7382  gripe_wrong_type_arg ("accumarray", vals);
7383  }
7384  }
7385  }
7386  else
7387  print_usage ();
7388 
7389  return retval;
7390 }
7391 
7392 DEFUN (__accumarray_min__, args, ,
7393  "-*- texinfo -*-\n\
7394 @deftypefn {Built-in Function} {} __accumarray_min__ (@var{idx}, @var{vals}, @var{zero}, @var{n})\n\
7395 Undocumented internal function.\n\
7396 @end deftypefn")
7397 {
7398  return do_accumarray_minmax_fun (args, true);
7399 }
7400 
7401 DEFUN (__accumarray_max__, args, ,
7402  "-*- texinfo -*-\n\
7403 @deftypefn {Built-in Function} {} __accumarray_max__ (@var{idx}, @var{vals}, @var{zero}, @var{n})\n\
7404 Undocumented internal function.\n\
7405 @end deftypefn")
7406 {
7407  return do_accumarray_minmax_fun (args, false);
7408 }
7409 
7410 template <class NDT>
7411 static NDT
7412 do_accumdim_sum (const idx_vector& idx, const NDT& vals,
7413  int dim = -1, octave_idx_type n = -1)
7414 {
7415  typedef typename NDT::element_type T;
7416  if (n < 0)
7417  n = idx.extent (0);
7418  else if (idx.extent (n) > n)
7419  error ("accumdim: index out of range");
7420 
7421  dim_vector vals_dim = vals.dims ();
7422  dim_vector rdv = vals_dim;
7423 
7424  if (dim < 0)
7425  dim = vals.dims ().first_non_singleton ();
7426  else if (dim >= rdv.length ())
7427  rdv.resize (dim+1, 1);
7428 
7429  rdv(dim) = n;
7430 
7431  NDT retval (rdv, T ());
7432 
7433  if (idx.length () != vals_dim(dim))
7434  error ("accumdim: dimension mismatch");
7435 
7436  retval.idx_add_nd (idx, vals, dim);
7437 
7438  return retval;
7439 }
7440 
7441 DEFUN (__accumdim_sum__, args, ,
7442  "-*- texinfo -*-\n\
7443 @deftypefn {Built-in Function} {} __accumdim_sum__ (@var{idx}, @var{vals}, @var{dim}, @var{n})\n\
7444 Undocumented internal function.\n\
7445 @end deftypefn")
7446 {
7447  octave_value retval;
7448  int nargin = args.length ();
7449  if (nargin >= 2 && nargin <= 4 && args(0).is_numeric_type ())
7450  {
7451  idx_vector idx = args(0).index_vector ();
7452  int dim = -1;
7453  if (nargin >= 3)
7454  dim = args(2).int_value () - 1;
7455 
7456  octave_idx_type n = -1;
7457  if (nargin == 4)
7458  n = args(3).idx_type_value (true);
7459 
7460  if (! error_state)
7461  {
7462  octave_value vals = args(1);
7463 
7464  if (vals.is_single_type ())
7465  {
7466  if (vals.is_complex_type ())
7467  retval = do_accumdim_sum (idx,
7468  vals.float_complex_array_value (),
7469  dim, n);
7470  else
7471  retval = do_accumdim_sum (idx, vals.float_array_value (),
7472  dim, n);
7473  }
7474  else if (vals.is_numeric_type () || vals.is_bool_type ())
7475  {
7476  if (vals.is_complex_type ())
7477  retval = do_accumdim_sum (idx, vals.complex_array_value (),
7478  dim, n);
7479  else
7480  retval = do_accumdim_sum (idx, vals.array_value (), dim, n);
7481  }
7482  else
7483  gripe_wrong_type_arg ("accumdim", vals);
7484  }
7485  }
7486  else
7487  print_usage ();
7488 
7489  return retval;
7490 }
7491 
7492 template <class NDT>
7493 static NDT
7494 do_merge (const Array<bool>& mask,
7495  const NDT& tval, const NDT& fval)
7496 {
7497  typedef typename NDT::element_type T;
7498  dim_vector dv = mask.dims ();
7499  NDT retval (dv);
7500 
7501  bool tscl = tval.numel () == 1;
7502  bool fscl = fval.numel () == 1;
7503 
7504  if ((! tscl && tval.dims () != dv)
7505  || (! fscl && fval.dims () != dv))
7506  error ("merge: MASK, TVAL, and FVAL dimensions must match");
7507  else
7508  {
7509  T *rv = retval.fortran_vec ();
7510  octave_idx_type n = retval.numel ();
7511 
7512  const T *tv = tval.data ();
7513  const T *fv = fval.data ();
7514  const bool *mv = mask.data ();
7515 
7516  if (tscl)
7517  {
7518  if (fscl)
7519  {
7520  T ts = tv[0];
7521  T fs = fv[0];
7522  for (octave_idx_type i = 0; i < n; i++)
7523  rv[i] = mv[i] ? ts : fs;
7524  }
7525  else
7526  {
7527  T ts = tv[0];
7528  for (octave_idx_type i = 0; i < n; i++)
7529  rv[i] = mv[i] ? ts : fv[i];
7530  }
7531  }
7532  else
7533  {
7534  if (fscl)
7535  {
7536  T fs = fv[0];
7537  for (octave_idx_type i = 0; i < n; i++)
7538  rv[i] = mv[i] ? tv[i] : fs;
7539  }
7540  else
7541  {
7542  for (octave_idx_type i = 0; i < n; i++)
7543  rv[i] = mv[i] ? tv[i] : fv[i];
7544  }
7545  }
7546  }
7547 
7548  return retval;
7549 }
7550 
7551 #define MAKE_INT_BRANCH(INTX) \
7552  else if (tval.is_ ## INTX ## _type () && fval.is_ ## INTX ## _type ()) \
7553  { \
7554  retval = do_merge (mask, \
7555  tval.INTX ## _array_value (), \
7556  fval.INTX ## _array_value ()); \
7557  }
7558 
7559 DEFUN (merge, args, ,
7560  "-*- texinfo -*-\n\
7561 @deftypefn {Built-in Function} {} merge (@var{mask}, @var{tval}, @var{fval})\n\
7562 @deftypefnx {Built-in Function} {} ifelse (@var{mask}, @var{tval}, @var{fval})\n\
7563 Merge elements of @var{true_val} and @var{false_val}, depending on the\n\
7564 value of @var{mask}.\n\
7565 \n\
7566 If @var{mask} is a logical scalar, the other two arguments can be arbitrary\n\
7567 values. Otherwise, @var{mask} must be a logical array, and @var{tval},\n\
7568 @var{fval} should be arrays of matching class, or cell arrays. In the\n\
7569 scalar mask case, @var{tval} is returned if @var{mask} is true, otherwise\n\
7570 @var{fval} is returned.\n\
7571 \n\
7572 In the array mask case, both @var{tval} and @var{fval} must be either\n\
7573 scalars or arrays with dimensions equal to @var{mask}. The result is\n\
7574 constructed as follows:\n\
7575 \n\
7576 @example\n\
7577 @group\n\
7578 result(mask) = tval(mask);\n\
7579 result(! mask) = fval(! mask);\n\
7580 @end group\n\
7581 @end example\n\
7582 \n\
7583 @var{mask} can also be arbitrary numeric type, in which case it is first\n\
7584 converted to logical.\n\
7585 @seealso{logical, diff}\n\
7586 @end deftypefn")
7587 {
7588  int nargin = args.length ();
7589  octave_value retval;
7590 
7591  if (nargin == 3 && (args(0).is_bool_type () || args(0).is_numeric_type ()))
7592  {
7593  octave_value mask_val = args(0);
7594 
7595  if (mask_val.is_scalar_type ())
7596  retval = mask_val.is_true () ? args(1) : args(2);
7597  else
7598  {
7599  boolNDArray mask = mask_val.bool_array_value ();
7600  octave_value tval = args(1);
7601  octave_value fval = args(2);
7602  if (tval.is_double_type () && fval.is_double_type ())
7603  {
7604  if (tval.is_complex_type () || fval.is_complex_type ())
7605  retval = do_merge (mask,
7606  tval.complex_array_value (),
7607  fval.complex_array_value ());
7608  else
7609  retval = do_merge (mask,
7610  tval.array_value (),
7611  fval.array_value ());
7612  }
7613  else if (tval.is_single_type () && fval.is_single_type ())
7614  {
7615  if (tval.is_complex_type () || fval.is_complex_type ())
7616  retval = do_merge (mask,
7617  tval.float_complex_array_value (),
7618  fval.float_complex_array_value ());
7619  else
7620  retval = do_merge (mask,
7621  tval.float_array_value (),
7622  fval.float_array_value ());
7623  }
7624  else if (tval.is_string () && fval.is_string ())
7625  {
7626  bool sq_string = tval.is_sq_string () || fval.is_sq_string ();
7627  retval = octave_value (do_merge (mask,
7628  tval.char_array_value (),
7629  fval.char_array_value ()),
7630  sq_string ? '\'' : '"');
7631  }
7632  else if (tval.is_cell () && fval.is_cell ())
7633  {
7634  retval = do_merge (mask,
7635  tval.cell_value (),
7636  fval.cell_value ());
7637  }
7638 
7639  MAKE_INT_BRANCH (int8)
7640  MAKE_INT_BRANCH (int16)
7641  MAKE_INT_BRANCH (int32)
7642  MAKE_INT_BRANCH (int64)
7643  MAKE_INT_BRANCH (uint8)
7644  MAKE_INT_BRANCH (uint16)
7645  MAKE_INT_BRANCH (uint32)
7646  MAKE_INT_BRANCH (uint64)
7647 
7648  else
7649  error ("merge: cannot merge %s with %s with array mask",
7650  tval.class_name ().c_str (),
7651  fval.class_name ().c_str ());
7652  }
7653  }
7654  else
7655  print_usage ();
7656 
7657  return retval;
7658 }
7659 
7660 DEFALIAS (ifelse, merge);
7661 
7662 #undef MAKE_INT_BRANCH
7663 
7664 template <class SparseT>
7665 static SparseT
7666 do_sparse_diff (const SparseT& array, octave_idx_type order,
7667  int dim)
7668 {
7669  SparseT retval = array;
7670  if (dim == 1)
7671  {
7672  octave_idx_type k = retval.columns ();
7673  while (order > 0 && k > 0)
7674  {
7675  idx_vector col1 (':'), col2 (':'), sl1 (1, k), sl2 (0, k-1);
7676  retval = SparseT (retval.index (col1, sl1))
7677  - SparseT (retval.index (col2, sl2));
7678  assert (retval.columns () == k-1);
7679  order--;
7680  k--;
7681  }
7682  }
7683  else
7684  {
7685  octave_idx_type k = retval.rows ();
7686  while (order > 0 && k > 0)
7687  {
7688  idx_vector col1 (':'), col2 (':'), sl1 (1, k), sl2 (0, k-1);
7689  retval = SparseT (retval.index (sl1, col1))
7690  - SparseT (retval.index (sl2, col2));
7691  assert (retval.rows () == k-1);
7692  order--;
7693  k--;
7694  }
7695  }
7696 
7697  return retval;
7698 }
7699 
7700 static octave_value
7701 do_diff (const octave_value& array, octave_idx_type order,
7702  int dim = -1)
7703 {
7704  octave_value retval;
7705 
7706  const dim_vector& dv = array.dims ();
7707  if (dim == -1)
7708  {
7709  dim = array.dims ().first_non_singleton ();
7710 
7711  // Bother Matlab. This behavior is really wicked.
7712  if (dv(dim) <= order)
7713  {
7714  if (dv(dim) == 1)
7715  retval = array.resize (dim_vector (0, 0));
7716  else
7717  {
7718  retval = array;
7719  while (order > 0)
7720  {
7721  if (dim == dv.length ())
7722  {
7723  retval = do_diff (array, order, dim - 1);
7724  order = 0;
7725  }
7726  else if (dv(dim) == 1)
7727  dim++;
7728  else
7729  {
7730  retval = do_diff (array, dv(dim) - 1, dim);
7731  order -= dv(dim) - 1;
7732  dim++;
7733  }
7734  }
7735  }
7736 
7737  return retval;
7738  }
7739  }
7740 
7741  if (array.is_integer_type ())
7742  {
7743  if (array.is_int8_type ())
7744  retval = array.int8_array_value ().diff (order, dim);
7745  else if (array.is_int16_type ())
7746  retval = array.int16_array_value ().diff (order, dim);
7747  else if (array.is_int32_type ())
7748  retval = array.int32_array_value ().diff (order, dim);
7749  else if (array.is_int64_type ())
7750  retval = array.int64_array_value ().diff (order, dim);
7751  else if (array.is_uint8_type ())
7752  retval = array.uint8_array_value ().diff (order, dim);
7753  else if (array.is_uint16_type ())
7754  retval = array.uint16_array_value ().diff (order, dim);
7755  else if (array.is_uint32_type ())
7756  retval = array.uint32_array_value ().diff (order, dim);
7757  else if (array.is_uint64_type ())
7758  retval = array.uint64_array_value ().diff (order, dim);
7759  else
7760  panic_impossible ();
7761  }
7762  else if (array.is_sparse_type ())
7763  {
7764  if (array.is_complex_type ())
7765  retval = do_sparse_diff (array.sparse_complex_matrix_value (),
7766  order, dim);
7767  else
7768  retval = do_sparse_diff (array.sparse_matrix_value (), order, dim);
7769  }
7770  else if (array.is_single_type ())
7771  {
7772  if (array.is_complex_type ())
7773  retval = array.float_complex_array_value ().diff (order, dim);
7774  else
7775  retval = array.float_array_value ().diff (order, dim);
7776  }
7777  else
7778  {
7779  if (array.is_complex_type ())
7780  retval = array.complex_array_value ().diff (order, dim);
7781  else
7782  retval = array.array_value ().diff (order, dim);
7783  }
7784 
7785  return retval;
7786 }
7787 
7788 DEFUN (diff, args, ,
7789  "-*- texinfo -*-\n\
7790 @deftypefn {Built-in Function} {} diff (@var{x})\n\
7791 @deftypefnx {Built-in Function} {} diff (@var{x}, @var{k})\n\
7792 @deftypefnx {Built-in Function} {} diff (@var{x}, @var{k}, @var{dim})\n\
7793 If @var{x} is a vector of length @math{n}, @code{diff (@var{x})} is the\n\
7794 vector of first differences\n\
7795 @tex\n\
7796  $x_2 - x_1, \\ldots{}, x_n - x_{n-1}$.\n\
7797 @end tex\n\
7798 @ifnottex\n\
7799  @var{x}(2) - @var{x}(1), @dots{}, @var{x}(n) - @var{x}(n-1).\n\
7800 @end ifnottex\n\
7801 \n\
7802 If @var{x} is a matrix, @code{diff (@var{x})} is the matrix of column\n\
7803 differences along the first non-singleton dimension.\n\
7804 \n\
7805 The second argument is optional. If supplied, @code{diff (@var{x},\n\
7806 @var{k})}, where @var{k} is a non-negative integer, returns the\n\
7807 @var{k}-th differences. It is possible that @var{k} is larger than\n\
7808 the first non-singleton dimension of the matrix. In this case,\n\
7809 @code{diff} continues to take the differences along the next\n\
7810 non-singleton dimension.\n\
7811 \n\
7812 The dimension along which to take the difference can be explicitly\n\
7813 stated with the optional variable @var{dim}. In this case the\n\
7814 @var{k}-th order differences are calculated along this dimension.\n\
7815 In the case where @var{k} exceeds @code{size (@var{x}, @var{dim})}\n\
7816 an empty matrix is returned.\n\
7817 @seealso{sort, merge}\n\
7818 @end deftypefn")
7819 {
7820  int nargin = args.length ();
7821  octave_value retval;
7822 
7823  if (nargin < 1 || nargin > 3)
7824  print_usage ();
7825  else if (! (args(0).is_numeric_type () || args(0).is_bool_type ()))
7826  error ("diff: X must be numeric or logical");
7827 
7828  if (! error_state)
7829  {
7830  int dim = -1;
7831  octave_idx_type order = 1;
7832  if (nargin > 1)
7833  {
7834  if (args(1).is_scalar_type ())
7835  order = args(1).idx_type_value (true, false);
7836  else if (! args(1).is_zero_by_zero ())
7837  error ("order K must be a scalar or []");
7838  if (! error_state && order < 0)
7839  error ("order K must be non-negative");
7840  }
7841 
7842  if (nargin > 2)
7843  {
7844  dim = args(2).int_value (true, false);
7845  if (! error_state && (dim < 1 || dim > args(0).ndims ()))
7846  error ("DIM must be a valid dimension");
7847  else
7848  dim -= 1;
7849  }
7850 
7851  if (! error_state)
7852  retval = do_diff (args(0), order, dim);
7853  }
7854 
7855  return retval;
7856 }
7857 
7858 /*
7859 %!assert (diff ([1, 2, 3, 4]), [1, 1, 1])
7860 %!assert (diff ([1, 3, 7, 19], 2), [2, 8])
7861 %!assert (diff ([1, 2; 5, 4; 8, 7; 9, 6; 3, 1]), [4, 2; 3, 3; 1, -1; -6, -5])
7862 %!assert (diff ([1, 2; 5, 4; 8, 7; 9, 6; 3, 1], 3), [-1, -5; -5, 0])
7863 %!assert (isempty (diff (1)))
7864 
7865 %!error diff ()
7866 %!error diff (1, 2, 3, 4)
7867 %!error diff ("foo")
7868 %!error diff ([1, 2; 3, 4], -1)
7869 */
7870 
7871 template <class T>
7872 static Array<T>
7874 {
7875  Array<T> retval;
7876 
7877  assert (rep.ndims () == 2 && rep.rows () == 2);
7878 
7879  octave_idx_type n = rep.columns ();
7880  octave_idx_type l = 0;
7881  for (octave_idx_type i = 0; i < n; i++)
7882  {
7883  octave_idx_type k = rep(1, i);
7884  if (k < 0)
7885  {
7886  error ("repelems: second row must contain non-negative numbers");
7887  return retval;
7888  }
7889 
7890  l += k;
7891  }
7892 
7893  retval.clear (1, l);
7894  T *dest = retval.fortran_vec ();
7895  l = 0;
7896  for (octave_idx_type i = 0; i < n; i++)
7897  {
7898  octave_idx_type k = rep(1, i);
7899  std::fill_n (dest, k, src.checkelem (rep(0, i) - 1));
7900  dest += k;
7901  }
7902 
7903  return retval;
7904 }
7905 
7906 DEFUN (repelems, args, ,
7907  "-*- texinfo -*-\n\
7908 @deftypefn {Built-in Function} {} repelems (@var{x}, @var{r})\n\
7909 Construct a vector of repeated elements from @var{x}.\n\
7910 \n\
7911 @var{r} is a 2x@var{N} integer matrix specifying which elements to repeat and\n\
7912 how often to repeat each element. Entries in the first row, @var{r}(1,j),\n\
7913 select an element to repeat. The corresponding entry in the second row,\n\
7914 @var{r}(2,j), specifies the repeat count. If @var{x} is a matrix then the\n\
7915 columns of @var{x} are imagined to be stacked on top of each other for\n\
7916 purposes of the selection index. A row vector is always returned.\n\
7917 \n\
7918 Conceptually the result is calculated as follows:\n\
7919 \n\
7920 @example\n\
7921 @group\n\
7922 y = [];\n\
7923 for i = 1:columns (@var{r})\n\
7924  y = [y, @var{x}(@var{r}(1,i)*ones(1, @var{r}(2,i)))];\n\
7925 endfor\n\
7926 @end group\n\
7927 @end example\n\
7928 @seealso{repmat, cat}\n\
7929 @end deftypefn")
7930 {
7931  octave_value retval;
7932 
7933  if (args.length () == 2)
7934  {
7935  octave_value x = args(0);
7936 
7937  const Matrix rm = args(1).matrix_value ();
7938  if (error_state)
7939  return retval;
7940  else if (rm.rows () != 2 || rm.ndims () != 2)
7941  {
7942  error ("repelems: R must be a matrix with two rows");
7943  return retval;
7944  }
7945  else
7946  {
7948 
7949  for (octave_idx_type i = 0; i < rm.numel (); i++)
7950  {
7951  octave_idx_type rx = rm(i);
7952  if (static_cast<double> (rx) != rm(i))
7953  {
7954  error ("repelems: R must be a matrix of integers");
7955  return retval;
7956  }
7957 
7958  r(i) = rx;
7959  }
7960 
7961  switch (x.builtin_type ())
7962  {
7963 #define BTYP_BRANCH(X, EX) \
7964  case btyp_ ## X: \
7965  retval = do_repelems (x.EX ## _value (), r); \
7966  break;
7967 
7968  BTYP_BRANCH (double, array);
7969  BTYP_BRANCH (float, float_array);
7970  BTYP_BRANCH (complex, complex_array);
7971  BTYP_BRANCH (float_complex, float_complex_array);
7972  BTYP_BRANCH (bool, bool_array);
7973  BTYP_BRANCH (char, char_array);
7974 
7975  BTYP_BRANCH (int8, int8_array);
7976  BTYP_BRANCH (int16, int16_array);
7977  BTYP_BRANCH (int32, int32_array);
7978  BTYP_BRANCH (int64, int64_array);
7979  BTYP_BRANCH (uint8, uint8_array);
7980  BTYP_BRANCH (uint16, uint16_array);
7981  BTYP_BRANCH (uint32, uint32_array);
7982  BTYP_BRANCH (uint64, uint64_array);
7983 
7984  BTYP_BRANCH (cell, cell);
7985  //BTYP_BRANCH (struct, map);//FIXME
7986 #undef BTYP_BRANCH
7987 
7988  default:
7989  gripe_wrong_type_arg ("repelems", x);
7990  }
7991  }
7992  }
7993  else
7994  print_usage ();
7995 
7996  return retval;
7997 }
7998 
7999 DEFUN (base64_encode, args, ,
8000  "-*- texinfo -*-\n\
8001 @deftypefn {Built-in Function} {@var{s} =} base64_encode (@var{x})\n\
8002 Encode a double matrix or array @var{x} into the base64 format string\n\
8003 @var{s}.\n\
8004 \n\
8005 @seealso{base64_decode}\n\
8006 @end deftypefn")
8007 {
8008  octave_value_list retval;
8009  int nargin = args.length ();
8010 
8011  if (nargin != 1)
8012  print_usage ();
8013  else
8014  {
8015  if (! args(0).is_numeric_type ())
8016  error ("base64_encode: encoding is supported only for numeric arrays");
8017  else if (args(0).is_complex_type ()
8018  || args(0).is_sparse_type ())
8019  error ("base64_encode: encoding complex or sparse data is not supported");
8020  else if (args(0).is_integer_type ())
8021  {
8022 #define MAKE_INT_BRANCH(X) \
8023  if (args(0).is_ ## X ## _type ()) \
8024  { \
8025  const X##NDArray in = args(0). X## _array_value (); \
8026  size_t inlen = \
8027  in.numel () * sizeof (X## _t) / sizeof (char); \
8028  const char* inc = \
8029  reinterpret_cast<const char*> (in.data ()); \
8030  char* out; \
8031  if (! error_state \
8032  && octave_base64_encode (inc, inlen, &out)) \
8033  { \
8034  retval(0) = octave_value (out); \
8035  ::free (out); \
8036  } \
8037  }
8038 
8039  MAKE_INT_BRANCH(int8)
8040  else MAKE_INT_BRANCH(int16)
8041  else MAKE_INT_BRANCH(int32)
8042  else MAKE_INT_BRANCH(int64)
8043  else MAKE_INT_BRANCH(uint8)
8044  else MAKE_INT_BRANCH(uint16)
8045  else MAKE_INT_BRANCH(uint32)
8046  else MAKE_INT_BRANCH(uint64)
8047 #undef MAKE_INT_BRANCH
8048 
8049  else
8050  panic_impossible ();
8051  }
8052  else if (args(0).is_single_type ())
8053  {
8054  const Array<float> in = args(0).float_array_value ();
8055  size_t inlen;
8056  inlen = in.numel () * sizeof (float) / sizeof (char);
8057  const char* inc;
8058  inc = reinterpret_cast<const char*> (in.data ());
8059  char* out;
8060  if (! error_state
8061  && octave_base64_encode (inc, inlen, &out))
8062  {
8063  retval(0) = octave_value (out);
8064  ::free (out);
8065  }
8066  }
8067  else
8068  {
8069  const Array<double> in = args(0).array_value ();
8070  size_t inlen;
8071  inlen = in.numel () * sizeof (double) / sizeof (char);
8072  const char* inc;
8073  inc = reinterpret_cast<const char*> (in.data ());
8074  char* out;
8075  if (! error_state
8076  && octave_base64_encode (inc, inlen, &out))
8077  {
8078  retval(0) = octave_value (out);
8079  ::free (out);
8080  }
8081  }
8082  }
8083  return retval;
8084 }
8085 
8086 /*
8087 %!assert (base64_encode (single (pi)), "2w9JQA==")
8088 %!assert (base64_encode (uint8 ([0 0 0])), "AAAA")
8089 %!assert (base64_encode (uint16 ([0 0 0])), "AAAAAAAA")
8090 %!assert (base64_encode (uint32 ([0 0 0])), "AAAAAAAAAAAAAAAA")
8091 %!assert (base64_encode (uint64 ([0 0 0])), "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
8092 %!assert (base64_encode (uint8 ([255 255 255])), "////")
8093 
8094 %!error base64_encode ()
8095 %!error base64_encode (1,2)
8096 %!error base64_encode ("A string")
8097 %!error base64_encode ({"A cell array"})
8098 %!error base64_encode (struct ())
8099 */
8100 
8101 DEFUN (base64_decode, args, ,
8102  "-*- texinfo -*-\n\
8103 @deftypefn {Built-in Function} {@var{x} =} base64_decode (@var{s})\n\
8104 @deftypefnx {Built-in Function} {@var{x} =} base64_decode (@var{s}, @var{dims})\n\
8105 Decode the double matrix or array @var{x} from the base64 encoded string\n\
8106 @var{s}.\n\
8107 \n\
8108 The optional input parameter @var{dims} should be a vector containing the\n\
8109 dimensions of the decoded array.\n\
8110 @seealso{base64_encode}\n\
8111 @end deftypefn")
8112 {
8113  octave_value retval;
8114 
8115  int nargin = args.length ();
8116 
8117  if (nargin < 1 || nargin > 2)
8118  print_usage ();
8119  else
8120  {
8121  dim_vector dims;
8122 
8123  if (nargin > 1)
8124  {
8126  args(1).octave_idx_type_vector_value ();
8127 
8128  if (! error_state)
8129  {
8130  dims = dim_vector::alloc (size.length ());
8131  for (octave_idx_type i = 0; i < size.length (); i++)
8132  dims(i) = size(i);
8133  }
8134  }
8135 
8136  const std::string str = args(0).string_value ();
8137 
8138  if (! error_state)
8139  {
8140  Array<double> res = octave_base64_decode (str);
8141 
8142  if (nargin > 1)
8143  res = res.reshape (dims);
8144 
8145  retval = res;
8146  }
8147  }
8148 
8149  return retval;
8150 }
8151 
8152 /*
8153 %!assert (base64_decode (base64_encode (pi)), pi)
8154 %!
8155 %!test
8156 %! in = randn (10);
8157 %! outv = base64_decode (base64_encode (in));
8158 %! outm = base64_decode (base64_encode (in), size (in));
8159 %! assert (outv, in(:).');
8160 %! assert (outm, in);
8161 
8162 %!error base64_decode ()
8163 %!error base64_decode (1,2,3)
8164 %!error base64_decode (1, "this is not a valid set of dimensions")
8165 %!error <input was not valid base64> base64_decode (1)
8166 %!error <input was not valid base64> base64_decode ("AQ=")
8167 %!error <incorrect input size> base64_decode ("AQ==")
8168 */
float lo_ieee_float_na_value(void)
Definition: lo-ieee.cc:194
sortmode is_sorted_rows(sortmode mode=UNSORTED) const
Definition: ov.h:1144
uint8NDArray uint8_array_value(void) const
Definition: ov.h:882
static TYPE do_single_type_concat(const octave_value_list &args, int dim)
Definition: data.cc:1750
void gripe_implicit_conversion(const char *id, const char *from, const char *to)
Definition: gripes.cc:180
SparseComplexMatrix cumsum(int dim=-1) const
Definition: CSparse.cc:7283
static Array< T > do_repelems(const Array< T > &src, const Array< octave_idx_type > &rep)
Definition: data.cc:7873
OCTAVE_API ColumnVector xrownorms(const Matrix &m, double p)
Definition: oct-norm.cc:571
boolNDArray all(int dim=-1) const
Definition: boolNDArray.cc:61
int bool
Definition: mex.h:56
bool is_object(void) const
Definition: ov.h:577
void get_dimensions(const octave_value &a, const char *warn_for, dim_vector &dim)
Definition: utils.cc:1141
octave_idx_type nnz(void) const
Definition: ov.h:492
NDArray cumsum(int dim=-1) const
Definition: dNDArray.cc:659
NDArray dsum(int dim=-1) const
Definition: fNDArray.cc:643
ComplexNDArray complex_array_value(bool frc_str_conv=false) const
Definition: ov.h:798
bool is_range(void) const
Definition: ov.h:571
static NDT do_merge(const Array< bool > &mask, const NDT &tval, const NDT &fval)
Definition: data.cc:7494
octave_idx_type cols(void) const
Definition: Sparse.h:264
Definition: Cell.h:35
NDArray cumsum(int dim=-1) const
Definition: boolNDArray.cc:81
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:551
charNDArray char_array_value(bool frc_str_conv=false) const
Definition: ov.h:817
static octave_map cat(int dim, octave_idx_type n, const octave_scalar_map *map_list)
Definition: oct-map.cc:662
intNDArray< octave_int64 > int64NDArray
Definition: int64NDArray.h:31
bool is_real_type(void) const
Definition: ov.h:651
assign_op
Definition: ov.h:131
T * data(void)
Definition: Sparse.h:509
void gripe_wrong_type_arg(const char *name, const char *s, bool is_error)
Definition: gripes.cc:135
octave_idx_type rows(void) const
Definition: Sparse.h:263
static octave_value fill_matrix(const octave_value_list &args, int val, const char *fcn)
Definition: data.cc:3965
int ndims(void) const
Definition: ov.h:479
const octave_base_value const Array< octave_idx_type > & ra_idx
octave_value reshape(const dim_vector &dv) const
Definition: ov.h:498
octave_idx_type rows(void) const
Definition: ov.h:473
template octave_value identity_matrix< uint64NDArray >(int, int)
octave_value do_cat_op(const octave_value &v1, const octave_value &v2, const Array< octave_idx_type > &ra_idx)
Definition: ov.cc:2304
template octave_value identity_matrix< uint16NDArray >(int, int)
FloatNDArray diff(octave_idx_type order=1, int dim=-1) const
Definition: fNDArray.cc:703
bool xisnan(double x)
Definition: lo-mappers.cc:144
dim_vector dims(void) const
Definition: Sparse.h:283
int8NDArray int8_array_value(void) const
Definition: ov.h:870
bool is_vector(void) const
Definition: dim-vector.h:430
std::string get_concat_class(const std::string &c1, const std::string &c2)
Definition: pt-mat.cc:204
static octave_value find_method(const std::string &name, const std::string &dispatch_type)
Definition: symtab.h:1501
bool is_uint16_type(void) const
Definition: ov.h:634
int ndims(void) const
Definition: Array.h:487
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
SparseMatrix sum(int dim=-1) const
Definition: dSparse.cc:7457
sortmode
Definition: oct-sort.h:103
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
void map_2_xlog2(const Array< T > &x, Array< T > &f, Array< ET > &e)
Definition: data.cc:466
template octave_value identity_matrix< boolNDArray >(int, int)
int16NDArray int16_array_value(void) const
Definition: ov.h:873
FloatNDArray cumsum(int dim=-1) const
Definition: fNDArray.cc:619
octave_idx_type length(void) const
Definition: oct-obj.h:89
intNDArray< octave_uint32 > uint32NDArray
Definition: uint32NDArray.h:31
static NDT do_accumarray_sum(const idx_vector &idx, const NDT &vals, octave_idx_type n=-1)
Definition: data.cc:7220
octave_value do_unary_op(octave_value::unary_op op, const octave_value &v)
Definition: ov.cc:2511
bool is_scalar_type(void) const
Definition: ov.h:657
octave_value diag(octave_idx_type k=0) const
Definition: ov.h:1126
intNDArray< octave_uint8 > uint8NDArray
Definition: uint8NDArray.h:31
bool is_numeric_type(void) const
Definition: ov.h:663
bool is_defined(void) const
Definition: ov.h:520
intNDArray< octave_uint16 > uint16NDArray
Definition: uint16NDArray.h:31
octave_int< T > mod(const octave_int< T > &x, const octave_int< T > &y)
Definition: oct-inttypes.h:959
NDArray prod(int dim=-1) const
Definition: dNDArray.cc:665
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:730
void resize(int n, int fill_value=0)
Definition: dim-vector.h:287
Definition: Range.h:31
uint64NDArray uint64_array_value(void) const
Definition: ov.h:891
static void transpose(octave_idx_type N, const octave_idx_type *ridx, const octave_idx_type *cidx, octave_idx_type *ridx2, octave_idx_type *cidx2)
Definition: symrcm.cc:382
binary_op
Definition: ov.h:87
SparseComplexMatrix prod(int dim=-1) const
Definition: CSparse.cc:7289
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
octave_value identity_matrix(int nr, int nc)
Definition: data.cc:5016
void error(const char *fmt,...)
Definition: error.cc:476
float float_value(bool frc_str_conv=false) const
Definition: ov.h:762
#define MAKE_INT_BRANCH(X)
Definition: data.cc:7551
int32NDArray int32_array_value(void) const
Definition: ov.h:876
double lo_ieee_inf_value(void)
Definition: lo-ieee.cc:110
bool is_int8_type(void) const
Definition: ov.h:619
static octave_value_list do_accumarray_minmax_fun(const octave_value_list &args, bool ismin)
Definition: data.cc:7324
Array< octave_idx_type > sort_rows_idx(sortmode mode=ASCENDING) const
Definition: ov.h:1141
#define RUSAGE_SELF
Definition: getrusage.cc:57
bool xisinf(double x)
Definition: lo-mappers.cc:160
static Sparse< T > cat(int dim, octave_idx_type n, const Sparse< T > *sparse_list)
Definition: Sparse.cc:2584
boolNDArray any(int dim=-1) const
Definition: boolNDArray.cc:67
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:507
bool is_cell(void) const
Definition: ov.h:529
T xrem(T x, T y)
Definition: lo-mappers.h:345
octave_idx_type * cidx(void)
Definition: Sparse.h:531
double double_value(void) const
Definition: oct-time.h:94
static void single_type_concat(Array< T > &result, const octave_value_list &args, int dim)
Definition: data.cc:1685
double lo_ieee_nan_value(void)
Definition: lo-ieee.cc:126
octave_idx_type nzmax(void) const
Definition: ov.h:494
static NDT do_accumarray_minmax(const idx_vector &idx, const NDT &vals, octave_idx_type n, bool ismin, const typename NDT::element_type &zero_val)
Definition: data.cc:7296
Definition: MArray.h:36
bool is_int32_type(void) const
Definition: ov.h:625
ComplexNDArray dsum(int dim=-1) const
Definition: fCNDArray.cc:633
intNDArray< octave_int16 > int16NDArray
Definition: int16NDArray.h:31
double scalar_value(bool frc_str_conv=false) const
Definition: ov.h:765
Array< double > octave_base64_decode(const std::string &str)
Definition: oct-base64.cc:57
double xlog2(double x)
Definition: lo-mappers.cc:93
builtin_type_t
Definition: ov-base.h:59
octave_idx_type idx_type_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.cc:1575
#define NaN
Definition: Faddeeva.cc:257
template octave_value identity_matrix< int8NDArray >(int, int)
static void check_dimensions(octave_idx_type &nr, octave_idx_type &nc, const char *warnfor)
Definition: utils.cc:1108
boolNDArray bool_array_value(bool warn=false) const
Definition: ov.h:811
int first_non_singleton(int def=0) const
Definition: dim-vector.h:435
octave_idx_type rows(void) const
Definition: Array.h:313
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:361
FloatNDArray sum(int dim=-1) const
Definition: fNDArray.cc:637
double lo_ieee_na_value(void)
Definition: lo-ieee.cc:118
octave_idx_type nnz(void) const
Definition: Sparse.h:248
template octave_value identity_matrix< uint32NDArray >(int, int)
SparseMatrix sum(int dim=-1) const
Definition: boolSparse.cc:191
FloatComplexNDArray cumsum(int dim=-1) const
Definition: fCNDArray.cc:608
bool concat(const dim_vector &dvb, int dim)
This corresponds to cat().
Definition: dim-vector.cc:177
int64NDArray int64_array_value(void) const
Definition: ov.h:879
Cell cell_value(void) const
Definition: ov.cc:1566
ComplexNDArray dprod(int dim=-1) const
Definition: fCNDArray.cc:621
bool is_float_type(void) const
Definition: ov.h:614
Array< std::string > cellstr_value(void) const
Definition: ov.h:900
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:337
octave_value single_subsref(const std::string &type, const octave_value_list &idx)
Definition: ov.cc:1285
static sortmode get_sort_mode_option(const octave_value &arg, const char *argn)
Definition: data.cc:6994
bool isvector(const T &array)
#define DEFALIAS(alias, name)
Definition: defun.h:63
octave_value_list do_multi_index_op(int nargout, const octave_value_list &idx)
Definition: ov.cc:1382
template octave_value identity_matrix< int16NDArray >(int, int)
octave_idx_type columns(void) const
Definition: ov.h:475
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition: ov.h:782
ComplexNDArray prod(int dim=-1) const
Definition: CNDArray.cc:616
ComplexNDArray sum(int dim=-1) const
Definition: CNDArray.cc:622
SparseBoolMatrix all(int dim=-1) const
Definition: boolSparse.cc:138
T xmod(T x, T y)
Definition: lo-mappers.h:312
F77_RET_T const double const double * f
intNDArray< octave_int8 > int8NDArray
Definition: int8NDArray.h:31
bool is_sparse_type(void) const
Definition: ov.h:666
#define octave_Inf
Definition: lo-ieee.h:31
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:395
bool is_bool_type(void) const
Definition: ov.h:645
octave_int< T > powf(const float &a, const octave_int< T > &b)
std::string string_value(bool force=false) const
Definition: ov.h:897
static octave_value unary_op_defun_body(octave_value::unary_op op, const octave_value_list &args)
Definition: data.cc:5951
static NDT do_accumdim_sum(const idx_vector &idx, const NDT &vals, int dim=-1, octave_idx_type n=-1)
Definition: data.cc:7412
static Array< T > cat(int dim, octave_idx_type n, const Array< T > *array_list)
Concatenation along a specified (0-based) dimension, equivalent to cat().
Definition: Array.cc:2634
FloatComplex float_complex_value(bool frc_str_conv=false) const
Definition: ov.h:788
Range range_value(void) const
Definition: ov.h:903
float lo_ieee_float_inf_value(void)
Definition: lo-ieee.cc:186
OCTAVE_API RowVector xcolnorms(const Matrix &m, double p)
Definition: oct-norm.cc:571
FloatComplexNDArray float_complex_array_value(bool frc_str_conv=false) const
Definition: ov.h:802
bool is_string(void) const
Definition: ov.h:562
double inc(void) const
Definition: Range.h:63
bool is_double_type(void) const
Definition: ov.h:608
const T * data(void) const
Definition: Array.h:479
double norm(const ColumnVector &v)
Definition: graphics.cc:5328
int error_state
Definition: error.cc:101
SparseBoolMatrix sparse_bool_matrix_value(bool warn=false) const
Definition: ov.h:827
bool is_complex_type(void) const
Definition: ov.h:654
octave_value & assign(assign_op op, const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov.cc:1430
static bool all_scalar_1x1(const octave_value_list &args)
Definition: data.cc:1673
octave_int< T > pow(const octave_int< T > &a, const octave_int< T > &b)
bool is_int64_type(void) const
Definition: ov.h:628
bool is_cellstr(void) const
Definition: ov.h:532
#define panic_impossible()
Definition: error.h:33
static octave_value attempt_type_conversion(const octave_value &ov, std::string dtype)
Definition: data.cc:1793
octave_value abs(void) const
Definition: ov.h:1158
OCTAVE_API double xnorm(const ColumnVector &x, double p)
Definition: oct-norm.cc:536
static octave_value do_cat(const octave_value_list &xargs, int dim, std::string fname)
Definition: data.cc:1914
dim_vector redim(int n) const
Definition: dim-vector.cc:266
octave_value do_class_concat(const octave_value_list &ovl, std::string cattype, int dim)
Definition: data.cc:1842
octave_int< uint64_t > octave_uint64
ComplexNDArray xsum(int dim=-1) const
Definition: CNDArray.cc:628
FloatNDArray prod(int dim=-1) const
Definition: fNDArray.cc:625
octave_idx_type length(void) const
Definition: ov.cc:1525
SparseMatrix cumsum(int dim=-1) const
Definition: dSparse.cc:7439
#define ANY_ALL(FCN)
Definition: data.cc:85
Definition: dMatrix.h:35
size_t size(T const (&)[z])
Definition: help.cc:103
static octave_value do_hypot(const octave_value &x, const octave_value &y)
Definition: data.cc:333
SparseComplexMatrix sparse_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:824
static dim_vector alloc(int n)
Definition: dim-vector.h:256
#define eps(C)
dim_vector dims(void) const
Definition: ov.h:470
SparseBoolMatrix any(int dim=-1) const
Definition: boolSparse.cc:144
static octave_map do_single_type_concat_map(const octave_value_list &args, int dim)
Definition: data.cc:1780
float lo_ieee_float_nan_value(void)
Definition: lo-ieee.cc:202
double arg(double x)
Definition: lo-mappers.h:37
T & xelem(octave_idx_type n)
Definition: Array.h:353
bool is_int16_type(void) const
Definition: ov.h:622
ComplexMatrix linspace(const ComplexColumnVector &x1, const ComplexColumnVector &x2, octave_idx_type n)
Definition: CMatrix.cc:3997
static octave_value do_linspace(const octave_value &base, const octave_value &limit, octave_idx_type n)
Definition: data.cc:5247
ComplexNDArray cumsum(int dim=-1) const
Definition: CNDArray.cc:610
void warning(const char *fmt,...)
Definition: error.cc:681
bool is_true(void) const
Definition: ov.h:671
Handles the reference counting for all the derived classes.
Definition: Array.h:45
OCTAVE_API double xfrobnorm(const Matrix &x)
Definition: oct-norm.cc:536
octave_value sort(octave_idx_type dim=0, sortmode mode=ASCENDING) const
Definition: ov.h:1132
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
bool octave_base64_encode(const char *inc, const size_t inlen, char **out)
Definition: oct-base64.cc:35
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
void clear(void)
Definition: Array.cc:84
bool is_empty(void) const
Definition: ov.h:526
octave_idx_type extent(octave_idx_type n) const
Definition: idx-vector.h:554
#define Inf
Definition: Faddeeva.cc:256
intNDArray< octave_int32 > int32NDArray
Definition: int32NDArray.h:31
SparseMatrix atan2(const double &x, const SparseMatrix &y)
Definition: dSparse.cc:689
#define octave_stdout
Definition: pager.h:144
This is a simple wrapper template that will subclass an Array type or any later type derived from ...
Definition: Array.h:762
bool is_sq_string(void) const
Definition: ov.h:565
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:779
octave_idx_type * ridx(void)
Definition: Sparse.h:518
NDArray sum(int dim=-1) const
Definition: dNDArray.cc:671
octave_value_list ovl(const octave_value &a0)
Definition: oct-obj.h:178
static octave_value binary_op_defun_body(octave_value::binary_op op, const octave_value_list &args)
Definition: data.cc:6060
template octave_value identity_matrix< int32NDArray >(int, int)
T & checkelem(octave_idx_type n)
Definition: Array.cc:189
bool bool_value(bool warn=false) const
Definition: ov.h:805
Array< octave_value > array_value(void) const
Definition: oct-obj.h:79
void free(void *)
bool is_uint8_type(void) const
Definition: ov.h:631
static double tic_toc_timestamp
Definition: data.cc:6395
octave_idx_type dims_to_numel(const dim_vector &dims, const octave_value_list &idx)
Definition: utils.cc:1221
SparseComplexMatrix sum(int dim=-1) const
Definition: CSparse.cc:7301
template octave_value identity_matrix< uint8NDArray >(int, int)
Complex complex_value(bool frc_str_conv=false) const
Definition: ov.h:785
std::string get_dispatch_type(const octave_value_list &args, builtin_type_t &builtin_type)
Definition: symtab.cc:611
static octave_value binary_assoc_op_defun_body(octave_value::binary_op op, octave_value::assign_op aop, const octave_value_list &args)
Definition: data.cc:6074
octave_int< T > rem(const octave_int< T > &x, const octave_int< T > &y)
Definition: oct-inttypes.h:954
std::string class_name(void) const
Definition: ov.h:1049
SparseMatrix prod(int dim=-1) const
Definition: dSparse.cc:7445
bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
Definition: dim-vector.cc:241
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:197
FloatComplexNDArray sum(int dim=-1) const
Definition: fCNDArray.cc:627
bool is_uint64_type(void) const
Definition: ov.h:640
double base(void) const
Definition: Range.h:61
Array< T > reshape(octave_idx_type nr, octave_idx_type nc) const
Definition: Array.h:460
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: oct-obj.h:93
ComplexNDArray diff(octave_idx_type order=1, int dim=-1) const
Definition: CNDArray.cc:640
Array< T > nth_element(const idx_vector &n, int dim=0) const
Returns the n-th element in increasing order, using the same ordering as used for sort...
Definition: Array.cc:2327
std::complex< float > FloatComplex
Definition: oct-cmplx.h:30
template octave_value identity_matrix< int64NDArray >(int, int)
static data_type string_to_data_type(const std::string &s)
Definition: data-conv.cc:283
static octave_value do_diff(const octave_value &array, octave_idx_type order, int dim=-1)
Definition: data.cc:7701
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:820
FloatComplexNDArray prod(int dim=-1) const
Definition: fCNDArray.cc:615
static SparseT do_sparse_diff(const SparseT &array, octave_idx_type order, int dim)
Definition: data.cc:7666
std::complex< double > Complex
Definition: oct-cmplx.h:29
const T * fortran_vec(void) const
Definition: Array.h:481
bool is_single_type(void) const
Definition: ov.h:611
#define BTYP_BRANCH(X, EX)
double double_value(bool frc_str_conv=false) const
Definition: ov.h:759
bool is_uint32_type(void) const
Definition: ov.h:637
FloatComplexNDArray diff(octave_idx_type order=1, int dim=-1) const
Definition: fCNDArray.cc:645
unary_op
Definition: ov.h:74
void chop_trailing_singletons(void)
Definition: dim-vector.h:214
octave_value do_colon_op(const octave_value &base, const octave_value &increment, const octave_value &limit, bool is_for_cmd_expr)
Definition: ov.cc:2393
uint32NDArray uint32_array_value(void) const
Definition: ov.h:888
builtin_type_t builtin_type(void) const
Definition: ov.h:603
int length(void) const
Definition: dim-vector.h:281
static void single_type_concat_map(octave_map &result, const octave_value_list &args, int dim)
Definition: data.cc:1761
Complex atan(const Complex &x)
Definition: lo-mappers.cc:231
#define INSTANTIATE_EYE(T)
Definition: data.cc:5046
uint16NDArray uint16_array_value(void) const
Definition: ov.h:885
static octave_value do_permute(const octave_value_list &args, bool inv)
Definition: data.cc:2576
octave_idx_type columns(void) const
Definition: Array.h:322
NDArray sum(int dim=-1) const
Definition: boolNDArray.cc:73
NDArray dprod(int dim=-1) const
Definition: fNDArray.cc:631
NDArray diff(octave_idx_type order=1, int dim=-1) const
Definition: dNDArray.cc:737
#define DATA_REDUCTION(FCN)
Definition: data.cc:1066
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
NDArray xsum(int dim=-1) const
Definition: dNDArray.cc:677
F77_RET_T const double * x
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:210
void maybe_warn_string_concat(bool all_dq_strings_p, bool all_sq_strings_p)
Definition: pt-mat.cc:679
octave_value do_binary_op(octave_value::binary_op op, const octave_value &v1, const octave_value &v2)
Definition: ov.cc:1978
intNDArray diff(octave_idx_type order=1, int dim=-1) const
Definition: intNDArray.cc:300
intNDArray< octave_uint64 > uint64NDArray
Definition: uint64NDArray.h:31
bool is_integer_type(void) const
Definition: ov.h:648