3Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
4 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
5Copyright (C) 2009 Jaroslav Hajek
6Copyright (C) 2009 VZLU Prague
8This file is part of Octave.
10Octave is free software; you can redistribute it and/or modify it
11under the terms of the GNU General Public License as published by the
12Free Software Foundation; either version 3 of the License, or (at your
13option) any later version.
15Octave is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20You should have received a copy of the GNU General Public License
21along with Octave; see the file COPYING. If not, see
22<http://www.gnu.org/licenses/>.
32#ifdef HAVE_SYS_TYPES_H
36#ifdef HAVE_SYS_RESOURCE_H
37#include <sys/resource.h>
58#include "ov-complex.h"
59#include "ov-flt-complex.h"
61#include "ov-flt-cx-mat.h"
62#include "ov-cx-sparse.h"
70#if ! defined (HAVE_HYPOTF) && defined (HAVE__HYPOTF)
77 octave_value retval; \
79 int nargin = args.length (); \
81 if (nargin == 1 || nargin == 2) \
83 int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
88 retval = args(0).FCN (dim); \
90 error (#FCN ": invalid dimension argument = %d", dim + 1); \
93 error (#FCN ": expecting dimension argument to be an integer"); \
102@deftypefn {Built-in Function} {} all (@var{x}, @var{dim})\n\
103The function @code{all} behaves like the function @code{any}, except\n\
104that it returns true only if all the elements of a vector, or all the\n\
105elements along dimension @var{dim} of a matrix, are nonzero.\n\
116%! assert((all (all (rand (3) + 1) == [1, 1, 1]) == 1
117%! && all (all (x) == [0, 1, 1]) == 1
118%! && all (x, 1) == [0, 1, 1]
119%! && all (x, 2) == [0; 1; 1]));
122%! x = ones (3, 'single');
124%! assert((all (all (single (rand (3) + 1)) == [1, 1, 1]) == 1
125%! && all (all (x) == [0, 1, 1]) == 1
126%! && all (x, 1) == [0, 1, 1]
127%! && all (x, 2) == [0; 1; 1]));
129%!error <Invalid call to all.*> all ();
130%!error <Invalid call to all.*> all (1, 2, 3);
136@deftypefn {Built-in Function} {} any (@var{x}, @var{dim})\n\
137For a vector argument, return 1 if any element of the vector is\n\
140For a matrix argument, return a row vector of ones and\n\
141zeros with each element indicating whether any of the elements of the\n\
142corresponding column of the matrix are nonzero. For example,\n\
147 @result{} [ 1, 1, 0, 0 ]\n\
151If the optional argument @var{dim} is supplied, work along dimension\n\
152@var{dim}. For example,\n\
156any (eye (2, 4), 2)\n\
157 @result{} [ 1; 1 ]\n\
170%! assert((all (any (x) == [0, 0, 1]) == 1
171%! && all (any (ones (3)) == [1, 1, 1]) == 1
172%! && any (x, 1) == [0, 0, 1]
173%! && any (x, 2) == [0; 0; 1]));
176%! x = zeros (3,'single');
178%! assert((all (any (x) == [0, 0, 1]) == 1
179%! && all (any (ones (3, 'single')) == [1, 1, 1]) == 1
180%! && any (x, 1) == [0, 0, 1]
181%! && any (x, 2) == [0; 0; 1]));
183%!error <Invalid call to any.*> any ();
184%!error <Invalid call to any.*> any (1, 2, 3);
188// These mapping functions may also be useful in other places, eh?
190typedef double (*d_dd_fcn) (double, double);
191typedef float (*f_ff_fcn) (float, float);
194map_d_m (d_dd_fcn f, double x, const NDArray& y)
196 NDArray retval (y.dims ());
197 double *r_data = retval.fortran_vec ();
199 const double *y_data = y.data ();
201 octave_idx_type nel = y.numel ();
203 for (octave_idx_type i = 0; i < nel; i++)
206 r_data[i] = f (x, y_data[i]);
213map_f_fm (f_ff_fcn f, float x, const FloatNDArray& y)
215 FloatNDArray retval (y.dims ());
216 float *r_data = retval.fortran_vec ();
218 const float *y_data = y.data ();
220 octave_idx_type nel = y.numel ();
222 for (octave_idx_type i = 0; i < nel; i++)
225 r_data[i] = f (x, y_data[i]);
232map_m_d (d_dd_fcn f, const NDArray& x, double y)
234 NDArray retval (x.dims ());
235 double *r_data = retval.fortran_vec ();
237 const double *x_data = x.data ();
239 octave_idx_type nel = x.numel ();
241 for (octave_idx_type i = 0; i < nel; i++)
244 r_data[i] = f (x_data[i], y);
251map_fm_f (f_ff_fcn f, const FloatNDArray& x, float y)
253 FloatNDArray retval (x.dims ());
254 float *r_data = retval.fortran_vec ();
256 const float *x_data = x.data ();
258 octave_idx_type nel = x.numel ();
260 for (octave_idx_type i = 0; i < nel; i++)
263 r_data[i] = f (x_data[i], y);
270map_m_m (d_dd_fcn f, const NDArray& x, const NDArray& y)
272 assert (x.dims () == y.dims ());
274 NDArray retval (x.dims ());
275 double *r_data = retval.fortran_vec ();
277 const double *x_data = x.data ();
278 const double *y_data = y.data ();
280 octave_idx_type nel = x.numel ();
282 for (octave_idx_type i = 0; i < nel; i++)
285 r_data[i] = f (x_data[i], y_data[i]);
292map_fm_fm (f_ff_fcn f, const FloatNDArray& x, const FloatNDArray& y)
294 assert (x.dims () == y.dims ());
296 FloatNDArray retval (x.dims ());
297 float *r_data = retval.fortran_vec ();
299 const float *x_data = x.data ();
300 const float *y_data = y.data ();
302 octave_idx_type nel = x.numel ();
304 for (octave_idx_type i = 0; i < nel; i++)
307 r_data[i] = f (x_data[i], y_data[i]);
314map_d_s (d_dd_fcn f, double x, const SparseMatrix& y)
316 octave_idx_type nr = y.rows ();
317 octave_idx_type nc = y.columns ();
319 double f_zero = f (x, 0.);
323 retval = SparseMatrix (nr, nc, f_zero);
325 for (octave_idx_type j = 0; j < nc; j++)
326 for (octave_idx_type i = y.cidx (j); i < y.cidx (j+1); i++)
329 retval.data (y.ridx(i) + j * nr) = f (x, y.data (i));
332 retval.maybe_compress (true);
336 octave_idx_type nz = y.nnz ();
337 retval = SparseMatrix (nr, nc, nz);
338 octave_idx_type ii = 0;
339 retval.cidx (ii) = 0;
341 for (octave_idx_type j = 0; j < nc; j++)
343 for (octave_idx_type i = y.cidx (j); i < y.cidx (j+1); i++)
346 double val = f (x, y.data (i));
350 retval.data (ii) = val;
351 retval.ridx (ii++) = y.ridx (i);
354 retval.cidx (j + 1) = ii;
357 retval.maybe_compress (false);
364map_s_d (d_dd_fcn f, const SparseMatrix& x, double y)
366 octave_idx_type nr = x.rows ();
367 octave_idx_type nc = x.columns ();
369 double f_zero = f (0., y);
373 retval = SparseMatrix (nr, nc, f_zero);
375 for (octave_idx_type j = 0; j < nc; j++)
376 for (octave_idx_type i = x.cidx (j); i < x.cidx (j+1); i++)
379 retval.data (x.ridx(i) + j * nr) = f (x.data (i), y);
382 retval.maybe_compress (true);
386 octave_idx_type nz = x.nnz ();
387 retval = SparseMatrix (nr, nc, nz);
388 octave_idx_type ii = 0;
389 retval.cidx (ii) = 0;
391 for (octave_idx_type j = 0; j < nc; j++)
393 for (octave_idx_type i = x.cidx (j); i < x.cidx (j+1); i++)
396 double val = f (x.data (i), y);
400 retval.data (ii) = val;
401 retval.ridx (ii++) = x.ridx (i);
404 retval.cidx (j + 1) = ii;
407 retval.maybe_compress (false);
414map_s_s (d_dd_fcn f, const SparseMatrix& x, const SparseMatrix& y)
416 octave_idx_type nr = x.rows ();
417 octave_idx_type nc = x.columns ();
419 octave_idx_type y_nr = y.rows ();
420 octave_idx_type y_nc = y.columns ();
422 assert (nr == y_nr && nc == y_nc);
425 double f_zero = f (0., 0.);
429 retval = SparseMatrix (nr, nc, f_zero);
430 octave_idx_type k1 = 0, k2 = 0;
432 for (octave_idx_type j = 0; j < nc; j++)
434 while (k1 < x.cidx(j+1) && k2 < y.cidx(j+1))
437 if (k1 >= x.cidx(j+1))
439 retval.data (y.ridx(k2) + j * nr) = f (0.0, y.data (k2));
442 else if (k2 >= y.cidx(j+1))
444 retval.data (x.ridx(k1) + j * nr) = f (x.data (k1), 0.0);
449 octave_idx_type rx = x.ridx(k1);
450 octave_idx_type ry = y.ridx(k2);
454 retval.data (rx + j * nr) = f (x.data (k1), 0.0);
459 retval.data (ry + j * nr) = f (0.0, y.data (k2));
464 retval.data (ry + j * nr) = f (x.data (k1), y.data (k2));
472 retval.maybe_compress (true);
476 octave_idx_type nz = x.nnz () + y.nnz ();
477 retval = SparseMatrix (nr, nc, nz);
478 octave_idx_type ii = 0;
479 retval.cidx (ii) = 0;
480 octave_idx_type k1 = 0, k2 = 0;
482 for (octave_idx_type j = 0; j < nc; j++)
484 while (k1 < x.cidx(j+1) && k2 < y.cidx(j+1))
489 if (k1 >= x.cidx(j+1))
492 val = f (0.0, y.data (k2++));
494 else if (k2 >= y.cidx(j+1))
497 val = f (x.data (k1++), 0.0);
501 octave_idx_type rx = x.ridx(k1);
502 octave_idx_type ry = y.ridx(k2);
507 val = f (x.data (k1++), 0.0);
512 val = f (0.0, y.data (k2++));
517 val = f (x.data (k1++), y.data (k2++));
522 retval.data (ii) = val;
523 retval.ridx (ii++) = r;
526 retval.cidx (j + 1) = ii;
529 retval.maybe_compress (false);
537@deftypefn {Mapping Function} {} atan2 (@var{y}, @var{x})\n\
538Compute atan (@var{y} / @var{x}) for corresponding elements of @var{y}\n\
539and @var{x}. Signal an error if @var{y} and @var{x} do not match in size\n\
545 int nargin = args.length ();
547 if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
549 if (args(0).is_integer_type () || args(1).is_integer_type ())
550 error ("atan2: not defined for integer types");
553 octave_value arg_y = args(0);
554 octave_value arg_x = args(1);
556 dim_vector y_dims = arg_y.dims ();
557 dim_vector x_dims = arg_x.dims ();
559 bool y_is_scalar = y_dims.all_ones ();
560 bool x_is_scalar = x_dims.all_ones ();
562 bool is_float = arg_y.is_single_type () || arg_x.is_single_type ();
564 if (y_is_scalar && x_is_scalar)
568 float y = arg_y.float_value ();
572 float x = arg_x.float_value ();
575 retval = atan2f (y, x);
580 double y = arg_y.double_value ();
584 double x = arg_x.double_value ();
587 retval = atan2 (y, x);
591 else if (y_is_scalar)
595 float y = arg_y.float_value ();
599 // Even if x is sparse return a full matrix here
600 FloatNDArray x = arg_x.float_array_value ();
603 retval = map_f_fm (atan2f, y, x);
608 double y = arg_y.double_value ();
612 // Even if x is sparse return a full matrix here
613 NDArray x = arg_x.array_value ();
616 retval = map_d_m (atan2, y, x);
620 else if (x_is_scalar)
622 if (arg_y.is_sparse_type ())
624 SparseMatrix y = arg_y.sparse_matrix_value ();
628 double x = arg_x.double_value ();
631 retval = map_s_d (atan2, y, x);
636 FloatNDArray y = arg_y.float_array_value ();
640 float x = arg_x.float_value ();
643 retval = map_fm_f (atan2f, y, x);
648 NDArray y = arg_y.array_value ();
652 double x = arg_x.double_value ();
655 retval = map_m_d (atan2, y, x);
659 else if (y_dims == x_dims)
661 // Even if y is sparse return a full matrix here
662 if (arg_x.is_sparse_type ())
664 SparseMatrix y = arg_y.sparse_matrix_value ();
668 SparseMatrix x = arg_x.sparse_matrix_value ();
671 retval = map_s_s (atan2, y, x);
676 FloatNDArray y = arg_y.array_value ();
680 FloatNDArray x = arg_x.array_value ();
683 retval = map_fm_fm (atan2f, y, x);
688 NDArray y = arg_y.array_value ();
692 NDArray x = arg_x.array_value ();
695 retval = map_m_m (atan2, y, x);
700 error ("atan2: nonconformant matrices");
710%!assert (size (atan2 (zeros (0, 2), zeros (0, 2))), [0, 2])
711%!assert (size (atan2 (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
712%!assert (size (atan2 (rand (2, 3, 4), 1)), [2, 3, 4])
713%!assert (size (atan2 (1, rand (2, 3, 4))), [2, 3, 4])
714%!assert (size (atan2 (1, 2)), [1, 1])
719%! v = [0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0];
720%! y = [0, rt3, 1, rt3, -rt3, -1, -rt3, 0];
721%! x = [1, 3, 1, 1, 1, 1, 3, 1];
722%! assert(atan2 (y, x), v, sqrt (eps));
727%! v = single([0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0]);
728%! y = single([0, rt3, 1, rt3, -rt3, -1, -rt3, 0]);
729%! x = single([1, 3, 1, 1, 1, 1, 3, 1]);
730%! assert(atan2 (y, x), v, sqrt (eps('single')));
732%!error <Invalid call to atan2.*> atan2 ();
733%!error <Invalid call to atan2.*> atan2 (1, 2, 3);
741@deftypefn {Built-in Function} {} hypot (@var{x}, @var{y})\n\
742Compute the element-by-element square root of the sum of the squares of\n\
743@var{x} and @var{y}. This is equivalent to\n\
744@code{sqrt (@var{x}.^2 + @var{y}.^2)}, but calculated in a manner that\n\
745avoids overflows for large values of @var{x} or @var{y}.\n\
750 int nargin = args.length ();
752 if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
754 if (args(0).is_integer_type () || args(1).is_integer_type ())
755 error ("hypot: not defined for integer types");
758 octave_value arg_x = args(0);
759 octave_value arg_y = args(1);
761 dim_vector x_dims = arg_x.dims ();
762 dim_vector y_dims = arg_y.dims ();
764 bool x_is_scalar = x_dims.all_ones ();
765 bool y_is_scalar = y_dims.all_ones ();
767 bool is_float = arg_y.is_single_type () || arg_x.is_single_type ();
769 if (y_is_scalar && x_is_scalar)
774 if (arg_x.is_complex_type ())
775 x = abs (arg_x.float_complex_value ());
777 x = arg_x.float_value ();
782 if (arg_y.is_complex_type ())
783 y = abs (arg_y.float_complex_value ());
785 y = arg_y.float_value ();
788 retval = hypotf (x, y);
794 if (arg_x.is_complex_type ())
795 x = abs (arg_x.complex_value ());
797 x = arg_x.double_value ();
802 if (arg_y.is_complex_type ())
803 y = abs (arg_y.complex_value ());
805 y = arg_y.double_value ();
808 retval = hypot (x, y);
812 else if (y_is_scalar)
817 if (arg_x.is_complex_type ())
818 x = arg_x.float_complex_array_value ().abs ();
820 x = arg_x.float_array_value ();
825 if (arg_y.is_complex_type ())
826 y = abs (arg_y.float_complex_value ());
828 y = arg_y.float_value ();
831 retval = map_fm_f (hypotf, x, y);
837 if (arg_x.is_complex_type ())
838 x = arg_x.complex_array_value ().abs ();
840 x = arg_x.array_value ();
845 if (arg_y.is_complex_type ())
846 y = abs (arg_y.complex_value ());
848 y = arg_y.double_value ();
851 retval = map_m_d (hypot, x, y);
855 else if (x_is_scalar)
860 if (arg_x.is_complex_type ())
861 x = abs (arg_x.float_complex_value ());
863 x = arg_x.float_value ();
868 if (arg_y.is_complex_type ())
869 y = arg_y.float_complex_array_value ().abs ();
871 y = arg_y.float_array_value ();
874 retval = map_f_fm (hypotf, x, y);
880 if (arg_x.is_complex_type ())
881 x = abs (arg_x.complex_value ());
883 x = arg_x.double_value ();
888 if (arg_y.is_complex_type ())
889 y = arg_y.complex_array_value ().abs ();
891 y = arg_y.array_value ();
894 retval = map_d_m (hypot, x, y);
898 else if (y_dims == x_dims)
900 if (arg_x.is_sparse_type () && arg_y.is_sparse_type ())
903 if (arg_x.is_complex_type ())
904 x = arg_x.sparse_complex_matrix_value ().abs ();
906 x = arg_x.sparse_matrix_value ();
911 if (arg_y.is_complex_type ())
912 y = arg_y.sparse_complex_matrix_value ().abs ();
914 y = arg_y.sparse_matrix_value ();
917 retval = map_s_s (hypot, x, y);
923 if (arg_x.is_complex_type ())
924 x = arg_x.float_complex_array_value ().abs ();
926 x = arg_x.float_array_value ();
931 if (arg_y.is_complex_type ())
932 y = arg_y.float_complex_array_value ().abs ();
934 y = arg_y.float_array_value ();
937 retval = map_fm_fm (hypotf, x, y);
943 if (arg_x.is_complex_type ())
944 x = arg_x.complex_array_value ().abs ();
946 x = arg_x.array_value ();
951 if (arg_y.is_complex_type ())
952 y = arg_y.complex_array_value ().abs ();
954 y = arg_y.array_value ();
957 retval = map_m_m (hypot, x, y);
962 error ("hypot: nonconformant matrices");
972%!assert (size (hypot (zeros (0, 2), zeros (0, 2))), [0, 2])
973%!assert (size (hypot (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
974%!assert (size (hypot (rand (2, 3, 4), 1)), [2, 3, 4])
975%!assert (size (hypot (1, rand (2, 3, 4))), [2, 3, 4])
976%!assert (size (hypot (1, 2)), [1, 1])
977%!assert (hypot (1:10, 1:10), sqrt(2) * [1:10], 16*eps)
978%!assert (hypot (single(1:10), single(1:10)), single(sqrt(2) * [1:10]));
981template<typename T, typename ET>
983map_2_xlog2 (const Array<T>& x, Array<T>& f, Array<ET>& e)
985 f = Array<T>(x.dims ());
986 e = Array<ET>(x.dims ());
987 for (octave_idx_type i = 0; i < x.numel (); i++)
990 f.xelem (i) = xlog2 (x(i), exp);
995DEFUN (log2, args, nargout,
997@deftypefn {Mapping Function} {} log2 (@var{x})\n\
998@deftypefnx {Mapping Function} {[@var{f}, @var{e}] =} log2 (@var{x})\n\
999Compute the base-2 logarithm of each element of @var{x}.\n\
1001If called with two output arguments, split @var{x} into\n\
1002binary mantissa and exponent so that\n\
1004${1 \\over 2} \\le \\left| f \\right| < 1$\n\
1007@code{1/2 <= abs(f) < 1}\n\
1009and @var{e} is an integer. If\n\
1011$x = 0$, $f = e = 0$.\n\
1014@code{x = 0}, @code{f = e = 0}.\n\
1016@seealso{pow2, log, log10, exp}\n\
1019 octave_value_list retval;
1021 if (args.length () == 1)
1024 retval(0) = args(0).log2 ();
1025 else if (args(0).is_single_type ())
1027 if (args(0).is_real_type ())
1030 FloatNDArray x = args(0).float_array_value ();
1031 // FIXME -- should E be an int value?
1033 map_2_xlog2 (x, f, e);
1037 else if (args(0).is_complex_type ())
1039 FloatComplexNDArray f;
1040 FloatComplexNDArray x = args(0).float_complex_array_value ();
1041 // FIXME -- should E be an int value?
1043 map_2_xlog2 (x, f, e);
1048 else if (args(0).is_real_type ())
1051 NDArray x = args(0).array_value ();
1052 // FIXME -- should E be an int value?
1054 map_2_xlog2 (x, f, e);
1058 else if (args(0).is_complex_type ())
1061 ComplexNDArray x = args(0).complex_array_value ();
1062 // FIXME -- should E be an int value?
1064 map_2_xlog2 (x, f, e);
1069 gripe_wrong_type_arg ("log2", args(0));
1078%!assert(log2 ([1/4, 1/2, 1, 2, 4]), [-2, -1, 0, 1, 2]);
1079%!assert(log2(Inf), Inf);
1080%!assert(isnan(log2(NaN)));
1081%!assert(log2(4*i), 2 + log2(1*i));
1082%!assert(log2(complex(0,Inf)), Inf + log2(i));
1085%! [f, e] = log2 ([0,-1; 2,-4; Inf,-Inf]);
1086%! assert (f, [0,-0.5; 0.5,-0.5; Inf,-Inf]);
1087%! assert (e(1:2,:), [0,1;2,3])
1090%! [f, e] = log2 (complex (zeros (3, 2), [0,-1; 2,-4; Inf,-Inf]));
1091%! assert (f, complex (zeros (3, 2), [0,-0.5; 0.5,-0.5; Inf,-Inf]));
1092%! assert (e(1:2,:), [0,1; 2,3]);
1097@deftypefn {Mapping Function} {} fmod (@var{x}, @var{y})\n\
1098Compute the floating point remainder of dividing @var{x} by @var{y}\n\
1099using the C library function @code{fmod}. The result has the same\n\
1100sign as @var{x}. If @var{y} is zero, the result is implementation-dependent.\n\
1101@seealso{mod, rem}\n\
1104 octave_value retval;
1106 int nargin = args.length ();
1108 if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
1110 octave_value arg_x = args(0);
1111 octave_value arg_y = args(1);
1113 dim_vector y_dims = arg_y.dims ();
1114 dim_vector x_dims = arg_x.dims ();
1116 bool y_is_scalar = y_dims.all_ones ();
1117 bool x_is_scalar = x_dims.all_ones ();
1119 bool is_float = arg_y.is_single_type () || arg_x.is_single_type ();
1121 if (y_is_scalar && x_is_scalar)
1125 float y = arg_y.float_value ();
1129 float x = arg_x.float_value ();
1132 retval = fmod (x, y);
1137 double y = arg_y.double_value ();
1141 double x = arg_x.double_value ();
1144 retval = fmod (x, y);
1148 else if (y_is_scalar)
1152 float y = arg_y.float_value ();
1156 FloatNDArray x = arg_x.float_array_value ();
1159 retval = map_fm_f (fmodf, x, y);
1164 double y = arg_y.double_value ();
1168 if (arg_x.is_sparse_type ())
1170 SparseMatrix x = arg_x.sparse_matrix_value ();
1173 retval = map_s_d (fmod, x, y);
1177 NDArray x = arg_x.array_value ();
1180 retval = map_m_d (fmod, x, y);
1185 else if (x_is_scalar)
1187 if (arg_y.is_sparse_type ())
1189 SparseMatrix y = arg_y.sparse_matrix_value ();
1193 double x = arg_x.double_value ();
1196 retval = map_d_s (fmod, x, y);
1201 FloatNDArray y = arg_y.float_array_value ();
1205 float x = arg_x.float_value ();
1208 retval = map_f_fm (fmodf, x, y);
1213 NDArray y = arg_y.array_value ();
1217 double x = arg_x.double_value ();
1220 retval = map_d_m (fmod, x, y);
1224 else if (y_dims == x_dims)
1226 if (arg_y.is_sparse_type () || arg_x.is_sparse_type ())
1228 SparseMatrix y = arg_y.sparse_matrix_value ();
1232 SparseMatrix x = arg_x.sparse_matrix_value ();
1235 retval = map_s_s (fmod, x, y);
1240 FloatNDArray y = arg_y.float_array_value ();
1244 FloatNDArray x = arg_x.float_array_value ();
1247 retval = map_fm_fm (fmodf, x, y);
1252 NDArray y = arg_y.array_value ();
1256 NDArray x = arg_x.array_value ();
1259 retval = map_m_m (fmod, x, y);
1264 error ("fmod: nonconformant matrices");
1273%!assert (size (fmod (zeros (0, 2), zeros (0, 2))), [0, 2])
1274%!assert (size (fmod (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
1275%!assert (size (fmod (rand (2, 3, 4), 1)), [2, 3, 4])
1276%!assert (size (fmod (1, rand (2, 3, 4))), [2, 3, 4])
1277%!assert (size (fmod (1, 2)), [1, 1])
1280// FIXME Need to convert the reduction functions of this file for single precision
1282#define NATIVE_REDUCTION_1(FCN, TYPE, DIM) \
1283 (arg.is_ ## TYPE ## _type ()) \
1285 TYPE ## NDArray tmp = arg. TYPE ##_array_value (); \
1287 if (! error_state) \
1289 octave_ ## TYPE::clear_conv_flags (); \
1290 retval = tmp.FCN (DIM); \
1291 if (octave_ ## TYPE::get_trunc_flag ()) \
1293 gripe_native_integer_math_truncated (#FCN, \
1294 octave_ ## TYPE::type_name ()); \
1295 octave_ ## TYPE::clear_conv_flags (); \
1300#define NATIVE_REDUCTION(FCN, BOOL_FCN) \
1302 octave_value retval; \
1304 int nargin = args.length (); \
1306 bool isnative = false; \
1307 bool isdouble = false; \
1309 if (nargin > 1 && args(nargin - 1).is_string ()) \
1311 std::string str = args(nargin - 1).string_value (); \
1313 if (! error_state) \
1315 if (str == "native") \
1317 else if (str == "double") \
1320 error ("sum: unrecognized string argument"); \
1325 if (nargin == 1 || nargin == 2) \
1327 octave_value arg = args(0); \
1329 int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
1331 if (! error_state) \
1335 if (arg.is_sparse_type ()) \
1337 if (arg.is_real_type ()) \
1339 SparseMatrix tmp = arg.sparse_matrix_value (); \
1341 if (! error_state) \
1342 retval = tmp.FCN (dim); \
1346 SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \
1348 if (! error_state) \
1349 retval = tmp.FCN (dim); \
1356 if NATIVE_REDUCTION_1 (FCN, uint8, dim) \
1357 else if NATIVE_REDUCTION_1 (FCN, uint16, dim) \
1358 else if NATIVE_REDUCTION_1 (FCN, uint32, dim) \
1359 else if NATIVE_REDUCTION_1 (FCN, uint64, dim) \
1360 else if NATIVE_REDUCTION_1 (FCN, int8, dim) \
1361 else if NATIVE_REDUCTION_1 (FCN, int16, dim) \
1362 else if NATIVE_REDUCTION_1 (FCN, int32, dim) \
1363 else if NATIVE_REDUCTION_1 (FCN, int64, dim) \
1364 else if (arg.is_bool_type ()) \
1366 boolNDArray tmp = arg.bool_array_value (); \
1367 if (! error_state) \
1368 retval = boolNDArray (tmp.BOOL_FCN (dim)); \
1370 else if (arg.is_char_matrix ()) \
1372 error (#FCN, ": invalid char type"); \
1374 else if (!isdouble && arg.is_single_type ()) \
1376 if (arg.is_complex_type ()) \
1378 FloatComplexNDArray tmp = \
1379 arg.float_complex_array_value (); \
1381 if (! error_state) \
1382 retval = tmp.FCN (dim); \
1384 else if (arg.is_real_type ()) \
1386 FloatNDArray tmp = arg.float_array_value (); \
1388 if (! error_state) \
1389 retval = tmp.FCN (dim); \
1392 else if (arg.is_complex_type ()) \
1394 ComplexNDArray tmp = arg.complex_array_value (); \
1396 if (! error_state) \
1397 retval = tmp.FCN (dim); \
1399 else if (arg.is_real_type ()) \
1401 NDArray tmp = arg.array_value (); \
1403 if (! error_state) \
1404 retval = tmp.FCN (dim); \
1408 gripe_wrong_type_arg (#FCN, arg); \
1412 else if (arg.is_bool_type ()) \
1414 boolNDArray tmp = arg.bool_array_value (); \
1415 if (! error_state) \
1416 retval = tmp.FCN (dim); \
1418 else if (!isdouble && arg.is_single_type ()) \
1420 if (arg.is_real_type ()) \
1422 FloatNDArray tmp = arg.float_array_value (); \
1424 if (! error_state) \
1425 retval = tmp.FCN (dim); \
1427 else if (arg.is_complex_type ()) \
1429 FloatComplexNDArray tmp = \
1430 arg.float_complex_array_value (); \
1432 if (! error_state) \
1433 retval = tmp.FCN (dim); \
1436 else if (arg.is_real_type ()) \
1438 NDArray tmp = arg.array_value (); \
1440 if (! error_state) \
1441 retval = tmp.FCN (dim); \
1443 else if (arg.is_complex_type ()) \
1445 ComplexNDArray tmp = arg.complex_array_value (); \
1447 if (! error_state) \
1448 retval = tmp.FCN (dim); \
1452 gripe_wrong_type_arg (#FCN, arg); \
1458 error (#FCN ": invalid dimension argument = %d", dim + 1); \
1467#define DATA_REDUCTION(FCN) \
1469 octave_value retval; \
1471 int nargin = args.length (); \
1473 if (nargin == 1 || nargin == 2) \
1475 octave_value arg = args(0); \
1477 int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
1479 if (! error_state) \
1483 if (arg.is_real_type ()) \
1485 if (arg.is_sparse_type ()) \
1487 SparseMatrix tmp = arg.sparse_matrix_value (); \
1489 if (! error_state) \
1490 retval = tmp.FCN (dim); \
1492 else if (arg.is_single_type ()) \
1494 FloatNDArray tmp = arg.float_array_value (); \
1496 if (! error_state) \
1497 retval = tmp.FCN (dim); \
1501 NDArray tmp = arg.array_value (); \
1503 if (! error_state) \
1504 retval = tmp.FCN (dim); \
1507 else if (arg.is_complex_type ()) \
1509 if (arg.is_sparse_type ()) \
1511 SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \
1513 if (! error_state) \
1514 retval = tmp.FCN (dim); \
1516 else if (arg.is_single_type ()) \
1518 FloatComplexNDArray tmp = arg.float_complex_array_value (); \
1520 if (! error_state) \
1521 retval = tmp.FCN (dim); \
1525 ComplexNDArray tmp = arg.complex_array_value (); \
1527 if (! error_state) \
1528 retval = tmp.FCN (dim); \
1533 gripe_wrong_type_arg (#FCN, arg); \
1538 error (#FCN ": invalid dimension argument = %d", dim + 1); \
1546DEFUN (cumprod, args, ,
1548@deftypefn {Built-in Function} {} cumprod (@var{x})\n\
1549@deftypefnx {Built-in Function} {} cumprod (@var{x}, @var{dim})\n\
1550Cumulative product of elements along dimension @var{dim}. If\n\
1551@var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
1553@seealso{prod, cumsum}\n\
1556 DATA_REDUCTION (cumprod);
1561%!assert (cumprod ([1, 2, 3]), [1, 2, 6]);
1562%!assert (cumprod ([-1; -2; -3]), [-1; 2; -6]);
1563%!assert (cumprod ([i, 2+i, -3+2i, 4]), [i, -1+2i, -1-8i, -4-32i]);
1564%!assert (cumprod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [1, 2, 3; i, 4i, 9i; -1+i, -8+8i, -27+27i]);
1566%!assert (cumprod (single([1, 2, 3])), single([1, 2, 6]));
1567%!assert (cumprod (single([-1; -2; -3])), single([-1; 2; -6]));
1568%!assert (cumprod (single([i, 2+i, -3+2i, 4])), single([i, -1+2i, -1-8i, -4-32i]));
1569%!assert (cumprod (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([1, 2, 3; i, 4i, 9i; -1+i, -8+8i, -27+27i]));
1571%!error <Invalid call to cumprod.*> cumprod ();
1573%!assert (cumprod ([2, 3; 4, 5], 1), [2, 3; 8, 15]);
1574%!assert (cumprod ([2, 3; 4, 5], 2), [2, 6; 4, 20]);
1576%!assert (cumprod (single([2, 3; 4, 5]), 1), single([2, 3; 8, 15]));
1577%!assert (cumprod (single([2, 3; 4, 5]), 2), single([2, 6; 4, 20]));
1581DEFUN (cumsum, args, ,
1583@deftypefn {Built-in Function} {} cumsum (@var{x})\n\
1584@deftypefnx {Built-in Function} {} cumsum (@var{x}, @var{dim})\n\
1585@deftypefnx {Built-in Function} {} cumsum (@dots{}, 'native')\n\
1586Cumulative sum of elements along dimension @var{dim}. If @var{dim}\n\
1587is omitted, it defaults to the first non-singleton dimension.\n\
1589The \"native\" argument implies the summation is performed in native type.\n\
1590 See @code{sum} for a complete description and example of the use of\n\
1592@seealso{sum, cumprod}\n\
1595 octave_value retval;
1597 int nargin = args.length ();
1599 bool isnative = false;
1600 bool isdouble = false;
1602 if (nargin > 1 && args(nargin - 1).is_string ())
1604 std::string str = args(nargin - 1).string_value ();
1608 if (str == "native")
1610 else if (str == "double")
1613 error ("sum: unrecognized string argument");
1621 if (nargin == 1 || nargin == 2)
1623 octave_value arg = args(0);
1628 dim = args(1).int_value () - 1;
1630 error ("cumsum: invalid dimension argument = %d", dim + 1);
1635 switch (arg.builtin_type ())
1638 if (arg.is_sparse_type ())
1639 retval = arg.sparse_matrix_value ().cumsum (dim);
1641 retval = arg.array_value ().cumsum (dim);
1644 if (arg.is_sparse_type ())
1645 retval = arg.sparse_complex_matrix_value ().cumsum (dim);
1647 retval = arg.complex_array_value ().cumsum (dim);
1651 retval = arg.array_value ().cumsum (dim);
1653 retval = arg.float_array_value ().cumsum (dim);
1655 case btyp_float_complex:
1657 retval = arg.complex_array_value ().cumsum (dim);
1659 retval = arg.float_complex_array_value ().cumsum (dim);
1662#define MAKE_INT_BRANCH(X) \
1665 retval = arg.X ## _array_value ().cumsum (dim); \
1667 retval = arg.array_value ().cumsum (dim); \
1669 MAKE_INT_BRANCH (int8);
1670 MAKE_INT_BRANCH (int16);
1671 MAKE_INT_BRANCH (int32);
1672 MAKE_INT_BRANCH (int64);
1673 MAKE_INT_BRANCH (uint8);
1674 MAKE_INT_BRANCH (uint16);
1675 MAKE_INT_BRANCH (uint32);
1676 MAKE_INT_BRANCH (uint64);
1677#undef MAKE_INT_BRANCH
1680 if (arg.is_sparse_type ())
1682 SparseMatrix cs = arg.sparse_matrix_value ().cumsum (dim);
1690 NDArray cs = arg.bool_array_value ().cumsum (dim);
1699 gripe_wrong_type_arg ("cumsum", arg);
1711%!assert (cumsum ([1, 2, 3]), [1, 3, 6]);
1712%!assert (cumsum ([-1; -2; -3]), [-1; -3; -6]);
1713%!assert (cumsum ([i, 2+i, -3+2i, 4]), [i, 2+2i, -1+4i, 3+4i]);
1714%!assert (cumsum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [1, 2, 3; 1+i, 2+2i, 3+3i; 2+2i, 4+4i, 6+6i]);
1716%!assert (cumsum (single([1, 2, 3])), single([1, 3, 6]));
1717%!assert (cumsum (single([-1; -2; -3])), single([-1; -3; -6]));
1718%!assert (cumsum (single([i, 2+i, -3+2i, 4])), single([i, 2+2i, -1+4i, 3+4i]));
1719%!assert (cumsum (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([1, 2, 3; 1+i, 2+2i, 3+3i; 2+2i, 4+4i, 6+6i]));
1721%!error <Invalid call to cumsum.*> cumsum ();
1723%!assert (cumsum ([1, 2; 3, 4], 1), [1, 2; 4, 6]);
1724%!assert (cumsum ([1, 2; 3, 4], 2), [1, 3; 3, 7]);
1726%!assert (cumsum (single([1, 2; 3, 4]), 1), single([1, 2; 4, 6]));
1727%!assert (cumsum (single([1, 2; 3, 4]), 2), single([1, 3; 3, 7]));
1733@deftypefn {Built-in Function} {} diag (@var{v}, @var{k})\n\
1734Return a diagonal matrix with vector @var{v} on diagonal @var{k}. The\n\
1735second argument is optional. If it is positive, the vector is placed on\n\
1736the @var{k}-th super-diagonal. If it is negative, it is placed on the\n\
1737@var{-k}-th sub-diagonal. The default value of @var{k} is 0, and the\n\
1738vector is placed on the main diagonal. For example,\n\
1742diag ([1, 2, 3], 1)\n\
1743 @result{} 0 1 0 0\n\
1751Given a matrix argument, instead of a vector, @code{diag} extracts the\n\
1752@var{k}-th diagonal of the matrix.\n\
1755 octave_value retval;
1757 int nargin = args.length ();
1759 if (nargin == 1 && args(0).is_defined ())
1760 retval = args(0).diag();
1761 else if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
1763 octave_idx_type k = args(1).int_value ();
1766 error ("diag: invalid second argument");
1768 retval = args(0).diag(k);
1770 else if (nargin == 3)
1772 octave_value arg0 = args(0);
1773 if (arg0.ndims () == 2 && (args(0).rows () == 1 || args(0).columns () == 1))
1775 octave_idx_type m = args(1).int_value (), n = args(2).int_value ();
1777 retval = arg0.diag ().resize (dim_vector (m, n));
1779 error ("diag: invalid dimensions");
1782 error ("diag: first argument must be a vector");
1792%!assert(full (diag ([1; 2; 3])), [1, 0, 0; 0, 2, 0; 0, 0, 3]);
1793%!assert(diag ([1; 2; 3], 1), [0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]);
1794%!assert(diag ([1; 2; 3], 2), [0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]);
1795%!assert(diag ([1; 2; 3],-1), [0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]);
1796%!assert(diag ([1; 2; 3],-2), [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0]);
1798%!assert(diag ([1, 0, 0; 0, 2, 0; 0, 0, 3]), [1; 2; 3]);
1799%!assert(diag ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0], 1), [1; 2; 3]);
1800%!assert(diag ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0], -1), [1; 2; 3]);
1802%!assert(full (diag (single([1; 2; 3]))), single([1, 0, 0; 0, 2, 0; 0, 0, 3]));
1803%!assert(diag (single([1; 2; 3]), 1), single([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]));
1804%!assert(diag (single([1; 2; 3]), 2), single([0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]));
1805%!assert(diag (single([1; 2; 3]),-1), single([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]));
1806%!assert(diag (single([1; 2; 3]),-2), single([0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0]));
1808%!assert(diag (single([1, 0, 0; 0, 2, 0; 0, 0, 3])), single([1; 2; 3]));
1809%!assert(diag (single([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), single([1; 2; 3]));
1810%!assert(diag (single([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), single([1; 2; 3]));
1812%!assert(diag (int8([1; 2; 3])), int8([1, 0, 0; 0, 2, 0; 0, 0, 3]));
1813%!assert(diag (int8([1; 2; 3]), 1), int8([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]));
1814%!assert(diag (int8([1; 2; 3]), 2), int8([0, 0, 1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 3; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0]));
1815%!assert(diag (int8([1; 2; 3]),-1), int8([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]));
1816%!assert(diag (int8([1; 2; 3]),-2), int8([0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0; 0, 2, 0, 0, 0; 0, 0, 3, 0, 0]));
1818%!assert(diag (int8([1, 0, 0; 0, 2, 0; 0, 0, 3])), int8([1; 2; 3]));
1819%!assert(diag (int8([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), int8([1; 2; 3]));
1820%!assert(diag (int8([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), int8([1; 2; 3]));
1822%!error <Invalid call to diag.*> diag ();
1828@deftypefn {Built-in Function} {} prod (@var{x})\n\
1829@deftypefnx {Built-in Function} {} prod (@var{x}, @var{dim})\n\
1830Product of elements along dimension @var{dim}. If @var{dim} is\n\
1831omitted, it defaults to the first non-singleton dimension.\n\
1832@seealso{cumprod, sum}\n\
1835 DATA_REDUCTION (prod);
1840%!assert (prod ([1, 2, 3]), 6);
1841%!assert (prod ([-1; -2; -3]), -6);
1842%!assert (prod ([i, 2+i, -3+2i, 4]), -4 - 32i);
1843%!assert (prod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [-1+i, -8+8i, -27+27i]);
1845%!assert (prod (single([1, 2, 3])), single(6));
1846%!assert (prod (single([-1; -2; -3])), single(-6));
1847%!assert (prod (single([i, 2+i, -3+2i, 4])), single(-4 - 32i));
1848%!assert (prod (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([-1+i, -8+8i, -27+27i]));
1850%!error <Invalid call to prod.*> prod ();
1852%!assert (prod ([1, 2; 3, 4], 1), [3, 8]);
1853%!assert (prod ([1, 2; 3, 4], 2), [2; 12]);
1854%!assert (prod (zeros (1, 0)), 1);
1855%!assert (prod (zeros (1, 0), 1), zeros (1, 0));
1856%!assert (prod (zeros (1, 0), 2), 1);
1857%!assert (prod (zeros (0, 1)), 1);
1858%!assert (prod (zeros (0, 1), 1), 1);
1859%!assert (prod (zeros (0, 1), 2), zeros (0, 1));
1860%!assert (prod (zeros (2, 0)), zeros (1, 0));
1861%!assert (prod (zeros (2, 0), 1), zeros (1, 0));
1862%!assert (prod (zeros (2, 0), 2), [1; 1]);
1863%!assert (prod (zeros (0, 2)), [1, 1]);
1864%!assert (prod (zeros (0, 2), 1), [1, 1]);
1865%!assert (prod (zeros (0, 2), 2), zeros(0, 1));
1867%!assert (prod (single([1, 2; 3, 4]), 1), single([3, 8]));
1868%!assert (prod (single([1, 2; 3, 4]), 2), single([2; 12]));
1869%!assert (prod (zeros (1, 0, 'single')), single(1));
1870%!assert (prod (zeros (1, 0, 'single'), 1), zeros (1, 0, 'single'));
1871%!assert (prod (zeros (1, 0, 'single'), 2), single(1));
1872%!assert (prod (zeros (0, 1, 'single')), single(1));
1873%!assert (prod (zeros (0, 1, 'single'), 1), single(1));
1874%!assert (prod (zeros (0, 1, 'single'), 2), zeros (0, 1, 'single'));
1875%!assert (prod (zeros (2, 0, 'single')), zeros (1, 0, 'single'));
1876%!assert (prod (zeros (2, 0, 'single'), 1), zeros (1, 0, 'single'));
1877%!assert (prod (zeros (2, 0, 'single'), 2), single([1; 1]));
1878%!assert (prod (zeros (0, 2, 'single')), single([1, 1]));
1879%!assert (prod (zeros (0, 2, 'single'), 1), single([1, 1]));
1880%!assert (prod (zeros (0, 2, 'single'), 2), zeros(0, 1, 'single'));
1884#define SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR) \
1887 int dv_len = dv.length (); \
1888 Array<octave_idx_type> ra_idx (dv_len > 1 ? dv_len : 2, 0); \
1890 for (int j = 1; j < n_args; j++) \
1894 TYPE ra = args(j).EXTRACTOR (); \
1896 if (! error_state) \
1898 result.insert (ra, ra_idx); \
1903 dim_vector dv_tmp = args (j).dims (); \
1905 if (dim >= dv_len) \
1908 error ("%s: indexing error", fname.c_str ()); \
1912 ra_idx (dim) += (dim < dv_tmp.length () ? dv_tmp (dim) : 1); \
1918#define DO_SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR) \
1923 SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR); \
1930do_cat (const octave_value_list& args, std::string fname)
1932 octave_value retval;
1934 int n_args = args.length ();
1938 else if (n_args == 2)
1940 else if (n_args > 2)
1942 octave_idx_type dim = args(0).int_value () - 1;
1946 error ("cat: expecting first argument to be a integer");
1953 dim_vector dv = args(1).dims ();
1954 std::string result_type = args(1).class_name ();
1956 bool all_sq_strings_p = args(1).is_sq_string ();
1957 bool all_dq_strings_p = args(1).is_dq_string ();
1958 bool all_real_p = args(1).is_real_type ();
1959 bool any_sparse_p = args(1).is_sparse_type();
1961 for (int i = 2; i < args.length (); i++)
1963 // add_dims constructs a dimension vector which holds the
1964 // dimensions of the final array after concatenation.
1966 if (! dv.concat (args(i).dims (), dim))
1968 // Dimensions do not match.
1969 error ("cat: dimension mismatch");
1974 get_concat_class (result_type, args(i).class_name ());
1976 if (all_sq_strings_p && ! args(i).is_sq_string ())
1977 all_sq_strings_p = false;
1978 if (all_dq_strings_p && ! args(i).is_dq_string ())
1979 all_dq_strings_p = false;
1980 if (all_real_p && ! args(i).is_real_type ())
1982 if (!any_sparse_p && args(i).is_sparse_type ())
1983 any_sparse_p = true;
1986 if (result_type == "double")
1991 DO_SINGLE_TYPE_CONCAT (SparseMatrix, sparse_matrix_value);
1993 DO_SINGLE_TYPE_CONCAT (SparseComplexMatrix, sparse_complex_matrix_value);
1998 DO_SINGLE_TYPE_CONCAT (NDArray, array_value);
2000 DO_SINGLE_TYPE_CONCAT (ComplexNDArray, complex_array_value);
2003 else if (result_type == "single")
2006 DO_SINGLE_TYPE_CONCAT (FloatNDArray, float_array_value);
2008 DO_SINGLE_TYPE_CONCAT (FloatComplexNDArray,
2009 float_complex_array_value);
2011 else if (result_type == "char")
2013 char type = all_dq_strings_p ? '"' : '\'';
2015 maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
2017 charNDArray result (dv, Vstring_fill_char);
2019 SINGLE_TYPE_CONCAT (charNDArray, char_array_value);
2021 retval = octave_value (result, type);
2023 else if (result_type == "logical")
2026 DO_SINGLE_TYPE_CONCAT (SparseBoolMatrix, sparse_bool_matrix_value);
2028 DO_SINGLE_TYPE_CONCAT (boolNDArray, bool_array_value);
2030 else if (result_type == "int8")
2031 DO_SINGLE_TYPE_CONCAT (int8NDArray, int8_array_value);
2032 else if (result_type == "int16")
2033 DO_SINGLE_TYPE_CONCAT (int16NDArray, int16_array_value);
2034 else if (result_type == "int32")
2035 DO_SINGLE_TYPE_CONCAT (int32NDArray, int32_array_value);
2036 else if (result_type == "int64")
2037 DO_SINGLE_TYPE_CONCAT (int64NDArray, int64_array_value);
2038 else if (result_type == "uint8")
2039 DO_SINGLE_TYPE_CONCAT (uint8NDArray, uint8_array_value);
2040 else if (result_type == "uint16")
2041 DO_SINGLE_TYPE_CONCAT (uint16NDArray, uint16_array_value);
2042 else if (result_type == "uint32")
2043 DO_SINGLE_TYPE_CONCAT (uint32NDArray, uint32_array_value);
2044 else if (result_type == "uint64")
2045 DO_SINGLE_TYPE_CONCAT (uint64NDArray, uint64_array_value);
2048 // The lines below might seem crazy, since we take a copy
2049 // of the first argument, resize it to be empty and then resize
2050 // it to be full. This is done since it means that there is no
2051 // recopying of data, as would happen if we used a single resize.
2052 // It should be noted that resize operation is also significantly
2053 // slower than the do_cat_op function, so it makes sense to have
2054 // an empty matrix and copy all data.
2056 // We might also start with a empty octave_value using
2057 // tmp = octave_value_typeinfo::lookup_type
2058 // (args(1).type_name());
2059 // and then directly resize. However, for some types there might
2060 // be some additional setup needed, and so this should be avoided.
2062 octave_value tmp = args (1);
2063 tmp = tmp.resize (dim_vector (0,0)).resize (dv);
2068 int dv_len = dv.length ();
2069 Array<octave_idx_type> ra_idx (dv_len, 0);
2071 for (int j = 1; j < n_args; j++)
2073 // Can't fast return here to skip empty matrices as something
2074 // like cat(1,[],single([])) must return an empty matrix of
2076 tmp = do_cat_op (tmp, args (j), ra_idx);
2081 dim_vector dv_tmp = args (j).dims ();
2086 error ("%s: indexing error", fname.c_str ());
2090 ra_idx (dim) += (dim < dv_tmp.length () ?
2098 // Reshape, chopping trailing singleton dimensions
2099 dv.chop_trailing_singletons ();
2100 retval = retval.reshape (dv);
2104 error ("%s: invalid dimension argument", fname.c_str ());
2112DEFUN (horzcat, args, ,
2114@deftypefn {Built-in Function} {} horzcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2115Return the horizontal concatenation of N-d array objects, @var{array1},\n\
2116@var{array2}, @dots{}, @var{arrayN} along dimension 2.\n\
2117@seealso{cat, vertcat}\n\
2120 octave_value_list args_tmp = args;
2124 octave_value d (dim);
2126 args_tmp.prepend (d);
2128 return do_cat (args_tmp, "horzcat");
2131DEFUN (vertcat, args, ,
2133@deftypefn {Built-in Function} {} vertcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2134Return the vertical concatenation of N-d array objects, @var{array1},\n\
2135@var{array2}, @dots{}, @var{arrayN} along dimension 1.\n\
2136@seealso{cat, horzcat}\n\
2139 octave_value_list args_tmp = args;
2143 octave_value d (dim);
2145 args_tmp.prepend (d);
2147 return do_cat (args_tmp, "vertcat");
2152@deftypefn {Built-in Function} {} cat (@var{dim}, @var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
2153Return the concatenation of N-d array objects, @var{array1},\n\
2154@var{array2}, @dots{}, @var{arrayN} along dimension @var{dim}.\n\
2168Alternatively, we can concatenate @var{A} and @var{B} along the\n\
2169second dimension the following way:\n\
2177@var{dim} can be larger than the dimensions of the N-d array objects\n\
2178and the result will thus have @var{dim} dimensions as the\n\
2179following example shows:\n\
2182cat (4, ones(2, 2), zeros (2, 2))\n\
2195@seealso{horzcat, vertcat}\n\
2198 return do_cat (args, "cat");
2203%!function ret = testcat (t1, t2, tr, cmplx)
2204%! assert (cat (1, cast ([], t1), cast([], t2)), cast ([], tr));
2206%! assert (cat (1, cast (1, t1), cast (2, t2)), cast ([1; 2], tr));
2207%! assert (cat (1, cast (1, t1), cast ([2; 3], t2)), cast ([1; 2; 3], tr));
2208%! assert (cat (1, cast ([1; 2], t1), cast (3, t2)), cast ([1; 2; 3], tr));
2209%! assert (cat (1, cast ([1; 2], t1), cast ([3; 4], t2)), cast ([1; 2; 3; 4], tr));
2210%! assert (cat (2, cast (1, t1), cast (2, t2)), cast ([1, 2], tr));
2211%! assert (cat (2, cast (1, t1), cast ([2, 3], t2)), cast ([1, 2, 3], tr));
2212%! assert (cat (2, cast ([1, 2], t1), cast (3, t2)), cast ([1, 2, 3], tr));
2213%! assert (cat (2, cast ([1, 2], t1), cast ([3, 4], t2)), cast ([1, 2, 3, 4], tr));
2215%! assert ([cast(1, t1); cast(2, t2)], cast ([1; 2], tr));
2216%! assert ([cast(1, t1); cast([2; 3], t2)], cast ([1; 2; 3], tr));
2217%! assert ([cast([1; 2], t1); cast(3, t2)], cast ([1; 2; 3], tr));
2218%! assert ([cast([1; 2], t1); cast([3; 4], t2)], cast ([1; 2; 3; 4], tr));
2219%! assert ([cast(1, t1), cast(2, t2)], cast ([1, 2], tr));
2220%! assert ([cast(1, t1), cast([2, 3], t2)], cast ([1, 2, 3], tr));
2221%! assert ([cast([1, 2], t1), cast(3, t2)], cast ([1, 2, 3], tr));
2222%! assert ([cast([1, 2], t1), cast([3, 4], t2)], cast ([1, 2, 3, 4], tr));
2224%! if (nargin == 3 || cmplx)
2225%! assert (cat (1, cast (1i, t1), cast (2, t2)), cast ([1i; 2], tr));
2226%! assert (cat (1, cast (1i, t1), cast ([2; 3], t2)), cast ([1i; 2; 3], tr));
2227%! assert (cat (1, cast ([1i; 2], t1), cast (3, t2)), cast ([1i; 2; 3], tr));
2228%! assert (cat (1, cast ([1i; 2], t1), cast ([3; 4], t2)), cast ([1i; 2; 3; 4], tr));
2229%! assert (cat (2, cast (1i, t1), cast (2, t2)), cast ([1i, 2], tr));
2230%! assert (cat (2, cast (1i, t1), cast ([2, 3], t2)), cast ([1i, 2, 3], tr));
2231%! assert (cat (2, cast ([1i, 2], t1), cast (3, t2)), cast ([1i, 2, 3], tr));
2232%! assert (cat (2, cast ([1i, 2], t1), cast ([3, 4], t2)), cast ([1i, 2, 3, 4], tr));
2234%! assert ([cast(1i, t1); cast(2, t2)], cast ([1i; 2], tr));
2235%! assert ([cast(1i, t1); cast([2; 3], t2)], cast ([1i; 2; 3], tr));
2236%! assert ([cast([1i; 2], t1); cast(3, t2)], cast ([1i; 2; 3], tr));
2237%! assert ([cast([1i; 2], t1); cast([3; 4], t2)], cast ([1i; 2; 3; 4], tr));
2238%! assert ([cast(1i, t1), cast(2, t2)], cast ([1i, 2], tr));
2239%! assert ([cast(1i, t1), cast([2, 3], t2)], cast ([1i, 2, 3], tr));
2240%! assert ([cast([1i, 2], t1), cast(3, t2)], cast ([1i, 2, 3], tr));
2241%! assert ([cast([1i, 2], t1), cast([3, 4], t2)], cast ([1i, 2, 3, 4], tr));
2243%! assert (cat (1, cast (1, t1), cast (2i, t2)), cast ([1; 2i], tr));
2244%! assert (cat (1, cast (1, t1), cast ([2i; 3], t2)), cast ([1; 2i; 3], tr));
2245%! assert (cat (1, cast ([1; 2], t1), cast (3i, t2)), cast ([1; 2; 3i], tr));
2246%! assert (cat (1, cast ([1; 2], t1), cast ([3i; 4], t2)), cast ([1; 2; 3i; 4], tr));
2247%! assert (cat (2, cast (1, t1), cast (2i, t2)), cast ([1, 2i], tr));
2248%! assert (cat (2, cast (1, t1), cast ([2i, 3], t2)), cast ([1, 2i, 3], tr));
2249%! assert (cat (2, cast ([1, 2], t1), cast (3i, t2)), cast ([1, 2, 3i], tr));
2250%! assert (cat (2, cast ([1, 2], t1), cast ([3i, 4], t2)), cast ([1, 2, 3i, 4], tr));
2252%! assert ([cast(1, t1); cast(2i, t2)], cast ([1; 2i], tr));
2253%! assert ([cast(1, t1); cast([2i; 3], t2)], cast ([1; 2i; 3], tr));
2254%! assert ([cast([1; 2], t1); cast(3i, t2)], cast ([1; 2; 3i], tr));
2255%! assert ([cast([1; 2], t1); cast([3i; 4], t2)], cast ([1; 2; 3i; 4], tr));
2256%! assert ([cast(1, t1), cast(2i, t2)], cast ([1, 2i], tr));
2257%! assert ([cast(1, t1), cast([2i, 3], t2)], cast ([1, 2i, 3], tr));
2258%! assert ([cast([1, 2], t1), cast(3i, t2)], cast ([1, 2, 3i], tr));
2259%! assert ([cast([1, 2], t1), cast([3i, 4], t2)], cast ([1, 2, 3i, 4], tr));
2261%! assert (cat (1, cast (1i, t1), cast (2i, t2)), cast ([1i; 2i], tr));
2262%! assert (cat (1, cast (1i, t1), cast ([2i; 3], t2)), cast ([1i; 2i; 3], tr));
2263%! assert (cat (1, cast ([1i; 2], t1), cast (3i, t2)), cast ([1i; 2; 3i], tr));
2264%! assert (cat (1, cast ([1i; 2], t1), cast ([3i; 4], t2)), cast ([1i; 2; 3i; 4], tr));
2265%! assert (cat (2, cast (1i, t1), cast (2i, t2)), cast ([1i, 2i], tr));
2266%! assert (cat (2, cast (1i, t1), cast ([2i, 3], t2)), cast ([1i, 2i, 3], tr));
2267%! assert (cat (2, cast ([1i, 2], t1), cast (3i, t2)), cast ([1i, 2, 3i], tr));
2268%! assert (cat (2, cast ([1i, 2], t1), cast ([3i, 4], t2)), cast ([1i, 2, 3i, 4], tr));
2270%! assert ([cast(1i, t1); cast(2i, t2)], cast ([1i; 2i], tr));
2271%! assert ([cast(1i, t1); cast([2i; 3], t2)], cast ([1i; 2i; 3], tr));
2272%! assert ([cast([1i; 2], t1); cast(3i, t2)], cast ([1i; 2; 3i], tr));
2273%! assert ([cast([1i; 2], t1); cast([3i; 4], t2)], cast ([1i; 2; 3i; 4], tr));
2274%! assert ([cast(1i, t1), cast(2i, t2)], cast ([1i, 2i], tr));
2275%! assert ([cast(1i, t1), cast([2i, 3], t2)], cast ([1i, 2i, 3], tr));
2276%! assert ([cast([1i, 2], t1), cast(3i, t2)], cast ([1i, 2, 3i], tr));
2277%! assert ([cast([1i, 2], t1), cast([3i, 4], t2)], cast ([1i, 2, 3i, 4], tr));
2281%!assert (testcat('double', 'double', 'double'));
2282%!assert (testcat('single', 'double', 'single'));
2283%!assert (testcat('double', 'single', 'single'));
2284%!assert (testcat('single', 'single', 'single'));
2286%!assert (testcat('double', 'int8', 'int8', false));
2287%!assert (testcat('int8', 'double', 'int8', false));
2288%!assert (testcat('single', 'int8', 'int8', false));
2289%!assert (testcat('int8', 'single', 'int8', false));
2290%!assert (testcat('int8', 'int8', 'int8', false));
2291%!assert (testcat('double', 'int16', 'int16', false));
2292%!assert (testcat('int16', 'double', 'int16', false));
2293%!assert (testcat('single', 'int16', 'int16', false));
2294%!assert (testcat('int16', 'single', 'int16', false));
2295%!assert (testcat('int16', 'int16', 'int16', false));
2296%!assert (testcat('double', 'int32', 'int32', false));
2297%!assert (testcat('int32', 'double', 'int32', false));
2298%!assert (testcat('single', 'int32', 'int32', false));
2299%!assert (testcat('int32', 'single', 'int32', false));
2300%!assert (testcat('int32', 'int32', 'int32', false));
2301%!assert (testcat('double', 'int64', 'int64', false));
2302%!assert (testcat('int64', 'double', 'int64', false));
2303%!assert (testcat('single', 'int64', 'int64', false));
2304%!assert (testcat('int64', 'single', 'int64', false));
2305%!assert (testcat('int64', 'int64', 'int64', false));
2307%!assert (testcat('double', 'uint8', 'uint8', false));
2308%!assert (testcat('uint8', 'double', 'uint8', false));
2309%!assert (testcat('single', 'uint8', 'uint8', false));
2310%!assert (testcat('uint8', 'single', 'uint8', false));
2311%!assert (testcat('uint8', 'uint8', 'uint8', false));
2312%!assert (testcat('double', 'uint16', 'uint16', false));
2313%!assert (testcat('uint16', 'double', 'uint16', false));
2314%!assert (testcat('single', 'uint16', 'uint16', false));
2315%!assert (testcat('uint16', 'single', 'uint16', false));
2316%!assert (testcat('uint16', 'uint16', 'uint16', false));
2317%!assert (testcat('double', 'uint32', 'uint32', false));
2318%!assert (testcat('uint32', 'double', 'uint32', false));
2319%!assert (testcat('single', 'uint32', 'uint32', false));
2320%!assert (testcat('uint32', 'single', 'uint32', false));
2321%!assert (testcat('uint32', 'uint32', 'uint32', false));
2322%!assert (testcat('double', 'uint64', 'uint64', false));
2323%!assert (testcat('uint64', 'double', 'uint64', false));
2324%!assert (testcat('single', 'uint64', 'uint64', false));
2325%!assert (testcat('uint64', 'single', 'uint64', false));
2326%!assert (testcat('uint64', 'uint64', 'uint64', false));
2331do_permute (const octave_value_list& args, bool inv)
2333 octave_value retval;
2335 if (args.length () == 2 && args(1).length () >= args(1).ndims ())
2337 Array<int> vec = args(1).int_vector_value ();
2339 // FIXME -- maybe we should create an idx_vector object
2340 // here and pass that to permute?
2342 int n = vec.length ();
2344 for (int i = 0; i < n; i++)
2347 octave_value ret = args(0).permute (vec, inv);
2358DEFUN (permute, args, ,
2360@deftypefn {Built-in Function} {} permute (@var{a}, @var{perm})\n\
2361Return the generalized transpose for an N-d array object @var{a}.\n\
2362The permutation vector @var{perm} must contain the elements\n\
2363@code{1:ndims(a)} (in any order, but each element must appear just once).\n\
2364@seealso{ipermute}\n\
2367 return do_permute (args, false);
2370DEFUN (ipermute, args, ,
2372@deftypefn {Built-in Function} {} ipermute (@var{a}, @var{iperm})\n\
2373The inverse of the @code{permute} function. The expression\n\
2376ipermute (permute (a, perm), perm)\n\
2378returns the original array @var{a}.\n\
2382 return do_permute (args, true);
2385DEFUN (length, args, ,
2387@deftypefn {Built-in Function} {} length (@var{a})\n\
2388Return the `length' of the object @var{a}. For matrix objects, the\n\
2389length is the number of rows or columns, whichever is greater (this\n\
2390odd definition is used for compatibility with @sc{matlab}).\n\
2393 octave_value retval;
2395 if (args.length () == 1)
2396 retval = args(0).length ();
2403DEFUN (ndims, args, ,
2405@deftypefn {Built-in Function} {} ndims (@var{a})\n\
2406Returns the number of dimensions of array @var{a}.\n\
2407For any array, the result will always be larger than or equal to 2.\n\
2408Trailing singleton dimensions are not counted.\n\
2411 octave_value retval;
2413 if (args.length () == 1)
2414 retval = args(0).ndims ();
2421DEFUN (numel, args, ,
2423@deftypefn {Built-in Function} {} numel (@var{a})\n\
2424@deftypefnx {Built-in Function} {} numel (@var{a}, @var{idx1}, @var{idx2}, @dots{})\n\
2425Returns the number of elements in the object @var{a}.\n\
2426Optionally, if indices @var{idx1}, @var{idx2}, @dots{} are supplied,\n\
2427return the number of elements that would result from the indexing\n\
2429 @var{a}(@var{idx1}, @var{idx2}, @dots{})\n\
2431This method is also called when an object appears as lvalue with cs-list\n\
2432indexing, i.e., @code{object@{@dots{}@}} or @code{object(@dots{}).field}.\n\
2436 octave_value retval;
2437 octave_idx_type nargin = args.length ();
2440 retval = args(0).numel ();
2441 else if (nargin > 1)
2443 // Don't use numel (const octave_value_list&) here as that corresponds to
2444 // an overloaded call, not to builtin!
2445 retval = dims_to_numel (args(0).dims (), args.slice (1, nargin-1));
2453DEFUN (size, args, nargout,
2455@deftypefn {Built-in Function} {} size (@var{a}, @var{n})\n\
2456Return the number rows and columns of @var{a}.\n\
2458With one input argument and one output argument, the result is returned\n\
2459in a row vector. If there are multiple output arguments, the number of\n\
2460rows is assigned to the first, and the number of columns to the second,\n\
2465size ([1, 2; 3, 4; 5, 6])\n\
2466 @result{} [ 3, 2 ]\n\
2468[nr, nc] = size ([1, 2; 3, 4; 5, 6])\n\
2474If given a second argument, @code{size} will return the size of the\n\
2475corresponding dimension. For example\n\
2479size ([1, 2; 3, 4; 5, 6], 2)\n\
2485returns the number of columns in the given matrix.\n\
2489 octave_value_list retval;
2491 int nargin = args.length ();
2495 const dim_vector dimensions = args(0).dims ();
2499 const dim_vector rdims = dimensions.redim (nargout);
2500 retval.resize (nargout);
2501 for (int i = 0; i < nargout; i++)
2502 retval(i) = rdims(i);
2506 int ndims = dimensions.length ();
2508 NoAlias<Matrix> m (1, ndims);
2510 for (int i = 0; i < ndims; i++)
2511 m(i) = dimensions(i);
2516 else if (nargin == 2 && nargout < 2)
2518 octave_idx_type nd = args(1).int_value (true);
2521 error ("size: expecting scalar as second argument");
2524 const dim_vector dv = args(0).dims ();
2528 if (nd <= dv.length ())
2529 retval(0) = dv(nd-1);
2534 error ("size: requested dimension (= %d) out of range", nd);
2543DEFUN (size_equal, args, ,
2545@deftypefn {Built-in Function} {} size_equal (@var{a}, @var{b}, @dots{})\n\
2546Return true if the dimensions of all arguments agree.\n\
2547Trailing singleton dimensions are ignored.\n\
2548Called with a single argument, size_equal returns true.\n\
2549@seealso{size, numel}\n\
2552 octave_value retval;
2554 int nargin = args.length ();
2560 dim_vector a_dims = args(0).dims ();
2562 for (int i = 1; i < nargin; ++i)
2564 dim_vector b_dims = args(i).dims ();
2566 if (a_dims != b_dims)
2581@deftypefn {Built-in Function} {@var{scalar} =} nnz (@var{a})\n\
2582Returns the number of non zero elements in @var{a}.\n\
2586 octave_value retval;
2588 if (args.length () == 1)
2589 retval = args(0).nnz ();
2596DEFUN (nzmax, args, ,
2598@deftypefn {Built-in Function} {@var{scalar} =} nzmax (@var{SM})\n\
2599Return the amount of storage allocated to the sparse matrix @var{SM}.\n\
2600Note that Octave tends to crop unused memory at the first opportunity\n\
2601for sparse objects. There are some cases of user created sparse objects\n\
2602where the value returned by @dfn{nzmax} will not be the same as @dfn{nnz},\n\
2603but in general they will give the same result.\n\
2604@seealso{sparse, spalloc}\n\
2607 octave_value retval;
2609 if (args.length() == 1)
2610 retval = args(0).nzmax ();
2619@deftypefn {Built-in Function} {} rows (@var{a})\n\
2620Return the number of rows of @var{a}.\n\
2621@seealso{size, numel, columns, length, isscalar, isvector, ismatrix}\n\
2624 octave_value retval;
2626 if (args.length () == 1)
2627 retval = args(0).rows ();
2634DEFUN (columns, args, ,
2636@deftypefn {Built-in Function} {} columns (@var{a})\n\
2637Return the number of columns of @var{a}.\n\
2638@seealso{size, numel, rows, length, isscalar, isvector, ismatrix}\n\
2641 octave_value retval;
2643 if (args.length () == 1)
2644 retval = args(0).columns ();
2653@deftypefn {Built-in Function} {} sum (@var{x})\n\
2654@deftypefnx {Built-in Function} {} sum (@var{x}, @var{dim})\n\
2655@deftypefnx {Built-in Function} {} sum (@dots{}, 'native')\n\
2656@deftypefnx {Built-in Function} {} sum (@dots{}, 'double')\n\
2657@deftypefnx {Built-in Function} {} sum (@dots{}, 'extra')\n\
2658Sum of elements along dimension @var{dim}. If @var{dim} is\n\
2659omitted, it defaults to the first non-singleton dimension.\n\
2661If the optional argument 'native' is given, then the sum is performed\n\
2662in the same type as the original argument, rather than in the default\n\
2663double type. For example\n\
2667sum ([true, true])\n\
2669sum ([true, true], 'native')\n\
2674On the contrary, if 'double' is given, the sum is performed in double precision\n\
2675even for single precision inputs.\n\
2677For double precision inputs, 'extra' indicates that a more accurate algorithm\n\
2678than straightforward summation is to be used. For single precision inputs, 'extra' is\n\
2679the same as 'double'. Otherwise, 'extra' has no effect.\n\
2680@seealso{cumsum, sumsq, prod}\n\
2683 octave_value retval;
2685 int nargin = args.length ();
2687 bool isnative = false;
2688 bool isdouble = false;
2689 bool isextra = false;
2691 if (nargin > 1 && args(nargin - 1).is_string ())
2693 std::string str = args(nargin - 1).string_value ();
2697 if (str == "native")
2699 else if (str == "double")
2701 else if (str == "extra")
2704 error ("sum: unrecognized string argument");
2712 if (nargin == 1 || nargin == 2)
2714 octave_value arg = args(0);
2719 dim = args(1).int_value () - 1;
2721 error ("sum: invalid dimension argument = %d", dim + 1);
2726 switch (arg.builtin_type ())
2729 if (arg.is_sparse_type ())
2732 warning ("sum: 'extra' not yet implemented for sparse matrices");
2733 retval = arg.sparse_matrix_value ().sum (dim);
2736 retval = arg.array_value ().xsum (dim);
2738 retval = arg.array_value ().sum (dim);
2741 if (arg.is_sparse_type ())
2744 warning ("sum: 'extra' not yet implemented for sparse matrices");
2745 retval = arg.sparse_complex_matrix_value ().sum (dim);
2748 retval = arg.complex_array_value ().xsum (dim);
2750 retval = arg.complex_array_value ().sum (dim);
2753 if (isdouble || isextra)
2754 retval = arg.float_array_value ().dsum (dim);
2756 retval = arg.float_array_value ().sum (dim);
2758 case btyp_float_complex:
2759 if (isdouble || isextra)
2760 retval = arg.float_complex_array_value ().dsum (dim);
2762 retval = arg.float_complex_array_value ().sum (dim);
2765#define MAKE_INT_BRANCH(X) \
2768 retval = arg.X ## _array_value ().sum (dim); \
2770 retval = arg.X ## _array_value ().dsum (dim); \
2772 MAKE_INT_BRANCH (int8);
2773 MAKE_INT_BRANCH (int16);
2774 MAKE_INT_BRANCH (int32);
2775 MAKE_INT_BRANCH (int64);
2776 MAKE_INT_BRANCH (uint8);
2777 MAKE_INT_BRANCH (uint16);
2778 MAKE_INT_BRANCH (uint32);
2779 MAKE_INT_BRANCH (uint64);
2780#undef MAKE_INT_BRANCH
2783 if (arg.is_sparse_type ())
2786 retval = arg.sparse_bool_matrix_value ().any (dim);
2788 retval = arg.sparse_matrix_value ().sum (dim);
2791 retval = arg.bool_array_value ().any (dim);
2793 retval = arg.bool_array_value ().sum (dim);
2797 gripe_wrong_type_arg ("sum", arg);
2809%!assert (sum([true,true]), 2)
2810%!assert (sum([true,true],'native'), true)
2811%!assert (sum(int8([127,10,-20])), 117);
2812%!assert (sum(int8([127,10,-20]),'native'), int8(107));
2814%!assert(sum ([1, 2, 3]), 6)
2815%!assert(sum ([-1; -2; -3]), -6);
2816%!assert(sum ([i, 2+i, -3+2i, 4]), 3+4i);
2817%!assert(sum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [2+2i, 4+4i, 6+6i]);
2819%!assert(sum (single([1, 2, 3])), single(6))
2820%!assert(sum (single([-1; -2; -3])), single(-6));
2821%!assert(sum (single([i, 2+i, -3+2i, 4])), single(3+4i));
2822%!assert(sum (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([2+2i, 4+4i, 6+6i]));
2824%!error <Invalid call to sum.*> sum ();
2826%!assert (sum ([1, 2; 3, 4], 1), [4, 6]);
2827%!assert (sum ([1, 2; 3, 4], 2), [3; 7]);
2828%!assert (sum (zeros (1, 0)), 0);
2829%!assert (sum (zeros (1, 0), 1), zeros(1, 0));
2830%!assert (sum (zeros (1, 0), 2), 0);
2831%!assert (sum (zeros (0, 1)), 0);
2832%!assert (sum (zeros (0, 1), 1), 0);
2833%!assert (sum (zeros (0, 1), 2), zeros(0, 1));
2834%!assert (sum (zeros (2, 0)), zeros(1, 0));
2835%!assert (sum (zeros (2, 0), 1), zeros(1, 0));
2836%!assert (sum (zeros (2, 0), 2), [0; 0]);
2837%!assert (sum (zeros (0, 2)), [0, 0]);
2838%!assert (sum (zeros (0, 2), 1), [0, 0]);
2839%!assert (sum (zeros (0, 2), 2), zeros(0, 1));
2840%!assert (sum (zeros (2, 2, 0, 3)), zeros(1, 2, 0, 3));
2841%!assert (sum (zeros (2, 2, 0, 3), 2), zeros(2, 1, 0, 3));
2842%!assert (sum (zeros (2, 2, 0, 3), 3), zeros(2, 2, 1, 3));
2843%!assert (sum (zeros (2, 2, 0, 3), 4), zeros(2, 2, 0));
2844%!assert (sum (zeros (2, 2, 0, 3), 7), zeros(2, 2, 0, 3));
2846%!assert (sum (single([1, 2; 3, 4]), 1), single([4, 6]));
2847%!assert (sum (single([1, 2; 3, 4]), 2), single([3; 7]));
2848%!assert (sum (zeros (1, 0, 'single')), single(0));
2849%!assert (sum (zeros (1, 0, 'single'), 1), zeros(1, 0, 'single'));
2850%!assert (sum (zeros (1, 0, 'single'), 2), single(0));
2851%!assert (sum (zeros (0, 1, 'single')), single(0));
2852%!assert (sum (zeros (0, 1, 'single'), 1), single(0));
2853%!assert (sum (zeros (0, 1, 'single'), 2), zeros(0, 1, 'single'));
2854%!assert (sum (zeros (2, 0, 'single')), zeros(1, 0, 'single'));
2855%!assert (sum (zeros (2, 0, 'single'), 1), zeros(1, 0, 'single'));
2856%!assert (sum (zeros (2, 0, 'single'), 2), single([0; 0]));
2857%!assert (sum (zeros (0, 2, 'single')), single([0, 0]));
2858%!assert (sum (zeros (0, 2, 'single'), 1), single([0, 0]));
2859%!assert (sum (zeros (0, 2, 'single'), 2), zeros(0, 1, 'single'));
2860%!assert (sum (zeros (2, 2, 0, 3, 'single')), zeros(1, 2, 0, 3, 'single'));
2861%!assert (sum (zeros (2, 2, 0, 3, 'single'), 2), zeros(2, 1, 0, 3, 'single'));
2862%!assert (sum (zeros (2, 2, 0, 3, 'single'), 3), zeros(2, 2, 1, 3, 'single'));
2863%!assert (sum (zeros (2, 2, 0, 3, 'single'), 4), zeros(2, 2, 0, 'single'));
2864%!assert (sum (zeros (2, 2, 0, 3, 'single'), 7), zeros(2, 2, 0, 3, 'single'));
2868DEFUN (sumsq, args, ,
2870@deftypefn {Built-in Function} {} sumsq (@var{x})\n\
2871@deftypefnx {Built-in Function} {} sumsq (@var{x}, @var{dim})\n\
2872Sum of squares of elements along dimension @var{dim}. If @var{dim}\n\
2873is omitted, it defaults to the first non-singleton dimension.\n\
2875This function is conceptually equivalent to computing\n\
2877sum (x .* conj (x), dim)\n\
2879but it uses less memory and avoids calling @code{conj} if @var{x} is real.\n\
2883 DATA_REDUCTION (sumsq);
2888%!assert(sumsq ([1, 2, 3]), 14)
2889%!assert(sumsq ([-1; -2; 4i]), 21);
2890%!assert(sumsq ([1, 2, 3; 2, 3, 4; 4i, 6i, 2]), [21, 49, 29]);
2892%!assert(sumsq (single([1, 2, 3])), single(14))
2893%!assert(sumsq (single([-1; -2; 4i])), single(21));
2894%!assert(sumsq (single([1, 2, 3; 2, 3, 4; 4i, 6i, 2])), single([21, 49, 29]));
2896%!error <Invalid call to sumsq.*> sumsq ();
2898%!assert (sumsq ([1, 2; 3, 4], 1), [10, 20]);
2899%!assert (sumsq ([1, 2; 3, 4], 2), [5; 25]);
2901%!assert (sumsq (single([1, 2; 3, 4]), 1), single([10, 20]));
2902%!assert (sumsq (single([1, 2; 3, 4]), 2), single([5; 25]));
2906DEFUN (islogical, args, ,
2908@deftypefn {Built-in Function} {} islogical (@var{x})\n\
2909Return true if @var{x} is a logical object.\n\
2912 octave_value retval;
2914 if (args.length () == 1)
2915 retval = args(0).is_bool_type ();
2922DEFALIAS (isbool, islogical);
2926%!assert (islogical(true), true)
2927%!assert (islogical(false), true)
2928%!assert (islogical([true, false]), true)
2929%!assert (islogical(1), false)
2930%!assert (islogical(1i), false)
2931%!assert (islogical([1,1]), false)
2932%!assert (islogical(single(1)), false)
2933%!assert (islogical(single(1i)), false)
2934%!assert (islogical(single([1,1])), false)
2938DEFUN (isinteger, args, ,
2940@deftypefn {Built-in Function} {} isinteger (@var{x})\n\
2941Return true if @var{x} is an integer object (int8, uint8, int16, etc.).\n\
2942Note that @code{isinteger (14)} is false because numeric constants in\n\
2943Octave are double precision floating point values.\n\
2944@seealso{isreal, isnumeric, class, isa}\n\
2947 octave_value retval;
2949 if (args.length () == 1)
2950 retval = args(0).is_integer_type ();
2957DEFUN (iscomplex, args, ,
2959@deftypefn {Built-in Function} {} iscomplex (@var{x})\n\
2960Return true if @var{x} is a complex-valued numeric object.\n\
2963 octave_value retval;
2965 if (args.length () == 1)
2966 retval = args(0).is_complex_type ();
2973DEFUN (isfloat, args, ,
2975@deftypefn {Built-in Function} {} isfloat (@var{x})\n\
2976Return true if @var{x} is a floating-point numeric object.\n\
2979 octave_value retval;
2981 if (args.length () == 1)
2982 retval = args(0).is_float_type ();
2989// FIXME -- perhaps this should be implemented with an
2990// octave_value member function?
2992DEFUN (complex, args, ,
2994@deftypefn {Built-in Function} {} complex (@var{x})\n\
2995@deftypefnx {Built-in Function} {} complex (@var{re}, @var{im})\n\
2996Return a complex result from real arguments. With 1 real argument @var{x},\n\
2997return the complex result @code{@var{x} + 0i}. With 2 real arguments,\n\
2998return the complex result @code{@var{re} + @var{im}}. @code{complex} can\n\
2999often be more convenient than expressions such as @code{a + i*b}.\n\
3004complex ([1, 2], [3, 4])\n\
3009@seealso{real, imag, iscomplex}\n\
3012 octave_value retval;
3014 int nargin = args.length ();
3018 octave_value arg = args(0);
3020 if (arg.is_complex_type ())
3024 if (arg.is_sparse_type ())
3026 SparseComplexMatrix val = arg.sparse_complex_matrix_value ();
3029 retval = octave_value (new octave_sparse_complex_matrix (val));
3031 else if (arg.is_single_type ())
3033 if (arg.numel () == 1)
3035 FloatComplex val = arg.float_complex_value ();
3038 retval = octave_value (new octave_float_complex (val));
3042 FloatComplexNDArray val = arg.float_complex_array_value ();
3045 retval = octave_value (new octave_float_complex_matrix (val));
3050 if (arg.numel () == 1)
3052 Complex val = arg.complex_value ();
3055 retval = octave_value (new octave_complex (val));
3059 ComplexNDArray val = arg.complex_array_value ();
3062 retval = octave_value (new octave_complex_matrix (val));
3067 error ("complex: invalid conversion");
3070 else if (nargin == 2)
3072 octave_value re = args(0);
3073 octave_value im = args(1);
3075 if (re.is_sparse_type () && im.is_sparse_type ())
3077 const SparseMatrix re_val = re.sparse_matrix_value ();
3078 const SparseMatrix im_val = im.sparse_matrix_value ();
3082 if (re.numel () == 1)
3084 SparseComplexMatrix result;
3085 if (re_val.nnz () == 0)
3086 result = Complex(0, 1) * SparseComplexMatrix (im_val);
3089 result = SparseComplexMatrix (im_val.dims (), re_val (0));
3090 octave_idx_type nr = im_val.rows ();
3091 octave_idx_type nc = im_val.cols ();
3093 for (octave_idx_type j = 0; j < nc; j++)
3095 octave_idx_type off = j * nr;
3096 for (octave_idx_type i = im_val.cidx(j);
3097 i < im_val.cidx(j + 1); i++)
3098 result.data (im_val.ridx(i) + off) =
3099 result.data (im_val.ridx(i) + off) +
3100 Complex (0, im_val.data (i));
3103 retval = octave_value (new octave_sparse_complex_matrix (result));
3105 else if (im.numel () == 1)
3107 SparseComplexMatrix result;
3108 if (im_val.nnz () == 0)
3109 result = SparseComplexMatrix (re_val);
3112 result = SparseComplexMatrix (re_val.rows(), re_val.cols(), Complex(0, im_val (0)));
3113 octave_idx_type nr = re_val.rows ();
3114 octave_idx_type nc = re_val.cols ();
3116 for (octave_idx_type j = 0; j < nc; j++)
3118 octave_idx_type off = j * nr;
3119 for (octave_idx_type i = re_val.cidx(j);
3120 i < re_val.cidx(j + 1); i++)
3121 result.data (re_val.ridx(i) + off) =
3122 result.data (re_val.ridx(i) + off) +
3126 retval = octave_value (new octave_sparse_complex_matrix (result));
3130 if (re_val.dims () == im_val.dims ())
3132 SparseComplexMatrix result = SparseComplexMatrix(re_val)
3133 + Complex(0, 1) * SparseComplexMatrix (im_val);
3134 retval = octave_value (new octave_sparse_complex_matrix (result));
3137 error ("complex: dimension mismatch");
3141 else if (re.is_single_type () || im.is_single_type ())
3143 if (re.numel () == 1)
3145 float re_val = re.float_value ();
3147 if (im.numel () == 1)
3149 float im_val = im.double_value ();
3152 retval = octave_value (new octave_float_complex (FloatComplex (re_val, im_val)));
3156 const FloatNDArray im_val = im.float_array_value ();
3160 FloatComplexNDArray result (im_val.dims (), FloatComplex ());
3162 for (octave_idx_type i = 0; i < im_val.numel (); i++)
3163 result.xelem (i) = FloatComplex (re_val, im_val(i));
3165 retval = octave_value (new octave_float_complex_matrix (result));
3171 const FloatNDArray re_val = re.float_array_value ();
3173 if (im.numel () == 1)
3175 float im_val = im.float_value ();
3179 FloatComplexNDArray result (re_val.dims (), FloatComplex ());
3181 for (octave_idx_type i = 0; i < re_val.numel (); i++)
3182 result.xelem (i) = FloatComplex (re_val(i), im_val);
3184 retval = octave_value (new octave_float_complex_matrix (result));
3189 const FloatNDArray im_val = im.float_array_value ();
3193 if (re_val.dims () == im_val.dims ())
3195 FloatComplexNDArray result (re_val.dims (), FloatComplex ());
3197 for (octave_idx_type i = 0; i < re_val.numel (); i++)
3198 result.xelem (i) = FloatComplex (re_val(i), im_val(i));
3200 retval = octave_value (new octave_float_complex_matrix (result));
3203 error ("complex: dimension mismatch");
3208 else if (re.numel () == 1)
3210 double re_val = re.double_value ();
3212 if (im.numel () == 1)
3214 double im_val = im.double_value ();
3217 retval = octave_value (new octave_complex (Complex (re_val, im_val)));
3221 const NDArray im_val = im.array_value ();
3225 ComplexNDArray result (im_val.dims (), Complex ());
3227 for (octave_idx_type i = 0; i < im_val.numel (); i++)
3228 result.xelem (i) = Complex (re_val, im_val(i));
3230 retval = octave_value (new octave_complex_matrix (result));
3236 const NDArray re_val = re.array_value ();
3238 if (im.numel () == 1)
3240 double im_val = im.double_value ();
3244 ComplexNDArray result (re_val.dims (), Complex ());
3246 for (octave_idx_type i = 0; i < re_val.numel (); i++)
3247 result.xelem (i) = Complex (re_val(i), im_val);
3249 retval = octave_value (new octave_complex_matrix (result));
3254 const NDArray im_val = im.array_value ();
3258 if (re_val.dims () == im_val.dims ())
3260 ComplexNDArray result (re_val.dims (), Complex ());
3262 for (octave_idx_type i = 0; i < re_val.numel (); i++)
3263 result.xelem (i) = Complex (re_val(i), im_val(i));
3265 retval = octave_value (new octave_complex_matrix (result));
3268 error ("complex: dimension mismatch");
3274 error ("complex: invalid conversion");
3282DEFUN (isreal, args, ,
3284@deftypefn {Built-in Function} {} isreal (@var{x})\n\
3285Return true if @var{x} is a real-valued numeric object.\n\
3288 octave_value retval;
3290 if (args.length () == 1)
3291 retval = args(0).is_real_type ();
3298DEFUN (isempty, args, ,
3300@deftypefn {Built-in Function} {} isempty (@var{a})\n\
3301Return 1 if @var{a} is an empty matrix (either the number of rows, or\n\
3302the number of columns, or both are zero). Otherwise, return 0.\n\
3305 octave_value retval = false;
3307 if (args.length () == 1)
3308 retval = args(0).is_empty ();
3315DEFUN (isnumeric, args, ,
3317@deftypefn {Built-in Function} {} isnumeric (@var{x})\n\
3318Return nonzero if @var{x} is a numeric object.\n\
3321 octave_value retval;
3323 if (args.length () == 1)
3324 retval = args(0).is_numeric_type ();
3331DEFUN (islist, args, ,
3333@deftypefn {Built-in Function} {} islist (@var{x})\n\
3334Return nonzero if @var{x} is a list.\n\
3337 octave_value retval;
3339 if (args.length () == 1)
3340 retval = args(0).is_list ();
3347DEFUN (ismatrix, args, ,
3349@deftypefn {Built-in Function} {} ismatrix (@var{a})\n\
3350Return 1 if @var{a} is a matrix. Otherwise, return 0.\n\
3353 octave_value retval = false;
3355 if (args.length () == 1)
3357 octave_value arg = args(0);
3359 if (arg.is_scalar_type () || arg.is_range ())
3361 else if (arg.is_matrix_type ())
3362 retval = (arg.rows () >= 1 && arg.columns () >= 1);