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