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