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