data.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1994-2012 John W. Eaton
00004 Copyright (C) 2009 Jaroslav Hajek
00005 Copyright (C) 2009-2010 VZLU Prague
00006 
00007 This file is part of Octave.
00008 
00009 Octave is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as published by the
00011 Free Software Foundation; either version 3 of the License, or (at your
00012 option) any later version.
00013 
00014 Octave is distributed in the hope that it will be useful, but WITHOUT
00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00017 for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with Octave; see the file COPYING.  If not, see
00021 <http://www.gnu.org/licenses/>.
00022 
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028 
00029 #include <sys/types.h>
00030 #include <sys/times.h>
00031 
00032 #ifdef HAVE_SYS_RESOURCE_H
00033 #include <sys/resource.h>
00034 #endif
00035 
00036 #include <cfloat>
00037 #include <ctime>
00038 
00039 #include <string>
00040 
00041 #include "lo-ieee.h"
00042 #include "lo-math.h"
00043 #include "oct-time.h"
00044 #include "str-vec.h"
00045 #include "quit.h"
00046 #include "mx-base.h"
00047 #include "oct-binmap.h"
00048 
00049 #include "Cell.h"
00050 #include "defun.h"
00051 #include "error.h"
00052 #include "gripes.h"
00053 #include "oct-map.h"
00054 #include "oct-obj.h"
00055 #include "ov.h"
00056 #include "ov-class.h"
00057 #include "ov-float.h"
00058 #include "ov-complex.h"
00059 #include "ov-flt-complex.h"
00060 #include "ov-cx-mat.h"
00061 #include "ov-flt-cx-mat.h"
00062 #include "ov-cx-sparse.h"
00063 #include "parse.h"
00064 #include "pt-mat.h"
00065 #include "utils.h"
00066 #include "variables.h"
00067 #include "pager.h"
00068 #include "xnorm.h"
00069 
00070 #if ! defined (CLOCKS_PER_SEC)
00071 #if defined (CLK_TCK)
00072 #define CLOCKS_PER_SEC CLK_TCK
00073 #else
00074 #error "no definition for CLOCKS_PER_SEC!"
00075 #endif
00076 #endif
00077 
00078 #if ! defined (HAVE_HYPOTF) && defined (HAVE__HYPOTF)
00079 #define hypotf _hypotf
00080 #define HAVE_HYPOTF 1
00081 #endif
00082 
00083 #define ANY_ALL(FCN) \
00084  \
00085   octave_value retval; \
00086  \
00087   int nargin = args.length (); \
00088  \
00089   if (nargin == 1 || nargin == 2) \
00090     { \
00091       int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
00092  \
00093       if (! error_state) \
00094         { \
00095           if (dim >= -1) \
00096             retval = args(0).FCN (dim); \
00097           else \
00098             error (#FCN ": invalid dimension argument = %d", dim + 1); \
00099         } \
00100       else \
00101         error (#FCN ": expecting dimension argument to be an integer"); \
00102     } \
00103   else \
00104     print_usage (); \
00105  \
00106   return retval
00107 
00108 DEFUN (all, args, ,
00109   "-*- texinfo -*-\n\
00110 @deftypefn  {Built-in Function} {} all (@var{x})\n\
00111 @deftypefnx {Built-in Function} {} all (@var{x}, @var{dim})\n\
00112 For a vector argument, return true (logical 1) if all elements of the vector\n\
00113 are nonzero.\n\
00114 \n\
00115 For a matrix argument, return a row vector of logical ones and\n\
00116 zeros with each element indicating whether all of the elements of the\n\
00117 corresponding column of the matrix are nonzero.  For example:\n\
00118 \n\
00119 @example\n\
00120 @group\n\
00121 all ([2, 3; 1, 0]))\n\
00122      @result{} [ 1, 0 ]\n\
00123 @end group\n\
00124 @end example\n\
00125 \n\
00126 If the optional argument @var{dim} is supplied, work along dimension\n\
00127 @var{dim}.\n\
00128 @seealso{any}\n\
00129 @end deftypefn")
00130 {
00131   ANY_ALL (all);
00132 }
00133 
00134 /*
00135 
00136 %!test
00137 %! x = ones (3);
00138 %! x(1,1) = 0;
00139 %! assert((all (all (rand (3) + 1) == [1, 1, 1]) == 1
00140 %! && all (all (x) == [0, 1, 1]) == 1
00141 %! && all (x, 1) == [0, 1, 1]
00142 %! && all (x, 2) == [0; 1; 1]));
00143 
00144 %!test
00145 %! x = ones (3, 'single');
00146 %! x(1,1) = 0;
00147 %! assert((all (all (single (rand (3) + 1)) == [1, 1, 1]) == 1
00148 %! && all (all (x) == [0, 1, 1]) == 1
00149 %! && all (x, 1) == [0, 1, 1]
00150 %! && all (x, 2) == [0; 1; 1]));
00151 
00152 %!error <Invalid call to all> all ();
00153 %!error <Invalid call to all> all (1, 2, 3);
00154 
00155  */
00156 
00157 DEFUN (any, args, ,
00158   "-*- texinfo -*-\n\
00159 @deftypefn  {Built-in Function} {} any (@var{x})\n\
00160 @deftypefnx {Built-in Function} {} any (@var{x}, @var{dim})\n\
00161 For a vector argument, return true (logical 1) if any element of the vector\n\
00162 is nonzero.\n\
00163 \n\
00164 For a matrix argument, return a row vector of logical ones and\n\
00165 zeros with each element indicating whether any of the elements of the\n\
00166 corresponding column of the matrix are nonzero.  For example:\n\
00167 \n\
00168 @example\n\
00169 @group\n\
00170 any (eye (2, 4))\n\
00171      @result{} [ 1, 1, 0, 0 ]\n\
00172 @end group\n\
00173 @end example\n\
00174 \n\
00175 If the optional argument @var{dim} is supplied, work along dimension\n\
00176 @var{dim}.  For example:\n\
00177 \n\
00178 @example\n\
00179 @group\n\
00180 any (eye (2, 4), 2)\n\
00181      @result{} [ 1; 1 ]\n\
00182 @end group\n\
00183 @end example\n\
00184 @seealso{all}\n\
00185 @end deftypefn")
00186 {
00187   ANY_ALL (any);
00188 }
00189 
00190 /*
00191 
00192 %!test
00193 %! x = zeros (3);
00194 %! x(3,3) = 1;
00195 %! assert((all (any (x) == [0, 0, 1]) == 1
00196 %! && all (any (ones (3)) == [1, 1, 1]) == 1
00197 %! && any (x, 1) == [0, 0, 1]
00198 %! && any (x, 2) == [0; 0; 1]));
00199 
00200 %!test
00201 %! x = zeros (3,'single');
00202 %! x(3,3) = 1;
00203 %! assert((all (any (x) == [0, 0, 1]) == 1
00204 %! && all (any (ones (3, 'single')) == [1, 1, 1]) == 1
00205 %! && any (x, 1) == [0, 0, 1]
00206 %! && any (x, 2) == [0; 0; 1]));
00207 
00208 %!error <Invalid call to any> any ();
00209 %!error <Invalid call to any> any (1, 2, 3);
00210 
00211  */
00212 
00213 // These mapping functions may also be useful in other places, eh?
00214 
00215 DEFUN (atan2, args, ,
00216   "-*- texinfo -*-\n\
00217 @deftypefn {Mapping Function} {} atan2 (@var{y}, @var{x})\n\
00218 Compute atan (@var{y} / @var{x}) for corresponding elements of @var{y}\n\
00219 and @var{x}.  Signal an error if @var{y} and @var{x} do not match in size\n\
00220 and orientation.\n\
00221 @end deftypefn")
00222 {
00223   octave_value retval;
00224 
00225   int nargin = args.length ();
00226 
00227   if (nargin == 2)
00228     {
00229       if (! args(0).is_numeric_type ())
00230         gripe_wrong_type_arg ("atan2", args(0));
00231       else if (! args(1).is_numeric_type ())
00232         gripe_wrong_type_arg ("atan2", args(1));
00233       else if (args(0).is_complex_type () || args(1).is_complex_type ())
00234         error ("atan2: not defined for complex numbers");
00235       else if (args(0).is_single_type () || args(1).is_single_type ())
00236         {
00237           if (args(0).is_scalar_type () && args(1).is_scalar_type ())
00238             retval = atan2f (args(0).float_value (), args(1).float_value ());
00239           else
00240             {
00241               FloatNDArray a0 = args(0).float_array_value ();
00242               FloatNDArray a1 = args(1).float_array_value ();
00243               retval = binmap<float> (a0, a1, ::atan2f, "atan2");
00244             }
00245         }
00246       else
00247         {
00248           bool a0_scalar = args(0).is_scalar_type ();
00249           bool a1_scalar = args(1).is_scalar_type ();
00250           if (a0_scalar && a1_scalar)
00251             retval = atan2 (args(0).scalar_value (), args(1).scalar_value ());
00252           else if ((a0_scalar || args(0).is_sparse_type ())
00253                    && (a1_scalar || args(1).is_sparse_type ()))
00254             {
00255               SparseMatrix m0 = args(0).sparse_matrix_value ();
00256               SparseMatrix m1 = args(1).sparse_matrix_value ();
00257               retval = binmap<double> (m0, m1, ::atan2, "atan2");
00258             }
00259           else
00260             {
00261               NDArray a0 = args(0).array_value ();
00262               NDArray a1 = args(1).array_value ();
00263               retval = binmap<double> (a0, a1, ::atan2, "atan2");
00264             }
00265         }
00266     }
00267   else
00268     print_usage ();
00269 
00270   return retval;
00271 }
00272 
00273 /*
00274 %!assert (size (atan2 (zeros (0, 2), zeros (0, 2))), [0, 2])
00275 %!assert (size (atan2 (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
00276 %!assert (size (atan2 (rand (2, 3, 4), 1)), [2, 3, 4])
00277 %!assert (size (atan2 (1, rand (2, 3, 4))), [2, 3, 4])
00278 %!assert (size (atan2 (1, 2)), [1, 1])
00279 
00280 %!test
00281 %! rt2 = sqrt (2);
00282 %! rt3 = sqrt (3);
00283 %! v = [0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0];
00284 %! y = [0, rt3, 1, rt3, -rt3, -1, -rt3, 0];
00285 %! x = [1, 3, 1, 1, 1, 1, 3, 1];
00286 %! assert(atan2 (y, x), v, sqrt (eps));
00287 
00288 %!test
00289 %! rt2 = sqrt (2);
00290 %! rt3 = sqrt (3);
00291 %! v = single([0, pi/6, pi/4, pi/3, -pi/3, -pi/4, -pi/6, 0]);
00292 %! y = single([0, rt3, 1, rt3, -rt3, -1, -rt3, 0]);
00293 %! x = single([1, 3, 1, 1, 1, 1, 3, 1]);
00294 %! assert(atan2 (y, x), v, sqrt (eps('single')));
00295 
00296 %!error <Invalid call to atan2> atan2 ();
00297 %!error <Invalid call to atan2> atan2 (1, 2, 3);
00298 
00299 */
00300 
00301 
00302 static octave_value
00303 do_hypot (const octave_value& x, const octave_value& y)
00304 {
00305   octave_value retval;
00306 
00307   octave_value arg0 = x, arg1 = y;
00308   if (! arg0.is_numeric_type ())
00309     gripe_wrong_type_arg ("hypot", arg0);
00310   else if (! arg1.is_numeric_type ())
00311     gripe_wrong_type_arg ("hypot", arg1);
00312   else
00313     {
00314       if (arg0.is_complex_type ())
00315         arg0 = arg0.abs ();
00316       if (arg1.is_complex_type ())
00317         arg1 = arg1.abs ();
00318 
00319       if (arg0.is_single_type () || arg1.is_single_type ())
00320         {
00321           if (arg0.is_scalar_type () && arg1.is_scalar_type ())
00322             retval = hypotf (arg0.float_value (), arg1.float_value ());
00323           else
00324             {
00325               FloatNDArray a0 = arg0.float_array_value ();
00326               FloatNDArray a1 = arg1.float_array_value ();
00327               retval = binmap<float> (a0, a1, ::hypotf, "hypot");
00328             }
00329         }
00330       else
00331         {
00332           bool a0_scalar = arg0.is_scalar_type ();
00333           bool a1_scalar = arg1.is_scalar_type ();
00334           if (a0_scalar && a1_scalar)
00335             retval = hypot (arg0.scalar_value (), arg1.scalar_value ());
00336           else if ((a0_scalar || arg0.is_sparse_type ())
00337                    && (a1_scalar || arg1.is_sparse_type ()))
00338             {
00339               SparseMatrix m0 = arg0.sparse_matrix_value ();
00340               SparseMatrix m1 = arg1.sparse_matrix_value ();
00341               retval = binmap<double> (m0, m1, ::hypot, "hypot");
00342             }
00343           else
00344             {
00345               NDArray a0 = arg0.array_value ();
00346               NDArray a1 = arg1.array_value ();
00347               retval = binmap<double> (a0, a1, ::hypot, "hypot");
00348             }
00349         }
00350     }
00351 
00352   return retval;
00353 }
00354 
00355 DEFUN (hypot, args, ,
00356   "-*- texinfo -*-\n\
00357 @deftypefn  {Built-in Function} {} hypot (@var{x}, @var{y})\n\
00358 @deftypefnx {Built-in Function} {} hypot (@var{x}, @var{y}, @var{z}, @dots{})\n\
00359 Compute the element-by-element square root of the sum of the squares of\n\
00360 @var{x} and @var{y}.  This is equivalent to\n\
00361 @code{sqrt (@var{x}.^2 + @var{y}.^2)}, but calculated in a manner that\n\
00362 avoids overflows for large values of @var{x} or @var{y}.\n\
00363 @code{hypot} can also be called with more than 2 arguments; in this case,\n\
00364 the arguments are accumulated from left to right:\n\
00365 \n\
00366 @example\n\
00367 @group\n\
00368   hypot (hypot (@var{x}, @var{y}), @var{z})\n\
00369   hypot (hypot (hypot (@var{x}, @var{y}), @var{z}), @var{w}), etc.\n\
00370 @end group\n\
00371 @end example\n\
00372 @end deftypefn")
00373 {
00374   octave_value retval;
00375 
00376   int nargin = args.length ();
00377 
00378   if (nargin == 2)
00379     {
00380       retval = do_hypot (args(0), args(1));
00381     }
00382   else if (nargin >= 3)
00383     {
00384       retval = args(0);
00385       for (int i = 1; i < nargin && ! error_state; i++)
00386         retval = do_hypot (retval, args(i));
00387     }
00388   else
00389     print_usage ();
00390 
00391   return retval;
00392 }
00393 
00394 /*
00395 %!assert (size (hypot (zeros (0, 2), zeros (0, 2))), [0, 2])
00396 %!assert (size (hypot (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
00397 %!assert (size (hypot (rand (2, 3, 4), 1)), [2, 3, 4])
00398 %!assert (size (hypot (1, rand (2, 3, 4))), [2, 3, 4])
00399 %!assert (size (hypot (1, 2)), [1, 1])
00400 %!assert (hypot (1:10, 1:10), sqrt(2) * [1:10], 16*eps)
00401 %!assert (hypot (single(1:10), single(1:10)), single(sqrt(2) * [1:10]));
00402 */
00403 
00404 template<typename T, typename ET>
00405 void
00406 map_2_xlog2 (const Array<T>& x, Array<T>& f, Array<ET>& e)
00407 {
00408   f = Array<T>(x.dims ());
00409   e = Array<ET>(x.dims ());
00410   for (octave_idx_type i = 0; i < x.numel (); i++)
00411     {
00412       int exp;
00413       f.xelem (i) = xlog2 (x(i), exp);
00414       e.xelem (i) = exp;
00415     }
00416 }
00417 
00418 DEFUN (log2, args, nargout,
00419   "-*- texinfo -*-\n\
00420 @deftypefn  {Mapping Function} {} log2 (@var{x})\n\
00421 @deftypefnx {Mapping Function} {[@var{f}, @var{e}] =} log2 (@var{x})\n\
00422 Compute the base-2 logarithm of each element of @var{x}.\n\
00423 \n\
00424 If called with two output arguments, split @var{x} into\n\
00425 binary mantissa and exponent so that\n\
00426 @tex\n\
00427 ${1 \\over 2} \\le \\left| f \\right| < 1$\n\
00428 @end tex\n\
00429 @ifnottex\n\
00430 @code{1/2 <= abs(f) < 1}\n\
00431 @end ifnottex\n\
00432 and @var{e} is an integer.  If\n\
00433 @tex\n\
00434 $x = 0$, $f = e = 0$.\n\
00435 @end tex\n\
00436 @ifnottex\n\
00437 @code{x = 0}, @code{f = e = 0}.\n\
00438 @end ifnottex\n\
00439 @seealso{pow2, log, log10, exp}\n\
00440 @end deftypefn")
00441 {
00442   octave_value_list retval;
00443 
00444   if (args.length () == 1)
00445     {
00446       if (nargout < 2)
00447         retval(0) = args(0).log2 ();
00448       else if (args(0).is_single_type ())
00449         {
00450           if (args(0).is_real_type ())
00451             {
00452               FloatNDArray f;
00453               FloatNDArray x = args(0).float_array_value ();
00454               // FIXME -- should E be an int value?
00455               FloatMatrix e;
00456               map_2_xlog2 (x, f, e);
00457               retval (1) = e;
00458               retval (0) = f;
00459             }
00460           else if (args(0).is_complex_type ())
00461             {
00462               FloatComplexNDArray f;
00463               FloatComplexNDArray x = args(0).float_complex_array_value ();
00464               // FIXME -- should E be an int value?
00465               FloatNDArray e;
00466               map_2_xlog2 (x, f, e);
00467               retval (1) = e;
00468               retval (0) = f;
00469             }
00470         }
00471       else if (args(0).is_real_type ())
00472         {
00473           NDArray f;
00474           NDArray x = args(0).array_value ();
00475           // FIXME -- should E be an int value?
00476           Matrix e;
00477           map_2_xlog2 (x, f, e);
00478           retval (1) = e;
00479           retval (0) = f;
00480         }
00481       else if (args(0).is_complex_type ())
00482         {
00483           ComplexNDArray f;
00484           ComplexNDArray x = args(0).complex_array_value ();
00485           // FIXME -- should E be an int value?
00486           NDArray e;
00487           map_2_xlog2 (x, f, e);
00488           retval (1) = e;
00489           retval (0) = f;
00490         }
00491       else
00492         gripe_wrong_type_arg ("log2", args(0));
00493     }
00494   else
00495     print_usage ();
00496 
00497   return retval;
00498 }
00499 
00500 /*
00501 %!assert(log2 ([1/4, 1/2, 1, 2, 4]), [-2, -1, 0, 1, 2]);
00502 %!assert(log2(Inf), Inf);
00503 %!assert(isnan(log2(NaN)));
00504 %!assert(log2(4*i), 2 + log2(1*i));
00505 %!assert(log2(complex(0,Inf)), Inf + log2(i));
00506 
00507 %!test
00508 %! [f, e] = log2 ([0,-1; 2,-4; Inf,-Inf]);
00509 %! assert (f, [0,-0.5; 0.5,-0.5; Inf,-Inf]);
00510 %! assert (e(1:2,:), [0,1;2,3])
00511 
00512 %!test
00513 %! [f, e] = log2 (complex (zeros (3, 2), [0,-1; 2,-4; Inf,-Inf]));
00514 %! assert (f, complex (zeros (3, 2), [0,-0.5; 0.5,-0.5; Inf,-Inf]));
00515 %! assert (e(1:2,:), [0,1; 2,3]);
00516 */
00517 
00518 DEFUN (rem, args, ,
00519   "-*- texinfo -*-\n\
00520 @deftypefn  {Mapping Function} {} rem (@var{x}, @var{y})\n\
00521 @deftypefnx {Mapping Function} {} fmod (@var{x}, @var{y})\n\
00522 Return the remainder of the division @code{@var{x} / @var{y}}, computed\n\
00523 using the expression\n\
00524 \n\
00525 @example\n\
00526 x - y .* fix (x ./ y)\n\
00527 @end example\n\
00528 \n\
00529 An error message is printed if the dimensions of the arguments do not\n\
00530 agree, or if either of the arguments is complex.\n\
00531 @seealso{mod}\n\
00532 @end deftypefn")
00533 {
00534   octave_value retval;
00535 
00536   int nargin = args.length ();
00537 
00538   if (nargin == 2)
00539     {
00540       if (! args(0).is_numeric_type ())
00541         gripe_wrong_type_arg ("rem", args(0));
00542       else if (! args(1).is_numeric_type ())
00543         gripe_wrong_type_arg ("rem", args(1));
00544       else if (args(0).is_complex_type () || args(1).is_complex_type ())
00545         error ("rem: not defined for complex numbers");
00546       else if (args(0).is_integer_type () || args(1).is_integer_type ())
00547         {
00548           builtin_type_t btyp0 = args(0).builtin_type ();
00549           builtin_type_t btyp1 = args(1).builtin_type ();
00550           if (btyp0 == btyp_double || btyp0 == btyp_float)
00551             btyp0 = btyp1;
00552           if (btyp1 == btyp_double || btyp1 == btyp_float)
00553             btyp1 = btyp0;
00554 
00555           if (btyp0 == btyp1)
00556             {
00557               switch (btyp0)
00558                 {
00559 #define MAKE_INT_BRANCH(X) \
00560                 case btyp_ ## X: \
00561                     { \
00562                     X##NDArray a0 = args(0).X##_array_value (); \
00563                     X##NDArray a1 = args(1).X##_array_value (); \
00564                     retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, rem, "rem"); \
00565                     } \
00566                   break
00567                 MAKE_INT_BRANCH (int8);
00568                 MAKE_INT_BRANCH (int16);
00569                 MAKE_INT_BRANCH (int32);
00570                 MAKE_INT_BRANCH (int64);
00571                 MAKE_INT_BRANCH (uint8);
00572                 MAKE_INT_BRANCH (uint16);
00573                 MAKE_INT_BRANCH (uint32);
00574                 MAKE_INT_BRANCH (uint64);
00575 #undef MAKE_INT_BRANCH
00576                 default:
00577                   panic_impossible ();
00578                 }
00579             }
00580           else
00581             error ("rem: cannot combine %s and %d",
00582                    args(0).class_name ().c_str (), args(1).class_name ().c_str ());
00583         }
00584       else if (args(0).is_single_type () || args(1).is_single_type ())
00585         {
00586           if (args(0).is_scalar_type () && args(1).is_scalar_type ())
00587             retval = xrem (args(0).float_value (), args(1).float_value ());
00588           else
00589             {
00590               FloatNDArray a0 = args(0).float_array_value ();
00591               FloatNDArray a1 = args(1).float_array_value ();
00592               retval = binmap<float> (a0, a1, xrem<float>, "rem");
00593             }
00594         }
00595       else
00596         {
00597           bool a0_scalar = args(0).is_scalar_type ();
00598           bool a1_scalar = args(1).is_scalar_type ();
00599           if (a0_scalar && a1_scalar)
00600             retval = xrem (args(0).scalar_value (), args(1).scalar_value ());
00601           else if ((a0_scalar || args(0).is_sparse_type ())
00602                    && (a1_scalar || args(1).is_sparse_type ()))
00603             {
00604               SparseMatrix m0 = args(0).sparse_matrix_value ();
00605               SparseMatrix m1 = args(1).sparse_matrix_value ();
00606               retval = binmap<double> (m0, m1, xrem<double>, "rem");
00607             }
00608           else
00609             {
00610               NDArray a0 = args(0).array_value ();
00611               NDArray a1 = args(1).array_value ();
00612               retval = binmap<double> (a0, a1, xrem<double>, "rem");
00613             }
00614         }
00615     }
00616   else
00617     print_usage ();
00618 
00619   return retval;
00620 }
00621 
00622 /*
00623 
00624 %!assert(rem ([1, 2, 3; -1, -2, -3], 2), [1, 0, 1; -1, 0, -1]);
00625 %!assert(rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3)),[1, 0, 1; -1, 0, -1]);
00626 %!error rem ();
00627 %!error rem (1, 2, 3);
00628 %!error rem ([1, 2], [3, 4, 5]);
00629 %!error rem (i, 1);
00630 %!assert(rem (uint8([1, 2, 3; -1, -2, -3]), uint8 (2)), uint8([1, 0, 1; -1, 0, -1]));
00631 %!assert(uint8(rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3))),uint8([1, 0, 1; -1, 0, -1]));
00632 %!error rem (uint(8),int8(5));
00633 %!error rem (uint8([1, 2]), uint8([3, 4, 5]));
00634 
00635 */
00636 
00637 /*
00638 %!assert (size (fmod (zeros (0, 2), zeros (0, 2))), [0, 2])
00639 %!assert (size (fmod (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
00640 %!assert (size (fmod (rand (2, 3, 4), 1)), [2, 3, 4])
00641 %!assert (size (fmod (1, rand (2, 3, 4))), [2, 3, 4])
00642 %!assert (size (fmod (1, 2)), [1, 1])
00643 */
00644 
00645 DEFALIAS (fmod, rem)
00646 
00647 DEFUN (mod, args, ,
00648   "-*- texinfo -*-\n\
00649 @deftypefn {Mapping Function} {} mod (@var{x}, @var{y})\n\
00650 Compute the modulo of @var{x} and @var{y}.  Conceptually this is given by\n\
00651 \n\
00652 @example\n\
00653 x - y .* floor (x ./ y)\n\
00654 @end example\n\
00655 \n\
00656 @noindent\n\
00657 and is written such that the correct modulus is returned for\n\
00658 integer types.  This function handles negative values correctly.  That\n\
00659 is, @code{mod (-1, 3)} is 2, not -1, as @code{rem (-1, 3)} returns.\n\
00660 @code{mod (@var{x}, 0)} returns @var{x}.\n\
00661 \n\
00662 An error results if the dimensions of the arguments do not agree, or if\n\
00663 either of the arguments is complex.\n\
00664 @seealso{rem}\n\
00665 @end deftypefn")
00666 {
00667   octave_value retval;
00668 
00669   int nargin = args.length ();
00670 
00671   if (nargin == 2)
00672     {
00673       if (! args(0).is_numeric_type ())
00674         gripe_wrong_type_arg ("mod", args(0));
00675       else if (! args(1).is_numeric_type ())
00676         gripe_wrong_type_arg ("mod", args(1));
00677       else if (args(0).is_complex_type () || args(1).is_complex_type ())
00678         error ("mod: not defined for complex numbers");
00679       else if (args(0).is_integer_type () || args(1).is_integer_type ())
00680         {
00681           builtin_type_t btyp0 = args(0).builtin_type ();
00682           builtin_type_t btyp1 = args(1).builtin_type ();
00683           if (btyp0 == btyp_double || btyp0 == btyp_float)
00684             btyp0 = btyp1;
00685           if (btyp1 == btyp_double || btyp1 == btyp_float)
00686             btyp1 = btyp0;
00687 
00688           if (btyp0 == btyp1)
00689             {
00690               switch (btyp0)
00691                 {
00692 #define MAKE_INT_BRANCH(X) \
00693                 case btyp_ ## X: \
00694                     { \
00695                     X##NDArray a0 = args(0).X##_array_value (); \
00696                     X##NDArray a1 = args(1).X##_array_value (); \
00697                     retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, mod, "mod"); \
00698                     } \
00699                   break
00700                 MAKE_INT_BRANCH (int8);
00701                 MAKE_INT_BRANCH (int16);
00702                 MAKE_INT_BRANCH (int32);
00703                 MAKE_INT_BRANCH (int64);
00704                 MAKE_INT_BRANCH (uint8);
00705                 MAKE_INT_BRANCH (uint16);
00706                 MAKE_INT_BRANCH (uint32);
00707                 MAKE_INT_BRANCH (uint64);
00708 #undef MAKE_INT_BRANCH
00709                 default:
00710                   panic_impossible ();
00711                 }
00712             }
00713           else
00714             error ("mod: cannot combine %s and %d",
00715                    args(0).class_name ().c_str (), args(1).class_name ().c_str ());
00716         }
00717       else if (args(0).is_single_type () || args(1).is_single_type ())
00718         {
00719           if (args(0).is_scalar_type () && args(1).is_scalar_type ())
00720             retval = xmod (args(0).float_value (), args(1).float_value ());
00721           else
00722             {
00723               FloatNDArray a0 = args(0).float_array_value ();
00724               FloatNDArray a1 = args(1).float_array_value ();
00725               retval = binmap<float> (a0, a1, xmod<float>, "mod");
00726             }
00727         }
00728       else
00729         {
00730           bool a0_scalar = args(0).is_scalar_type ();
00731           bool a1_scalar = args(1).is_scalar_type ();
00732           if (a0_scalar && a1_scalar)
00733             retval = xmod (args(0).scalar_value (), args(1).scalar_value ());
00734           else if ((a0_scalar || args(0).is_sparse_type ())
00735                    && (a1_scalar || args(1).is_sparse_type ()))
00736             {
00737               SparseMatrix m0 = args(0).sparse_matrix_value ();
00738               SparseMatrix m1 = args(1).sparse_matrix_value ();
00739               retval = binmap<double> (m0, m1, xmod<double>, "mod");
00740             }
00741           else
00742             {
00743               NDArray a0 = args(0).array_value ();
00744               NDArray a1 = args(1).array_value ();
00745               retval = binmap<double> (a0, a1, xmod<double>, "mod");
00746             }
00747         }
00748     }
00749   else
00750     print_usage ();
00751 
00752   return retval;
00753 }
00754 
00755 /*
00756 ## empty input test
00757 %!assert (isempty(mod([], [])));
00758 
00759 ## x mod y, y != 0 tests
00760 %!assert (mod(5, 3), 2);
00761 %!assert (mod(-5, 3), 1);
00762 %!assert (mod(0, 3), 0);
00763 %!assert (mod([-5, 5, 0], [3, 3, 3]), [1, 2, 0]);
00764 %!assert (mod([-5; 5; 0], [3; 3; 3]), [1; 2; 0]);
00765 %!assert (mod([-5, 5; 0, 3], [3, 3 ; 3, 1]), [1, 2 ; 0, 0]);
00766 
00767 ## x mod 0 tests
00768 %!assert (mod(5, 0), 5);
00769 %!assert (mod(-5, 0), -5);
00770 %!assert (mod([-5, 5, 0], [3, 0, 3]), [1, 5, 0]);
00771 %!assert (mod([-5; 5; 0], [3; 0; 3]), [1; 5; 0]);
00772 %!assert (mod([-5, 5; 0, 3], [3, 0 ; 3, 1]), [1, 5 ; 0, 0]);
00773 %!assert (mod([-5, 5; 0, 3], [0, 0 ; 0, 0]), [-5, 5; 0, 3]);
00774 
00775 ## mixed scalar/matrix tests
00776 %!assert (mod([-5, 5; 0, 3], 0), [-5, 5; 0, 3]);
00777 %!assert (mod([-5, 5; 0, 3], 3), [1, 2; 0, 0]);
00778 %!assert (mod(-5,[0,0; 0,0]), [-5, -5; -5, -5]);
00779 %!assert (mod(-5,[3,0; 3,1]), [1, -5; 1, 0]);
00780 %!assert (mod(-5,[3,2; 3,1]), [1, 1; 1, 0]);
00781 
00782 ## integer types
00783 %!assert (mod(uint8(5),uint8(4)),uint8(1))
00784 %!assert (mod(uint8([1:5]),uint8(4)),uint8([1,2,3,0,1]))
00785 %!assert (mod(uint8([1:5]),uint8(0)),uint8([1:5]))
00786 %!error (mod(uint8(5),int8(4)))
00787 
00788 ## mixed integer/real types
00789 %!assert (mod(uint8(5),4),uint8(1))
00790 %!assert (mod(5,uint8(4)),uint8(1))
00791 %!assert (mod(uint8([1:5]),4),uint8([1,2,3,0,1]))
00792 
00793 ## non-integer real numbers
00794 %!assert (mod (2.1, 0.1), 0)
00795 %!assert (mod (2.1, 0.2), 0.1, eps)
00796 */
00797 
00798 // FIXME Need to convert the reduction functions of this file for single precision
00799 
00800 #define NATIVE_REDUCTION_1(FCN, TYPE, DIM) \
00801   (arg.is_ ## TYPE ## _type ()) \
00802     { \
00803       TYPE ## NDArray tmp = arg. TYPE ##_array_value (); \
00804       \
00805       if (! error_state) \
00806         { \
00807           retval = tmp.FCN (DIM); \
00808         } \
00809     }
00810 
00811 #define NATIVE_REDUCTION(FCN, BOOL_FCN) \
00812  \
00813   octave_value retval; \
00814  \
00815   int nargin = args.length (); \
00816  \
00817   bool isnative = false; \
00818   bool isdouble = false; \
00819   \
00820   if (nargin > 1 && args(nargin - 1).is_string ()) \
00821     { \
00822       std::string str = args(nargin - 1).string_value (); \
00823       \
00824       if (! error_state) \
00825         { \
00826           if (str == "native") \
00827             isnative = true; \
00828           else if (str == "double") \
00829             isdouble = true; \
00830           else \
00831             error ("sum: unrecognized string argument"); \
00832           nargin --; \
00833         } \
00834     } \
00835   \
00836   if (nargin == 1 || nargin == 2) \
00837     { \
00838       octave_value arg = args(0); \
00839  \
00840       int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
00841  \
00842       if (! error_state) \
00843         { \
00844           if (dim >= -1) \
00845             { \
00846               if (arg.is_sparse_type ()) \
00847                 { \
00848                   if (arg.is_real_type ()) \
00849                     { \
00850                       SparseMatrix tmp = arg.sparse_matrix_value (); \
00851                       \
00852                       if (! error_state) \
00853                         retval = tmp.FCN (dim); \
00854                     } \
00855                   else \
00856                     { \
00857                       SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \
00858                       \
00859                       if (! error_state) \
00860                         retval = tmp.FCN (dim); \
00861                     } \
00862                 } \
00863               else \
00864                 { \
00865                   if (isnative) \
00866                     { \
00867                       if NATIVE_REDUCTION_1 (FCN, uint8, dim) \
00868                       else if NATIVE_REDUCTION_1 (FCN, uint16, dim) \
00869                       else if NATIVE_REDUCTION_1 (FCN, uint32, dim) \
00870                       else if NATIVE_REDUCTION_1 (FCN, uint64, dim) \
00871                       else if NATIVE_REDUCTION_1 (FCN, int8, dim) \
00872                       else if NATIVE_REDUCTION_1 (FCN, int16, dim) \
00873                       else if NATIVE_REDUCTION_1 (FCN, int32, dim) \
00874                       else if NATIVE_REDUCTION_1 (FCN, int64, dim) \
00875                       else if (arg.is_bool_type ()) \
00876                         { \
00877                           boolNDArray tmp = arg.bool_array_value (); \
00878                           if (! error_state) \
00879                             retval = boolNDArray (tmp.BOOL_FCN (dim)); \
00880                         } \
00881                       else if (arg.is_char_matrix ()) \
00882                         { \
00883                           error (#FCN, ": invalid char type"); \
00884                         } \
00885                       else if (!isdouble && arg.is_single_type ()) \
00886                         { \
00887                           if (arg.is_complex_type ()) \
00888                             { \
00889                               FloatComplexNDArray tmp = \
00890                                 arg.float_complex_array_value (); \
00891                               \
00892                               if (! error_state) \
00893                                 retval = tmp.FCN (dim); \
00894                             } \
00895                           else if (arg.is_real_type ()) \
00896                             { \
00897                               FloatNDArray tmp = arg.float_array_value (); \
00898                               \
00899                               if (! error_state) \
00900                                 retval = tmp.FCN (dim); \
00901                             } \
00902                         } \
00903                       else if (arg.is_complex_type ()) \
00904                         { \
00905                           ComplexNDArray tmp = arg.complex_array_value (); \
00906                           \
00907                           if (! error_state) \
00908                             retval = tmp.FCN (dim); \
00909                         } \
00910                       else if (arg.is_real_type ()) \
00911                         { \
00912                           NDArray tmp = arg.array_value (); \
00913                           \
00914                           if (! error_state) \
00915                             retval = tmp.FCN (dim); \
00916                         } \
00917                       else \
00918                         { \
00919                           gripe_wrong_type_arg (#FCN, arg); \
00920                           return retval; \
00921                         } \
00922                     } \
00923                   else if (arg.is_bool_type ()) \
00924                     { \
00925                       boolNDArray tmp = arg.bool_array_value (); \
00926                       if (! error_state) \
00927                         retval = tmp.FCN (dim); \
00928                     } \
00929                   else if (!isdouble && arg.is_single_type ()) \
00930                     { \
00931                       if (arg.is_real_type ()) \
00932                         { \
00933                           FloatNDArray tmp = arg.float_array_value (); \
00934                           \
00935                           if (! error_state) \
00936                             retval = tmp.FCN (dim); \
00937                         } \
00938                       else if (arg.is_complex_type ()) \
00939                         { \
00940                           FloatComplexNDArray tmp = \
00941                             arg.float_complex_array_value (); \
00942                           \
00943                           if (! error_state) \
00944                             retval = tmp.FCN (dim); \
00945                         } \
00946                     } \
00947                   else if (arg.is_real_type ()) \
00948                     { \
00949                       NDArray tmp = arg.array_value (); \
00950                       \
00951                       if (! error_state) \
00952                         retval = tmp.FCN (dim); \
00953                     } \
00954                   else if (arg.is_complex_type ()) \
00955                     { \
00956                       ComplexNDArray tmp = arg.complex_array_value (); \
00957                       \
00958                       if (! error_state) \
00959                         retval = tmp.FCN (dim); \
00960                     } \
00961                   else \
00962                     { \
00963                       gripe_wrong_type_arg (#FCN, arg); \
00964                       return retval; \
00965                     } \
00966                 } \
00967             } \
00968           else \
00969             error (#FCN ": invalid dimension argument = %d", dim + 1); \
00970         } \
00971       \
00972     } \
00973   else \
00974     print_usage (); \
00975  \
00976   return retval
00977 
00978 #define DATA_REDUCTION(FCN) \
00979  \
00980   octave_value retval; \
00981  \
00982   int nargin = args.length (); \
00983  \
00984   if (nargin == 1 || nargin == 2) \
00985     { \
00986       octave_value arg = args(0); \
00987  \
00988       int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \
00989  \
00990       if (! error_state) \
00991         { \
00992           if (dim >= -1) \
00993             { \
00994               if (arg.is_real_type ()) \
00995                 { \
00996                   if (arg.is_sparse_type ()) \
00997                     { \
00998                       SparseMatrix tmp = arg.sparse_matrix_value (); \
00999  \
01000                       if (! error_state) \
01001                         retval = tmp.FCN (dim); \
01002                     } \
01003                   else if (arg.is_single_type ()) \
01004                     { \
01005                       FloatNDArray tmp = arg.float_array_value (); \
01006  \
01007                       if (! error_state) \
01008                         retval = tmp.FCN (dim); \
01009                     } \
01010                   else \
01011                     { \
01012                       NDArray tmp = arg.array_value (); \
01013  \
01014                       if (! error_state) \
01015                         retval = tmp.FCN (dim); \
01016                     } \
01017                 } \
01018               else if (arg.is_complex_type ()) \
01019                 { \
01020                   if (arg.is_sparse_type ()) \
01021                     { \
01022                       SparseComplexMatrix tmp = arg.sparse_complex_matrix_value (); \
01023  \
01024                       if (! error_state) \
01025                         retval = tmp.FCN (dim); \
01026                     } \
01027                   else if (arg.is_single_type ()) \
01028                     { \
01029                       FloatComplexNDArray tmp = arg.float_complex_array_value (); \
01030  \
01031                       if (! error_state) \
01032                         retval = tmp.FCN (dim); \
01033                     } \
01034                   else \
01035                     { \
01036                       ComplexNDArray tmp = arg.complex_array_value (); \
01037  \
01038                       if (! error_state) \
01039                         retval = tmp.FCN (dim); \
01040                     } \
01041                 } \
01042               else \
01043                 { \
01044                   gripe_wrong_type_arg (#FCN, arg); \
01045                   return retval; \
01046                 } \
01047             } \
01048           else \
01049             error (#FCN ": invalid dimension argument = %d", dim + 1); \
01050         } \
01051     } \
01052   else \
01053     print_usage (); \
01054  \
01055   return retval
01056 
01057 DEFUN (cumprod, args, ,
01058   "-*- texinfo -*-\n\
01059 @deftypefn  {Built-in Function} {} cumprod (@var{x})\n\
01060 @deftypefnx {Built-in Function} {} cumprod (@var{x}, @var{dim})\n\
01061 Cumulative product of elements along dimension @var{dim}.  If\n\
01062 @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
01063 \n\
01064 @seealso{prod, cumsum}\n\
01065 @end deftypefn")
01066 {
01067   DATA_REDUCTION (cumprod);
01068 }
01069 
01070 /*
01071 
01072 %!assert (cumprod ([1, 2, 3]), [1, 2, 6]);
01073 %!assert (cumprod ([-1; -2; -3]), [-1; 2; -6]);
01074 %!assert (cumprod ([i, 2+i, -3+2i, 4]), [i, -1+2i, -1-8i, -4-32i]);
01075 %!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]);
01076 
01077 %!assert (cumprod (single([1, 2, 3])), single([1, 2, 6]));
01078 %!assert (cumprod (single([-1; -2; -3])), single([-1; 2; -6]));
01079 %!assert (cumprod (single([i, 2+i, -3+2i, 4])), single([i, -1+2i, -1-8i, -4-32i]));
01080 %!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]));
01081 
01082 %!error <Invalid call to cumprod> cumprod ();
01083 
01084 %!assert (cumprod ([2, 3; 4, 5], 1), [2, 3; 8, 15]);
01085 %!assert (cumprod ([2, 3; 4, 5], 2), [2, 6; 4, 20]);
01086 
01087 %!assert (cumprod (single([2, 3; 4, 5]), 1), single([2, 3; 8, 15]));
01088 %!assert (cumprod (single([2, 3; 4, 5]), 2), single([2, 6; 4, 20]));
01089 
01090  */
01091 
01092 DEFUN (cumsum, args, ,
01093   "-*- texinfo -*-\n\
01094 @deftypefn  {Built-in Function} {} cumsum (@var{x})\n\
01095 @deftypefnx {Built-in Function} {} cumsum (@var{x}, @var{dim})\n\
01096 @deftypefnx {Built-in Function} {} cumsum (@dots{}, 'native')\n\
01097 @deftypefnx {Built-in Function} {} cumsum (@dots{}, 'double')\n\
01098 @deftypefnx {Built-in Function} {} cumsum (@dots{}, 'extra')\n\
01099 Cumulative sum of elements along dimension @var{dim}.  If @var{dim}\n\
01100 is omitted, it defaults to the first non-singleton dimension.\n\
01101 \n\
01102 See @code{sum} for an explanation of the optional parameters 'native',\n\
01103 'double', and 'extra'.\n\
01104 @seealso{sum, cumprod}\n\
01105 @end deftypefn")
01106 {
01107   octave_value retval;
01108 
01109   int nargin = args.length ();
01110 
01111   bool isnative = false;
01112   bool isdouble = false;
01113 
01114   if (nargin > 1 && args(nargin - 1).is_string ())
01115     {
01116       std::string str = args(nargin - 1).string_value ();
01117 
01118       if (! error_state)
01119         {
01120           if (str == "native")
01121             isnative = true;
01122           else if (str == "double")
01123             isdouble = true;
01124           else
01125             error ("sum: unrecognized string argument");
01126           nargin --;
01127         }
01128     }
01129 
01130   if (error_state)
01131     return retval;
01132 
01133   if (nargin == 1 || nargin == 2)
01134     {
01135       octave_value arg = args(0);
01136 
01137       int dim = -1;
01138       if (nargin == 2)
01139         {
01140           dim = args(1).int_value () - 1;
01141           if (dim < 0)
01142             error ("cumsum: invalid dimension argument = %d", dim + 1);
01143         }
01144 
01145       if (! error_state)
01146         {
01147           switch (arg.builtin_type ())
01148             {
01149             case btyp_double:
01150               if (arg.is_sparse_type ())
01151                 retval = arg.sparse_matrix_value ().cumsum (dim);
01152               else
01153                 retval = arg.array_value ().cumsum (dim);
01154               break;
01155             case btyp_complex:
01156               if (arg.is_sparse_type ())
01157                 retval = arg.sparse_complex_matrix_value ().cumsum (dim);
01158               else
01159                 retval = arg.complex_array_value ().cumsum (dim);
01160               break;
01161             case btyp_float:
01162               if (isdouble)
01163                 retval = arg.array_value ().cumsum (dim);
01164               else
01165                 retval = arg.float_array_value ().cumsum (dim);
01166               break;
01167             case btyp_float_complex:
01168               if (isdouble)
01169                 retval = arg.complex_array_value ().cumsum (dim);
01170               else
01171                 retval = arg.float_complex_array_value ().cumsum (dim);
01172               break;
01173 
01174 #define MAKE_INT_BRANCH(X) \
01175             case btyp_ ## X: \
01176               if (isnative) \
01177                 retval = arg.X ## _array_value ().cumsum (dim); \
01178               else \
01179                 retval = arg.array_value ().cumsum (dim); \
01180               break
01181             MAKE_INT_BRANCH (int8);
01182             MAKE_INT_BRANCH (int16);
01183             MAKE_INT_BRANCH (int32);
01184             MAKE_INT_BRANCH (int64);
01185             MAKE_INT_BRANCH (uint8);
01186             MAKE_INT_BRANCH (uint16);
01187             MAKE_INT_BRANCH (uint32);
01188             MAKE_INT_BRANCH (uint64);
01189 #undef MAKE_INT_BRANCH
01190 
01191             case btyp_bool:
01192               if (arg.is_sparse_type ())
01193                 {
01194                   SparseMatrix cs = arg.sparse_matrix_value ().cumsum (dim);
01195                   if (isnative)
01196                     retval = cs != 0.0;
01197                   else
01198                     retval = cs;
01199                 }
01200               else
01201                 {
01202                   NDArray cs = arg.bool_array_value ().cumsum (dim);
01203                   if (isnative)
01204                     retval = cs != 0.0;
01205                   else
01206                     retval = cs;
01207                 }
01208               break;
01209 
01210             default:
01211               gripe_wrong_type_arg ("cumsum", arg);
01212             }
01213         }
01214     }
01215   else
01216     print_usage ();
01217 
01218   return retval;
01219 }
01220 
01221 /*
01222 
01223 %!assert (cumsum ([1, 2, 3]), [1, 3, 6]);
01224 %!assert (cumsum ([-1; -2; -3]), [-1; -3; -6]);
01225 %!assert (cumsum ([i, 2+i, -3+2i, 4]), [i, 2+2i, -1+4i, 3+4i]);
01226 %!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]);
01227 
01228 %!assert (cumsum (single([1, 2, 3])), single([1, 3, 6]));
01229 %!assert (cumsum (single([-1; -2; -3])), single([-1; -3; -6]));
01230 %!assert (cumsum (single([i, 2+i, -3+2i, 4])), single([i, 2+2i, -1+4i, 3+4i]));
01231 %!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]));
01232 
01233 %!error <Invalid call to cumsum> cumsum ();
01234 
01235 %!assert (cumsum ([1, 2; 3, 4], 1), [1, 2; 4, 6]);
01236 %!assert (cumsum ([1, 2; 3, 4], 2), [1, 3; 3, 7]);
01237 
01238 %!assert (cumsum (single([1, 2; 3, 4]), 1), single([1, 2; 4, 6]));
01239 %!assert (cumsum (single([1, 2; 3, 4]), 2), single([1, 3; 3, 7]));
01240 
01241  */
01242 
01243 DEFUN (diag, args, ,
01244   "-*- texinfo -*-\n\
01245 @deftypefn  {Built-in Function} {@var{M} =} diag (@var{v})\n\
01246 @deftypefnx {Built-in Function} {@var{M} =} diag (@var{v}, @var{k})\n\
01247 @deftypefnx {Built-in Function} {@var{M} =} diag (@var{v}, @var{m}, @var{n})\n\
01248 @deftypefnx {Built-in Function} {@var{v} =} diag (@var{M})\n\
01249 @deftypefnx {Built-in Function} {@var{v} =} diag (@var{M}, @var{k})\n\
01250 Return a diagonal matrix with vector @var{v} on diagonal @var{k}.  The\n\
01251 second argument is optional.  If it is positive, the vector is placed on\n\
01252 the @var{k}-th super-diagonal.  If it is negative, it is placed on the\n\
01253 @var{-k}-th sub-diagonal.  The default value of @var{k} is 0, and the\n\
01254 vector is placed on the main diagonal.  For example:\n\
01255 \n\
01256 @example\n\
01257 @group\n\
01258 diag ([1, 2, 3], 1)\n\
01259      @result{}  0  1  0  0\n\
01260          0  0  2  0\n\
01261          0  0  0  3\n\
01262          0  0  0  0\n\
01263 @end group\n\
01264 @end example\n\
01265 \n\
01266 @noindent\n\
01267 The 3-input form returns a diagonal matrix with vector @var{v} on the main\n\
01268 diagonal and the resulting matrix being of size @var{m} rows x @var{n}\n\
01269 columns.\n\
01270 \n\
01271 Given a matrix argument, instead of a vector, @code{diag} extracts the\n\
01272 @var{k}-th diagonal of the matrix.\n\
01273 @end deftypefn")
01274 {
01275   octave_value retval;
01276 
01277   int nargin = args.length ();
01278 
01279   if (nargin == 1 && args(0).is_defined ())
01280     retval = args(0).diag();
01281   else if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
01282     {
01283       octave_idx_type k = args(1).int_value ();
01284 
01285       if (error_state)
01286         error ("diag: invalid argument K");
01287       else
01288         retval = args(0).diag(k);
01289     }
01290   else if (nargin == 3)
01291     {
01292       octave_value arg0 = args(0);
01293       if (arg0.ndims () == 2 && (args(0).rows () == 1 || args(0).columns () == 1))
01294         {
01295           octave_idx_type m = args(1).int_value (), n = args(2).int_value ();
01296           if (! error_state)
01297             {
01298               if (arg0.is_cell ())
01299                 {
01300                   Cell rhs = arg0.cell_value ();
01301                   Cell tmp (m, n);
01302 
01303                   for (octave_idx_type i = 0; i < rhs.numel (); i++)
01304                     tmp.xelem (i, i) = rhs.xelem (i);
01305 
01306                   retval = tmp;
01307                 }
01308               else
01309                 retval = arg0.diag ().resize (dim_vector (m, n), true);
01310             }
01311           else
01312             error ("diag: invalid dimensions");
01313         }
01314       else
01315         error ("diag: V must be a vector");
01316     }
01317   else
01318     print_usage ();
01319 
01320   return retval;
01321 }
01322 
01323 /*
01324 
01325 %!assert(full (diag ([1; 2; 3])), [1, 0, 0; 0, 2, 0; 0, 0, 3]);
01326 %!assert(diag ([1; 2; 3], 1), [0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]);
01327 %!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]);
01328 %!assert(diag ([1; 2; 3],-1), [0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]);
01329 %!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]);
01330 
01331 %!assert(diag ([1, 0, 0; 0, 2, 0; 0, 0, 3]), [1; 2; 3]);
01332 %!assert(diag ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0], 1), [1; 2; 3]);
01333 %!assert(diag ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0], -1), [1; 2; 3]);
01334 %!assert(diag (ones(1, 0), 2), zeros (2));
01335 %!assert(diag (1:3, 4, 2), [1, 0; 0, 2; 0, 0; 0, 0]);
01336 
01337 %!assert(full (diag (single([1; 2; 3]))), single([1, 0, 0; 0, 2, 0; 0, 0, 3]));
01338 %!assert(diag (single([1; 2; 3]), 1), single([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]));
01339 %!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]));
01340 %!assert(diag (single([1; 2; 3]),-1), single([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]));
01341 %!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]));
01342 
01343 %!assert(diag (single([1, 0, 0; 0, 2, 0; 0, 0, 3])), single([1; 2; 3]));
01344 %!assert(diag (single([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), single([1; 2; 3]));
01345 %!assert(diag (single([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), single([1; 2; 3]));
01346 
01347 %!assert(diag (int8([1; 2; 3])), int8([1, 0, 0; 0, 2, 0; 0, 0, 3]));
01348 %!assert(diag (int8([1; 2; 3]), 1), int8([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]));
01349 %!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]));
01350 %!assert(diag (int8([1; 2; 3]),-1), int8([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]));
01351 %!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]));
01352 
01353 %!assert(diag (int8([1, 0, 0; 0, 2, 0; 0, 0, 3])), int8([1; 2; 3]));
01354 %!assert(diag (int8([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), int8([1; 2; 3]));
01355 %!assert(diag (int8([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), int8([1; 2; 3]));
01356 
01357 ## bug #37411
01358 %!assert (diag (diag ([5, 2, 3])(:,1)), diag([5 0 0 ]))
01359 %!assert (diag (diag ([5, 2, 3])(:,1), 2),  [0 0 5 0 0; zeros(4, 5)])
01360 %!assert (diag (diag ([5, 2, 3])(:,1), -2), [[0 0 5 0 0]', zeros(5, 4)])
01361 
01362 ## Test non-square size
01363 %!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])
01364 %!assert (diag (1, 2, 3), [1,0,0; 0,0,0]);
01365 %!assert (diag ({1}, 2, 3), {1,[],[]; [],[],[]});
01366 %!assert (diag ({1,2}, 3, 4), {1,[],[],[]; [],2,[],[]; [],[],[],[]});
01367 
01368 %% Test input validation
01369 %!error <Invalid call to diag> diag ();
01370 %!error <Invalid call to diag> diag (1,2,3,4);
01371 %!error diag (ones (2), 3, 3);
01372 %!error diag (1:3, -4, 3);
01373 
01374  */
01375 
01376 DEFUN (prod, args, ,
01377   "-*- texinfo -*-\n\
01378 @deftypefn  {Built-in Function} {} prod (@var{x})\n\
01379 @deftypefnx {Built-in Function} {} prod (@var{x}, @var{dim})\n\
01380 Product of elements along dimension @var{dim}.  If @var{dim} is\n\
01381 omitted, it defaults to the first non-singleton dimension.\n\
01382 @seealso{cumprod, sum}\n\
01383 @end deftypefn")
01384 {
01385   DATA_REDUCTION (prod);
01386 }
01387 
01388 /*
01389 
01390 %!assert (prod ([1, 2, 3]), 6);
01391 %!assert (prod ([-1; -2; -3]), -6);
01392 %!assert (prod ([i, 2+i, -3+2i, 4]), -4 - 32i);
01393 %!assert (prod ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [-1+i, -8+8i, -27+27i]);
01394 
01395 %!assert (prod (single([1, 2, 3])), single(6));
01396 %!assert (prod (single([-1; -2; -3])), single(-6));
01397 %!assert (prod (single([i, 2+i, -3+2i, 4])), single(-4 - 32i));
01398 %!assert (prod (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([-1+i, -8+8i, -27+27i]));
01399 
01400 %!error <Invalid call to prod> prod ();
01401 
01402 %!assert (prod ([1, 2; 3, 4], 1), [3, 8]);
01403 %!assert (prod ([1, 2; 3, 4], 2), [2; 12]);
01404 %!assert (prod (zeros (1, 0)), 1);
01405 %!assert (prod (zeros (1, 0), 1), zeros (1, 0));
01406 %!assert (prod (zeros (1, 0), 2), 1);
01407 %!assert (prod (zeros (0, 1)), 1);
01408 %!assert (prod (zeros (0, 1), 1), 1);
01409 %!assert (prod (zeros (0, 1), 2), zeros (0, 1));
01410 %!assert (prod (zeros (2, 0)), zeros (1, 0));
01411 %!assert (prod (zeros (2, 0), 1), zeros (1, 0));
01412 %!assert (prod (zeros (2, 0), 2), [1; 1]);
01413 %!assert (prod (zeros (0, 2)), [1, 1]);
01414 %!assert (prod (zeros (0, 2), 1), [1, 1]);
01415 %!assert (prod (zeros (0, 2), 2), zeros(0, 1));
01416 
01417 %!assert (prod (single([1, 2; 3, 4]), 1), single([3, 8]));
01418 %!assert (prod (single([1, 2; 3, 4]), 2), single([2; 12]));
01419 %!assert (prod (zeros (1, 0, 'single')), single(1));
01420 %!assert (prod (zeros (1, 0, 'single'), 1), zeros (1, 0, 'single'));
01421 %!assert (prod (zeros (1, 0, 'single'), 2), single(1));
01422 %!assert (prod (zeros (0, 1, 'single')), single(1));
01423 %!assert (prod (zeros (0, 1, 'single'), 1), single(1));
01424 %!assert (prod (zeros (0, 1, 'single'), 2), zeros (0, 1, 'single'));
01425 %!assert (prod (zeros (2, 0, 'single')), zeros (1, 0, 'single'));
01426 %!assert (prod (zeros (2, 0, 'single'), 1), zeros (1, 0, 'single'));
01427 %!assert (prod (zeros (2, 0, 'single'), 2), single([1; 1]));
01428 %!assert (prod (zeros (0, 2, 'single')), single([1, 1]));
01429 %!assert (prod (zeros (0, 2, 'single'), 1), single([1, 1]));
01430 %!assert (prod (zeros (0, 2, 'single'), 2), zeros(0, 1, 'single'));
01431 
01432  */
01433 
01434 static bool
01435 all_scalar_1x1 (const octave_value_list& args)
01436 {
01437   int n_args = args.length ();
01438   for (int i = 0; i < n_args; i++)
01439     if (args(i).numel () != 1)
01440       return false;
01441 
01442   return true;
01443 }
01444 
01445 template <class TYPE, class T>
01446 static void
01447 single_type_concat (Array<T>& result,
01448                     const octave_value_list& args,
01449                     int dim)
01450 {
01451   int n_args = args.length ();
01452   if (! (equal_types<T, char>::value
01453          || equal_types<T, octave_value>::value)
01454       && all_scalar_1x1 (args))
01455     {
01456       // Optimize all scalars case.
01457       dim_vector dv (1, 1);
01458       if (dim == -1 || dim == -2)
01459         dim = -dim - 1;
01460       else if (dim >= 2)
01461         dv.resize (dim+1, 1);
01462       dv(dim) = n_args;
01463 
01464       result.clear (dv);
01465 
01466       for (int j = 0; j < n_args && ! error_state; j++)
01467         {
01468           octave_quit ();
01469 
01470           result(j) = octave_value_extract<T> (args(j));
01471         }
01472     }
01473   else
01474     {
01475       OCTAVE_LOCAL_BUFFER (Array<T>, array_list, n_args);
01476 
01477       for (int j = 0; j < n_args && ! error_state; j++)
01478         {
01479           octave_quit ();
01480 
01481           array_list[j] = octave_value_extract<TYPE> (args(j));
01482         }
01483 
01484       if (! error_state)
01485         result = Array<T>::cat (dim, n_args, array_list);
01486     }
01487 }
01488 
01489 template <class TYPE, class T>
01490 static void
01491 single_type_concat (Sparse<T>& result,
01492                     const octave_value_list& args,
01493                     int dim)
01494 {
01495   int n_args = args.length ();
01496   OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_list, n_args);
01497 
01498   for (int j = 0; j < n_args && ! error_state; j++)
01499     {
01500       octave_quit ();
01501 
01502       sparse_list[j] = octave_value_extract<TYPE> (args(j));
01503     }
01504 
01505   if (! error_state)
01506     result = Sparse<T>::cat (dim, n_args, sparse_list);
01507 }
01508 
01509 // Dispatcher.
01510 template<class TYPE>
01511 static TYPE
01512 do_single_type_concat (const octave_value_list& args, int dim)
01513 {
01514   TYPE result;
01515 
01516   single_type_concat<TYPE, typename TYPE::element_type> (result, args, dim);
01517 
01518   return result;
01519 }
01520 
01521 template<class MAP>
01522 static void
01523 single_type_concat_map (octave_map& result,
01524                         const octave_value_list& args,
01525                         int dim)
01526 {
01527   int n_args = args.length ();
01528   OCTAVE_LOCAL_BUFFER (MAP, map_list, n_args);
01529 
01530   for (int j = 0; j < n_args && ! error_state; j++)
01531     {
01532       octave_quit ();
01533 
01534       map_list[j] = octave_value_extract<MAP> (args(j));
01535     }
01536 
01537   if (! error_state)
01538     result = octave_map::cat (dim, n_args, map_list);
01539 }
01540 
01541 static octave_map
01542 do_single_type_concat_map (const octave_value_list& args,
01543                            int dim)
01544 {
01545   octave_map result;
01546   if (all_scalar_1x1 (args)) // optimize all scalars case.
01547     single_type_concat_map<octave_scalar_map> (result, args, dim);
01548   else
01549     single_type_concat_map<octave_map> (result, args, dim);
01550 
01551   return result;
01552 }
01553 
01554 static octave_value
01555 attempt_type_conversion (const octave_value& ov, std::string dtype)
01556 {
01557   octave_value retval;
01558 
01559   // First try to find function in the class of OV that can convert to
01560   // the dispatch type dtype.  It will have the name of the dispatch
01561   // type.
01562 
01563   std::string cname = ov.class_name ();
01564 
01565   octave_value fcn = symbol_table::find_method (dtype, cname);
01566 
01567   if (fcn.is_defined ())
01568     {
01569       octave_value_list result
01570         = fcn.do_multi_index_op (1, octave_value_list (1, ov));
01571 
01572       if (! error_state && result.length () > 0)
01573         retval = result(0);
01574       else
01575         error ("conversion from %s to %s failed", dtype.c_str (),
01576                cname.c_str ());
01577     }
01578   else
01579     {
01580       // No conversion function available.  Try the constructor for the
01581       // dispatch type.
01582 
01583       fcn = symbol_table::find_method (dtype, dtype);
01584 
01585       if (fcn.is_defined ())
01586         {
01587           octave_value_list result
01588             = fcn.do_multi_index_op (1, octave_value_list (1, ov));
01589 
01590           if (! error_state && result.length () > 0)
01591             retval = result(0);
01592           else
01593             error ("%s constructor failed for %s argument", dtype.c_str (),
01594                    cname.c_str ());
01595         }
01596       else
01597         error ("no constructor for %s!", dtype.c_str ());
01598     }
01599 
01600   return retval;
01601 }
01602 
01603 octave_value
01604 do_class_concat (const octave_value_list& ovl, std::string cattype, int dim)
01605 {
01606   octave_value retval;
01607 
01608   // Get dominant type for list
01609 
01610   std::string dtype = get_dispatch_type (ovl);
01611 
01612   octave_value fcn = symbol_table::find_method (cattype, dtype);
01613 
01614   if (fcn.is_defined ())
01615     {
01616       // Have method for dominant type, so call it and let it handle
01617       // conversions.
01618 
01619       octave_value_list tmp2 = fcn.do_multi_index_op (1, ovl);
01620 
01621       if (! error_state)
01622         {
01623           if (tmp2.length () > 0)
01624             retval = tmp2(0);
01625           else
01626             {
01627               error ("%s/%s method did not return a value",
01628                      dtype.c_str (), cattype.c_str ());
01629               goto done;
01630             }
01631         }
01632       else
01633         goto done;
01634     }
01635   else
01636     {
01637       // No method for dominant type, so attempt type conversions for
01638       // all elements that are not of the dominant type, then do the
01639       // default operation for octave_class values.
01640 
01641       octave_idx_type j = 0;
01642       octave_idx_type len = ovl.length ();
01643       octave_value_list tmp (len, octave_value ());
01644       for (octave_idx_type k = 0; k < len; k++)
01645         {
01646           octave_value elt = ovl(k);
01647 
01648           std::string t1_type = elt.class_name ();
01649 
01650           if (t1_type == dtype)
01651             tmp(j++) = elt;
01652           else if (elt.is_object () || ! elt.is_empty ())
01653             {
01654               tmp(j++) = attempt_type_conversion (elt, dtype);
01655 
01656               if (error_state)
01657                 goto done;
01658             }
01659         }
01660 
01661       tmp.resize (j);
01662 
01663       octave_map m = do_single_type_concat_map (tmp, dim);
01664 
01665       std::string cname = tmp(0).class_name ();
01666       std::list<std::string> parents = tmp(0).parent_class_name_list ();
01667 
01668       retval = octave_value (new octave_class (m, cname, parents));
01669     }
01670 
01671  done:
01672   return retval;
01673 }
01674 
01675 static octave_value
01676 do_cat (const octave_value_list& xargs, int dim, std::string fname)
01677 {
01678   octave_value retval;
01679 
01680   // We may need to convert elements of the list to cells, so make a
01681   // copy.  This should be efficient, it is done mostly by incrementing
01682   // reference counts.
01683   octave_value_list args = xargs;
01684 
01685   int n_args = args.length ();
01686 
01687   if (n_args == 0)
01688     retval = Matrix ();
01689   else if (n_args == 1)
01690     retval = args(0);
01691   else if (n_args > 1)
01692     {
01693       std::string result_type;
01694 
01695       bool all_sq_strings_p = true;
01696       bool all_dq_strings_p = true;
01697       bool all_real_p = true;
01698       bool all_cmplx_p = true;
01699       bool any_sparse_p = false;
01700       bool any_cell_p = false;
01701       bool any_class_p = false;
01702 
01703       bool first_elem_is_struct = false;
01704 
01705       for (int i = 0; i < n_args; i++)
01706         {
01707           if (i == 0)
01708             {
01709               result_type = args(i).class_name ();
01710 
01711               first_elem_is_struct = args(i).is_map ();
01712             }
01713           else
01714             result_type = get_concat_class (result_type, args(i).class_name ());
01715 
01716           if (all_sq_strings_p && ! args(i).is_sq_string ())
01717             all_sq_strings_p = false;
01718           if (all_dq_strings_p && ! args(i).is_dq_string ())
01719             all_dq_strings_p = false;
01720           if (all_real_p && ! args(i).is_real_type ())
01721             all_real_p = false;
01722           if (all_cmplx_p && ! (args(i).is_complex_type () || args(i).is_real_type ()))
01723             all_cmplx_p = false;
01724           if (!any_sparse_p && args(i).is_sparse_type ())
01725             any_sparse_p = true;
01726           if (!any_cell_p && args(i).is_cell ())
01727             any_cell_p = true;
01728           if (!any_class_p && args(i).is_object ())
01729             any_class_p = true;
01730         }
01731 
01732       if (any_cell_p && ! any_class_p && ! first_elem_is_struct)
01733         {
01734           for (int i = 0; i < n_args; i++)
01735             {
01736               if (! args(i).is_cell ())
01737                 args(i) = Cell (args(i));
01738             }
01739         }
01740 
01741       if (any_class_p)
01742         {
01743           retval = do_class_concat (args, fname, dim);
01744         }
01745       else if (result_type == "double")
01746         {
01747           if (any_sparse_p)
01748             {
01749               if (all_real_p)
01750                 retval = do_single_type_concat<SparseMatrix> (args, dim);
01751               else
01752                 retval = do_single_type_concat<SparseComplexMatrix> (args, dim);
01753             }
01754           else
01755             {
01756               if (all_real_p)
01757                 retval = do_single_type_concat<NDArray> (args, dim);
01758               else
01759                 retval = do_single_type_concat<ComplexNDArray> (args, dim);
01760             }
01761         }
01762       else if (result_type == "single")
01763         {
01764           if (all_real_p)
01765             retval = do_single_type_concat<FloatNDArray> (args, dim);
01766           else
01767             retval = do_single_type_concat<FloatComplexNDArray> (args, dim);
01768         }
01769       else if (result_type == "char")
01770         {
01771           char type = all_dq_strings_p ? '"' : '\'';
01772 
01773           maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
01774 
01775           charNDArray result =  do_single_type_concat<charNDArray> (args, dim);
01776 
01777           retval = octave_value (result, type);
01778         }
01779       else if (result_type == "logical")
01780         {
01781           if (any_sparse_p)
01782             retval = do_single_type_concat<SparseBoolMatrix> (args, dim);
01783           else
01784             retval = do_single_type_concat<boolNDArray> (args, dim);
01785         }
01786       else if (result_type == "int8")
01787         retval = do_single_type_concat<int8NDArray> (args, dim);
01788       else if (result_type == "int16")
01789         retval = do_single_type_concat<int16NDArray> (args, dim);
01790       else if (result_type == "int32")
01791         retval = do_single_type_concat<int32NDArray> (args, dim);
01792       else if (result_type == "int64")
01793         retval = do_single_type_concat<int64NDArray> (args, dim);
01794       else if (result_type == "uint8")
01795         retval = do_single_type_concat<uint8NDArray> (args, dim);
01796       else if (result_type == "uint16")
01797         retval = do_single_type_concat<uint16NDArray> (args, dim);
01798       else if (result_type == "uint32")
01799         retval = do_single_type_concat<uint32NDArray> (args, dim);
01800       else if (result_type == "uint64")
01801         retval = do_single_type_concat<uint64NDArray> (args, dim);
01802       else if (result_type == "cell")
01803         retval = do_single_type_concat<Cell> (args, dim);
01804       else if (result_type == "struct")
01805         retval = do_single_type_concat_map (args, dim);
01806       else
01807         {
01808           dim_vector  dv = args(0).dims ();
01809 
01810           // Default concatenation.
01811           bool (dim_vector::*concat_rule) (const dim_vector&, int) = &dim_vector::concat;
01812 
01813           if (dim == -1 || dim == -2)
01814             {
01815               concat_rule = &dim_vector::hvcat;
01816               dim = -dim - 1;
01817             }
01818 
01819           for (int i = 1; i < args.length (); i++)
01820             {
01821               if (! (dv.*concat_rule) (args(i).dims (), dim))
01822                 {
01823                   // Dimensions do not match.
01824                   error ("cat: dimension mismatch");
01825                   return retval;
01826                 }
01827             }
01828 
01829           // The lines below might seem crazy, since we take a copy
01830           // of the first argument, resize it to be empty and then resize
01831           // it to be full. This is done since it means that there is no
01832           // recopying of data, as would happen if we used a single resize.
01833           // It should be noted that resize operation is also significantly
01834           // slower than the do_cat_op function, so it makes sense to have
01835           // an empty matrix and copy all data.
01836           //
01837           // We might also start with a empty octave_value using
01838           //   tmp = octave_value_typeinfo::lookup_type
01839           //                                (args(1).type_name());
01840           // and then directly resize. However, for some types there might
01841           // be some additional setup needed, and so this should be avoided.
01842 
01843           octave_value tmp = args (0);
01844           tmp = tmp.resize (dim_vector (0,0)).resize (dv);
01845 
01846           if (error_state)
01847             return retval;
01848 
01849           int dv_len = dv.length ();
01850           Array<octave_idx_type> ra_idx (dim_vector (dv_len, 1), 0);
01851 
01852           for (int j = 0; j < n_args; j++)
01853             {
01854               // Can't fast return here to skip empty matrices as something
01855               // like cat(1,[],single([])) must return an empty matrix of
01856               // the right type.
01857               tmp = do_cat_op (tmp, args (j), ra_idx);
01858 
01859               if (error_state)
01860                 return retval;
01861 
01862               dim_vector dv_tmp = args (j).dims ();
01863 
01864               if (dim >= dv_len)
01865                 {
01866                   if (j > 1)
01867                     error ("%s: indexing error", fname.c_str ());
01868                   break;
01869                 }
01870               else
01871                 ra_idx (dim) += (dim < dv_tmp.length () ?
01872                                  dv_tmp (dim) : 1);
01873             }
01874           retval = tmp;
01875         }
01876     }
01877   else
01878     print_usage ();
01879 
01880   return retval;
01881 }
01882 
01883 DEFUN (horzcat, args, ,
01884        "-*- texinfo -*-\n\
01885 @deftypefn {Built-in Function} {} horzcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
01886 Return the horizontal concatenation of N-D array objects, @var{array1},\n\
01887 @var{array2}, @dots{}, @var{arrayN} along dimension 2.\n\
01888 \n\
01889 Arrays may also be concatenated horizontally using the syntax for creating\n\
01890 new matrices.  For example:\n\
01891 \n\
01892 @example\n\
01893 @var{hcat} = [ @var{array1}, @var{array2}, @dots{} ];\n\
01894 @end example\n\
01895 @seealso{cat, vertcat}\n\
01896 @end deftypefn")
01897 {
01898   return do_cat (args, -2, "horzcat");
01899 }
01900 
01901 /*
01902 %% test concatenation with all zero matrices
01903 %!assert(horzcat ('', 65*ones(1,10)), 'AAAAAAAAAA');
01904 %!assert(horzcat (65*ones(1,10), ''), 'AAAAAAAAAA');
01905 
01906 %!assert (class (horzcat (int64(1), int64(1))), 'int64')
01907 %!assert (class (horzcat (int64(1), int32(1))), 'int64')
01908 %!assert (class (horzcat (int64(1), int16(1))), 'int64')
01909 %!assert (class (horzcat (int64(1), int8(1))), 'int64')
01910 %!assert (class (horzcat (int64(1), uint64(1))), 'int64')
01911 %!assert (class (horzcat (int64(1), uint32(1))), 'int64')
01912 %!assert (class (horzcat (int64(1), uint16(1))), 'int64')
01913 %!assert (class (horzcat (int64(1), uint8(1))), 'int64')
01914 %!assert (class (horzcat (int64(1), single(1))), 'int64')
01915 %!assert (class (horzcat (int64(1), double(1))), 'int64')
01916 %!assert (class (horzcat (int64(1), cell(1))), 'cell')
01917 %!assert (class (horzcat (int64(1), true)), 'int64')
01918 %!assert (class (horzcat (int64(1), 'a')), 'char')
01919 
01920 %!assert (class (horzcat (int32(1), int64(1))), 'int32')
01921 %!assert (class (horzcat (int32(1), int32(1))), 'int32')
01922 %!assert (class (horzcat (int32(1), int16(1))), 'int32')
01923 %!assert (class (horzcat (int32(1), int8(1))), 'int32')
01924 %!assert (class (horzcat (int32(1), uint64(1))), 'int32')
01925 %!assert (class (horzcat (int32(1), uint32(1))), 'int32')
01926 %!assert (class (horzcat (int32(1), uint16(1))), 'int32')
01927 %!assert (class (horzcat (int32(1), uint8(1))), 'int32')
01928 %!assert (class (horzcat (int32(1), single(1))), 'int32')
01929 %!assert (class (horzcat (int32(1), double(1))), 'int32')
01930 %!assert (class (horzcat (int32(1), cell(1))), 'cell')
01931 %!assert (class (horzcat (int32(1), true)), 'int32')
01932 %!assert (class (horzcat (int32(1), 'a')), 'char')
01933 
01934 %!assert (class (horzcat (int16(1), int64(1))), 'int16')
01935 %!assert (class (horzcat (int16(1), int32(1))), 'int16')
01936 %!assert (class (horzcat (int16(1), int16(1))), 'int16')
01937 %!assert (class (horzcat (int16(1), int8(1))), 'int16')
01938 %!assert (class (horzcat (int16(1), uint64(1))), 'int16')
01939 %!assert (class (horzcat (int16(1), uint32(1))), 'int16')
01940 %!assert (class (horzcat (int16(1), uint16(1))), 'int16')
01941 %!assert (class (horzcat (int16(1), uint8(1))), 'int16')
01942 %!assert (class (horzcat (int16(1), single(1))), 'int16')
01943 %!assert (class (horzcat (int16(1), double(1))), 'int16')
01944 %!assert (class (horzcat (int16(1), cell(1))), 'cell')
01945 %!assert (class (horzcat (int16(1), true)), 'int16')
01946 %!assert (class (horzcat (int16(1), 'a')), 'char')
01947 
01948 %!assert (class (horzcat (int8(1), int64(1))), 'int8')
01949 %!assert (class (horzcat (int8(1), int32(1))), 'int8')
01950 %!assert (class (horzcat (int8(1), int16(1))), 'int8')
01951 %!assert (class (horzcat (int8(1), int8(1))), 'int8')
01952 %!assert (class (horzcat (int8(1), uint64(1))), 'int8')
01953 %!assert (class (horzcat (int8(1), uint32(1))), 'int8')
01954 %!assert (class (horzcat (int8(1), uint16(1))), 'int8')
01955 %!assert (class (horzcat (int8(1), uint8(1))), 'int8')
01956 %!assert (class (horzcat (int8(1), single(1))), 'int8')
01957 %!assert (class (horzcat (int8(1), double(1))), 'int8')
01958 %!assert (class (horzcat (int8(1), cell(1))), 'cell')
01959 %!assert (class (horzcat (int8(1), true)), 'int8')
01960 %!assert (class (horzcat (int8(1), 'a')), 'char')
01961 
01962 %!assert (class (horzcat (uint64(1), int64(1))), 'uint64')
01963 %!assert (class (horzcat (uint64(1), int32(1))), 'uint64')
01964 %!assert (class (horzcat (uint64(1), int16(1))), 'uint64')
01965 %!assert (class (horzcat (uint64(1), int8(1))), 'uint64')
01966 %!assert (class (horzcat (uint64(1), uint64(1))), 'uint64')
01967 %!assert (class (horzcat (uint64(1), uint32(1))), 'uint64')
01968 %!assert (class (horzcat (uint64(1), uint16(1))), 'uint64')
01969 %!assert (class (horzcat (uint64(1), uint8(1))), 'uint64')
01970 %!assert (class (horzcat (uint64(1), single(1))), 'uint64')
01971 %!assert (class (horzcat (uint64(1), double(1))), 'uint64')
01972 %!assert (class (horzcat (uint64(1), cell(1))), 'cell')
01973 %!assert (class (horzcat (uint64(1), true)), 'uint64')
01974 %!assert (class (horzcat (uint64(1), 'a')), 'char')
01975 
01976 %!assert (class (horzcat (uint32(1), int64(1))), 'uint32')
01977 %!assert (class (horzcat (uint32(1), int32(1))), 'uint32')
01978 %!assert (class (horzcat (uint32(1), int16(1))), 'uint32')
01979 %!assert (class (horzcat (uint32(1), int8(1))), 'uint32')
01980 %!assert (class (horzcat (uint32(1), uint64(1))), 'uint32')
01981 %!assert (class (horzcat (uint32(1), uint32(1))), 'uint32')
01982 %!assert (class (horzcat (uint32(1), uint16(1))), 'uint32')
01983 %!assert (class (horzcat (uint32(1), uint8(1))), 'uint32')
01984 %!assert (class (horzcat (uint32(1), single(1))), 'uint32')
01985 %!assert (class (horzcat (uint32(1), double(1))), 'uint32')
01986 %!assert (class (horzcat (uint32(1), cell(1))), 'cell')
01987 %!assert (class (horzcat (uint32(1), true)), 'uint32')
01988 %!assert (class (horzcat (uint32(1), 'a')), 'char')
01989 
01990 %!assert (class (horzcat (uint16(1), int64(1))), 'uint16')
01991 %!assert (class (horzcat (uint16(1), int32(1))), 'uint16')
01992 %!assert (class (horzcat (uint16(1), int16(1))), 'uint16')
01993 %!assert (class (horzcat (uint16(1), int8(1))), 'uint16')
01994 %!assert (class (horzcat (uint16(1), uint64(1))), 'uint16')
01995 %!assert (class (horzcat (uint16(1), uint32(1))), 'uint16')
01996 %!assert (class (horzcat (uint16(1), uint16(1))), 'uint16')
01997 %!assert (class (horzcat (uint16(1), uint8(1))), 'uint16')
01998 %!assert (class (horzcat (uint16(1), single(1))), 'uint16')
01999 %!assert (class (horzcat (uint16(1), double(1))), 'uint16')
02000 %!assert (class (horzcat (uint16(1), cell(1))), 'cell')
02001 %!assert (class (horzcat (uint16(1), true)), 'uint16')
02002 %!assert (class (horzcat (uint16(1), 'a')), 'char')
02003 
02004 %!assert (class (horzcat (uint8(1), int64(1))), 'uint8')
02005 %!assert (class (horzcat (uint8(1), int32(1))), 'uint8')
02006 %!assert (class (horzcat (uint8(1), int16(1))), 'uint8')
02007 %!assert (class (horzcat (uint8(1), int8(1))), 'uint8')
02008 %!assert (class (horzcat (uint8(1), uint64(1))), 'uint8')
02009 %!assert (class (horzcat (uint8(1), uint32(1))), 'uint8')
02010 %!assert (class (horzcat (uint8(1), uint16(1))), 'uint8')
02011 %!assert (class (horzcat (uint8(1), uint8(1))), 'uint8')
02012 %!assert (class (horzcat (uint8(1), single(1))), 'uint8')
02013 %!assert (class (horzcat (uint8(1), double(1))), 'uint8')
02014 %!assert (class (horzcat (uint8(1), cell(1))), 'cell')
02015 %!assert (class (horzcat (uint8(1), true)), 'uint8')
02016 %!assert (class (horzcat (uint8(1), 'a')), 'char')
02017 
02018 %!assert (class (horzcat (single(1), int64(1))), 'int64')
02019 %!assert (class (horzcat (single(1), int32(1))), 'int32')
02020 %!assert (class (horzcat (single(1), int16(1))), 'int16')
02021 %!assert (class (horzcat (single(1), int8(1))), 'int8')
02022 %!assert (class (horzcat (single(1), uint64(1))), 'uint64')
02023 %!assert (class (horzcat (single(1), uint32(1))), 'uint32')
02024 %!assert (class (horzcat (single(1), uint16(1))), 'uint16')
02025 %!assert (class (horzcat (single(1), uint8(1))), 'uint8')
02026 %!assert (class (horzcat (single(1), single(1))), 'single')
02027 %!assert (class (horzcat (single(1), double(1))), 'single')
02028 %!assert (class (horzcat (single(1), cell(1))), 'cell')
02029 %!assert (class (horzcat (single(1), true)), 'single')
02030 %!assert (class (horzcat (single(1), 'a')), 'char')
02031 
02032 %!assert (class (horzcat (double(1), int64(1))), 'int64')
02033 %!assert (class (horzcat (double(1), int32(1))), 'int32')
02034 %!assert (class (horzcat (double(1), int16(1))), 'int16')
02035 %!assert (class (horzcat (double(1), int8(1))), 'int8')
02036 %!assert (class (horzcat (double(1), uint64(1))), 'uint64')
02037 %!assert (class (horzcat (double(1), uint32(1))), 'uint32')
02038 %!assert (class (horzcat (double(1), uint16(1))), 'uint16')
02039 %!assert (class (horzcat (double(1), uint8(1))), 'uint8')
02040 %!assert (class (horzcat (double(1), single(1))), 'single')
02041 %!assert (class (horzcat (double(1), double(1))), 'double')
02042 %!assert (class (horzcat (double(1), cell(1))), 'cell')
02043 %!assert (class (horzcat (double(1), true)), 'double')
02044 %!assert (class (horzcat (double(1), 'a')), 'char')
02045 
02046 %!assert (class (horzcat (cell(1), int64(1))), 'cell')
02047 %!assert (class (horzcat (cell(1), int32(1))), 'cell')
02048 %!assert (class (horzcat (cell(1), int16(1))), 'cell')
02049 %!assert (class (horzcat (cell(1), int8(1))), 'cell')
02050 %!assert (class (horzcat (cell(1), uint64(1))), 'cell')
02051 %!assert (class (horzcat (cell(1), uint32(1))), 'cell')
02052 %!assert (class (horzcat (cell(1), uint16(1))), 'cell')
02053 %!assert (class (horzcat (cell(1), uint8(1))), 'cell')
02054 %!assert (class (horzcat (cell(1), single(1))), 'cell')
02055 %!assert (class (horzcat (cell(1), double(1))), 'cell')
02056 %!assert (class (horzcat (cell(1), cell(1))), 'cell')
02057 %!assert (class (horzcat (cell(1), true)), 'cell')
02058 %!assert (class (horzcat (cell(1), 'a')), 'cell')
02059 
02060 %!assert (class (horzcat (true, int64(1))), 'int64')
02061 %!assert (class (horzcat (true, int32(1))), 'int32')
02062 %!assert (class (horzcat (true, int16(1))), 'int16')
02063 %!assert (class (horzcat (true, int8(1))), 'int8')
02064 %!assert (class (horzcat (true, uint64(1))), 'uint64')
02065 %!assert (class (horzcat (true, uint32(1))), 'uint32')
02066 %!assert (class (horzcat (true, uint16(1))), 'uint16')
02067 %!assert (class (horzcat (true, uint8(1))), 'uint8')
02068 %!assert (class (horzcat (true, single(1))), 'single')
02069 %!assert (class (horzcat (true, double(1))), 'double')
02070 %!assert (class (horzcat (true, cell(1))), 'cell')
02071 %!assert (class (horzcat (true, true)), 'logical')
02072 %!assert (class (horzcat (true, 'a')), 'char')
02073 
02074 %!assert (class (horzcat ('a', int64(1))), 'char')
02075 %!assert (class (horzcat ('a', int32(1))), 'char')
02076 %!assert (class (horzcat ('a', int16(1))), 'char')
02077 %!assert (class (horzcat ('a', int8(1))), 'char')
02078 %!assert (class (horzcat ('a', int64(1))), 'char')
02079 %!assert (class (horzcat ('a', int32(1))), 'char')
02080 %!assert (class (horzcat ('a', int16(1))), 'char')
02081 %!assert (class (horzcat ('a', int8(1))), 'char')
02082 %!assert (class (horzcat ('a', single(1))), 'char')
02083 %!assert (class (horzcat ('a', double(1))), 'char')
02084 %!assert (class (horzcat ('a', cell(1))), 'cell')
02085 %!assert (class (horzcat ('a', true)), 'char')
02086 %!assert (class (horzcat ('a', 'a')), 'char')
02087 
02088 %!assert (class (horzcat (cell(1), struct('foo', 'bar'))), 'cell')
02089 %!error horzcat (struct('foo', 'bar'), cell(1));
02090 */
02091 
02092 DEFUN (vertcat, args, ,
02093   "-*- texinfo -*-\n\
02094 @deftypefn {Built-in Function} {} vertcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
02095 Return the vertical concatenation of N-D array objects, @var{array1},\n\
02096 @var{array2}, @dots{}, @var{arrayN} along dimension 1.\n\
02097 \n\
02098 Arrays may also be concatenated vertically using the syntax for creating\n\
02099 new matrices.  For example:\n\
02100 \n\
02101 @example\n\
02102 @var{vcat} = [ @var{array1}; @var{array2}; @dots{} ];\n\
02103 @end example\n\
02104 @seealso{cat, horzcat}\n\
02105 @end deftypefn")
02106 {
02107   return do_cat (args, -1, "vertcat");
02108 }
02109 
02110 /*
02111 %!test
02112 %! c = {'foo'; 'bar'; 'bazoloa'};
02113 %! assert (vertcat (c, 'a', 'bc', 'def'), {'foo'; 'bar'; 'bazoloa'; 'a'; 'bc'; 'def'});
02114 */
02115 
02116 DEFUN (cat, args, ,
02117   "-*- texinfo -*-\n\
02118 @deftypefn {Built-in Function} {} cat (@var{dim}, @var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
02119 Return the concatenation of N-D array objects, @var{array1},\n\
02120 @var{array2}, @dots{}, @var{arrayN} along dimension @var{dim}.\n\
02121 \n\
02122 @example\n\
02123 @group\n\
02124 A = ones (2, 2);\n\
02125 B = zeros (2, 2);\n\
02126 cat (2, A, B)\n\
02127     @result{} 1 1 0 0\n\
02128        1 1 0 0\n\
02129 @end group\n\
02130 @end example\n\
02131 \n\
02132 Alternatively, we can concatenate @var{A} and @var{B} along the\n\
02133 second dimension the following way:\n\
02134 \n\
02135 @example\n\
02136 @group\n\
02137 [A, B].\n\
02138 @end group\n\
02139 @end example\n\
02140 \n\
02141 @var{dim} can be larger than the dimensions of the N-D array objects\n\
02142 and the result will thus have @var{dim} dimensions as the\n\
02143 following example shows:\n\
02144 \n\
02145 @example\n\
02146 @group\n\
02147 cat (4, ones (2, 2), zeros (2, 2))\n\
02148     @result{} ans =\n\
02149 \n\
02150        ans(:,:,1,1) =\n\
02151 \n\
02152          1 1\n\
02153          1 1\n\
02154 \n\
02155        ans(:,:,1,2) =\n\
02156          0 0\n\
02157          0 0\n\
02158 @end group\n\
02159 @end example\n\
02160 @seealso{horzcat, vertcat}\n\
02161 @end deftypefn")
02162 {
02163   octave_value retval;
02164 
02165   if (args.length () > 0)
02166     {
02167       int dim = args(0).int_value () - 1;
02168 
02169       if (! error_state)
02170         {
02171           if (dim >= 0)
02172             retval = do_cat (args.slice (1, args.length () - 1), dim, "cat");
02173           else
02174             error ("cat: DIM must be a valid dimension");
02175         }
02176       else
02177         error ("cat: DIM must be an integer");
02178     }
02179   else
02180     print_usage ();
02181 
02182   return retval;
02183 }
02184 
02185 /*
02186 
02187 %!function ret = __testcat (t1, t2, tr, cmplx)
02188 %! assert (cat (1, cast ([], t1), cast([], t2)), cast ([], tr));
02189 %!
02190 %! assert (cat (1, cast (1, t1), cast (2, t2)), cast ([1; 2], tr));
02191 %! assert (cat (1, cast (1, t1), cast ([2; 3], t2)), cast ([1; 2; 3], tr));
02192 %! assert (cat (1, cast ([1; 2], t1), cast (3, t2)), cast ([1; 2; 3], tr));
02193 %! assert (cat (1, cast ([1; 2], t1), cast ([3; 4], t2)), cast ([1; 2; 3; 4], tr));
02194 %! assert (cat (2, cast (1, t1), cast (2, t2)), cast ([1, 2], tr));
02195 %! assert (cat (2, cast (1, t1), cast ([2, 3], t2)), cast ([1, 2, 3], tr));
02196 %! assert (cat (2, cast ([1, 2], t1), cast (3, t2)), cast ([1, 2, 3], tr));
02197 %! assert (cat (2, cast ([1, 2], t1), cast ([3, 4], t2)), cast ([1, 2, 3, 4], tr));
02198 %!
02199 %! assert ([cast(1, t1); cast(2, t2)], cast ([1; 2], tr));
02200 %! assert ([cast(1, t1); cast([2; 3], t2)], cast ([1; 2; 3], tr));
02201 %! assert ([cast([1; 2], t1); cast(3, t2)], cast ([1; 2; 3], tr));
02202 %! assert ([cast([1; 2], t1); cast([3; 4], t2)], cast ([1; 2; 3; 4], tr));
02203 %! assert ([cast(1, t1), cast(2, t2)], cast ([1, 2], tr));
02204 %! assert ([cast(1, t1), cast([2, 3], t2)], cast ([1, 2, 3], tr));
02205 %! assert ([cast([1, 2], t1), cast(3, t2)], cast ([1, 2, 3], tr));
02206 %! assert ([cast([1, 2], t1), cast([3, 4], t2)], cast ([1, 2, 3, 4], tr));
02207 %!
02208 %! if (nargin == 3 || cmplx)
02209 %!   assert (cat (1, cast (1i, t1), cast (2, t2)), cast ([1i; 2], tr));
02210 %!   assert (cat (1, cast (1i, t1), cast ([2; 3], t2)), cast ([1i; 2; 3], tr));
02211 %!   assert (cat (1, cast ([1i; 2], t1), cast (3, t2)), cast ([1i; 2; 3], tr));
02212 %!   assert (cat (1, cast ([1i; 2], t1), cast ([3; 4], t2)), cast ([1i; 2; 3; 4], tr));
02213 %!   assert (cat (2, cast (1i, t1), cast (2, t2)), cast ([1i, 2], tr));
02214 %!   assert (cat (2, cast (1i, t1), cast ([2, 3], t2)), cast ([1i, 2, 3], tr));
02215 %!   assert (cat (2, cast ([1i, 2], t1), cast (3, t2)), cast ([1i, 2, 3], tr));
02216 %!   assert (cat (2, cast ([1i, 2], t1), cast ([3, 4], t2)), cast ([1i, 2, 3, 4], tr));
02217 %!
02218 %!   assert ([cast(1i, t1); cast(2, t2)], cast ([1i; 2], tr));
02219 %!   assert ([cast(1i, t1); cast([2; 3], t2)], cast ([1i; 2; 3], tr));
02220 %!   assert ([cast([1i; 2], t1); cast(3, t2)], cast ([1i; 2; 3], tr));
02221 %!   assert ([cast([1i; 2], t1); cast([3; 4], t2)], cast ([1i; 2; 3; 4], tr));
02222 %!   assert ([cast(1i, t1), cast(2, t2)], cast ([1i, 2], tr));
02223 %!   assert ([cast(1i, t1), cast([2, 3], t2)], cast ([1i, 2, 3], tr));
02224 %!   assert ([cast([1i, 2], t1), cast(3, t2)], cast ([1i, 2, 3], tr));
02225 %!   assert ([cast([1i, 2], t1), cast([3, 4], t2)], cast ([1i, 2, 3, 4], tr));
02226 %!
02227 %!   assert (cat (1, cast (1, t1), cast (2i, t2)), cast ([1; 2i], tr));
02228 %!   assert (cat (1, cast (1, t1), cast ([2i; 3], t2)), cast ([1; 2i; 3], tr));
02229 %!   assert (cat (1, cast ([1; 2], t1), cast (3i, t2)), cast ([1; 2; 3i], tr));
02230 %!   assert (cat (1, cast ([1; 2], t1), cast ([3i; 4], t2)), cast ([1; 2; 3i; 4], tr));
02231 %!   assert (cat (2, cast (1, t1), cast (2i, t2)), cast ([1, 2i], tr));
02232 %!   assert (cat (2, cast (1, t1), cast ([2i, 3], t2)), cast ([1, 2i, 3], tr));
02233 %!   assert (cat (2, cast ([1, 2], t1), cast (3i, t2)), cast ([1, 2, 3i], tr));
02234 %!   assert (cat (2, cast ([1, 2], t1), cast ([3i, 4], t2)), cast ([1, 2, 3i, 4], tr));
02235 %!
02236 %!   assert ([cast(1, t1); cast(2i, t2)], cast ([1; 2i], tr));
02237 %!   assert ([cast(1, t1); cast([2i; 3], t2)], cast ([1; 2i; 3], tr));
02238 %!   assert ([cast([1; 2], t1); cast(3i, t2)], cast ([1; 2; 3i], tr));
02239 %!   assert ([cast([1; 2], t1); cast([3i; 4], t2)], cast ([1; 2; 3i; 4], tr));
02240 %!   assert ([cast(1, t1), cast(2i, t2)], cast ([1, 2i], tr));
02241 %!   assert ([cast(1, t1), cast([2i, 3], t2)], cast ([1, 2i, 3], tr));
02242 %!   assert ([cast([1, 2], t1), cast(3i, t2)], cast ([1, 2, 3i], tr));
02243 %!   assert ([cast([1, 2], t1), cast([3i, 4], t2)], cast ([1, 2, 3i, 4], tr));
02244 %!
02245 %!   assert (cat (1, cast (1i, t1), cast (2i, t2)), cast ([1i; 2i], tr));
02246 %!   assert (cat (1, cast (1i, t1), cast ([2i; 3], t2)), cast ([1i; 2i; 3], tr));
02247 %!   assert (cat (1, cast ([1i; 2], t1), cast (3i, t2)), cast ([1i; 2; 3i], tr));
02248 %!   assert (cat (1, cast ([1i; 2], t1), cast ([3i; 4], t2)), cast ([1i; 2; 3i; 4], tr));
02249 %!   assert (cat (2, cast (1i, t1), cast (2i, t2)), cast ([1i, 2i], tr));
02250 %!   assert (cat (2, cast (1i, t1), cast ([2i, 3], t2)), cast ([1i, 2i, 3], tr));
02251 %!   assert (cat (2, cast ([1i, 2], t1), cast (3i, t2)), cast ([1i, 2, 3i], tr));
02252 %!   assert (cat (2, cast ([1i, 2], t1), cast ([3i, 4], t2)), cast ([1i, 2, 3i, 4], tr));
02253 %!
02254 %!   assert ([cast(1i, t1); cast(2i, t2)], cast ([1i; 2i], tr));
02255 %!   assert ([cast(1i, t1); cast([2i; 3], t2)], cast ([1i; 2i; 3], tr));
02256 %!   assert ([cast([1i; 2], t1); cast(3i, t2)], cast ([1i; 2; 3i], tr));
02257 %!   assert ([cast([1i; 2], t1); cast([3i; 4], t2)], cast ([1i; 2; 3i; 4], tr));
02258 %!   assert ([cast(1i, t1), cast(2i, t2)], cast ([1i, 2i], tr));
02259 %!   assert ([cast(1i, t1), cast([2i, 3], t2)], cast ([1i, 2i, 3], tr));
02260 %!   assert ([cast([1i, 2], t1), cast(3i, t2)], cast ([1i, 2, 3i], tr));
02261 %!   assert ([cast([1i, 2], t1), cast([3i, 4], t2)], cast ([1i, 2, 3i, 4], tr));
02262 %! endif
02263 %! ret = true;
02264 %!endfunction
02265 
02266 %!assert (__testcat('double', 'double', 'double'))
02267 %!assert (__testcat('single', 'double', 'single'))
02268 %!assert (__testcat('double', 'single', 'single'))
02269 %!assert (__testcat('single', 'single', 'single'))
02270 
02271 %!assert (__testcat('double', 'int8', 'int8', false))
02272 %!assert (__testcat('int8', 'double', 'int8', false))
02273 %!assert (__testcat('single', 'int8', 'int8', false))
02274 %!assert (__testcat('int8', 'single', 'int8', false))
02275 %!assert (__testcat('int8', 'int8', 'int8', false))
02276 %!assert (__testcat('double', 'int16', 'int16', false))
02277 %!assert (__testcat('int16', 'double', 'int16', false))
02278 %!assert (__testcat('single', 'int16', 'int16', false))
02279 %!assert (__testcat('int16', 'single', 'int16', false))
02280 %!assert (__testcat('int16', 'int16', 'int16', false))
02281 %!assert (__testcat('double', 'int32', 'int32', false))
02282 %!assert (__testcat('int32', 'double', 'int32', false))
02283 %!assert (__testcat('single', 'int32', 'int32', false))
02284 %!assert (__testcat('int32', 'single', 'int32', false))
02285 %!assert (__testcat('int32', 'int32', 'int32', false))
02286 %!assert (__testcat('double', 'int64', 'int64', false))
02287 %!assert (__testcat('int64', 'double', 'int64', false))
02288 %!assert (__testcat('single', 'int64', 'int64', false))
02289 %!assert (__testcat('int64', 'single', 'int64', false))
02290 %!assert (__testcat('int64', 'int64', 'int64', false))
02291 
02292 %!assert (__testcat('double', 'uint8', 'uint8', false))
02293 %!assert (__testcat('uint8', 'double', 'uint8', false))
02294 %!assert (__testcat('single', 'uint8', 'uint8', false))
02295 %!assert (__testcat('uint8', 'single', 'uint8', false))
02296 %!assert (__testcat('uint8', 'uint8', 'uint8', false))
02297 %!assert (__testcat('double', 'uint16', 'uint16', false))
02298 %!assert (__testcat('uint16', 'double', 'uint16', false))
02299 %!assert (__testcat('single', 'uint16', 'uint16', false))
02300 %!assert (__testcat('uint16', 'single', 'uint16', false))
02301 %!assert (__testcat('uint16', 'uint16', 'uint16', false))
02302 %!assert (__testcat('double', 'uint32', 'uint32', false))
02303 %!assert (__testcat('uint32', 'double', 'uint32', false))
02304 %!assert (__testcat('single', 'uint32', 'uint32', false))
02305 %!assert (__testcat('uint32', 'single', 'uint32', false))
02306 %!assert (__testcat('uint32', 'uint32', 'uint32', false))
02307 %!assert (__testcat('double', 'uint64', 'uint64', false))
02308 %!assert (__testcat('uint64', 'double', 'uint64', false))
02309 %!assert (__testcat('single', 'uint64', 'uint64', false))
02310 %!assert (__testcat('uint64', 'single', 'uint64', false))
02311 %!assert (__testcat('uint64', 'uint64', 'uint64', false))
02312 
02313 %!assert (cat (3, [], [1,2;3,4]), [1,2;3,4])
02314 %!assert (cat (3, [1,2;3,4], []), [1,2;3,4])
02315 %!assert (cat (3, [], [1,2;3,4], []), [1,2;3,4])
02316 %!assert (cat (3, [], [], []), zeros (0, 0, 3))
02317 
02318 %!assert (cat (3, [], [], 1, 2), cat (3, 1, 2))
02319 %!assert (cat (3, [], [], [1,2;3,4]), [1,2;3,4])
02320 %!assert (cat (4, [], [], [1,2;3,4]), [1,2;3,4])
02321 %!error <dimension mismatch> cat (3, cat (3, [], []), [1,2;3,4])
02322 %!error <dimension mismatch> cat (3, zeros (0, 0, 2), [1,2;3,4])
02323 
02324 %!assert ([zeros(3,2,2); ones(1,2,2)], repmat([0;0;0;1],[1,2,2]) )
02325 %!assert ([zeros(3,2,2); ones(1,2,2)], vertcat(zeros(3,2,2), ones(1,2,2)) )
02326 
02327 */
02328 
02329 static octave_value
02330 do_permute (const octave_value_list& args, bool inv)
02331 {
02332   octave_value retval;
02333 
02334   if (args.length () == 2 && args(1).length () >= args(1).ndims ())
02335     {
02336       Array<int> vec = args(1).int_vector_value ();
02337 
02338       // FIXME -- maybe we should create an idx_vector object
02339       // here and pass that to permute?
02340 
02341       int n = vec.length ();
02342 
02343       for (int i = 0; i < n; i++)
02344         vec(i)--;
02345 
02346       octave_value ret = args(0).permute (vec, inv);
02347 
02348       if (! error_state)
02349         retval = ret;
02350     }
02351   else
02352     print_usage ();
02353 
02354   return retval;
02355 }
02356 
02357 DEFUN (permute, args, ,
02358   "-*- texinfo -*-\n\
02359 @deftypefn {Built-in Function} {} permute (@var{A}, @var{perm})\n\
02360 Return the generalized transpose for an N-D array object @var{A}.\n\
02361 The permutation vector @var{perm} must contain the elements\n\
02362 @code{1:ndims(A)} (in any order, but each element must appear only once).\n\
02363 @seealso{ipermute}\n\
02364 @end deftypefn")
02365 {
02366   return do_permute (args, false);
02367 }
02368 
02369 DEFUN (ipermute, args, ,
02370   "-*- texinfo -*-\n\
02371 @deftypefn {Built-in Function} {} ipermute (@var{A}, @var{iperm})\n\
02372 The inverse of the @code{permute} function.  The expression\n\
02373 \n\
02374 @example\n\
02375 ipermute (permute (A, perm), perm)\n\
02376 @end example\n\
02377 \n\
02378 @noindent\n\
02379 returns the original array @var{A}.\n\
02380 @seealso{permute}\n\
02381 @end deftypefn")
02382 {
02383   return do_permute (args, true);
02384 }
02385 
02386 DEFUN (length, args, ,
02387   "-*- texinfo -*-\n\
02388 @deftypefn {Built-in Function} {} length (@var{a})\n\
02389 Return the \"length\" of the object @var{a}.  For matrix objects, the\n\
02390 length is the number of rows or columns, whichever is greater (this\n\
02391 odd definition is used for compatibility with @sc{matlab}).\n\
02392 @end deftypefn")
02393 {
02394   octave_value retval;
02395 
02396   if (args.length () == 1)
02397     retval = args(0).length ();
02398   else
02399     print_usage ();
02400 
02401   return retval;
02402 }
02403 
02404 DEFUN (ndims, args, ,
02405   "-*- texinfo -*-\n\
02406 @deftypefn {Built-in Function} {} ndims (@var{a})\n\
02407 Return the number of dimensions of @var{a}.\n\
02408 For any array, the result will always be larger than or equal to 2.\n\
02409 Trailing singleton dimensions are not counted.\n\
02410 \n\
02411 @example\n\
02412 @group\n\
02413   ndims (ones (4, 1, 2, 1))\n\
02414      @result{} 3\n\
02415 @end group\n\
02416 @end example\n\
02417 @end deftypefn")
02418 {
02419   octave_value retval;
02420 
02421   if (args.length () == 1)
02422     retval = args(0).ndims ();
02423   else
02424     print_usage ();
02425 
02426   return retval;
02427 }
02428 
02429 DEFUN (numel, args, ,
02430   "-*- texinfo -*-\n\
02431 @deftypefn  {Built-in Function} {} numel (@var{a})\n\
02432 @deftypefnx {Built-in Function} {} numel (@var{a}, @var{idx1}, @var{idx2}, @dots{})\n\
02433 Return the number of elements in the object @var{a}.\n\
02434 Optionally, if indices @var{idx1}, @var{idx2}, @dots{} are supplied,\n\
02435 return the number of elements that would result from the indexing\n\
02436 \n\
02437 @example\n\
02438   @var{a}(@var{idx1}, @var{idx2}, @dots{})\n\
02439 @end example\n\
02440 \n\
02441 Note that the indices do not have to be numerical.  For example,\n\
02442 \n\
02443 @example\n\
02444 @group\n\
02445   @var{a} = 1;\n\
02446   @var{b} = ones (2, 3);\n\
02447   numel (@var{a}, @var{b});\n\
02448 @end group\n\
02449 @end example\n\
02450 \n\
02451 @noindent\n\
02452 will return 6, as this is the number of ways to index with @var{b}.\n\
02453 \n\
02454 This method is also called when an object appears as lvalue with cs-list\n\
02455 indexing, i.e., @code{object@{@dots{}@}} or @code{object(@dots{}).field}.\n\
02456 @seealso{size}\n\
02457 @end deftypefn")
02458 {
02459   octave_value retval;
02460   octave_idx_type nargin = args.length ();
02461 
02462   if (nargin == 1)
02463     retval = args(0).numel ();
02464   else if (nargin > 1)
02465     {
02466       // Don't use numel (const octave_value_list&) here as that corresponds to
02467       // an overloaded call, not to builtin!
02468       retval = dims_to_numel (args(0).dims (), args.slice (1, nargin-1));
02469     }
02470   else
02471     print_usage ();
02472 
02473   return retval;
02474 }
02475 
02476 DEFUN (size, args, nargout,
02477   "-*- texinfo -*-\n\
02478 @deftypefn  {Built-in Function} {} size (@var{a})\n\
02479 @deftypefnx {Built-in Function} {} size (@var{a}, @var{dim})\n\
02480 Return the number of rows and columns of @var{a}.\n\
02481 \n\
02482 With one input argument and one output argument, the result is returned\n\
02483 in a row vector.  If there are multiple output arguments, the number of\n\
02484 rows is assigned to the first, and the number of columns to the second,\n\
02485 etc.  For example:\n\
02486 \n\
02487 @example\n\
02488 @group\n\
02489 size ([1, 2; 3, 4; 5, 6])\n\
02490      @result{} [ 3, 2 ]\n\
02491 \n\
02492 [nr, nc] = size ([1, 2; 3, 4; 5, 6])\n\
02493      @result{} nr = 3\n\
02494      @result{} nc = 2\n\
02495 @end group\n\
02496 @end example\n\
02497 \n\
02498 If given a second argument, @code{size} will return the size of the\n\
02499 corresponding dimension.  For example,\n\
02500 \n\
02501 @example\n\
02502 @group\n\
02503 size ([1, 2; 3, 4; 5, 6], 2)\n\
02504      @result{} 2\n\
02505 @end group\n\
02506 @end example\n\
02507 \n\
02508 @noindent\n\
02509 returns the number of columns in the given matrix.\n\
02510 @seealso{numel}\n\
02511 @end deftypefn")
02512 {
02513   octave_value_list retval;
02514 
02515   int nargin = args.length ();
02516 
02517   if (nargin == 1)
02518     {
02519       const dim_vector dimensions = args(0).dims ();
02520 
02521       if (nargout > 1)
02522         {
02523           const dim_vector rdims = dimensions.redim (nargout);
02524           retval.resize (nargout);
02525           for (int i = 0; i < nargout; i++)
02526             retval(i) = rdims(i);
02527         }
02528       else
02529         {
02530           int ndims = dimensions.length ();
02531 
02532           NoAlias<Matrix> m (1, ndims);
02533 
02534           for (int i = 0; i < ndims; i++)
02535             m(i) = dimensions(i);
02536 
02537           retval(0) = m;
02538         }
02539     }
02540   else if (nargin == 2 && nargout < 2)
02541     {
02542       octave_idx_type nd = args(1).int_value (true);
02543 
02544       if (error_state)
02545         error ("size: DIM must be a scalar");
02546       else
02547         {
02548           const dim_vector dv = args(0).dims ();
02549 
02550           if (nd > 0)
02551             {
02552               if (nd <= dv.length ())
02553                 retval(0) = dv(nd-1);
02554               else
02555                 retval(0) = 1;
02556             }
02557           else
02558             error ("size: requested dimension DIM (= %d) out of range", nd);
02559         }
02560     }
02561   else
02562     print_usage ();
02563 
02564   return retval;
02565 }
02566 
02567 DEFUN (size_equal, args, ,
02568    "-*- texinfo -*-\n\
02569 @deftypefn {Built-in Function} {} size_equal (@var{a}, @var{b}, @dots{})\n\
02570 Return true if the dimensions of all arguments agree.\n\
02571 Trailing singleton dimensions are ignored.\n\
02572 Called with a single or no argument, size_equal returns true.\n\
02573 @seealso{size, numel}\n\
02574 @end deftypefn")
02575 {
02576   octave_value retval;
02577 
02578   int nargin = args.length ();
02579 
02580   retval = true;
02581 
02582   if (nargin >= 1)
02583     {
02584       dim_vector a_dims = args(0).dims ();
02585 
02586       for (int i = 1; i < nargin; ++i)
02587         {
02588           dim_vector b_dims = args(i).dims ();
02589 
02590           if (a_dims != b_dims)
02591             {
02592               retval = false;
02593               break;
02594             }
02595         }
02596     }
02597 
02598   return retval;
02599 }
02600 
02601 DEFUN (nnz, args, ,
02602    "-*- texinfo -*-\n\
02603 @deftypefn {Built-in Function} {@var{scalar} =} nnz (@var{a})\n\
02604 Return the number of non zero elements in @var{a}.\n\
02605 @seealso{sparse}\n\
02606 @end deftypefn")
02607 {
02608   octave_value retval;
02609 
02610   if (args.length () == 1)
02611     retval = args(0).nnz ();
02612   else
02613     print_usage ();
02614 
02615   return retval;
02616 }
02617 
02618 DEFUN (nzmax, args, ,
02619    "-*- texinfo -*-\n\
02620 @deftypefn {Built-in Function} {@var{scalar} =} nzmax (@var{SM})\n\
02621 Return the amount of storage allocated to the sparse matrix @var{SM}.\n\
02622 Note that Octave tends to crop unused memory at the first opportunity\n\
02623 for sparse objects.  There are some cases of user created sparse objects\n\
02624 where the value returned by @dfn{nzmax} will not be the same as @dfn{nnz},\n\
02625 but in general they will give the same result.\n\
02626 @seealso{sparse, spalloc}\n\
02627 @end deftypefn")
02628 {
02629   octave_value retval;
02630 
02631   if (args.length() == 1)
02632     retval = args(0).nzmax ();
02633   else
02634     print_usage ();
02635 
02636   return retval;
02637 }
02638 
02639 DEFUN (rows, args, ,
02640   "-*- texinfo -*-\n\
02641 @deftypefn {Built-in Function} {} rows (@var{a})\n\
02642 Return the number of rows of @var{a}.\n\
02643 @seealso{columns, size, length, numel, isscalar, isvector, ismatrix}\n\
02644 @end deftypefn")
02645 {
02646   octave_value retval;
02647 
02648   if (args.length () == 1)
02649     retval = args(0).rows ();
02650   else
02651     print_usage ();
02652 
02653   return retval;
02654 }
02655 
02656 DEFUN (columns, args, ,
02657   "-*- texinfo -*-\n\
02658 @deftypefn {Built-in Function} {} columns (@var{a})\n\
02659 Return the number of columns of @var{a}.\n\
02660 @seealso{rows, size, length, numel, isscalar, isvector, ismatrix}\n\
02661 @end deftypefn")
02662 {
02663   octave_value retval;
02664 
02665   if (args.length () == 1)
02666     retval = args(0).columns ();
02667   else
02668     print_usage ();
02669 
02670   return retval;
02671 }
02672 
02673 DEFUN (sum, args, ,
02674   "-*- texinfo -*-\n\
02675 @deftypefn  {Built-in Function} {} sum (@var{x})\n\
02676 @deftypefnx {Built-in Function} {} sum (@var{x}, @var{dim})\n\
02677 @deftypefnx {Built-in Function} {} sum (@dots{}, 'native')\n\
02678 @deftypefnx {Built-in Function} {} sum (@dots{}, 'double')\n\
02679 @deftypefnx {Built-in Function} {} sum (@dots{}, 'extra')\n\
02680 Sum of elements along dimension @var{dim}.  If @var{dim} is\n\
02681 omitted, it defaults to the first non-singleton dimension.\n\
02682 \n\
02683 If the optional argument 'native' is given, then the sum is performed\n\
02684 in the same type as the original argument, rather than in the default\n\
02685 double type.  For example:\n\
02686 \n\
02687 @example\n\
02688 @group\n\
02689 sum ([true, true])\n\
02690   @result{} 2\n\
02691 sum ([true, true], 'native')\n\
02692   @result{} true\n\
02693 @end group\n\
02694 @end example\n\
02695 \n\
02696 On the contrary, if 'double' is given, the sum is performed in double\n\
02697 precision even for single precision inputs.\n\
02698 \n\
02699 For double precision inputs, 'extra' indicates that a more accurate algorithm\n\
02700 than straightforward summation is to be used.  For single precision inputs,\n\
02701 'extra' is the same as 'double'.  Otherwise, 'extra' has no effect.\n\
02702 @seealso{cumsum, sumsq, prod}\n\
02703 @end deftypefn")
02704 {
02705   octave_value retval;
02706 
02707   int nargin = args.length ();
02708 
02709   bool isnative = false;
02710   bool isdouble = false;
02711   bool isextra = false;
02712 
02713   if (nargin > 1 && args(nargin - 1).is_string ())
02714     {
02715       std::string str = args(nargin - 1).string_value ();
02716 
02717       if (! error_state)
02718         {
02719           if (str == "native")
02720             isnative = true;
02721           else if (str == "double")
02722             isdouble = true;
02723           else if (str == "extra")
02724             isextra = true;
02725           else
02726             error ("sum: unrecognized string argument");
02727           nargin --;
02728         }
02729     }
02730 
02731   if (error_state)
02732     return retval;
02733 
02734   if (nargin == 1 || nargin == 2)
02735     {
02736       octave_value arg = args(0);
02737 
02738       int dim = -1;
02739       if (nargin == 2)
02740         {
02741           dim = args(1).int_value () - 1;
02742           if (dim < 0)
02743             error ("sum: invalid dimension DIM = %d", dim + 1);
02744         }
02745 
02746       if (! error_state)
02747         {
02748           switch (arg.builtin_type ())
02749             {
02750             case btyp_double:
02751               if (arg.is_sparse_type ())
02752                 {
02753                   if (isextra)
02754                     warning ("sum: 'extra' not yet implemented for sparse matrices");
02755                   retval = arg.sparse_matrix_value ().sum (dim);
02756                 }
02757               else if (isextra)
02758                 retval = arg.array_value ().xsum (dim);
02759               else
02760                 retval = arg.array_value ().sum (dim);
02761               break;
02762             case btyp_complex:
02763               if (arg.is_sparse_type ())
02764                 {
02765                   if (isextra)
02766                     warning ("sum: 'extra' not yet implemented for sparse matrices");
02767                   retval = arg.sparse_complex_matrix_value ().sum (dim);
02768                 }
02769               else if (isextra)
02770                 retval = arg.complex_array_value ().xsum (dim);
02771               else
02772                 retval = arg.complex_array_value ().sum (dim);
02773               break;
02774             case btyp_float:
02775               if (isdouble || isextra)
02776                 retval = arg.float_array_value ().dsum (dim);
02777               else
02778                 retval = arg.float_array_value ().sum (dim);
02779               break;
02780             case btyp_float_complex:
02781               if (isdouble || isextra)
02782                 retval = arg.float_complex_array_value ().dsum (dim);
02783               else
02784                 retval = arg.float_complex_array_value ().sum (dim);
02785               break;
02786 
02787 #define MAKE_INT_BRANCH(X) \
02788             case btyp_ ## X: \
02789               if (isnative) \
02790                 retval = arg.X ## _array_value ().sum (dim); \
02791               else \
02792                 retval = arg.X ## _array_value ().dsum (dim); \
02793               break
02794             MAKE_INT_BRANCH (int8);
02795             MAKE_INT_BRANCH (int16);
02796             MAKE_INT_BRANCH (int32);
02797             MAKE_INT_BRANCH (int64);
02798             MAKE_INT_BRANCH (uint8);
02799             MAKE_INT_BRANCH (uint16);
02800             MAKE_INT_BRANCH (uint32);
02801             MAKE_INT_BRANCH (uint64);
02802 #undef MAKE_INT_BRANCH
02803 
02804             case btyp_bool:
02805               if (arg.is_sparse_type ())
02806                 {
02807                   if (isnative)
02808                     retval = arg.sparse_bool_matrix_value ().any (dim);
02809                   else
02810                     retval = arg.sparse_bool_matrix_value ().sum (dim);
02811                 }
02812               else if (isnative)
02813                 retval = arg.bool_array_value ().any (dim);
02814               else
02815                 retval = arg.bool_array_value ().sum (dim);
02816               break;
02817 
02818             default:
02819               gripe_wrong_type_arg ("sum", arg);
02820             }
02821         }
02822     }
02823   else
02824     print_usage ();
02825 
02826   return retval;
02827 }
02828 
02829 /*
02830 
02831 %!assert (sum([true,true]), 2)
02832 %!assert (sum([true,true],'native'), true)
02833 %!assert (sum(int8([127,10,-20])), 117);
02834 %!assert (sum(int8([127,10,-20]),'native'), int8(107));
02835 
02836 %!assert(sum ([1, 2, 3]), 6)
02837 %!assert(sum ([-1; -2; -3]), -6);
02838 %!assert(sum ([i, 2+i, -3+2i, 4]), 3+4i);
02839 %!assert(sum ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), [2+2i, 4+4i, 6+6i]);
02840 
02841 %!assert(sum (single([1, 2, 3])), single(6))
02842 %!assert(sum (single([-1; -2; -3])), single(-6));
02843 %!assert(sum (single([i, 2+i, -3+2i, 4])), single(3+4i));
02844 %!assert(sum (single([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single([2+2i, 4+4i, 6+6i]));
02845 
02846 %!error <Invalid call to sum> sum ();
02847 
02848 %!assert (sum ([1, 2; 3, 4], 1), [4, 6]);
02849 %!assert (sum ([1, 2; 3, 4], 2), [3; 7]);
02850 %!assert (sum (zeros (1, 0)), 0);
02851 %!assert (sum (zeros (1, 0), 1), zeros(1, 0));
02852 %!assert (sum (zeros (1, 0), 2), 0);
02853 %!assert (sum (zeros (0, 1)), 0);
02854 %!assert (sum (zeros (0, 1), 1), 0);
02855 %!assert (sum (zeros (0, 1), 2), zeros(0, 1));
02856 %!assert (sum (zeros (2, 0)),  zeros(1, 0));
02857 %!assert (sum (zeros (2, 0), 1), zeros(1, 0));
02858 %!assert (sum (zeros (2, 0), 2),  [0; 0]);
02859 %!assert (sum (zeros (0, 2)), [0, 0]);
02860 %!assert (sum (zeros (0, 2), 1), [0, 0]);
02861 %!assert (sum (zeros (0, 2), 2), zeros(0, 1));
02862 %!assert (sum (zeros (2, 2, 0, 3)), zeros(1, 2, 0, 3));
02863 %!assert (sum (zeros (2, 2, 0, 3), 2), zeros(2, 1, 0, 3));
02864 %!assert (sum (zeros (2, 2, 0, 3), 3), zeros(2, 2, 1, 3));
02865 %!assert (sum (zeros (2, 2, 0, 3), 4), zeros(2, 2, 0));
02866 %!assert (sum (zeros (2, 2, 0, 3), 7), zeros(2, 2, 0, 3));
02867 
02868 %!assert (sum (single([1, 2; 3, 4]), 1), single([4, 6]));
02869 %!assert (sum (single([1, 2; 3, 4]), 2), single([3; 7]));
02870 %!assert (sum (zeros (1, 0, 'single')), single(0));
02871 %!assert (sum (zeros (1, 0, 'single'), 1), zeros(1, 0, 'single'));
02872 %!assert (sum (zeros (1, 0, 'single'), 2), single(0));
02873 %!assert (sum (zeros (0, 1, 'single')), single(0));
02874 %!assert (sum (zeros (0, 1, 'single'), 1), single(0));
02875 %!assert (sum (zeros (0, 1, 'single'), 2), zeros(0, 1, 'single'));
02876 %!assert (sum (zeros (2, 0, 'single')),  zeros(1, 0, 'single'));
02877 %!assert (sum (zeros (2, 0, 'single'), 1), zeros(1, 0, 'single'));
02878 %!assert (sum (zeros (2, 0, 'single'), 2),  single([0; 0]));
02879 %!assert (sum (zeros (0, 2, 'single')), single([0, 0]));
02880 %!assert (sum (zeros (0, 2, 'single'), 1), single([0, 0]));
02881 %!assert (sum (zeros (0, 2, 'single'), 2), zeros(0, 1, 'single'));
02882 %!assert (sum (zeros (2, 2, 0, 3, 'single')), zeros(1, 2, 0, 3, 'single'));
02883 %!assert (sum (zeros (2, 2, 0, 3, 'single'), 2), zeros(2, 1, 0, 3, 'single'));
02884 %!assert (sum (zeros (2, 2, 0, 3, 'single'), 3), zeros(2, 2, 1, 3, 'single'));
02885 %!assert (sum (zeros (2, 2, 0, 3, 'single'), 4), zeros(2, 2, 0, 'single'));
02886 %!assert (sum (zeros (2, 2, 0, 3, 'single'), 7), zeros(2, 2, 0, 3, 'single'));
02887 
02888 */
02889 
02890 DEFUN (sumsq, args, ,
02891   "-*- texinfo -*-\n\
02892 @deftypefn  {Built-in Function} {} sumsq (@var{x})\n\
02893 @deftypefnx {Built-in Function} {} sumsq (@var{x}, @var{dim})\n\
02894 Sum of squares of elements along dimension @var{dim}.  If @var{dim}\n\
02895 is omitted, it defaults to the first non-singleton dimension.\n\
02896 \n\
02897 This function is conceptually equivalent to computing\n\
02898 \n\
02899 @example\n\
02900 sum (x .* conj (x), dim)\n\
02901 @end example\n\
02902 \n\
02903 @noindent\n\
02904 but it uses less memory and avoids calling @code{conj} if @var{x} is real.\n\
02905 @seealso{sum}\n\
02906 @end deftypefn")
02907 {
02908   DATA_REDUCTION (sumsq);
02909 }
02910 
02911 /*
02912 
02913 %!assert(sumsq ([1, 2, 3]), 14)
02914 %!assert(sumsq ([-1; -2; 4i]), 21);
02915 %!assert(sumsq ([1, 2, 3; 2, 3, 4; 4i, 6i, 2]), [21, 49, 29]);
02916 
02917 %!assert(sumsq (single([1, 2, 3])), single(14))
02918 %!assert(sumsq (single([-1; -2; 4i])), single(21));
02919 %!assert(sumsq (single([1, 2, 3; 2, 3, 4; 4i, 6i, 2])), single([21, 49, 29]));
02920 
02921 %!error <Invalid call to sumsq> sumsq ();
02922 
02923 %!assert (sumsq ([1, 2; 3, 4], 1), [10, 20]);
02924 %!assert (sumsq ([1, 2; 3, 4], 2), [5; 25]);
02925 
02926 %!assert (sumsq (single([1, 2; 3, 4]), 1), single([10, 20]));
02927 %!assert (sumsq (single([1, 2; 3, 4]), 2), single([5; 25]));
02928 
02929  */
02930 
02931 DEFUN (islogical, args, ,
02932   "-*- texinfo -*-\n\
02933 @deftypefn  {Built-in Function} {} islogical (@var{x})\n\
02934 @deftypefnx {Built-in Function} {} isbool (@var{x})\n\
02935 Return true if @var{x} is a logical object.\n\
02936 @seealso{isfloat, isinteger, ischar, isnumeric, isa}\n\
02937 @end deftypefn")
02938 {
02939   octave_value retval;
02940 
02941   if (args.length () == 1)
02942     retval = args(0).is_bool_type ();
02943   else
02944     print_usage ();
02945 
02946   return retval;
02947 }
02948 
02949 DEFALIAS (isbool, islogical);
02950 
02951 /*
02952 
02953 %!assert (islogical(true), true)
02954 %!assert (islogical(false), true)
02955 %!assert (islogical([true, false]), true)
02956 %!assert (islogical(1), false)
02957 %!assert (islogical(1i), false)
02958 %!assert (islogical([1,1]), false)
02959 %!assert (islogical(single(1)), false)
02960 %!assert (islogical(single(1i)), false)
02961 %!assert (islogical(single([1,1])), false)
02962 %!assert (islogical(sparse ([true, false])), true)
02963 %!assert (islogical(sparse ([1, 0])), false)
02964 
02965  */
02966 
02967 DEFUN (isinteger, args, ,
02968   "-*- texinfo -*-\n\
02969 @deftypefn {Built-in Function} {} isinteger (@var{x})\n\
02970 Return true if @var{x} is an integer object (int8, uint8, int16, etc.).\n\
02971 Note that @w{@code{isinteger (14)}} is false because numeric constants in\n\
02972 Octave are double precision floating point values.\n\
02973 @seealso{isfloat, ischar, islogical, isnumeric, isa}\n\
02974 @end deftypefn")
02975 {
02976   octave_value retval;
02977 
02978   if (args.length () == 1)
02979     retval = args(0).is_integer_type ();
02980   else
02981     print_usage ();
02982 
02983   return retval;
02984 }
02985 
02986 DEFUN (iscomplex, args, ,
02987   "-*- texinfo -*-\n\
02988 @deftypefn {Built-in Function} {} iscomplex (@var{x})\n\
02989 Return true if @var{x} is a complex-valued numeric object.\n\
02990 @seealso{isreal, isnumeric}\n\
02991 @end deftypefn")
02992 {
02993   octave_value retval;
02994 
02995   if (args.length () == 1)
02996     retval = args(0).is_complex_type ();
02997   else
02998     print_usage ();
02999 
03000   return retval;
03001 }
03002 
03003 DEFUN (isfloat, args, ,
03004   "-*- texinfo -*-\n\
03005 @deftypefn {Built-in Function} {} isfloat (@var{x})\n\
03006 Return true if @var{x} is a floating-point numeric object.\n\
03007 Objects of class double or single are floating-point objects.\n\
03008 @seealso{isinteger, ischar, islogical, isnumeric, isa}\n\
03009 @end deftypefn")
03010 {
03011   octave_value retval;
03012 
03013   if (args.length () == 1)
03014     retval = args(0).is_float_type ();
03015   else
03016     print_usage ();
03017 
03018   return retval;
03019 }
03020 
03021 // FIXME -- perhaps this should be implemented with an
03022 // octave_value member function?
03023 
03024 DEFUN (complex, args, ,
03025   "-*- texinfo -*-\n\
03026 @deftypefn  {Built-in Function} {} complex (@var{x})\n\
03027 @deftypefnx {Built-in Function} {} complex (@var{re}, @var{im})\n\
03028 Return a complex result from real arguments.  With 1 real argument @var{x},\n\
03029 return the complex result @code{@var{x} + 0i}.  With 2 real arguments,\n\
03030 return the complex result @code{@var{re} + @var{im}}.  @code{complex} can\n\
03031 often be more convenient than expressions such as @code{a + i*b}.\n\
03032 For example:\n\
03033 \n\
03034 @example\n\
03035 @group\n\
03036 complex ([1, 2], [3, 4])\n\
03037 @result{}\n\
03038    1 + 3i   2 + 4i\n\
03039 @end group\n\
03040 @end example\n\
03041 @seealso{real, imag, iscomplex}\n\
03042 @end deftypefn")
03043 {
03044   octave_value retval;
03045 
03046   int nargin = args.length ();
03047 
03048   if (nargin == 1)
03049     {
03050       octave_value arg = args(0);
03051 
03052       if (arg.is_complex_type ())
03053         retval = arg;
03054       else
03055         {
03056           if (arg.is_sparse_type ())
03057             {
03058               SparseComplexMatrix val = arg.sparse_complex_matrix_value ();
03059 
03060               if (! error_state)
03061                 retval = octave_value (new octave_sparse_complex_matrix (val));
03062             }
03063           else if (arg.is_single_type ())
03064             {
03065               if (arg.numel () == 1)
03066                 {
03067                   FloatComplex val = arg.float_complex_value ();
03068 
03069                   if (! error_state)
03070                     retval = octave_value (new octave_float_complex (val));
03071                 }
03072               else
03073                 {
03074                   FloatComplexNDArray val = arg.float_complex_array_value ();
03075 
03076                   if (! error_state)
03077                     retval = octave_value (new octave_float_complex_matrix (val));
03078                 }
03079             }
03080           else
03081             {
03082               if (arg.numel () == 1)
03083                 {
03084                   Complex val = arg.complex_value ();
03085 
03086                   if (! error_state)
03087                     retval = octave_value (new octave_complex (val));
03088                 }
03089               else
03090                 {
03091                   ComplexNDArray val = arg.complex_array_value ();
03092 
03093                   if (! error_state)
03094                     retval = octave_value (new octave_complex_matrix (val));
03095                 }
03096             }
03097 
03098           if (error_state)
03099             error ("complex: invalid conversion");
03100         }
03101     }
03102   else if (nargin == 2)
03103     {
03104       octave_value re = args(0);
03105       octave_value im = args(1);
03106 
03107       if (re.is_sparse_type () && im.is_sparse_type ())
03108         {
03109           const SparseMatrix re_val = re.sparse_matrix_value ();
03110           const SparseMatrix im_val = im.sparse_matrix_value ();
03111 
03112           if (!error_state)
03113             {
03114               if (re.numel () == 1)
03115                 {
03116                   SparseComplexMatrix result;
03117                   if (re_val.nnz () == 0)
03118                     result = Complex(0, 1) * SparseComplexMatrix (im_val);
03119                   else
03120                     {
03121                       result = SparseComplexMatrix (im_val.dims (), re_val (0));
03122                       octave_idx_type nr = im_val.rows ();
03123                       octave_idx_type nc = im_val.cols ();
03124 
03125                       for (octave_idx_type j = 0; j < nc; j++)
03126                         {
03127                           octave_idx_type off = j * nr;
03128                           for (octave_idx_type i = im_val.cidx(j);
03129                                i < im_val.cidx(j + 1); i++)
03130                             result.data (im_val.ridx(i) + off) =
03131                               result.data (im_val.ridx(i) + off) +
03132                               Complex (0, im_val.data (i));
03133                         }
03134                     }
03135                   retval = octave_value (new octave_sparse_complex_matrix (result));
03136                 }
03137               else if (im.numel () == 1)
03138                 {
03139                   SparseComplexMatrix result;
03140                   if (im_val.nnz () == 0)
03141                     result = SparseComplexMatrix (re_val);
03142                   else
03143                     {
03144                       result = SparseComplexMatrix (re_val.rows(), re_val.cols(), Complex(0, im_val (0)));
03145                       octave_idx_type nr = re_val.rows ();
03146                       octave_idx_type nc = re_val.cols ();
03147 
03148                       for (octave_idx_type j = 0; j < nc; j++)
03149                         {
03150                           octave_idx_type off = j * nr;
03151                           for (octave_idx_type i = re_val.cidx(j);
03152                                i < re_val.cidx(j + 1); i++)
03153                             result.data (re_val.ridx(i) + off) =
03154                               result.data (re_val.ridx(i) + off) +
03155                               re_val.data (i);
03156                         }
03157                     }
03158                   retval = octave_value (new octave_sparse_complex_matrix (result));
03159                 }
03160               else
03161                 {
03162                   if (re_val.dims () == im_val.dims ())
03163                     {
03164                       SparseComplexMatrix result = SparseComplexMatrix(re_val)
03165                         + Complex(0, 1) * SparseComplexMatrix (im_val);
03166                       retval = octave_value (new octave_sparse_complex_matrix (result));
03167                     }
03168                   else
03169                     error ("complex: dimension mismatch");
03170                 }
03171             }
03172         }
03173       else if (re.is_single_type () || im.is_single_type ())
03174         {
03175           if (re.numel () == 1)
03176             {
03177               float re_val = re.float_value ();
03178 
03179               if (im.numel () == 1)
03180                 {
03181                   float im_val = im.double_value ();
03182 
03183                   if (! error_state)
03184                     retval = octave_value (new octave_float_complex (FloatComplex (re_val, im_val)));
03185                 }
03186               else
03187                 {
03188                   const FloatNDArray im_val = im.float_array_value ();
03189 
03190                   if (! error_state)
03191                     {
03192                       FloatComplexNDArray result (im_val.dims (), FloatComplex ());
03193 
03194                       for (octave_idx_type i = 0; i < im_val.numel (); i++)
03195                         result.xelem (i) = FloatComplex (re_val, im_val(i));
03196 
03197                       retval = octave_value (new octave_float_complex_matrix (result));
03198                     }
03199                 }
03200             }
03201           else
03202             {
03203               const FloatNDArray re_val = re.float_array_value ();
03204 
03205               if (im.numel () == 1)
03206                 {
03207                   float im_val = im.float_value ();
03208 
03209                   if (! error_state)
03210                     {
03211                       FloatComplexNDArray result (re_val.dims (), FloatComplex ());
03212 
03213                       for (octave_idx_type i = 0; i < re_val.numel (); i++)
03214                         result.xelem (i) = FloatComplex (re_val(i), im_val);
03215 
03216                       retval = octave_value (new octave_float_complex_matrix (result));
03217                     }
03218                 }
03219               else
03220                 {
03221                   const FloatNDArray im_val = im.float_array_value ();
03222 
03223                   if (! error_state)
03224                     {
03225                       if (re_val.dims () == im_val.dims ())
03226                         {
03227                           FloatComplexNDArray result (re_val.dims (), FloatComplex ());
03228 
03229                           for (octave_idx_type i = 0; i < re_val.numel (); i++)
03230                             result.xelem (i) = FloatComplex (re_val(i), im_val(i));
03231 
03232                           retval = octave_value (new octave_float_complex_matrix (result));
03233                         }
03234                       else
03235                         error ("complex: dimension mismatch");
03236                     }
03237                 }
03238             }
03239         }
03240       else if (re.numel () == 1)
03241         {
03242           double re_val = re.double_value ();
03243 
03244           if (im.numel () == 1)
03245             {
03246               double im_val = im.double_value ();
03247 
03248               if (! error_state)
03249                 retval = octave_value (new octave_complex (Complex (re_val, im_val)));
03250             }
03251           else
03252             {
03253               const NDArray im_val = im.array_value ();
03254 
03255               if (! error_state)
03256                 {
03257                   ComplexNDArray result (im_val.dims (), Complex ());
03258 
03259                   for (octave_idx_type i = 0; i < im_val.numel (); i++)
03260                     result.xelem (i) = Complex (re_val, im_val(i));
03261 
03262                   retval = octave_value (new octave_complex_matrix (result));
03263                 }
03264             }
03265         }
03266       else
03267         {
03268           const NDArray re_val = re.array_value ();
03269 
03270           if (im.numel () == 1)
03271             {
03272               double im_val = im.double_value ();
03273 
03274               if (! error_state)
03275                 {
03276                   ComplexNDArray result (re_val.dims (), Complex ());
03277 
03278                   for (octave_idx_type i = 0; i < re_val.numel (); i++)
03279                     result.xelem (i) = Complex (re_val(i), im_val);
03280 
03281                   retval = octave_value (new octave_complex_matrix (result));
03282                 }
03283             }
03284           else
03285             {
03286               const NDArray im_val = im.array_value ();
03287 
03288               if (! error_state)
03289                 {
03290                   if (re_val.dims () == im_val.dims ())
03291                     {
03292                       ComplexNDArray result (re_val.dims (), Complex ());
03293 
03294                       for (octave_idx_type i = 0; i < re_val.numel (); i++)
03295                         result.xelem (i) = Complex (re_val(i), im_val(i));
03296 
03297                       retval = octave_value (new octave_complex_matrix (result));
03298                     }
03299                   else
03300                     error ("complex: dimension mismatch");
03301                 }
03302             }
03303         }
03304 
03305       if (error_state)
03306         error ("complex: invalid conversion");
03307     }
03308   else
03309     print_usage ();
03310 
03311   return retval;
03312 }
03313 
03314 DEFUN (isreal, args, ,
03315   "-*- texinfo -*-\n\
03316 @deftypefn {Built-in Function} {} isreal (@var{x})\n\
03317 Return true if @var{x} is a non-complex matrix or scalar.\n\
03318 For compatibility with @sc{matlab}, this includes logical and character\n\
03319 matrices.\n\
03320 @seealso{iscomplex, isnumeric}\n\
03321 @end deftypefn")
03322 {
03323   octave_value retval;
03324 
03325   if (args.length () == 1)
03326     retval = args(0).is_real_type ();
03327   else
03328     print_usage ();
03329 
03330   return retval;
03331 }
03332 
03333 DEFUN (isempty, args, ,
03334   "-*- texinfo -*-\n\
03335 @deftypefn {Built-in Function} {} isempty (@var{a})\n\
03336 Return true if @var{a} is an empty matrix (any one of its dimensions is\n\
03337 zero).  Otherwise, return false.\n\
03338 @seealso{isnull}\n\
03339 @end deftypefn")
03340 {
03341   octave_value retval = false;
03342 
03343   if (args.length () == 1)
03344     retval = args(0).is_empty ();
03345   else
03346     print_usage ();
03347 
03348   return retval;
03349 }
03350 
03351 DEFUN (isnumeric, args, ,
03352   "-*- texinfo -*-\n\
03353 @deftypefn {Built-in Function} {} isnumeric (@var{x})\n\
03354 Return true if @var{x} is a numeric object, i.e., an integer, real, or\n\
03355 complex array.  Logical and character arrays are not considered to be\n\
03356 numeric.\n\
03357 @seealso{isinteger, isfloat, isreal, iscomplex, islogical, ischar, iscell, isstruct}\n\
03358 @end deftypefn")
03359 {
03360   octave_value retval;
03361 
03362   if (args.length () == 1)
03363     retval = args(0).is_numeric_type ();
03364   else
03365     print_usage ();
03366 
03367   return retval;
03368 }
03369 
03370 /*
03371 
03372 %!assert (isnumeric(1), true)
03373 %!assert (isnumeric(1i), true)
03374 %!assert (isnumeric([1,1]), true)
03375 %!assert (isnumeric(single(1)), true)
03376 %!assert (isnumeric(single(1i)), true)
03377 %!assert (isnumeric(single([1,1])), true)
03378 %!assert (isnumeric(int8(1)), true)
03379 %!assert (isnumeric(uint8([1,1])), true)
03380 %!assert (isnumeric("Hello World"), false)
03381 %!assert (isnumeric(true), false)
03382 %!assert (isnumeric(false), false)
03383 %!assert (isnumeric([true, false]), false)
03384 %!assert (isnumeric(sparse ([true, false])), false)
03385 
03386 */
03387 
03388 DEFUN (ismatrix, args, ,
03389   "-*- texinfo -*-\n\
03390 @deftypefn {Built-in Function} {} ismatrix (@var{a})\n\
03391 Return true if @var{a} is a numeric, logical, or character matrix.\n\
03392 Scalars (1x1 matrices) and vectors (@nospell{1xN} or @nospell{Nx1} matrices)\n\
03393 are subsets of the more general N-dimensional matrix and @code{ismatrix}\n\
03394 will return true for these objects as well.\n\
03395 @seealso{isscalar, isvector, iscell, isstruct, issparse}\n\
03396 @end deftypefn")
03397 {
03398   octave_value retval = false;
03399 
03400   if (args.length () == 1)
03401     {
03402       octave_value arg = args(0);
03403 
03404       retval = arg.is_matrix_type () || arg.is_scalar_type () || arg.is_range ();
03405     }
03406   else
03407     print_usage ();
03408 
03409   return retval;
03410 }
03411 
03412 /*
03413 
03414 %!assert(ismatrix ([]));
03415 %!assert(ismatrix (1));
03416 %!assert(ismatrix ([1, 2, 3]));
03417 %!assert(ismatrix ([1, 2; 3, 4]));
03418 %!assert(ismatrix (zeros (3, 2, 4)));
03419 
03420 %!assert(ismatrix (single([])));
03421 %!assert(ismatrix (single(1)));
03422 %!assert(ismatrix (single([1, 2, 3])));
03423 %!assert(ismatrix (single([1, 2; 3, 4])));
03424 
03425 %!assert(ismatrix ("t"));
03426 %!assert(ismatrix ("test"));
03427 %!assert(ismatrix (["test"; "ing"]));
03428 
03429 %!test
03430 %! s.a = 1;
03431 %! assert(ismatrix (s), false);
03432 
03433 %!error <Invalid call to ismatrix> ismatrix ();
03434 %!error <Invalid call to ismatrix> ismatrix ([1, 2; 3, 4], 2);
03435 
03436  */
03437 
03438 static octave_value
03439 fill_matrix (const octave_value_list& args, int val, const char *fcn)
03440 {
03441   octave_value retval;
03442 
03443   int nargin = args.length ();
03444 
03445   oct_data_conv::data_type dt = oct_data_conv::dt_double;
03446 
03447   dim_vector dims (1, 1);
03448 
03449   if (nargin > 0 && args(nargin-1).is_string ())
03450     {
03451       std::string nm = args(nargin-1).string_value ();
03452       nargin--;
03453 
03454       dt = oct_data_conv::string_to_data_type (nm);
03455 
03456       if (error_state)
03457         return retval;
03458     }
03459 
03460   switch (nargin)
03461     {
03462     case 0:
03463       break;
03464 
03465     case 1:
03466       get_dimensions (args(0), fcn, dims);
03467       break;
03468 
03469     default:
03470       {
03471         dims.resize (nargin);
03472 
03473         for (int i = 0; i < nargin; i++)
03474           {
03475             dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
03476 
03477             if (error_state)
03478               {
03479                 error ("%s: expecting scalar integer arguments", fcn);
03480                 break;
03481               }
03482           }
03483       }
03484       break;
03485     }
03486 
03487   if (! error_state)
03488     {
03489       dims.chop_trailing_singletons ();
03490 
03491       check_dimensions (dims, fcn);
03492 
03493       // FIXME -- perhaps this should be made extensible by
03494       // using the class name to lookup a function to call to create
03495       // the new value.
03496 
03497       // Note that automatic narrowing will handle conversion from
03498       // NDArray to scalar.
03499 
03500       if (! error_state)
03501         {
03502           switch (dt)
03503             {
03504             case oct_data_conv::dt_int8:
03505               retval = int8NDArray (dims, val);
03506               break;
03507 
03508             case oct_data_conv::dt_uint8:
03509               retval = uint8NDArray (dims, val);
03510               break;
03511 
03512             case oct_data_conv::dt_int16:
03513               retval = int16NDArray (dims, val);
03514               break;
03515 
03516             case oct_data_conv::dt_uint16:
03517               retval = uint16NDArray (dims, val);
03518               break;
03519 
03520             case oct_data_conv::dt_int32:
03521               retval = int32NDArray (dims, val);
03522               break;
03523 
03524             case oct_data_conv::dt_uint32:
03525               retval = uint32NDArray (dims, val);
03526               break;
03527 
03528             case oct_data_conv::dt_int64:
03529               retval = int64NDArray (dims, val);
03530               break;
03531 
03532             case oct_data_conv::dt_uint64:
03533               retval = uint64NDArray (dims, val);
03534               break;
03535 
03536             case oct_data_conv::dt_single:
03537               retval = FloatNDArray (dims, val);
03538               break;
03539 
03540             case oct_data_conv::dt_double:
03541               {
03542                 if (val == 1 && dims.length () == 2 && dims (0) == 1)
03543                   retval = Range (1.0, 0.0, dims (1)); // packed form
03544                 else
03545                   retval = NDArray (dims, val);
03546               }
03547               break;
03548 
03549             case oct_data_conv::dt_logical:
03550               retval = boolNDArray (dims, val);
03551               break;
03552 
03553             default:
03554               error ("%s: invalid class name", fcn);
03555               break;
03556             }
03557         }
03558     }
03559 
03560   return retval;
03561 }
03562 
03563 static octave_value
03564 fill_matrix (const octave_value_list& args, double val, float fval,
03565              const char *fcn)
03566 {
03567   octave_value retval;
03568 
03569   int nargin = args.length ();
03570 
03571   oct_data_conv::data_type dt = oct_data_conv::dt_double;
03572 
03573   dim_vector dims (1, 1);
03574 
03575   if (nargin > 0 && args(nargin-1).is_string ())
03576     {
03577       std::string nm = args(nargin-1).string_value ();
03578       nargin--;
03579 
03580       dt = oct_data_conv::string_to_data_type (nm);
03581 
03582       if (error_state)
03583         return retval;
03584     }
03585 
03586   switch (nargin)
03587     {
03588     case 0:
03589       break;
03590 
03591     case 1:
03592       get_dimensions (args(0), fcn, dims);
03593       break;
03594 
03595     default:
03596       {
03597         dims.resize (nargin);
03598 
03599         for (int i = 0; i < nargin; i++)
03600           {
03601             dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
03602 
03603             if (error_state)
03604               {
03605                 error ("%s: expecting scalar integer arguments", fcn);
03606                 break;
03607               }
03608           }
03609       }
03610       break;
03611     }
03612 
03613   if (! error_state)
03614     {
03615       dims.chop_trailing_singletons ();
03616 
03617       check_dimensions (dims, fcn);
03618 
03619       // Note that automatic narrowing will handle conversion from
03620       // NDArray to scalar.
03621 
03622       if (! error_state)
03623         {
03624           switch (dt)
03625             {
03626             case oct_data_conv::dt_single:
03627               retval = FloatNDArray (dims, fval);
03628               break;
03629 
03630             case oct_data_conv::dt_double:
03631               retval = NDArray (dims, val);
03632               break;
03633 
03634             default:
03635               error ("%s: invalid class name", fcn);
03636               break;
03637             }
03638         }
03639     }
03640 
03641   return retval;
03642 }
03643 
03644 static octave_value
03645 fill_matrix (const octave_value_list& args, double val, const char *fcn)
03646 {
03647   octave_value retval;
03648 
03649   int nargin = args.length ();
03650 
03651   oct_data_conv::data_type dt = oct_data_conv::dt_double;
03652 
03653   dim_vector dims (1, 1);
03654 
03655   if (nargin > 0 && args(nargin-1).is_string ())
03656     {
03657       std::string nm = args(nargin-1).string_value ();
03658       nargin--;
03659 
03660       dt = oct_data_conv::string_to_data_type (nm);
03661 
03662       if (error_state)
03663         return retval;
03664     }
03665 
03666   switch (nargin)
03667     {
03668     case 0:
03669       break;
03670 
03671     case 1:
03672       get_dimensions (args(0), fcn, dims);
03673       break;
03674 
03675     default:
03676       {
03677         dims.resize (nargin);
03678 
03679         for (int i = 0; i < nargin; i++)
03680           {
03681             dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
03682 
03683             if (error_state)
03684               {
03685                 error ("%s: expecting scalar integer arguments", fcn);
03686                 break;
03687               }
03688           }
03689       }
03690       break;
03691     }
03692 
03693   if (! error_state)
03694     {
03695       dims.chop_trailing_singletons ();
03696 
03697       check_dimensions (dims, fcn);
03698 
03699       // Note that automatic narrowing will handle conversion from
03700       // NDArray to scalar.
03701 
03702       if (! error_state)
03703         {
03704           switch (dt)
03705             {
03706             case oct_data_conv::dt_single:
03707               retval = FloatNDArray (dims, static_cast <float> (val));
03708               break;
03709 
03710             case oct_data_conv::dt_double:
03711               retval = NDArray (dims, val);
03712               break;
03713 
03714             default:
03715               error ("%s: invalid class name", fcn);
03716               break;
03717             }
03718         }
03719     }
03720 
03721   return retval;
03722 }
03723 
03724 static octave_value
03725 fill_matrix (const octave_value_list& args, const Complex& val,
03726              const char *fcn)
03727 {
03728   octave_value retval;
03729 
03730   int nargin = args.length ();
03731 
03732   oct_data_conv::data_type dt = oct_data_conv::dt_double;
03733 
03734   dim_vector dims (1, 1);
03735 
03736   if (nargin > 0 && args(nargin-1).is_string ())
03737     {
03738       std::string nm = args(nargin-1).string_value ();
03739       nargin--;
03740 
03741       dt = oct_data_conv::string_to_data_type (nm);
03742 
03743       if (error_state)
03744         return retval;
03745     }
03746 
03747   switch (nargin)
03748     {
03749     case 0:
03750       break;
03751 
03752     case 1:
03753       get_dimensions (args(0), fcn, dims);
03754       break;
03755 
03756     default:
03757       {
03758         dims.resize (nargin);
03759 
03760         for (int i = 0; i < nargin; i++)
03761           {
03762             dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
03763 
03764             if (error_state)
03765               {
03766                 error ("%s: expecting scalar integer arguments", fcn);
03767                 break;
03768               }
03769           }
03770       }
03771       break;
03772     }
03773 
03774   if (! error_state)
03775     {
03776       dims.chop_trailing_singletons ();
03777 
03778       check_dimensions (dims, fcn);
03779 
03780       // Note that automatic narrowing will handle conversion from
03781       // NDArray to scalar.
03782 
03783       if (! error_state)
03784         {
03785           switch (dt)
03786             {
03787             case oct_data_conv::dt_single:
03788               retval = FloatComplexNDArray (dims, static_cast<FloatComplex> (val));
03789               break;
03790 
03791             case oct_data_conv::dt_double:
03792               retval = ComplexNDArray (dims, val);
03793               break;
03794 
03795             default:
03796               error ("%s: invalid class name", fcn);
03797               break;
03798             }
03799         }
03800     }
03801 
03802   return retval;
03803 }
03804 
03805 static octave_value
03806 fill_matrix (const octave_value_list& args, bool val, const char *fcn)
03807 {
03808   octave_value retval;
03809 
03810   int nargin = args.length ();
03811 
03812   dim_vector dims (1, 1);
03813 
03814   switch (nargin)
03815     {
03816     case 0:
03817       break;
03818 
03819     case 1:
03820       get_dimensions (args(0), fcn, dims);
03821       break;
03822 
03823     default:
03824       {
03825         dims.resize (nargin);
03826 
03827         for (int i = 0; i < nargin; i++)
03828           {
03829             dims(i) = args(i).is_empty () ? 0 : args(i).idx_type_value ();
03830 
03831             if (error_state)
03832               {
03833                 error ("%s: expecting scalar integer arguments", fcn);
03834                 break;
03835               }
03836           }
03837       }
03838       break;
03839     }
03840 
03841   if (! error_state)
03842     {
03843       dims.chop_trailing_singletons ();
03844 
03845       check_dimensions (dims, fcn);
03846 
03847       // Note that automatic narrowing will handle conversion from
03848       // NDArray to scalar.
03849 
03850       if (! error_state)
03851         retval = boolNDArray (dims, val);
03852     }
03853 
03854   return retval;
03855 }
03856 
03857 DEFUN (ones, args, ,
03858   "-*- texinfo -*-\n\
03859 @deftypefn  {Built-in Function} {} ones (@var{n})\n\
03860 @deftypefnx {Built-in Function} {} ones (@var{m}, @var{n})\n\
03861 @deftypefnx {Built-in Function} {} ones (@var{m}, @var{n}, @var{k}, @dots{})\n\
03862 @deftypefnx {Built-in Function} {} ones ([@var{m} @var{n} @dots{}])\n\
03863 @deftypefnx {Built-in Function} {} ones (@dots{}, @var{class})\n\
03864 Return a matrix or N-dimensional array whose elements are all 1.\n\
03865 If invoked with a single scalar integer argument @var{n}, return a square\n\
03866 @nospell{NxN} matrix.  If invoked with two or more scalar\n\
03867 integer arguments, or a vector of integer values, return an array with\n\
03868 the given dimensions.\n\
03869 \n\
03870 If you need to create a matrix whose values are all the same, you should\n\
03871 use an expression like\n\
03872 \n\
03873 @example\n\
03874 val_matrix = val * ones (m, n)\n\
03875 @end example\n\
03876 \n\
03877 The optional argument @var{class} specifies the class of the return array\n\
03878 and defaults to double.  For example:\n\
03879 \n\
03880 @example\n\
03881 val = ones (m,n, \"uint8\")\n\
03882 @end example\n\
03883 @seealso{zeros}\n\
03884 @end deftypefn")
03885 {
03886   return fill_matrix (args, 1, "ones");
03887 }
03888 
03889 /*
03890 
03891 %!assert(ones (3), [1, 1, 1; 1, 1, 1; 1, 1, 1]);
03892 %!assert(ones (2, 3), [1, 1, 1; 1, 1, 1]);
03893 %!assert(ones (3, 2), [1, 1; 1, 1; 1, 1]);
03894 %!assert(size (ones (3, 4, 5)),  [3, 4, 5]);
03895 
03896 %!assert(ones (3,'single'), single([1, 1, 1; 1, 1, 1; 1, 1, 1]));
03897 %!assert(ones (2, 3,'single'), single([1, 1, 1; 1, 1, 1]));
03898 %!assert(ones (3, 2,'single'), single([1, 1; 1, 1; 1, 1]));
03899 %!assert(size (ones (3, 4, 5, 'single')),  [3, 4, 5]);
03900 
03901 %!assert(ones (3,'int8'), int8([1, 1, 1; 1, 1, 1; 1, 1, 1]));
03902 %!assert(ones (2, 3,'int8'), int8([1, 1, 1; 1, 1, 1]));
03903 %!assert(ones (3, 2,'int8'), int8([1, 1; 1, 1; 1, 1]));
03904 %!assert(size (ones (3, 4, 5, 'int8')),  [3, 4, 5]);
03905 
03906  */
03907 
03908 DEFUN (zeros, args, ,
03909   "-*- texinfo -*-\n\
03910 @deftypefn  {Built-in Function} {} zeros (@var{n})\n\
03911 @deftypefnx {Built-in Function} {} zeros (@var{m}, @var{n})\n\
03912 @deftypefnx {Built-in Function} {} zeros (@var{m}, @var{n}, @var{k}, @dots{})\n\
03913 @deftypefnx {Built-in Function} {} zeros ([@var{m} @var{n} @dots{}])\n\
03914 @deftypefnx {Built-in Function} {} zeros (@dots{}, @var{class})\n\
03915 Return a matrix or N-dimensional array whose elements are all 0.\n\
03916 If invoked with a single scalar integer argument, return a square\n\
03917 @nospell{NxN} matrix.  If invoked with two or more scalar\n\
03918 integer arguments, or a vector of integer values, return an array with\n\
03919 the given dimensions.\n\
03920 \n\
03921 The optional argument @var{class} specifies the class of the return array\n\
03922 and defaults to double.  For example:\n\
03923 \n\
03924 @example\n\
03925 val = zeros (m,n, \"uint8\")\n\
03926 @end example\n\
03927 @seealso{ones}\n\
03928 @end deftypefn")
03929 {
03930   return fill_matrix (args, 0, "zeros");
03931 }
03932 
03933 /*
03934 
03935 %!assert(zeros (3), [0, 0, 0; 0, 0, 0; 0, 0, 0]);
03936 %!assert(zeros (2, 3), [0, 0, 0; 0, 0, 0]);
03937 %!assert(zeros (3, 2), [0, 0; 0, 0; 0, 0]);
03938 %!assert(size (zeros (3, 4, 5)),  [3, 4, 5]);
03939 
03940 %!assert(zeros (3,'single'), single([0, 0, 0; 0, 0, 0; 0, 0, 0]));
03941 %!assert(zeros (2, 3,'single'), single([0, 0, 0; 0, 0, 0]));
03942 %!assert(zeros (3, 2,'single'), single([0, 0; 0, 0; 0, 0]));
03943 %!assert(size (zeros (3, 4, 5, 'single')),  [3, 4, 5]);
03944 
03945 %!assert(zeros (3,'int8'), int8([0, 0, 0; 0, 0, 0; 0, 0, 0]));
03946 %!assert(zeros (2, 3,'int8'), int8([0, 0, 0; 0, 0, 0]));
03947 %!assert(zeros (3, 2,'int8'), int8([0, 0; 0, 0; 0, 0]));
03948 %!assert(size (zeros (3, 4, 5, 'int8')),  [3, 4, 5]);
03949 
03950  */
03951 
03952 DEFUN (Inf, args, ,
03953   "-*- texinfo -*-\n\
03954 @c List other form of function in documentation index\n\
03955 @findex inf\n\
03956 \n\
03957 @deftypefn  {Built-in Function} {} Inf\n\
03958 @deftypefnx {Built-in Function} {} Inf (@var{n})\n\
03959 @deftypefnx {Built-in Function} {} Inf (@var{n}, @var{m})\n\
03960 @deftypefnx {Built-in Function} {} Inf (@var{n}, @var{m}, @var{k}, @dots{})\n\
03961 @deftypefnx {Built-in Function} {} Inf (@dots{}, @var{class})\n\
03962 Return a scalar, matrix or N-dimensional array whose elements are all equal\n\
03963 to the IEEE representation for positive infinity.\n\
03964 \n\
03965 Infinity is produced when results are too large to be represented using the\n\
03966 the IEEE floating point format for numbers.  Two common examples which\n\
03967 produce infinity are division by zero and overflow.\n\
03968 \n\
03969 @example\n\
03970 @group\n\
03971 [1/0 e^800]\n\
03972 @result{}\n\
03973 Inf   Inf\n\
03974 @end group\n\
03975 @end example\n\
03976 \n\
03977 When called with no arguments, return a scalar with the value @samp{Inf}.\n\
03978 When called with a single argument, return a square matrix with the dimension\n\
03979 specified.  When called with more than one scalar argument the first two\n\
03980 arguments are taken as the number of rows and columns and any further\n\
03981 arguments specify additional matrix dimensions.\n\
03982 The optional argument @var{class} specifies the return type and may be\n\
03983 either \"double\" or \"single\".\n\
03984 @seealso{isinf}\n\
03985 @end deftypefn")
03986 {
03987   return fill_matrix (args, lo_ieee_inf_value (),
03988                       lo_ieee_float_inf_value (), "Inf");
03989 }
03990 
03991 DEFALIAS (inf, Inf);
03992 
03993 /*
03994 
03995 %!assert(inf (3), [Inf, Inf, Inf; Inf, Inf, Inf; Inf, Inf, Inf]);
03996 %!assert(inf (2, 3), [Inf, Inf, Inf; Inf, Inf, Inf]);
03997 %!assert(inf (3, 2), [Inf, Inf; Inf, Inf; Inf, Inf]);
03998 %!assert(size (inf (3, 4, 5)),  [3, 4, 5]);
03999 
04000 %!assert(inf (3,'single'), single([Inf, Inf, Inf; Inf, Inf, Inf; Inf, Inf, Inf]));
04001 %!assert(inf (2, 3,'single'), single([Inf, Inf, Inf; Inf, Inf, Inf]));
04002 %!assert(inf (3, 2,'single'), single([Inf, Inf; Inf, Inf; Inf, Inf]));
04003 %!assert(size (inf (3, 4, 5, 'single')),  [3, 4, 5]);
04004 
04005 %!error(inf (3,'int8'));
04006 %!error(inf (2, 3,'int8'));
04007 %!error(inf (3, 2,'int8'));
04008 %!error(inf (3, 4, 5, 'int8'));
04009 
04010  */
04011 
04012 DEFUN (NaN, args, ,
04013   "-*- texinfo -*-\n\
04014 @c List other form of function in documentation index\n\
04015 @findex nan\n\
04016 \n\
04017 @deftypefn  {Built-in Function} {} NaN\n\
04018 @deftypefnx {Built-in Function} {} NaN (@var{n})\n\
04019 @deftypefnx {Built-in Function} {} NaN (@var{n}, @var{m})\n\
04020 @deftypefnx {Built-in Function} {} NaN (@var{n}, @var{m}, @var{k}, @dots{})\n\
04021 @deftypefnx {Built-in Function} {} NaN (@dots{}, @var{class})\n\
04022 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
04023 to the IEEE symbol NaN (Not a Number).\n\
04024 NaN is the result of operations which do not produce a well defined numerical\n\
04025 result.  Common operations which produce a NaN are arithmetic with infinity\n\
04026 @tex\n\
04027 ($\\infty - \\infty$), zero divided by zero ($0/0$),\n\
04028 @end tex\n\
04029 @ifnottex\n\
04030 (Inf - Inf), zero divided by zero (0/0),\n\
04031 @end ifnottex\n\
04032 and any operation involving another NaN value (5 + NaN).\n\
04033 \n\
04034 Note that NaN always compares not equal to NaN (NaN != NaN).  This behavior\n\
04035 is specified by the IEEE standard for floating point arithmetic.  To\n\
04036 find NaN values, use the @code{isnan} function.\n\
04037 \n\
04038 When called with no arguments, return a scalar with the value @samp{NaN}.\n\
04039 When called with a single argument, return a square matrix with the dimension\n\
04040 specified.  When called with more than one scalar argument the first two\n\
04041 arguments are taken as the number of rows and columns and any further\n\
04042 arguments specify additional matrix dimensions.\n\
04043 The optional argument @var{class} specifies the return type and may be\n\
04044 either \"double\" or \"single\".\n\
04045 @seealso{isnan}\n\
04046 @end deftypefn")
04047 {
04048   return fill_matrix (args, lo_ieee_nan_value (),
04049                       lo_ieee_float_nan_value (), "NaN");
04050 }
04051 
04052 DEFALIAS (nan, NaN);
04053 
04054 /*
04055 %!assert(NaN (3), [NaN, NaN, NaN; NaN, NaN, NaN; NaN, NaN, NaN]);
04056 %!assert(NaN (2, 3), [NaN, NaN, NaN; NaN, NaN, NaN]);
04057 %!assert(NaN (3, 2), [NaN, NaN; NaN, NaN; NaN, NaN]);
04058 %!assert(size (NaN (3, 4, 5)),  [3, 4, 5]);
04059 
04060 %!assert(NaN (3,'single'), single([NaN, NaN, NaN; NaN, NaN, NaN; NaN, NaN, NaN]));
04061 %!assert(NaN (2, 3,'single'), single([NaN, NaN, NaN; NaN, NaN, NaN]));
04062 %!assert(NaN (3, 2,'single'), single([NaN, NaN; NaN, NaN; NaN, NaN]));
04063 %!assert(size (NaN (3, 4, 5, 'single')),  [3, 4, 5]);
04064 
04065 %!error(NaN (3,'int8'));
04066 %!error(NaN (2, 3,'int8'));
04067 %!error(NaN (3, 2,'int8'));
04068 %!error(NaN (3, 4, 5, 'int8'));
04069 
04070  */
04071 
04072 DEFUN (e, args, ,
04073   "-*- texinfo -*-\n\
04074 @deftypefn  {Built-in Function} {} e\n\
04075 @deftypefnx {Built-in Function} {} e (@var{n})\n\
04076 @deftypefnx {Built-in Function} {} e (@var{n}, @var{m})\n\
04077 @deftypefnx {Built-in Function} {} e (@var{n}, @var{m}, @var{k}, @dots{})\n\
04078 @deftypefnx {Built-in Function} {} e (@dots{}, @var{class})\n\
04079 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
04080 to the base of natural logarithms.  The constant\n\
04081 @tex\n\
04082 $e$ satisfies the equation $\\log (e) = 1$.\n\
04083 @end tex\n\
04084 @ifnottex\n\
04085 @samp{e} satisfies the equation @code{log} (e) = 1.\n\
04086 @end ifnottex\n\
04087 \n\
04088 When called with no arguments, return a scalar with the value @math{e}.  When\n\
04089 called with a single argument, return a square matrix with the dimension\n\
04090 specified.  When called with more than one scalar argument the first two\n\
04091 arguments are taken as the number of rows and columns and any further\n\
04092 arguments specify additional matrix dimensions.\n\
04093 The optional argument @var{class} specifies the return type and may be\n\
04094 either \"double\" or \"single\".\n\
04095 @end deftypefn")
04096 {
04097 #if defined (M_E)
04098   double e_val = M_E;
04099 #else
04100   double e_val = exp (1.0);
04101 #endif
04102 
04103   return fill_matrix (args, e_val, "e");
04104 }
04105 
04106 DEFUN (eps, args, ,
04107   "-*- texinfo -*-\n\
04108 @deftypefn  {Built-in Function} {} eps\n\
04109 @deftypefnx {Built-in Function} {} eps (@var{x})\n\
04110 @deftypefnx {Built-in Function} {} eps (@var{n}, @var{m})\n\
04111 @deftypefnx {Built-in Function} {} eps (@var{n}, @var{m}, @var{k}, @dots{})\n\
04112 @deftypefnx {Built-in Function} {} eps (@dots{}, @var{class})\n\
04113 Return a scalar, matrix or N-dimensional array whose elements are all eps,\n\
04114 the machine precision.  More precisely, @code{eps} is the relative spacing\n\
04115 between any two adjacent numbers in the machine's floating point system.\n\
04116 This number is obviously system dependent.  On machines that support IEEE\n\
04117 floating point arithmetic, @code{eps} is approximately\n\
04118 @tex\n\
04119 $2.2204\\times10^{-16}$ for double precision and $1.1921\\times10^{-7}$\n\
04120 @end tex\n\
04121 @ifnottex\n\
04122 2.2204e-16 for double precision and 1.1921e-07\n\
04123 @end ifnottex\n\
04124 for single precision.\n\
04125 \n\
04126 When called with no arguments, return a scalar with the value\n\
04127 @code{eps(1.0)}.\n\
04128 Given a single argument @var{x}, return the distance between @var{x} and\n\
04129 the next largest value.\n\
04130 When called with more than one argument the first two arguments are taken as\n\
04131 the number of rows and columns and any further\n\
04132 arguments specify additional matrix dimensions.\n\
04133 The optional argument @var{class} specifies the return type and may be\n\
04134 either \"double\" or \"single\".\n\
04135 @end deftypefn")
04136 {
04137   int nargin = args.length ();
04138   octave_value retval;
04139 
04140   if (nargin == 1 && ! args(0).is_string ())
04141     {
04142       if (args(0).is_single_type ())
04143         {
04144           float val = args(0).float_value ();
04145 
04146           if (! error_state)
04147             {
04148               val  = ::fabsf(val);
04149               if (xisnan (val) || xisinf (val))
04150                 retval = fill_matrix (octave_value ("single"),
04151                                       lo_ieee_nan_value (),
04152                                       lo_ieee_float_nan_value (), "eps");
04153               else if (val < FLT_MIN)
04154                 retval = fill_matrix (octave_value ("single"), 0e0,
04155                                       powf (2.0, -149e0), "eps");
04156               else
04157                 {
04158                   int expon;
04159                   frexpf (val, &expon);
04160                   val = std::pow (static_cast <float> (2.0),
04161                                   static_cast <float> (expon - 24));
04162                   retval = fill_matrix (octave_value ("single"), DBL_EPSILON,
04163                                         val, "eps");
04164                 }
04165             }
04166         }
04167       else
04168         {
04169           double val = args(0).double_value ();
04170 
04171           if (! error_state)
04172             {
04173               val  = ::fabs(val);
04174               if (xisnan (val) || xisinf (val))
04175                 retval = fill_matrix (octave_value_list (),
04176                                       lo_ieee_nan_value (),
04177                                       lo_ieee_float_nan_value (), "eps");
04178               else if (val < DBL_MIN)
04179                 retval = fill_matrix (octave_value_list (),
04180                                       pow (2.0, -1074e0), 0e0, "eps");
04181               else
04182                 {
04183                   int expon;
04184                   frexp (val, &expon);
04185                   val = std::pow (static_cast <double> (2.0),
04186                                   static_cast <double> (expon - 53));
04187                   retval = fill_matrix (octave_value_list (), val,
04188                                         FLT_EPSILON, "eps");
04189                 }
04190             }
04191         }
04192     }
04193   else
04194     retval = fill_matrix (args, DBL_EPSILON, FLT_EPSILON, "eps");
04195 
04196   return retval;
04197 }
04198 
04199 /*
04200 
04201 %!assert(eps(1/2),2^(-53))
04202 %!assert(eps(1),2^(-52))
04203 %!assert(eps(2),2^(-51))
04204 %!assert(eps(realmax),2^971)
04205 %!assert(eps(0),2^(-1074))
04206 %!assert(eps(realmin/2),2^(-1074))
04207 %!assert(eps(realmin/16),2^(-1074))
04208 %!assert(eps(Inf),NaN)
04209 %!assert(eps(NaN),NaN)
04210 %!assert(eps(single(1/2)),single(2^(-24)))
04211 %!assert(eps(single(1)),single(2^(-23)))
04212 %!assert(eps(single(2)),single(2^(-22)))
04213 %!assert(eps(realmax('single')),single(2^104))
04214 %!assert(eps(single(0)),single(2^(-149)))
04215 %!assert(eps(realmin('single')/2),single(2^(-149)))
04216 %!assert(eps(realmin('single')/16),single(2^(-149)))
04217 %!assert(eps(single(Inf)),single(NaN))
04218 %!assert(eps(single(NaN)),single(NaN))
04219 
04220 */
04221 
04222 
04223 DEFUN (pi, args, ,
04224   "-*- texinfo -*-\n\
04225 @deftypefn  {Built-in Function} {} pi\n\
04226 @deftypefnx {Built-in Function} {} pi (@var{n})\n\
04227 @deftypefnx {Built-in Function} {} pi (@var{n}, @var{m})\n\
04228 @deftypefnx {Built-in Function} {} pi (@var{n}, @var{m}, @var{k}, @dots{})\n\
04229 @deftypefnx {Built-in Function} {} pi (@dots{}, @var{class})\n\
04230 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
04231 to the ratio of the circumference of a circle to its\n\
04232 @tex\n\
04233 diameter($\\pi$).\n\
04234 @end tex\n\
04235 @ifnottex\n\
04236 diameter.\n\
04237 @end ifnottex\n\
04238 Internally, @code{pi} is computed as @samp{4.0 * atan (1.0)}.\n\
04239 \n\
04240 When called with no arguments, return a scalar with the value of\n\
04241 @tex\n\
04242 $\\pi$.\n\
04243 @end tex\n\
04244 @ifnottex\n\
04245 pi.\n\
04246 @end ifnottex\n\
04247 When called with a single argument, return a square matrix with the dimension\n\
04248 specified.  When called with more than one scalar argument the first two\n\
04249 arguments are taken as the number of rows and columns and any further\n\
04250 arguments specify additional matrix dimensions.\n\
04251 The optional argument @var{class} specifies the return type and may be\n\
04252 either \"double\" or \"single\".\n\
04253 @end deftypefn")
04254 {
04255 #if defined (M_PI)
04256   double pi_val = M_PI;
04257 #else
04258   double pi_val = 4.0 * atan (1.0);
04259 #endif
04260 
04261   return fill_matrix (args, pi_val, "pi");
04262 }
04263 
04264 DEFUN (realmax, args, ,
04265   "-*- texinfo -*-\n\
04266 @deftypefn  {Built-in Function} {} realmax\n\
04267 @deftypefnx {Built-in Function} {} realmax (@var{n})\n\
04268 @deftypefnx {Built-in Function} {} realmax (@var{n}, @var{m})\n\
04269 @deftypefnx {Built-in Function} {} realmax (@var{n}, @var{m}, @var{k}, @dots{})\n\
04270 @deftypefnx {Built-in Function} {} realmax (@dots{}, @var{class})\n\
04271 Return a scalar, matrix or N-dimensional array whose elements are all equal\n\
04272 to the largest floating point number that is representable.  The actual\n\
04273 value is system dependent.  On machines that support IEEE\n\
04274 floating point arithmetic, @code{realmax} is approximately\n\
04275 @tex\n\
04276 $1.7977\\times10^{308}$ for double precision and $3.4028\\times10^{38}$\n\
04277 @end tex\n\
04278 @ifnottex\n\
04279 1.7977e+308 for double precision and 3.4028e+38\n\
04280 @end ifnottex\n\
04281 for single precision.\n\
04282 \n\
04283 When called with no arguments, return a scalar with the value\n\
04284 @code{realmax(\"double\")}.\n\
04285 When called with a single argument, return a square matrix with the dimension\n\
04286 specified.  When called with more than one scalar argument the first two\n\
04287 arguments are taken as the number of rows and columns and any further\n\
04288 arguments specify additional matrix dimensions.\n\
04289 The optional argument @var{class} specifies the return type and may be\n\
04290 either \"double\" or \"single\".\n\
04291 @seealso{realmin, intmax, bitmax}\n\
04292 @end deftypefn")
04293 {
04294   return fill_matrix (args, DBL_MAX, FLT_MAX, "realmax");
04295 }
04296 
04297 DEFUN (realmin, args, ,
04298   "-*- texinfo -*-\n\
04299 @deftypefn  {Built-in Function} {} realmin\n\
04300 @deftypefnx {Built-in Function} {} realmin (@var{n})\n\
04301 @deftypefnx {Built-in Function} {} realmin (@var{n}, @var{m})\n\
04302 @deftypefnx {Built-in Function} {} realmin (@var{n}, @var{m}, @var{k}, @dots{})\n\
04303 @deftypefnx {Built-in Function} {} realmin (@dots{}, @var{class})\n\
04304 Return a scalar, matrix or N-dimensional array whose elements are all equal\n\
04305 to the smallest normalized floating point number that is representable.\n\
04306 The actual value is system dependent.  On machines that support\n\
04307 IEEE floating point arithmetic, @code{realmin} is approximately\n\
04308 @tex\n\
04309 $2.2251\\times10^{-308}$ for double precision and $1.1755\\times10^{-38}$\n\
04310 @end tex\n\
04311 @ifnottex\n\
04312 2.2251e-308 for double precision and 1.1755e-38\n\
04313 @end ifnottex\n\
04314 for single precision.\n\
04315 \n\
04316 When called with no arguments, return a scalar with the value\n\
04317 @code{realmin(\"double\")}.\n\
04318 When called with a single argument, return a square matrix with the dimension\n\
04319 specified.  When called with more than one scalar argument the first two\n\
04320 arguments are taken as the number of rows and columns and any further\n\
04321 arguments specify additional matrix dimensions.\n\
04322 The optional argument @var{class} specifies the return type and may be\n\
04323 either \"double\" or \"single\".\n\
04324 @seealso{realmax, intmin}\n\
04325 @end deftypefn")
04326 {
04327   return fill_matrix (args, DBL_MIN, FLT_MIN, "realmin");
04328 }
04329 
04330 DEFUN (I, args, ,
04331   "-*- texinfo -*-\n\
04332 @c List other forms of function in documentation index\n\
04333 @findex i\n\
04334 @findex j\n\
04335 @findex J\n\
04336 \n\
04337 @deftypefn  {Built-in Function} {} I\n\
04338 @deftypefnx {Built-in Function} {} I (@var{n})\n\
04339 @deftypefnx {Built-in Function} {} I (@var{n}, @var{m})\n\
04340 @deftypefnx {Built-in Function} {} I (@var{n}, @var{m}, @var{k}, @dots{})\n\
04341 @deftypefnx {Built-in Function} {} I (@dots{}, @var{class})\n\
04342 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
04343 to the pure imaginary unit, defined as\n\
04344 @tex\n\
04345 $\\sqrt{-1}$.\n\
04346 @end tex\n\
04347 @ifnottex\n\
04348 @code{sqrt (-1)}.\n\
04349 @end ifnottex\n\
04350  I, and its equivalents i, J, and j, are functions so any of the names may\n\
04351 be reused for other purposes (such as i for a counter variable).\n\
04352 \n\
04353 When called with no arguments, return a scalar with the value @math{i}.  When\n\
04354 called with a single argument, return a square matrix with the dimension\n\
04355 specified.  When called with more than one scalar argument the first two\n\
04356 arguments are taken as the number of rows and columns and any further\n\
04357 arguments specify additional matrix dimensions.\n\
04358 The optional argument @var{class} specifies the return type and may be\n\
04359 either \"double\" or \"single\".\n\
04360 @end deftypefn")
04361 {
04362   return fill_matrix (args, Complex (0.0, 1.0), "I");
04363 }
04364 
04365 DEFALIAS (i, I);
04366 DEFALIAS (J, I);
04367 DEFALIAS (j, I);
04368 
04369 DEFUN (NA, args, ,
04370   "-*- texinfo -*-\n\
04371 @deftypefn  {Built-in Function} {} NA\n\
04372 @deftypefnx {Built-in Function} {} NA (@var{n})\n\
04373 @deftypefnx {Built-in Function} {} NA (@var{n}, @var{m})\n\
04374 @deftypefnx {Built-in Function} {} NA (@var{n}, @var{m}, @var{k}, @dots{})\n\
04375 @deftypefnx {Built-in Function} {} NA (@dots{}, @var{class})\n\
04376 Return a scalar, matrix, or N-dimensional array whose elements are all equal\n\
04377 to the special constant used to designate missing values.\n\
04378 \n\
04379 Note that NA always compares not equal to NA (NA != NA).\n\
04380 To find NA values, use the @code{isna} function.\n\
04381 \n\
04382 When called with no arguments, return a scalar with the value @samp{NA}.\n\
04383 When called with a single argument, return a square matrix with the dimension\n\
04384 specified.  When called with more than one scalar argument the first two\n\
04385 arguments are taken as the number of rows and columns and any further\n\
04386 arguments specify additional matrix dimensions.\n\
04387 The optional argument @var{class} specifies the return type and may be\n\
04388 either \"double\" or \"single\".\n\
04389 @seealso{isna}\n\
04390 @end deftypefn")
04391 {
04392   return fill_matrix (args, lo_ieee_na_value (),
04393                       lo_ieee_float_na_value (), "NA");
04394 }
04395 
04396 /*
04397 
04398 %!assert(single(NA('double')),NA('single'))
04399 %!assert(double(NA('single')),NA('double'))
04400 
04401  */
04402 
04403 DEFUN (false, args, ,
04404   "-*- texinfo -*-\n\
04405 @deftypefn  {Built-in Function} {} false (@var{x})\n\
04406 @deftypefnx {Built-in Function} {} false (@var{n}, @var{m})\n\
04407 @deftypefnx {Built-in Function} {} false (@var{n}, @var{m}, @var{k}, @dots{})\n\
04408 Return a matrix or N-dimensional array whose elements are all logical 0.\n\
04409 If invoked with a single scalar integer argument, return a square\n\
04410 matrix of the specified size.  If invoked with two or more scalar\n\
04411 integer arguments, or a vector of integer values, return an array with\n\
04412 given dimensions.\n\
04413 @seealso{true}\n\
04414 @end deftypefn")
04415 {
04416   return fill_matrix (args, false, "false");
04417 }
04418 
04419 DEFUN (true, args, ,
04420   "-*- texinfo -*-\n\
04421 @deftypefn  {Built-in Function} {} true (@var{x})\n\
04422 @deftypefnx {Built-in Function} {} true (@var{n}, @var{m})\n\
04423 @deftypefnx {Built-in Function} {} true (@var{n}, @var{m}, @var{k}, @dots{})\n\
04424 Return a matrix or N-dimensional array whose elements are all logical 1.\n\
04425 If invoked with a single scalar integer argument, return a square\n\
04426 matrix of the specified size.  If invoked with two or more scalar\n\
04427 integer arguments, or a vector of integer values, return an array with\n\
04428 given dimensions.\n\
04429 @seealso{false}\n\
04430 @end deftypefn")
04431 {
04432   return fill_matrix (args, true, "true");
04433 }
04434 
04435 template <class MT>
04436 octave_value
04437 identity_matrix (int nr, int nc)
04438 {
04439   octave_value retval;
04440 
04441   typename MT::element_type one (1);
04442 
04443   if (nr == 1 && nc == 1)
04444     retval = one;
04445   else
04446     {
04447       dim_vector dims (nr, nc);
04448 
04449       typename MT::element_type zero (0);
04450 
04451       MT m (dims, zero);
04452 
04453       if (nr > 0 && nc > 0)
04454         {
04455           int n = std::min (nr, nc);
04456 
04457           for (int i = 0; i < n; i++)
04458             m(i,i) = one;
04459         }
04460 
04461       retval = m;
04462     }
04463 
04464   return retval;
04465 }
04466 
04467 #define INSTANTIATE_EYE(T) \
04468   template octave_value identity_matrix<T> (int, int)
04469 
04470 INSTANTIATE_EYE (int8NDArray);
04471 INSTANTIATE_EYE (uint8NDArray);
04472 INSTANTIATE_EYE (int16NDArray);
04473 INSTANTIATE_EYE (uint16NDArray);
04474 INSTANTIATE_EYE (int32NDArray);
04475 INSTANTIATE_EYE (uint32NDArray);
04476 INSTANTIATE_EYE (int64NDArray);
04477 INSTANTIATE_EYE (uint64NDArray);
04478 INSTANTIATE_EYE (FloatNDArray);
04479 INSTANTIATE_EYE (NDArray);
04480 INSTANTIATE_EYE (boolNDArray);
04481 
04482 static octave_value
04483 identity_matrix (int nr, int nc, oct_data_conv::data_type dt)
04484 {
04485   octave_value retval;
04486 
04487   // FIXME -- perhaps this should be made extensible by using
04488   // the class name to lookup a function to call to create the new
04489   // value.
04490 
04491   if (! error_state)
04492     {
04493       switch (dt)
04494         {
04495         case oct_data_conv::dt_int8:
04496           retval = identity_matrix<int8NDArray> (nr, nc);
04497           break;
04498 
04499         case oct_data_conv::dt_uint8:
04500           retval = identity_matrix<uint8NDArray> (nr, nc);
04501           break;
04502 
04503         case oct_data_conv::dt_int16:
04504           retval = identity_matrix<int16NDArray> (nr, nc);
04505           break;
04506 
04507         case oct_data_conv::dt_uint16:
04508           retval = identity_matrix<uint16NDArray> (nr, nc);
04509           break;
04510 
04511         case oct_data_conv::dt_int32:
04512           retval = identity_matrix<int32NDArray> (nr, nc);
04513           break;
04514 
04515         case oct_data_conv::dt_uint32:
04516           retval = identity_matrix<uint32NDArray> (nr, nc);
04517           break;
04518 
04519         case oct_data_conv::dt_int64:
04520           retval = identity_matrix<int64NDArray> (nr, nc);
04521           break;
04522 
04523         case oct_data_conv::dt_uint64:
04524           retval = identity_matrix<uint64NDArray> (nr, nc);
04525           break;
04526 
04527         case oct_data_conv::dt_single:
04528           retval = FloatDiagMatrix (nr, nc, 1.0f);
04529           break;
04530 
04531         case oct_data_conv::dt_double:
04532           retval = DiagMatrix (nr, nc, 1.0);
04533           break;
04534 
04535         case oct_data_conv::dt_logical:
04536           retval = identity_matrix<boolNDArray> (nr, nc);
04537           break;
04538 
04539         default:
04540           error ("eye: invalid class name");
04541           break;
04542         }
04543     }
04544 
04545   return retval;
04546 }
04547 
04548 #undef INT_EYE_MATRIX
04549 
04550 DEFUN (eye, args, ,
04551   "-*- texinfo -*-\n\
04552 @deftypefn  {Built-in Function} {} eye (@var{n})\n\
04553 @deftypefnx {Built-in Function} {} eye (@var{m}, @var{n})\n\
04554 @deftypefnx {Built-in Function} {} eye ([@var{m} @var{n}])\n\
04555 @deftypefnx {Built-in Function} {} eye (@dots{}, @var{class})\n\
04556 Return an identity matrix.  If invoked with a single scalar argument @var{n},\n\
04557 return a square @nospell{NxN} identity matrix.  If\n\
04558 supplied two scalar arguments (@var{m}, @var{n}), @code{eye} takes them to be\n\
04559 the number of rows and columns.  If given a vector with two elements,\n\
04560 @code{eye} uses the values of the elements as the number of rows and columns,\n\
04561 respectively.  For example:\n\
04562 \n\
04563 @example\n\
04564 @group\n\
04565 eye (3)\n\
04566      @result{}  1  0  0\n\
04567          0  1  0\n\
04568          0  0  1\n\
04569 @end group\n\
04570 @end example\n\
04571 \n\
04572 The following expressions all produce the same result:\n\
04573 \n\
04574 @example\n\
04575 @group\n\
04576 eye (2)\n\
04577 @equiv{}\n\
04578 eye (2, 2)\n\
04579 @equiv{}\n\
04580 eye (size ([1, 2; 3, 4])\n\
04581 @end group\n\
04582 @end example\n\
04583 \n\
04584 The optional argument @var{class}, allows @code{eye} to return an array of\n\
04585 the specified type, like\n\
04586 \n\
04587 @example\n\
04588 val = zeros (n,m, \"uint8\")\n\
04589 @end example\n\
04590 \n\
04591 Calling @code{eye} with no arguments is equivalent to calling it\n\
04592 with an argument of 1.  Any negative dimensions are treated as zero. \n\
04593 These odd definitions are for compatibility with @sc{matlab}.\n\
04594 @seealso{speye}\n\
04595 @end deftypefn")
04596 {
04597   octave_value retval;
04598 
04599   int nargin = args.length ();
04600 
04601   oct_data_conv::data_type dt = oct_data_conv::dt_double;
04602 
04603   // Check for type information.
04604 
04605   if (nargin > 0 && args(nargin-1).is_string ())
04606     {
04607       std::string nm = args(nargin-1).string_value ();
04608       nargin--;
04609 
04610       dt = oct_data_conv::string_to_data_type (nm);
04611 
04612       if (error_state)
04613         return retval;
04614     }
04615 
04616   switch (nargin)
04617     {
04618     case 0:
04619       retval = identity_matrix (1, 1, dt);
04620       break;
04621 
04622     case 1:
04623       {
04624         octave_idx_type nr, nc;
04625         get_dimensions (args(0), "eye", nr, nc);
04626 
04627         if (! error_state)
04628           retval = identity_matrix (nr, nc, dt);
04629       }
04630       break;
04631 
04632     case 2:
04633       {
04634         octave_idx_type nr, nc;
04635         get_dimensions (args(0), args(1), "eye", nr, nc);
04636 
04637         if (! error_state)
04638           retval = identity_matrix (nr, nc, dt);
04639       }
04640       break;
04641 
04642     default:
04643       print_usage ();
04644       break;
04645     }
04646 
04647   return retval;
04648 }
04649 
04650 
04651 /*
04652 
04653 %!assert (full (eye(3)), [1, 0, 0; 0, 1, 0; 0, 0, 1]);
04654 %!assert (full (eye(2, 3)), [1, 0, 0; 0, 1, 0]);
04655 
04656 %!assert (full (eye(3,'single')), single([1, 0, 0; 0, 1, 0; 0, 0, 1]));
04657 %!assert (full (eye(2, 3,'single')), single([1, 0, 0; 0, 1, 0]));
04658 
04659 %!assert (eye(3,'int8'), int8([1, 0, 0; 0, 1, 0; 0, 0, 1]));
04660 %!assert (eye(2, 3,'int8'), int8([1, 0, 0; 0, 1, 0]));
04661 
04662 %!error <Invalid call to eye> eye (1, 2, 3);
04663 
04664  */
04665 
04666 template <class MT>
04667 static octave_value
04668 do_linspace (const octave_value& base, const octave_value& limit,
04669              octave_idx_type n)
04670 {
04671   typedef typename MT::column_vector_type CVT;
04672   typedef typename MT::element_type T;
04673 
04674   octave_value retval;
04675 
04676   if (base.is_scalar_type ())
04677     {
04678       T bs = octave_value_extract<T> (base);
04679       if (limit.is_scalar_type ())
04680         {
04681           T ls = octave_value_extract<T> (limit);
04682           retval = linspace (bs, ls, n);
04683         }
04684       else
04685         {
04686           CVT lv = octave_value_extract<CVT> (limit);
04687           CVT bv (lv.length (), bs);
04688           retval = linspace (bv, lv, n);
04689         }
04690     }
04691   else
04692     {
04693       CVT bv = octave_value_extract<CVT> (base);
04694       if (limit.is_scalar_type ())
04695         {
04696           T ls = octave_value_extract<T> (limit);
04697           CVT lv (bv.length (), ls);
04698           retval = linspace (bv, lv, n);
04699         }
04700       else
04701         {
04702           CVT lv = octave_value_extract<CVT> (limit);
04703           retval = linspace (bv, lv, n);
04704         }
04705     }
04706 
04707   return retval;
04708 }
04709 
04710 DEFUN (linspace, args, ,
04711   "-*- texinfo -*-\n\
04712 @deftypefn  {Built-in Function} {} linspace (@var{base}, @var{limit})\n\
04713 @deftypefnx {Built-in Function} {} linspace (@var{base}, @var{limit}, @var{n})\n\
04714 Return a row vector with @var{n} linearly spaced elements between\n\
04715 @var{base} and @var{limit}.  If the number of elements is greater than one,\n\
04716 then the endpoints @var{base} and @var{limit} are always included in\n\
04717 the range.  If @var{base} is greater than @var{limit}, the elements are\n\
04718 stored in decreasing order.  If the number of points is not specified, a\n\
04719 value of 100 is used.\n\
04720 \n\
04721 The @code{linspace} function always returns a row vector if both\n\
04722 @var{base} and @var{limit} are scalars.  If one, or both, of them are column\n\
04723 vectors, @code{linspace} returns a matrix.\n\
04724 \n\
04725 For compatibility with @sc{matlab}, return the second argument (@var{limit})\n\
04726 if fewer than two values are requested.\n\
04727 @end deftypefn")
04728 {
04729   octave_value retval;
04730 
04731   int nargin = args.length ();
04732 
04733   octave_idx_type npoints = 100;
04734 
04735   if (nargin != 2 && nargin != 3)
04736     {
04737       print_usage ();
04738       return retval;
04739     }
04740 
04741   if (nargin == 3)
04742     npoints = args(2).idx_type_value ();
04743 
04744   if (! error_state)
04745     {
04746       octave_value arg_1 = args(0);
04747       octave_value arg_2 = args(1);
04748 
04749       if (arg_1.is_single_type () || arg_2.is_single_type ())
04750         {
04751           if (arg_1.is_complex_type () || arg_2.is_complex_type ())
04752             retval = do_linspace<FloatComplexMatrix> (arg_1, arg_2, npoints);
04753           else
04754             retval = do_linspace<FloatMatrix> (arg_1, arg_2, npoints);
04755 
04756         }
04757       else
04758         {
04759           if (arg_1.is_complex_type () || arg_2.is_complex_type ())
04760             retval = do_linspace<ComplexMatrix> (arg_1, arg_2, npoints);
04761           else
04762             retval = do_linspace<Matrix> (arg_1, arg_2, npoints);
04763         }
04764     }
04765   else
04766     error ("linspace: N must be an integer");
04767 
04768   return retval;
04769 }
04770 
04771 
04772 /*
04773 
04774 %!test
04775 %! x1 = linspace (1, 2);
04776 %! x2 = linspace (1, 2, 10);
04777 %! x3 = linspace (1, -2, 10);
04778 %! assert((size (x1) == [1, 100] && x1(1) == 1 && x1(100) == 2
04779 %! && size (x2) == [1, 10] && x2(1) == 1 && x2(10) == 2
04780 %! && size (x3) == [1, 10] && x3(1) == 1 && x3(10) == -2));
04781 
04782 
04783 % assert(linspace ([1, 2; 3, 4], 5, 6), linspace (1, 5, 6));
04784 
04785 %!error <Invalid call to linspace> linspace ();
04786 %!error <Invalid call to linspace> linspace (1, 2, 3, 4);
04787 
04788 %!test
04789 %! fail("linspace ([1, 2; 3, 4], 5, 6)","warning");
04790 
04791 */
04792 
04793 // FIXME -- should accept dimensions as separate args for N-d
04794 // arrays as well as 1-d and 2-d arrays.
04795 
04796 DEFUN (resize, args, ,
04797   "-*- texinfo -*-\n\
04798 @deftypefn  {Built-in Function} {} resize (@var{x}, @var{m})\n\
04799 @deftypefnx {Built-in Function} {} resize (@var{x}, @var{m}, @var{n}, @dots{})\n\
04800 @deftypefnx {Built-in Function} {} resize (@var{x}, [@var{m} @var{n} @dots{}])\n\
04801 Resize @var{x} cutting off elements as necessary.\n\
04802 \n\
04803 In the result, element with certain indices is equal to the corresponding\n\
04804 element of @var{x} if the indices are within the bounds of @var{x};\n\
04805 otherwise, the element is set to zero.\n\
04806 \n\
04807 In other words, the statement\n\
04808 \n\
04809 @example\n\
04810   y = resize (x, dv);\n\
04811 @end example\n\
04812 \n\
04813 @noindent\n\
04814 is equivalent to the following code:\n\
04815 \n\
04816 @example\n\
04817 @group\n\
04818   y = zeros (dv, class (x));\n\
04819   sz = min (dv, size (x));\n\
04820   for i = 1:length (sz), idx@{i@} = 1:sz(i); endfor\n\
04821   y(idx@{:@}) = x(idx@{:@});\n\
04822 @end group\n\
04823 @end example\n\
04824 \n\
04825 @noindent\n\
04826 but is performed more efficiently.\n\
04827 \n\
04828 If only @var{m} is supplied, and it is a scalar, the dimension of the\n\
04829 result is @var{m}-by-@var{m}.\n\
04830 If @var{m}, @var{n}, @dots{} are all scalars, then the dimensions of\n\
04831 the result are @var{m}-by-@var{n}-by-@dots{}.\n\
04832 If given a vector as input, then the\n\
04833 dimensions of the result are given by the elements of that vector.\n\
04834 \n\
04835 An object can be resized to more dimensions than it has;\n\
04836 in such case the missing dimensions are assumed to be 1.\n\
04837 Resizing an object to fewer dimensions is not possible.\n\
04838 @seealso{reshape, postpad}\n\
04839 @end deftypefn")
04840 {
04841   octave_value retval;
04842   int nargin = args.length ();
04843 
04844   if (nargin == 2)
04845     {
04846       Array<double> vec = args(1).vector_value ();
04847       int ndim = vec.length ();
04848       if (ndim == 1)
04849         {
04850           octave_idx_type m = static_cast<octave_idx_type> (vec(0));
04851           retval = args(0);
04852           retval = retval.resize (dim_vector (m, m), true);
04853         }
04854       else
04855         {
04856           dim_vector dv;
04857           dv.resize (ndim);
04858           for (int i = 0; i < ndim; i++)
04859             dv(i) = static_cast<octave_idx_type> (vec(i));
04860           retval = args(0);
04861           retval = retval.resize (dv, true);
04862         }
04863     }
04864   else if (nargin > 2)
04865     {
04866       dim_vector dv;
04867       dv.resize (nargin - 1);
04868       for (octave_idx_type i = 1; i < nargin; i++)
04869         dv(i-1) = static_cast<octave_idx_type> (args(i).scalar_value ());
04870       if (!error_state)
04871         {
04872           retval = args(0);
04873           retval = retval.resize (dv, true);
04874         }
04875 
04876     }
04877   else
04878     print_usage ();
04879   return retval;
04880 }
04881 
04882 // FIXME -- should use octave_idx_type for dimensions.
04883 
04884 DEFUN (reshape, args, ,
04885   "-*- texinfo -*-\n\
04886 @deftypefn  {Built-in Function} {} reshape (@var{A}, @var{m}, @var{n}, @dots{})\n\
04887 @deftypefnx {Built-in Function} {} reshape (@var{A}, [@var{m} @var{n} @dots{}])\n\
04888 @deftypefnx {Built-in Function} {} reshape (@var{A}, @dots{}, [], @dots{})\n\
04889 @deftypefnx {Built-in Function} {} reshape (@var{A}, @var{size})\n\
04890 Return a matrix with the specified dimensions (@var{m}, @var{n}, @dots{})\n\
04891 whose elements are taken from the matrix @var{A}.  The elements of the\n\
04892 matrix are accessed in column-major order (like Fortran arrays are stored).\n\
04893 \n\
04894 The following code demonstrates reshaping a 1x4 row vector into a 2x2 square\n\
04895 matrix.\n\
04896 \n\
04897 @example\n\
04898 @group\n\
04899 reshape ([1, 2, 3, 4], 2, 2)\n\
04900      @result{}  1  3\n\
04901          2  4\n\
04902 @end group\n\
04903 @end example\n\
04904 \n\
04905 @noindent\n\
04906 Note that the total number of elements in the original\n\
04907 matrix (@code{prod (size (@var{A}))}) must match the total number of elements\n\
04908 in the new matrix (@code{prod ([@var{m} @var{n} @dots{}])}).\n\
04909 \n\
04910 A single dimension of the return matrix may be left unspecified and Octave\n\
04911 will determine its size automatically.  An empty matrix ([]) is used to flag\n\
04912 the unspecified dimension.\n\
04913 @seealso{resize}\n\
04914 @end deftypefn")
04915 {
04916   octave_value retval;
04917 
04918   int nargin = args.length ();
04919 
04920   dim_vector new_dims;
04921 
04922   if (nargin == 2)
04923     {
04924       Array<octave_idx_type> new_size = args(1).octave_idx_type_vector_value ();
04925 
04926       new_dims = dim_vector::alloc (new_size.length ());
04927 
04928       for (octave_idx_type i = 0; i < new_size.length (); i++)
04929         {
04930           if (new_size(i) < 0)
04931             {
04932               error ("reshape: SIZE must be non-negative");
04933               break;
04934             }
04935           else
04936             new_dims(i) = new_size(i);
04937         }
04938     }
04939   else if (nargin > 2)
04940     {
04941       new_dims = dim_vector::alloc (nargin-1);
04942       int empty_dim = -1;
04943 
04944       for (int i = 1; i < nargin; i++)
04945         {
04946           if (args(i).is_empty ())
04947             {
04948               if (empty_dim > 0)
04949                 {
04950                   error ("reshape: only a single dimension can be unknown");
04951                   break;
04952                 }
04953               else
04954                 {
04955                   empty_dim = i;
04956                   new_dims(i-1) = 1;
04957                 }
04958             }
04959           else
04960             {
04961               new_dims(i-1) = args(i).idx_type_value ();
04962 
04963               if (error_state)
04964                 break;
04965               else if (new_dims(i-1) < 0)
04966                 {
04967                   error ("reshape: SIZE must be non-negative");
04968                   break;
04969                 }
04970             }
04971         }
04972 
04973       if (! error_state && (empty_dim > 0))
04974         {
04975           octave_idx_type nel = new_dims.numel ();
04976 
04977           if (nel == 0)
04978             new_dims(empty_dim-1) = 0;
04979           else
04980             {
04981               octave_idx_type a_nel = args(0).numel ();
04982               octave_idx_type size_empty_dim = a_nel / nel;
04983 
04984               if (a_nel != size_empty_dim * nel)
04985                 error ("reshape: SIZE is not divisible by the product of known dimensions (= %d)", nel);
04986               else
04987                 new_dims(empty_dim-1) = size_empty_dim;
04988             }
04989         }
04990     }
04991   else
04992     {
04993       print_usage ();
04994       return retval;
04995     }
04996 
04997   if (! error_state)
04998     retval = args(0).reshape (new_dims);
04999 
05000   return retval;
05001 }
05002 
05003 /*
05004 
05005 %!assert(size (reshape (ones (4, 4), 2, 8)), [2, 8])
05006 %!assert(size (reshape (ones (4, 4), 8, 2)), [8, 2])
05007 %!assert(size (reshape (ones (15, 4), 1, 60)), [1, 60])
05008 %!assert(size (reshape (ones (15, 4), 60, 1)), [60, 1])
05009 
05010 %!assert(size (reshape (ones (4, 4, 'single'), 2, 8)), [2, 8])
05011 %!assert(size (reshape (ones (4, 4, 'single'), 8, 2)), [8, 2])
05012 %!assert(size (reshape (ones (15, 4, 'single'), 1, 60)), [1, 60])
05013 %!assert(size (reshape (ones (15, 4, 'single'), 60, 1)), [60, 1])
05014 
05015 %!test
05016 %! s.a = 1;
05017 %! fail("reshape (s, 2, 3)");
05018 
05019 %!error <Invalid call to reshape> reshape ();
05020 %!error reshape (1, 2, 3, 4);
05021 
05022  */
05023 
05024 DEFUN (vec, args, ,
05025   "-*- texinfo -*-\n\
05026 @deftypefn  {Built-in Function} {@var{v} =} vec (@var{x})\n\
05027 @deftypefnx {Built-in Function} {@var{v} =} vec (@var{x}, @var{dim})\n\
05028 Return the vector obtained by stacking the columns of the matrix @var{x}\n\
05029 one above the other.  Without @var{dim} this is equivalent to\n\
05030 @code{@var{x}(:)}.  If @var{dim} is supplied, the dimensions of @var{v}\n\
05031 are set to @var{dim} with all elements along the last dimension.\n\
05032 This is equivalent to @code{shiftdim (@var{x}(:), 1-@var{dim})}.\n\
05033 @seealso{vech}\n\
05034 @end deftypefn")
05035 {
05036   octave_value retval;
05037   int dim = 1;
05038 
05039   int nargin = args.length ();
05040 
05041   if (nargin < 1 || nargin > 2)
05042     print_usage () ;
05043 
05044   if (! error_state && nargin == 2)
05045     {
05046       dim = args(1).idx_type_value ();
05047 
05048       if (dim < 1)
05049         error ("vec: DIM must be greater than zero");
05050     }
05051 
05052   if (! error_state)
05053     {
05054       octave_value colon (octave_value::magic_colon_t);
05055       octave_value arg = args(0);
05056       retval = arg.single_subsref ("(", colon);
05057 
05058 
05059       if (! error_state && dim > 1)
05060         {
05061           dim_vector new_dims = dim_vector::alloc (dim);
05062 
05063           for (int i = 0; i < dim-1; i++)
05064             new_dims(i) = 1;
05065 
05066           new_dims(dim-1) = retval.numel ();
05067 
05068           retval = retval.reshape (new_dims);
05069         }
05070     }
05071 
05072   return retval;
05073 }
05074 
05075 /*
05076 
05077 %!assert(vec ([1, 2; 3, 4]), [1; 3; 2; 4])
05078 %!assert(vec ([1, 3, 2, 4]), [1; 3; 2; 4]);
05079 %!assert(vec ([1, 2, 3, 4], 2), [1, 2, 3, 4]);
05080 %!assert(vec ([1, 2; 3, 4]), vec ([1, 2; 3, 4], 1));
05081 %!assert(vec ([1, 2; 3, 4], 1), [1; 3; 2; 4]);
05082 %!assert(vec ([1, 2; 3, 4], 2), [1, 3, 2, 4]);
05083 %!assert(vec ([1, 3; 2, 4], 3), reshape ([1, 2, 3, 4], 1, 1, 4));
05084 %!assert(vec ([1, 3; 2, 4], 3), shiftdim (vec ([1, 3; 2, 4]), -2));
05085 
05086 %!error vec ();
05087 %!error vec (1, 2, 3);
05088 %!error vec ([1, 2; 3, 4], 0);
05089 
05090 */
05091 
05092 DEFUN (squeeze, args, ,
05093   "-*- texinfo -*-\n\
05094 @deftypefn {Built-in Function} {} squeeze (@var{x})\n\
05095 Remove singleton dimensions from @var{x} and return the result.\n\
05096 Note that for compatibility with @sc{matlab}, all objects have\n\
05097 a minimum of two dimensions and row vectors are left unchanged.\n\
05098 @end deftypefn")
05099 {
05100   octave_value retval;
05101 
05102   if (args.length () == 1)
05103     retval = args(0).squeeze ();
05104   else
05105     print_usage ();
05106 
05107   return retval;
05108 }
05109 
05110 DEFUN (full, args, ,
05111     "-*- texinfo -*-\n\
05112 @deftypefn {Loadable Function} {@var{FM} =} full (@var{SM})\n\
05113 Return a full storage matrix from a sparse, diagonal, permutation matrix\n\
05114 or a range.\n\
05115 @seealso{sparse}\n\
05116 @end deftypefn")
05117 {
05118   octave_value retval;
05119 
05120   if (args.length () == 1)
05121     retval = args(0).full_value ();
05122   else
05123     print_usage ();
05124 
05125   return retval;
05126 }
05127 
05128 // Compute various norms of the vector X.
05129 
05130 DEFUN (norm, args, ,
05131   "-*- texinfo -*-\n\
05132 @deftypefn  {Built-in Function} {} norm (@var{A})\n\
05133 @deftypefnx {Built-in Function} {} norm (@var{A}, @var{p})\n\
05134 @deftypefnx {Built-in Function} {} norm (@var{A}, @var{p}, @var{opt})\n\
05135 Compute the p-norm of the matrix @var{A}.  If the second argument is\n\
05136 missing, @code{p = 2} is assumed.\n\
05137 \n\
05138 If @var{A} is a matrix (or sparse matrix):\n\
05139 \n\
05140 @table @asis\n\
05141 @item @var{p} = @code{1}\n\
05142 1-norm, the largest column sum of the absolute values of @var{A}.\n\
05143 \n\
05144 @item @var{p} = @code{2}\n\
05145 Largest singular value of @var{A}.\n\
05146 \n\
05147 @item @var{p} = @code{Inf} or @code{\"inf\"}\n\
05148 @cindex infinity norm\n\
05149 Infinity norm, the largest row sum of the absolute values of @var{A}.\n\
05150 \n\
05151 @item @var{p} = @code{\"fro\"}\n\
05152 @cindex Frobenius norm\n\
05153 Frobenius norm of @var{A}, @code{sqrt (sum (diag (@var{A}' * @var{A})))}.\n\
05154 \n\
05155 @item other @var{p}, @code{@var{p} > 1}\n\
05156 @cindex general p-norm\n\
05157 maximum @code{norm (A*x, p)} such that @code{norm (x, p) == 1}\n\
05158 @end table\n\
05159 \n\
05160 If @var{A} is a vector or a scalar:\n\
05161 \n\
05162 @table @asis\n\
05163 @item @var{p} = @code{Inf} or @code{\"inf\"}\n\
05164 @code{max (abs (@var{A}))}.\n\
05165 \n\
05166 @item @var{p} = @code{-Inf}\n\
05167 @code{min (abs (@var{A}))}.\n\
05168 \n\
05169 @item @var{p} = @code{\"fro\"}\n\
05170 Frobenius norm of @var{A}, @code{sqrt (sumsq (abs (A)))}.\n\
05171 \n\
05172 @item @var{p} = 0\n\
05173 Hamming norm - the number of nonzero elements.\n\
05174 \n\
05175 @item other @var{p}, @code{@var{p} > 1}\n\
05176 p-norm of @var{A}, @code{(sum (abs (@var{A}) .^ @var{p})) ^ (1/@var{p})}.\n\
05177 \n\
05178 @item other @var{p} @code{@var{p} < 1}\n\
05179 the p-pseudonorm defined as above.\n\
05180 @end table\n\
05181 \n\
05182 If @var{opt} is the value @code{\"rows\"}, treat each row as a vector and\n\
05183 compute its norm.  The result is returned as a column vector.\n\
05184 Similarly, if @var{opt} is @code{\"columns\"} or @code{\"cols\"} then compute\n\
05185 the norms of each column and return a row vector.\n\
05186 @seealso{cond, svd}\n\
05187 @end deftypefn")
05188 {
05189   octave_value_list retval;
05190 
05191   int nargin = args.length ();
05192 
05193   if (nargin >= 1 && nargin <= 3)
05194     {
05195       octave_value x_arg = args(0);
05196 
05197       if (x_arg.ndims () == 2)
05198         {
05199           enum { sfmatrix, sfcols, sfrows, sffrob, sfinf } strflag = sfmatrix;
05200           if (nargin > 1 && args(nargin-1).is_string ())
05201             {
05202               std::string str = args(nargin-1).string_value ();
05203               if (str == "cols" || str == "columns")
05204                 strflag = sfcols;
05205               else if (str == "rows")
05206                 strflag = sfrows;
05207               else if (str == "fro")
05208                 strflag = sffrob;
05209               else if (str == "inf")
05210                 strflag = sfinf;
05211               else
05212                 error ("norm: unrecognized option: %s", str.c_str ());
05213               // we've handled the last parameter, so act as if it was removed
05214               nargin --;
05215             }
05216           else if (nargin > 1 && ! args(1).is_scalar_type ())
05217             gripe_wrong_type_arg ("norm", args(1), true);
05218 
05219           if (! error_state)
05220             {
05221               octave_value p_arg = (nargin > 1) ? args(1) : octave_value (2);
05222               switch (strflag)
05223                 {
05224                 case sfmatrix:
05225                   retval(0) = xnorm (x_arg, p_arg);
05226                   break;
05227                 case sfcols:
05228                   retval(0) = xcolnorms (x_arg, p_arg);
05229                   break;
05230                 case sfrows:
05231                   retval(0) = xrownorms (x_arg, p_arg);
05232                   break;
05233                 case sffrob:
05234                   retval(0) = xfrobnorm (x_arg);
05235                   break;
05236                 case sfinf:
05237                   retval(0) = xnorm (x_arg, octave_Inf);
05238                   break;
05239                 }
05240             }
05241         }
05242       else
05243         error ("norm: only valid for 2-D objects");
05244     }
05245   else
05246     print_usage ();
05247 
05248   return retval;
05249 }
05250 
05251 /*
05252 %!shared x
05253 %! x = [1, -3, 4, 5, -7];
05254 %!assert(norm(x,1), 20);
05255 %!assert(norm(x,2), 10);
05256 %!assert(norm(x,3), 8.24257059961711, -4*eps);
05257 %!assert(norm(x,Inf), 7);
05258 %!assert(norm(x,-Inf), 1);
05259 %!assert(norm(x,"inf"), 7);
05260 %!assert(norm(x,"fro"), 10, -eps);
05261 %!assert(norm(x), 10);
05262 %!assert(norm([1e200, 1]), 1e200);
05263 %!assert(norm([3+4i, 3-4i, sqrt(31)]), 9, -4*eps);
05264 %!shared m
05265 %! m = magic (4);
05266 %!assert(norm(m,1), 34);
05267 %!assert(norm(m,2), 34, -eps);
05268 %!assert(norm(m,Inf), 34);
05269 %!assert(norm(m,"inf"), 34);
05270 %!shared m2, flo, fhi
05271 %! m2 = [1,2;3,4];
05272 %! flo = 1e-300;
05273 %! fhi = 1e+300;
05274 %!assert (norm(flo*m2,"fro"), sqrt(30)*flo, -eps)
05275 %!assert (norm(fhi*m2,"fro"), sqrt(30)*fhi, -eps)
05276 
05277 %!shared x
05278 %! x = single([1, -3, 4, 5, -7]);
05279 %!assert(norm(x,1), single(20));
05280 %!assert(norm(x,2), single(10));
05281 %!assert(norm(x,3), single(8.24257059961711), -4*eps('single'));
05282 %!assert(norm(x,Inf), single(7));
05283 %!assert(norm(x,-Inf), single(1));
05284 %!assert(norm(x,"inf"), single(7));
05285 %!assert(norm(x,"fro"), single(10), -eps('single'));
05286 %!assert(norm(x), single(10));
05287 %!assert(norm(single([1e200, 1])), single(1e200));
05288 %!assert(norm(single([3+4i, 3-4i, sqrt(31)])), single(9), -4*eps('single'));
05289 %!shared m
05290 %! m = single(magic (4));
05291 %!assert(norm(m,1), single(34));
05292 %!assert(norm(m,2), single(34), -eps('single'));
05293 %!assert(norm(m,Inf), single(34));
05294 %!assert(norm(m,"inf"), single(34));
05295 %!shared m2, flo, fhi
05296 %! m2 = single([1,2;3,4]);
05297 %! flo = single(1e-300);
05298 %! fhi = single(1e+300);
05299 %!assert (norm(flo*m2,"fro"), single(sqrt(30)*flo), -eps('single'))
05300 %!assert (norm(fhi*m2,"fro"), single(sqrt(30)*fhi), -eps('single'))
05301 */
05302 
05303 static octave_value
05304 unary_op_defun_body (octave_value::unary_op op,
05305                      const octave_value_list& args)
05306 {
05307   octave_value retval;
05308   if (args.length () == 1)
05309     retval = do_unary_op (op, args(0));
05310   else
05311     print_usage ();
05312 
05313   return retval;
05314 }
05315 
05316 DEFUN (not, args, ,
05317   "-*- texinfo -*-\n\
05318 @deftypefn {Built-in Function} {} not (@var{x})\n\
05319 Return the logical NOT of @var{x}.  This function is equivalent to\n\
05320 @code{! x}.\n\
05321 @seealso{and, or, xor}\n\
05322 @end deftypefn")
05323 {
05324   return unary_op_defun_body (octave_value::op_not, args);
05325 }
05326 
05327 DEFUN (uplus, args, ,
05328   "-*- texinfo -*-\n\
05329 @deftypefn {Built-in Function} {} uplus (@var{x})\n\
05330 This function and @w{@xcode{+ x}} are equivalent.\n\
05331 @end deftypefn")
05332 {
05333   return unary_op_defun_body (octave_value::op_uplus, args);
05334 }
05335 
05336 DEFUN (uminus, args, ,
05337   "-*- texinfo -*-\n\
05338 @deftypefn {Built-in Function} {} uminus (@var{x})\n\
05339 This function and @w{@xcode{- x}} are equivalent.\n\
05340 @end deftypefn")
05341 {
05342   return unary_op_defun_body (octave_value::op_uminus, args);
05343 }
05344 
05345 DEFUN (transpose, args, ,
05346   "-*- texinfo -*-\n\
05347 @deftypefn {Built-in Function} {} transpose (@var{x})\n\
05348 Return the transpose of @var{x}.\n\
05349 This function and @xcode{x.'} are equivalent.\n\
05350 @seealso{ctranspose}\n\
05351 @end deftypefn")
05352 {
05353   return unary_op_defun_body (octave_value::op_transpose, args);
05354 }
05355 
05356 /*
05357 
05358 %!assert (2.', 2);
05359 %!assert (2i.',2i);
05360 %!assert ([1:4].',[1;2;3;4]);
05361 %!assert ([1;2;3;4].',[1:4]);
05362 %!assert ([1,2;3,4].',[1,3;2,4]);
05363 %!assert ([1,2i;3,4].',[1,3;2i,4]);
05364 
05365 %!assert (transpose ([1,2;3,4]),[1,3;2,4]);
05366 
05367 %!assert (single(2).', single(2));
05368 %!assert (single(2i).',single(2i));
05369 %!assert (single([1:4]).',single([1;2;3;4]));
05370 %!assert (single([1;2;3;4]).',single([1:4]));
05371 %!assert (single([1,2;3,4]).',single([1,3;2,4]));
05372 %!assert (single([1,2i;3,4]).',single([1,3;2i,4]));
05373 
05374 %!assert (transpose (single([1,2;3,4])),single([1,3;2,4]));
05375 
05376 */
05377 
05378 DEFUN (ctranspose, args, ,
05379   "-*- texinfo -*-\n\
05380 @deftypefn {Built-in Function} {} ctranspose (@var{x})\n\
05381 Return the complex conjugate transpose of @var{x}.\n\
05382 This function and @xcode{x'} are equivalent.\n\
05383 @seealso{transpose}\n\
05384 @end deftypefn")
05385 {
05386   return unary_op_defun_body (octave_value::op_hermitian, args);
05387 }
05388 
05389 /*
05390 
05391 %!assert (2', 2);
05392 %!assert (2i',-2i);
05393 %!assert ([1:4]',[1;2;3;4]);
05394 %!assert ([1;2;3;4]',[1:4]);
05395 %!assert ([1,2;3,4]',[1,3;2,4]);
05396 %!assert ([1,2i;3,4]',[1,3;-2i,4]);
05397 
05398 %!assert (ctranspose ([1,2i;3,4]),[1,3;-2i,4]);
05399 
05400 %!assert (single(2)', single(2));
05401 %!assert (single(2i)',single(-2i));
05402 %!assert (single([1:4])',single([1;2;3;4]));
05403 %!assert (single([1;2;3;4])',single([1:4]));
05404 %!assert (single([1,2;3,4])',single([1,3;2,4]));
05405 %!assert (single([1,2i;3,4])',single([1,3;-2i,4]));
05406 
05407 %!assert (ctranspose (single([1,2i;3,4])),single([1,3;-2i,4]));
05408 
05409 */
05410 
05411 static octave_value
05412 binary_op_defun_body (octave_value::binary_op op,
05413                       const octave_value_list& args)
05414 {
05415   octave_value retval;
05416 
05417   if (args.length () == 2)
05418     retval = do_binary_op (op, args(0), args(1));
05419   else
05420     print_usage ();
05421 
05422   return retval;
05423 }
05424 
05425 static octave_value
05426 binary_assoc_op_defun_body (octave_value::binary_op op,
05427                             octave_value::assign_op aop,
05428                             const octave_value_list& args)
05429 {
05430   octave_value retval;
05431   int nargin = args.length ();
05432 
05433   switch (nargin)
05434     {
05435     case 0:
05436       print_usage ();
05437       break;
05438     case 1:
05439       retval = args(0);
05440       break;
05441     case 2:
05442       retval = do_binary_op (op, args(0), args(1));
05443      break;
05444     default:
05445      retval = do_binary_op (op, args(0), args(1));
05446      for (int i = 2; i < nargin; i++)
05447        retval.assign (aop, args(i));
05448      break;
05449     }
05450 
05451   return retval;
05452 }
05453 
05454 DEFUN (plus, args, ,
05455   "-*- texinfo -*-\n\
05456 @deftypefn  {Built-in Function} {} plus (@var{x}, @var{y})\n\
05457 @deftypefnx {Built-in Function} {} plus (@var{x1}, @var{x2}, @dots{})\n\
05458 This function and @w{@xcode{x + y}} are equivalent.\n\
05459 If more arguments are given, the summation is applied\n\
05460 cumulatively from left to right:\n\
05461 \n\
05462 @example\n\
05463   (@dots{}((x1 + x2) + x3) + @dots{})\n\
05464 @end example\n\
05465 \n\
05466 At least one argument is required.\n\
05467 @seealso{minus}\n\
05468 @end deftypefn")
05469 {
05470   return binary_assoc_op_defun_body (octave_value::op_add,
05471                                      octave_value::op_add_eq, args);
05472 }
05473 
05474 DEFUN (minus, args, ,
05475   "-*- texinfo -*-\n\
05476 @deftypefn {Built-in Function} {} minus (@var{x}, @var{y})\n\
05477 This function and @w{@xcode{x - y}} are equivalent.\n\
05478 @seealso{plus}\n\
05479 @end deftypefn")
05480 {
05481   return binary_op_defun_body (octave_value::op_sub, args);
05482 }
05483 
05484 DEFUN (mtimes, args, ,
05485   "-*- texinfo -*-\n\
05486 @deftypefn  {Built-in Function} {} mtimes (@var{x}, @var{y})\n\
05487 @deftypefnx {Built-in Function} {} mtimes (@var{x1}, @var{x2}, @dots{})\n\
05488 Return the matrix multiplication product of inputs.\n\
05489 This function and @w{@xcode{x * y}} are equivalent.\n\
05490 If more arguments are given, the multiplication is applied\n\
05491 cumulatively from left to right:\n\
05492 \n\
05493 @example\n\
05494   (@dots{}((x1 * x2) * x3) * @dots{})\n\
05495 @end example\n\
05496 \n\
05497 At least one argument is required.\n\
05498 @seealso{times}\n\
05499 @end deftypefn")
05500 {
05501   return binary_assoc_op_defun_body (octave_value::op_mul,
05502                                      octave_value::op_mul_eq, args);
05503 }
05504 
05505 DEFUN (mrdivide, args, ,
05506   "-*- texinfo -*-\n\
05507 @deftypefn {Built-in Function} {} mrdivide (@var{x}, @var{y})\n\
05508 Return the matrix right division of @var{x} and @var{y}.\n\
05509 This function and @w{@xcode{x / y}} are equivalent.\n\
05510 @seealso{mldivide, rdivide}\n\
05511 @end deftypefn")
05512 {
05513   return binary_op_defun_body (octave_value::op_div, args);
05514 }
05515 
05516 DEFUN (mpower, args, ,
05517   "-*- texinfo -*-\n\
05518 @deftypefn {Built-in Function} {} mpower (@var{x}, @var{y})\n\
05519 Return the matrix power operation of @var{x} raised to the @var{y} power.\n\
05520 This function and @w{@xcode{x ^ y}} are equivalent.\n\
05521 @seealso{power}\n\
05522 @end deftypefn")
05523 {
05524   return binary_op_defun_body (octave_value::op_pow, args);
05525 }
05526 
05527 DEFUN (mldivide, args, ,
05528   "-*- texinfo -*-\n\
05529 @deftypefn {Built-in Function} {} mldivide (@var{x}, @var{y})\n\
05530 Return the matrix left division of @var{x} and @var{y}.\n\
05531 This function and @w{@xcode{x \\ y}} are equivalent.\n\
05532 @seealso{mrdivide, ldivide}\n\
05533 @end deftypefn")
05534 {
05535   return binary_op_defun_body (octave_value::op_ldiv, args);
05536 }
05537 
05538 DEFUN (lt, args, ,
05539   "-*- texinfo -*-\n\
05540 @deftypefn {Built-in Function} {} lt (@var{x}, @var{y})\n\
05541 This function is equivalent to @w{@code{x < y}}.\n\
05542 @end deftypefn")
05543 {
05544   return binary_op_defun_body (octave_value::op_lt, args);
05545 }
05546 
05547 DEFUN (le, args, ,
05548   "-*- texinfo -*-\n\
05549 @deftypefn {Built-in Function} {} le (@var{x}, @var{y})\n\
05550 This function is equivalent to @w{@code{x <= y}}.\n\
05551 @end deftypefn")
05552 {
05553   return binary_op_defun_body (octave_value::op_le, args);
05554 }
05555 
05556 DEFUN (eq, args, ,
05557   "-*- texinfo -*-\n\
05558 @deftypefn {Built-in Function} {} eq (@var{x}, @var{y})\n\
05559 Return true if the two inputs are equal.\n\
05560 This function is equivalent to @w{@code{x == y}}.\n\
05561 @seealso{ne, isequal}\n\
05562 @end deftypefn")
05563 {
05564   return binary_op_defun_body (octave_value::op_eq, args);
05565 }
05566 
05567 DEFUN (ge, args, ,
05568   "-*- texinfo -*-\n\
05569 @deftypefn {Built-in Function} {} ge (@var{x}, @var{y})\n\
05570 This function is equivalent to @w{@code{x >= y}}.\n\
05571 @end deftypefn")
05572 {
05573   return binary_op_defun_body (octave_value::op_ge, args);
05574 }
05575 
05576 DEFUN (gt, args, ,
05577   "-*- texinfo -*-\n\
05578 @deftypefn {Built-in Function} {} gt (@var{x}, @var{y})\n\
05579 This function is equivalent to @w{@code{x > y}}.\n\
05580 @end deftypefn")
05581 {
05582   return binary_op_defun_body (octave_value::op_gt, args);
05583 }
05584 
05585 DEFUN (ne, args, ,
05586   "-*- texinfo -*-\n\
05587 @deftypefn {Built-in Function} {} ne (@var{x}, @var{y})\n\
05588 Return true if the two inputs are not equal.\n\
05589 This function is equivalent to @w{@code{x != y}}.\n\
05590 @seealso{eq, isequal}\n\
05591 @end deftypefn")
05592 {
05593   return binary_op_defun_body (octave_value::op_ne, args);
05594 }
05595 
05596 DEFUN (times, args, ,
05597   "-*- texinfo -*-\n\
05598 @deftypefn  {Built-in Function} {} times (@var{x}, @var{y})\n\
05599 @deftypefnx {Built-in Function} {} times (@var{x1}, @var{x2}, @dots{})\n\
05600 Return the element-by-element multiplication product of inputs.\n\
05601 This function and @w{@xcode{x .* y}} are equivalent.\n\
05602 If more arguments are given, the multiplication is applied\n\
05603 cumulatively from left to right:\n\
05604 \n\
05605 @example\n\
05606   (@dots{}((x1 .* x2) .* x3) .* @dots{})\n\
05607 @end example\n\
05608 \n\
05609 At least one argument is required.\n\
05610 @seealso{mtimes}\n\
05611 @end deftypefn")
05612 {
05613   return binary_assoc_op_defun_body (octave_value::op_el_mul,
05614                                      octave_value::op_el_mul_eq, args);
05615 }
05616 
05617 DEFUN (rdivide, args, ,
05618   "-*- texinfo -*-\n\
05619 @deftypefn {Built-in Function} {} rdivide (@var{x}, @var{y})\n\
05620 Return the element-by-element right division of @var{x} and @var{y}.\n\
05621 This function and @w{@xcode{x ./ y}} are equivalent.\n\
05622 @seealso{ldivide, mrdivide}\n\
05623 @end deftypefn")
05624 {
05625   return binary_op_defun_body (octave_value::op_el_div, args);
05626 }
05627 
05628 DEFUN (power, args, ,
05629   "-*- texinfo -*-\n\
05630 @deftypefn {Built-in Function} {} power (@var{x}, @var{y})\n\
05631 Return the element-by-element operation of @var{x} raised to the\n\
05632 @var{y} power.  If several complex results are possible,\n\
05633 returns the one with smallest non-negative argument (angle).  Use\n\
05634 @code{realpow}, @code{realsqrt}, @code{cbrt}, or @code{nthroot} if a\n\
05635 real result is preferred.\n\
05636 \n\
05637 This function and @w{@xcode{x .^ y}} are equivalent.\n\
05638 @seealso{mpower, realpow, realsqrt, cbrt, nthroot}\n\
05639 @end deftypefn")
05640 {
05641   return binary_op_defun_body (octave_value::op_el_pow, args);
05642 }
05643 
05644 DEFUN (ldivide, args, ,
05645   "-*- texinfo -*-\n\
05646 @deftypefn {Built-in Function} {} ldivide (@var{x}, @var{y})\n\
05647 Return the element-by-element left division of @var{x} and @var{y}.\n\
05648 This function and @w{@xcode{x .\\ y}} are equivalent.\n\
05649 @seealso{rdivide, mldivide}\n\
05650 @end deftypefn")
05651 {
05652   return binary_op_defun_body (octave_value::op_el_ldiv, args);
05653 }
05654 
05655 DEFUN (and, args, ,
05656   "-*- texinfo -*-\n\
05657 @deftypefn  {Built-in Function} {} and (@var{x}, @var{y})\n\
05658 @deftypefnx {Built-in Function} {} and (@var{x1}, @var{x2}, @dots{})\n\
05659 Return the logical AND of @var{x} and @var{y}.\n\
05660 This function is equivalent to @w{@code{x & y}}.\n\
05661 If more arguments are given, the logical and is applied\n\
05662 cumulatively from left to right:\n\
05663 \n\
05664 @example\n\
05665   (@dots{}((x1 & x2) & x3) & @dots{})\n\
05666 @end example\n\
05667 \n\
05668 At least one argument is required.\n\
05669 @seealso{or, not, xor}\n\
05670 @end deftypefn")
05671 {
05672   return binary_assoc_op_defun_body (octave_value::op_el_and,
05673                                      octave_value::op_el_and_eq, args);
05674 }
05675 
05676 DEFUN (or, args, ,
05677   "-*- texinfo -*-\n\
05678 @deftypefn  {Built-in Function} {} or (@var{x}, @var{y})\n\
05679 @deftypefnx {Built-in Function} {} or (@var{x1}, @var{x2}, @dots{})\n\
05680 Return the logical OR of @var{x} and @var{y}.\n\
05681 This function is equivalent to @w{@code{x | y}}.\n\
05682 If more arguments are given, the logical or is applied\n\
05683 cumulatively from left to right:\n\
05684 \n\
05685 @example\n\
05686   (@dots{}((x1 | x2) | x3) | @dots{})\n\
05687 @end example\n\
05688 \n\
05689 At least one argument is required.\n\
05690 @seealso{and, not, xor}\n\
05691 @end deftypefn")
05692 {
05693   return binary_assoc_op_defun_body (octave_value::op_el_or,
05694                                      octave_value::op_el_or_eq, args);
05695 }
05696 
05697 static double tic_toc_timestamp = -1.0;
05698 
05699 DEFUN (tic, args, nargout,
05700   "-*- texinfo -*-\n\
05701 @deftypefn  {Built-in Function} {} tic ()\n\
05702 @deftypefnx {Built-in Function} {} toc ()\n\
05703 Set or check a wall-clock timer.  Calling @code{tic} without an\n\
05704 output argument sets the timer.  Subsequent calls to @code{toc}\n\
05705 return the number of seconds since the timer was set.  For example,\n\
05706 \n\
05707 @example\n\
05708 @group\n\
05709 tic ();\n\
05710 # many computations later@dots{}\n\
05711 elapsed_time = toc ();\n\
05712 @end group\n\
05713 @end example\n\
05714 \n\
05715 @noindent\n\
05716 will set the variable @code{elapsed_time} to the number of seconds since\n\
05717 the most recent call to the function @code{tic}.\n\
05718 \n\
05719 If called with one output argument then this function returns a scalar\n\
05720 of type @code{uint64} and the wall-clock timer is not started.\n\
05721 \n\
05722 @example\n\
05723 @group\n\
05724 t = tic; sleep (5); (double (tic ()) - double (t)) * 1e-6\n\
05725      @result{} 5\n\
05726 @end group\n\
05727 @end example\n\
05728 \n\
05729 Nested timing with @code{tic} and @code{toc} is not supported.\n\
05730 Therefore @code{toc} will always return the elapsed time from the most\n\
05731 recent call to @code{tic}.\n\
05732 \n\
05733 If you are more interested in the CPU time that your process used, you\n\
05734 should use the @code{cputime} function instead.  The @code{tic} and\n\
05735 @code{toc} functions report the actual wall clock time that elapsed\n\
05736 between the calls.  This may include time spent processing other jobs or\n\
05737 doing nothing at all.  For example:\n\
05738 \n\
05739 @example\n\
05740 @group\n\
05741 tic (); sleep (5); toc ()\n\
05742      @result{} 5\n\
05743 t = cputime (); sleep (5); cputime () - t\n\
05744      @result{} 0\n\
05745 @end group\n\
05746 @end example\n\
05747 \n\
05748 @noindent\n\
05749 (This example also illustrates that the CPU timer may have a fairly\n\
05750 coarse resolution.)\n\
05751 @end deftypefn")
05752 {
05753   octave_value retval;
05754 
05755   int nargin = args.length ();
05756 
05757   if (nargin != 0)
05758     warning ("tic: ignoring extra arguments");
05759 
05760   octave_time now;
05761 
05762   double tmp = now.double_value ();
05763 
05764   if (nargout > 0)
05765     retval = static_cast<octave_uint64> (1e6 * tmp);
05766   else
05767     tic_toc_timestamp = tmp;
05768 
05769   return retval;
05770 }
05771 
05772 DEFUN (toc, args, nargout,
05773   "-*- texinfo -*-\n\
05774 @deftypefn {Built-in Function} {} toc ()\n\
05775 See tic.\n\
05776 @end deftypefn")
05777 {
05778   octave_value retval;
05779 
05780   int nargin = args.length ();
05781 
05782   if (nargin != 0)
05783     warning ("tic: ignoring extra arguments");
05784 
05785   if (tic_toc_timestamp < 0)
05786     {
05787       warning ("toc called before timer set");
05788       if (nargout > 0)
05789         retval = Matrix ();
05790     }
05791   else
05792     {
05793       octave_time now;
05794 
05795       double tmp = now.double_value () - tic_toc_timestamp;
05796 
05797       if (nargout > 0)
05798         retval = tmp;
05799       else
05800         octave_stdout << "Elapsed time is " << tmp << " seconds.\n";
05801     }
05802 
05803   return retval;
05804 }
05805 
05806 DEFUN (cputime, args, ,
05807   "-*- texinfo -*-\n\
05808 @deftypefn {Built-in Function} {[@var{total}, @var{user}, @var{system}] =} cputime ();\n\
05809 Return the CPU time used by your Octave session.  The first output is\n\
05810 the total time spent executing your process and is equal to the sum of\n\
05811 second and third outputs, which are the number of CPU seconds spent\n\
05812 executing in user mode and the number of CPU seconds spent executing in\n\
05813 system mode, respectively.  If your system does not have a way to report\n\
05814 CPU time usage, @code{cputime} returns 0 for each of its output values.\n\
05815 Note that because Octave used some CPU time to start, it is reasonable\n\
05816 to check to see if @code{cputime} works by checking to see if the total\n\
05817 CPU time used is nonzero.\n\
05818 @end deftypefn")
05819 {
05820   octave_value_list retval;
05821   int nargin = args.length ();
05822   double usr = 0.0;
05823   double sys = 0.0;
05824 
05825   if (nargin != 0)
05826     warning ("tic: ignoring extra arguments");
05827 
05828 #if defined (HAVE_GETRUSAGE)
05829 
05830   struct rusage ru;
05831 
05832   getrusage (RUSAGE_SELF, &ru);
05833 
05834   usr = static_cast<double> (ru.ru_utime.tv_sec) +
05835     static_cast<double> (ru.ru_utime.tv_usec) * 1e-6;
05836 
05837   sys = static_cast<double> (ru.ru_stime.tv_sec) +
05838     static_cast<double> (ru.ru_stime.tv_usec) * 1e-6;
05839 
05840 #else
05841 
05842   struct tms t;
05843 
05844   times (&t);
05845 
05846   unsigned long ticks;
05847   unsigned long seconds;
05848   unsigned long fraction;
05849 
05850   ticks = t.tms_utime + t.tms_cutime;
05851   fraction = ticks % CLOCKS_PER_SEC;
05852   seconds = ticks / CLOCKS_PER_SEC;
05853 
05854   usr = static_cast<double> (seconds) + static_cast<double>(fraction) /
05855     static_cast<double>(CLOCKS_PER_SEC);
05856 
05857   ticks = t.tms_stime + t.tms_cstime;
05858   fraction = ticks % CLOCKS_PER_SEC;
05859   seconds = ticks / CLOCKS_PER_SEC;
05860 
05861   sys = static_cast<double> (seconds) + static_cast<double>(fraction) /
05862     static_cast<double>(CLOCKS_PER_SEC);
05863 
05864 #endif
05865 
05866   retval (2) = sys;
05867   retval (1) = usr;
05868   retval (0) = sys + usr;
05869 
05870   return retval;
05871 }
05872 
05873 DEFUN (sort, args, nargout,
05874   "-*- texinfo -*-\n\
05875 @deftypefn  {Loadable Function} {[@var{s}, @var{i}] =} sort (@var{x})\n\
05876 @deftypefnx {Loadable Function} {[@var{s}, @var{i}] =} sort (@var{x}, @var{dim})\n\
05877 @deftypefnx {Loadable Function} {[@var{s}, @var{i}] =} sort (@var{x}, @var{mode})\n\
05878 @deftypefnx {Loadable Function} {[@var{s}, @var{i}] =} sort (@var{x}, @var{dim}, @var{mode})\n\
05879 Return a copy of @var{x} with the elements arranged in increasing\n\
05880 order.  For matrices, @code{sort} orders the elements within columns\n\
05881 \n\
05882 For example:\n\
05883 \n\
05884 @example\n\
05885 @group\n\
05886 sort ([1, 2; 2, 3; 3, 1])\n\
05887      @result{}  1  1\n\
05888          2  2\n\
05889          3  3\n\
05890 @end group\n\
05891 @end example\n\
05892 \n\
05893 If the optional argument @var{dim} is given, then the matrix is sorted\n\
05894 along the dimension defined by @var{dim}.  The optional argument @code{mode}\n\
05895 defines the order in which the values will be sorted.  Valid values of\n\
05896 @code{mode} are `ascend' or `descend'.\n\
05897 \n\
05898 The @code{sort} function may also be used to produce a matrix\n\
05899 containing the original row indices of the elements in the sorted\n\
05900 matrix.  For example:\n\
05901 \n\
05902 @example\n\
05903 @group\n\
05904 [s, i] = sort ([1, 2; 2, 3; 3, 1])\n\
05905      @result{} s = 1  1\n\
05906             2  2\n\
05907             3  3\n\
05908      @result{} i = 1  3\n\
05909             2  1\n\
05910             3  2\n\
05911 @end group\n\
05912 @end example\n\
05913 \n\
05914 For equal elements, the indices are such that equal elements are listed\n\
05915 in the order in which they appeared in the original list.\n\
05916 \n\
05917 Sorting of complex entries is done first by magnitude (@code{abs (@var{z})})\n\
05918 and for any ties by phase angle (@code{angle (z)}).  For example:\n\
05919 \n\
05920 @example\n\
05921 @group\n\
05922 sort ([1+i; 1; 1-i])\n\
05923      @result{} 1 + 0i\n\
05924         1 - 1i\n\
05925         1 + 1i\n\
05926 @end group\n\
05927 @end example\n\
05928 \n\
05929 NaN values are treated as being greater than any other value and are sorted\n\
05930 to the end of the list.\n\
05931 \n\
05932 The @code{sort} function may also be used to sort strings and cell arrays\n\
05933 of strings, in which case ASCII dictionary order (uppercase 'A' precedes\n\
05934 lowercase 'a') of the strings is used.\n\
05935 \n\
05936 The algorithm used in @code{sort} is optimized for the sorting of partially\n\
05937 ordered lists.\n\
05938 @end deftypefn")
05939 {
05940   octave_value_list retval;
05941 
05942   int nargin = args.length ();
05943   sortmode smode = ASCENDING;
05944 
05945   if (nargin < 1 || nargin > 3)
05946     {
05947       print_usage ();
05948       return retval;
05949     }
05950 
05951   bool return_idx = nargout > 1;
05952 
05953   octave_value arg = args(0);
05954 
05955   int dim = 0;
05956   if (nargin > 1)
05957     {
05958       if (args(1).is_string ())
05959         {
05960           std::string mode = args(1).string_value();
05961           if (mode == "ascend")
05962             smode = ASCENDING;
05963           else if (mode == "descend")
05964             smode = DESCENDING;
05965           else
05966             {
05967               error ("sort: MODE must be either \"ascend\" or \"descend\"");
05968               return retval;
05969             }
05970         }
05971       else
05972         dim = args(1).nint_value () - 1;
05973     }
05974 
05975   if (nargin > 2)
05976     {
05977       if (args(1).is_string ())
05978         {
05979           print_usage ();
05980           return retval;
05981         }
05982 
05983       if (! args(2).is_string ())
05984         {
05985           error ("sort: MODE must be a string");
05986           return retval;
05987         }
05988       std::string mode = args(2).string_value();
05989       if (mode == "ascend")
05990         smode = ASCENDING;
05991       else if (mode == "descend")
05992         smode = DESCENDING;
05993       else
05994         {
05995           error ("sort: MODE must be either \"ascend\" or \"descend\"");
05996           return retval;
05997         }
05998     }
05999 
06000   const dim_vector dv = arg.dims ();
06001   if (nargin == 1 || args(1).is_string ())
06002     {
06003       // Find first non singleton dimension
06004       dim = dv.first_non_singleton ();
06005     }
06006   else
06007     {
06008       if (dim < 0)
06009         {
06010           error ("sort: DIM must be a valid dimension");
06011           return retval;
06012         }
06013     }
06014 
06015   if (return_idx)
06016     {
06017       retval.resize (2);
06018 
06019       Array<octave_idx_type> sidx;
06020 
06021       retval (0) = arg.sort (sidx, dim, smode);
06022       retval (1) = idx_vector (sidx, dv(dim)); // No checking, the extent is known.
06023     }
06024   else
06025     retval(0) = arg.sort (dim, smode);
06026 
06027   return retval;
06028 }
06029 
06030 /*
06031 
06032 %% Double
06033 %!assert (sort ([NaN, 1, -1, 2, Inf]), [-1, 1, 2, Inf, NaN])
06034 %!assert (sort ([NaN, 1, -1, 2, Inf], 1), [NaN, 1, -1, 2, Inf])
06035 %!assert (sort ([NaN, 1, -1, 2, Inf], 2), [-1, 1, 2, Inf, NaN])
06036 %!assert (sort ([NaN, 1, -1, 2, Inf], 3), [NaN, 1, -1, 2, Inf])
06037 %!assert (sort ([NaN, 1, -1, 2, Inf], "ascend"), [-1, 1, 2, Inf, NaN])
06038 %!assert (sort ([NaN, 1, -1, 2, Inf], 2, "ascend"), [-1, 1, 2, Inf, NaN])
06039 %!assert (sort ([NaN, 1, -1, 2, Inf], "descend"), [NaN, Inf, 2, 1, -1])
06040 %!assert (sort ([NaN, 1, -1, 2, Inf], 2, "descend"), [NaN, Inf, 2, 1, -1])
06041 %!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4]), [3, 1, 6, 4; 8, 2, 7, 5])
06042 %!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4], 1), [3, 1, 6, 4; 8, 2, 7, 5])
06043 %!assert (sort ([3, 1, 7, 5; 8, 2, 6, 4], 2), [1, 3, 5, 7; 2, 4, 6, 8])
06044 %!assert (sort (1), 1)
06045 
06046 %!test
06047 %! [v, i] = sort ([NaN, 1, -1, Inf, 1]);
06048 %! assert (v, [-1, 1, 1, Inf, NaN])
06049 %! assert (i, [3, 2, 5, 4, 1])
06050 
06051 %% Complex
06052 %!assert (sort ([NaN, 1i, -1, 2, Inf]), [1i, -1, 2, Inf, NaN])
06053 %!assert (sort ([NaN, 1i, -1, 2, Inf], 1), [NaN, 1i, -1, 2, Inf])
06054 %!assert (sort ([NaN, 1i, -1, 2, Inf], 2), [1i, -1, 2, Inf, NaN])
06055 %!assert (sort ([NaN, 1i, -1, 2, Inf], 3), [NaN, 1i, -1, 2, Inf])
06056 %!assert (sort ([NaN, 1i, -1, 2, Inf], "ascend"), [1i, -1, 2, Inf, NaN])
06057 %!assert (sort ([NaN, 1i, -1, 2, Inf], 2, "ascend"), [1i, -1, 2, Inf, NaN])
06058 %!assert (sort ([NaN, 1i, -1, 2, Inf], "descend"), [NaN, Inf, 2, -1, 1i])
06059 %!assert (sort ([NaN, 1i, -1, 2, Inf], 2, "descend"), [NaN, Inf, 2, -1, 1i])
06060 %!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4]), [3, 1i, 6, 4; 8, 2, 7, 5])
06061 %!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4], 1), [3, 1i, 6, 4; 8, 2, 7, 5])
06062 %!assert (sort ([3, 1i, 7, 5; 8, 2, 6, 4], 2), [1i, 3, 5, 7; 2, 4, 6, 8])
06063 %!assert (sort (1i), 1i)
06064 
06065 %!test
06066 %! [v, i] = sort ([NaN, 1i, -1, Inf, 1, 1i]);
06067 %! assert (v, [1, 1i, 1i, -1, Inf, NaN])
06068 %! assert (i, [5, 2, 6, 3, 4, 1])
06069 
06070 %% Single
06071 %!assert (sort (single([NaN, 1, -1, 2, Inf])), single([-1, 1, 2, Inf, NaN]))
06072 %!assert (sort (single([NaN, 1, -1, 2, Inf]), 1), single([NaN, 1, -1, 2, Inf]))
06073 %!assert (sort (single([NaN, 1, -1, 2, Inf]), 2), single([-1, 1, 2, Inf, NaN]))
06074 %!assert (sort (single([NaN, 1, -1, 2, Inf]), 3), single([NaN, 1, -1, 2, Inf]))
06075 %!assert (sort (single([NaN, 1, -1, 2, Inf]), "ascend"), single([-1, 1, 2, Inf, NaN]))
06076 %!assert (sort (single([NaN, 1, -1, 2, Inf]), 2, "ascend"), single([-1, 1, 2, Inf, NaN]))
06077 %!assert (sort (single([NaN, 1, -1, 2, Inf]), "descend"), single([NaN, Inf, 2, 1, -1]))
06078 %!assert (sort (single([NaN, 1, -1, 2, Inf]), 2, "descend"), single([NaN, Inf, 2, 1, -1]))
06079 %!assert (sort (single([3, 1, 7, 5; 8, 2, 6, 4])), single([3, 1, 6, 4; 8, 2, 7, 5]))
06080 %!assert (sort (single([3, 1, 7, 5; 8, 2, 6, 4]), 1), single([3, 1, 6, 4; 8, 2, 7, 5]))
06081 %!assert (sort (single([3, 1, 7, 5; 8, 2, 6, 4]), 2), single([1, 3, 5, 7; 2, 4, 6, 8]))
06082 %!assert (sort (single(1)), single(1))
06083 
06084 %!test
06085 %! [v, i] = sort (single([NaN, 1, -1, Inf, 1]));
06086 %! assert (v, single([-1, 1, 1, Inf, NaN]))
06087 %! assert (i, [3, 2, 5, 4, 1])
06088 
06089 %% Single Complex
06090 %!assert (sort (single([NaN, 1i, -1, 2, Inf])), single([1i, -1, 2, Inf, NaN]))
06091 %!assert (sort (single([NaN, 1i, -1, 2, Inf]), 1), single([NaN, 1i, -1, 2, Inf]))
06092 %!assert (sort (single([NaN, 1i, -1, 2, Inf]), 2), single([1i, -1, 2, Inf, NaN]))
06093 %!assert (sort (single([NaN, 1i, -1, 2, Inf]), 3), single([NaN, 1i, -1, 2, Inf]))
06094 %!assert (sort (single([NaN, 1i, -1, 2, Inf]), "ascend"), single([1i, -1, 2, Inf, NaN]))
06095 %!assert (sort (single([NaN, 1i, -1, 2, Inf]), 2, "ascend"), single([1i, -1, 2, Inf, NaN]))
06096 %!assert (sort (single([NaN, 1i, -1, 2, Inf]), "descend"), single([NaN, Inf, 2, -1, 1i]))
06097 %!assert (sort (single([NaN, 1i, -1, 2, Inf]), 2, "descend"), single([NaN, Inf, 2, -1, 1i]))
06098 %!assert (sort (single([3, 1i, 7, 5; 8, 2, 6, 4])), single([3, 1i, 6, 4; 8, 2, 7, 5]))
06099 %!assert (sort (single([3, 1i, 7, 5; 8, 2, 6, 4]), 1), single([3, 1i, 6, 4; 8, 2, 7, 5]))
06100 %!assert (sort (single([3, 1i, 7, 5; 8, 2, 6, 4]), 2), single([1i, 3, 5, 7; 2, 4, 6, 8]))
06101 %!assert (sort (single(1i)),single( 1i))
06102 
06103 %!test
06104 %! [v, i] = sort (single([NaN, 1i, -1, Inf, 1, 1i]));
06105 %! assert (v, single([1, 1i, 1i, -1, Inf, NaN]))
06106 %! assert (i, [5, 2, 6, 3, 4, 1])
06107 
06108 %% Bool
06109 %!assert (sort ([true, false, true, false]), [false, false, true, true])
06110 %!assert (sort ([true, false, true, false], 1), [true, false, true, false])
06111 %!assert (sort ([true, false, true, false], 2), [false, false, true, true])
06112 %!assert (sort ([true, false, true, false], 3), [true, false, true, false])
06113 %!assert (sort ([true, false, true, false], "ascend"), [false, false, true, true])
06114 %!assert (sort ([true, false, true, false], 2, "ascend"), [false, false, true, true])
06115 %!assert (sort ([true, false, true, false], "descend"), [true, true, false, false])
06116 %!assert (sort ([true, false, true, false], 2, "descend"), [true, true, false, false])
06117 %!assert (sort (true), true)
06118 
06119 %!test
06120 %! [v, i] = sort ([true, false, true, false]);
06121 %! assert (v, [false, false, true, true])
06122 %! assert (i, [2, 4, 1, 3])
06123 
06124 %% Sparse Double
06125 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf])), sparse ([-1, 0, 0, 1, 2, Inf, NaN]))
06126 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 1), sparse ([0, NaN, 1, 0, -1, 2, Inf]))
06127 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2), sparse ([-1, 0, 0, 1, 2, Inf, NaN]))
06128 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 3), sparse ([0, NaN, 1, 0, -1, 2, Inf]))
06129 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), "ascend"), sparse ([-1, 0, 0, 1, 2, Inf, NaN]))
06130 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2, "ascend"), sparse ([-1, 0, 0, 1, 2, Inf, NaN]))
06131 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), "descend"), sparse ([NaN, Inf, 2, 1, 0, 0, -1]))
06132 %!assert (sort (sparse ([0, NaN, 1, 0, -1, 2, Inf]), 2, "descend"), sparse ([NaN, Inf, 2, 1, 0, 0, -1]))
06133 
06134 %!shared a
06135 %! a = randn (10, 10);
06136 %! a (a < 0) = 0;
06137 %!assert (sort (sparse (a)), sparse (sort (a)))
06138 %!assert (sort (sparse (a), 1), sparse (sort (a, 1)))
06139 %!assert (sort (sparse (a), 2), sparse (sort (a, 2)))
06140 %!test
06141 %! [v, i] = sort (a);
06142 %! [vs, is] = sort (sparse (a));
06143 %! assert (vs, sparse (v))
06144 %! assert (is, i)
06145 
06146 %% Sparse Complex
06147 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf])), sparse ([0, 0, 1i, -1, 2, Inf, NaN]))
06148 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 1), sparse ([0, NaN, 1i, 0, -1, 2, Inf]))
06149 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2), sparse ([0, 0, 1i, -1, 2, Inf, NaN]))
06150 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 3), sparse ([0, NaN, 1i, 0, -1, 2, Inf]))
06151 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), "ascend"), sparse ([0, 0, 1i, -1, 2, Inf, NaN]))
06152 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2, "ascend"), sparse ([0, 0, 1i, -1, 2, Inf, NaN]))
06153 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), "descend"), sparse ([NaN, Inf, 2, -1, 1i, 0, 0]))
06154 %!assert (sort (sparse ([0, NaN, 1i, 0, -1, 2, Inf]), 2, "descend"), sparse ([NaN, Inf, 2, -1, 1i, 0, 0]))
06155 
06156 %!shared a
06157 %! a = randn (10, 10);
06158 %! a (a < 0) = 0;
06159 %! a = 1i * a;
06160 %!assert (sort (sparse (a)), sparse (sort (a)))
06161 %!assert (sort (sparse (a), 1), sparse (sort (a, 1)))
06162 %!assert (sort (sparse (a), 2), sparse (sort (a, 2)))
06163 %!test
06164 %! [v, i] = sort (a);
06165 %! [vs, is] = sort (sparse (a));
06166 %! assert (vs, sparse (v))
06167 %! assert (is, i)
06168 
06169 %% Sparse Bool
06170 %!assert (sort (sparse ([true, false, true, false])), sparse ([false, false, true, true]))
06171 %!assert (sort (sparse([true, false, true, false]), 1), sparse ([true, false, true, false]))
06172 %!assert (sort (sparse ([true, false, true, false]), 2), sparse ([false, false, true, true]))
06173 %!assert (sort (sparse ([true, false, true, false]), 3), sparse ([true, false, true, false]))
06174 %!assert (sort (sparse ([true, false, true, false]), "ascend"), sparse([false, false, true, true]))
06175 %!assert (sort (sparse ([true, false, true, false]), 2, "ascend"), sparse([false, false, true, true]))
06176 %!assert (sort (sparse ([true, false, true, false]), "descend"), sparse ([true, true, false, false]))
06177 %!assert (sort (sparse ([true, false, true, false]), 2, "descend"), sparse([true, true, false, false]))
06178 
06179 %!test
06180 %! [v, i] = sort (sparse([true, false, true, false]));
06181 %! assert (v, sparse([false, false, true, true]))
06182 %! assert (i, [2, 4, 1, 3])
06183 
06184 %% Cell string array
06185 %!shared a, b, c
06186 %! a = {"Alice", "Cecile", "Eric", "Barry", "David"};
06187 %! b = {"Alice", "Barry", "Cecile", "David", "Eric"};
06188 %! c = {"Eric", "David", "Cecile", "Barry", "Alice"};
06189 %!assert (sort (a), b);
06190 %!assert (sort (a, 1), a)
06191 %!assert (sort (a, 2), b)
06192 %!assert (sort (a, 3), a)
06193 %!assert (sort (a, "ascend"), b)
06194 %!assert (sort (a, 2, "ascend"), b)
06195 %!assert (sort (a, "descend"), c)
06196 %!assert (sort (a, 2, "descend"), c)
06197 
06198 %!test
06199 %! [v, i] = sort (a);
06200 %! assert (i, [1, 4, 2, 5, 3])
06201 
06202 %!error <Invalid call to sort> sort ();
06203 %!error <Invalid call to sort> sort (1, 2, 3, 4);
06204 
06205 */
06206 
06207 // Sort the rows of the matrix @var{a} according to the order
06208 // specified by @var{mode}, which can either be 'ascend' or 'descend'
06209 // and return the index vector corresponding to the sort order.
06210 //
06211 // This function does not yet support sparse matrices.
06212 
06213 DEFUN (__sort_rows_idx__, args, ,
06214   "-*- texinfo -*-\n\
06215 @deftypefn {Built-in Function} {} __sort_rows_idx__ (@var{a}, @var{mode})\n\
06216 Undocumented internal function.\n\
06217 @end deftypefn\n")
06218 {
06219   octave_value retval;
06220 
06221   int nargin = args.length ();
06222   sortmode smode = ASCENDING;
06223 
06224   if (nargin < 1 || nargin > 2 || (nargin == 2 && ! args(1).is_string ()))
06225     {
06226       print_usage ();
06227       return retval;
06228     }
06229 
06230   if (nargin > 1)
06231     {
06232       std::string mode = args(1).string_value();
06233       if (mode == "ascend")
06234         smode = ASCENDING;
06235       else if (mode == "descend")
06236         smode = DESCENDING;
06237       else
06238         {
06239           error ("__sort_rows_idx__: MODE must be either \"ascend\" or \"descend\"");
06240           return retval;
06241         }
06242     }
06243 
06244   octave_value arg = args(0);
06245 
06246   if (arg.is_sparse_type ())
06247     error ("__sort_rows_idx__: sparse matrices not yet supported");
06248   if (arg.ndims () == 2)
06249     {
06250       Array<octave_idx_type> idx = arg.sort_rows_idx (smode);
06251 
06252       retval = octave_value (idx, true, true);
06253     }
06254   else
06255     error ("__sort_rows_idx__: needs a 2-dimensional object");
06256 
06257   return retval;
06258 }
06259 
06260 static sortmode
06261 get_sort_mode_option (const octave_value& arg, const char *argn)
06262 {
06263   // FIXME -- we initialize to UNSORTED here to avoid a GCC warning
06264   // about possibly using sortmode uninitialized.
06265   // FIXME -- shouldn't these modes be scoped inside a class?
06266   sortmode smode = UNSORTED;
06267 
06268   std::string mode = arg.string_value ();
06269 
06270   if (error_state)
06271     error ("issorted: expecting %s argument to be a character string", argn);
06272   else if (mode == "ascending")
06273     smode = ASCENDING;
06274   else if (mode == "descending")
06275     smode = DESCENDING;
06276   else if (mode == "either")
06277     smode = UNSORTED;
06278   else
06279     error ("issorted: MODE must be \"ascending\", \"descending\", or \"either\"");
06280 
06281   return smode;
06282 }
06283 
06284 DEFUN (issorted, args, ,
06285   "-*- texinfo -*-\n\
06286 @deftypefn  {Built-in Function} {} issorted (@var{a})\n\
06287 @deftypefnx {Built-in Function} {} issorted (@var{a}, @var{mode})\n\
06288 @deftypefnx {Built-in Function} {} issorted (@var{a}, \"rows\", @var{mode})\n\
06289 Return true if the array is sorted according to @var{mode}, which\n\
06290 may be either \"ascending\", \"descending\", or \"either\".  By default,\n\
06291  @var{mode} is \"ascending\".  NaNs are treated in the same manner as\n\
06292 @code{sort}.\n\
06293 \n\
06294 If the optional argument \"rows\" is supplied, check whether\n\
06295 the array is sorted by rows as output by the function @code{sortrows}\n\
06296 (with no options).\n\
06297 \n\
06298 This function does not support sparse matrices.\n\
06299 @seealso{sort, sortrows}\n\
06300 @end deftypefn\n")
06301 {
06302   octave_value retval;
06303 
06304   int nargin = args.length ();
06305 
06306   if (nargin < 1 || nargin > 3)
06307     {
06308       print_usage ();
06309       return retval;
06310     }
06311 
06312   bool by_rows = false;
06313 
06314   sortmode smode = ASCENDING;
06315 
06316   if (nargin > 1)
06317     {
06318       octave_value mode_arg;
06319 
06320       if (nargin == 3)
06321         smode = get_sort_mode_option (args(2), "third");
06322 
06323       std::string tmp = args(1).string_value ();
06324 
06325       if (! error_state)
06326         {
06327           if (tmp == "rows")
06328             by_rows = true;
06329           else
06330             smode = get_sort_mode_option (args(1), "second");
06331         }
06332       else
06333         error ("expecting second argument to be character string");
06334 
06335       if (error_state)
06336         return retval;
06337     }
06338 
06339   octave_value arg = args(0);
06340 
06341   if (by_rows)
06342     {
06343       if (arg.is_sparse_type ())
06344         error ("issorted: sparse matrices not yet supported");
06345       if (arg.ndims () == 2)
06346         retval = arg.is_sorted_rows (smode) != UNSORTED;
06347       else
06348         error ("issorted: A must be a 2-dimensional object");
06349     }
06350   else
06351     {
06352       if (arg.dims ().is_vector ())
06353         retval = args(0).is_sorted (smode) != UNSORTED;
06354       else
06355         error ("issorted: needs a vector");
06356     }
06357 
06358   return retval;
06359 }
06360 
06361 /*
06362 %!shared sm, um, sv, uv
06363 %! sm = [1, 2; 3, 4];
06364 %! um = [3, 1; 2, 4];
06365 %! sv = [1, 2, 3, 4];
06366 %! uv = [2, 1, 4, 3];
06367 %!assert(issorted (sm, "rows"));
06368 %!assert(!issorted (um, "rows"));
06369 %!assert(issorted (sv));
06370 %!assert(!issorted (uv));
06371 %!assert(issorted (sv'));
06372 %!assert(!issorted (uv'));
06373 %!assert(issorted (sm, "rows", "ascending"));
06374 %!assert(!issorted (um, "rows", "ascending"));
06375 %!assert(issorted (sv, "ascending"));
06376 %!assert(!issorted (uv, "ascending"));
06377 %!assert(issorted (sv', "ascending"));
06378 %!assert(!issorted (uv', "ascending"));
06379 %!assert(!issorted (sm, "rows", "descending"));
06380 %!assert(issorted (flipud (sm), "rows", "descending"));
06381 %!assert(!issorted (sv, "descending"));
06382 %!assert(issorted (fliplr (sv), "descending"));
06383 %!assert(!issorted (sv', "descending"));
06384 %!assert(issorted (fliplr (sv)', "descending"));
06385 %!assert(!issorted (um, "rows", "either"));
06386 %!assert(!issorted (uv, "either"));
06387 %!assert(issorted (sm, "rows", "either"));
06388 %!assert(issorted (flipud (sm), "rows", "either"));
06389 %!assert(issorted (sv, "either"));
06390 %!assert(issorted (fliplr (sv), "either"));
06391 %!assert(issorted (sv', "either"));
06392 %!assert(issorted (fliplr (sv)', "either"));
06393 */
06394 
06395 DEFUN (nth_element, args, ,
06396   "-*- texinfo -*-\n\
06397 @deftypefn  {Built-in Function} {} nth_element (@var{x}, @var{n})\n\
06398 @deftypefnx {Built-in Function} {} nth_element (@var{x}, @var{n}, @var{dim})\n\
06399 Select the n-th smallest element of a vector, using the ordering defined by\n\
06400 @code{sort}.  In other words, the result is equivalent to\n\
06401 @code{sort(@var{x})(@var{n})}.\n\
06402 @var{n} can also be a contiguous range, either ascending @code{l:u}\n\
06403 or descending @code{u:-1:l}, in which case a range of elements is returned.\n\
06404 If @var{x} is an array, @code{nth_element} operates along the dimension\n\
06405 defined by @var{dim}, or the first non-singleton dimension if @var{dim} is\n\
06406 not given.\n\
06407 \n\
06408 nth_element encapsulates the C++ standard library algorithms nth_element and\n\
06409 partial_sort.  On average, the complexity of the operation is O(M*log(K)),\n\
06410 where @w{@code{M = size (@var{x}, @var{dim})}} and\n\
06411 @w{@code{K = length (@var{n})}}.\n\
06412 This function is intended for cases where the ratio K/M is small; otherwise,\n\
06413 it may be better to use @code{sort}.\n\
06414 @seealso{sort, min, max}\n\
06415 @end deftypefn")
06416 {
06417   octave_value retval;
06418   int nargin = args.length ();
06419 
06420   if (nargin == 2 || nargin == 3)
06421     {
06422       octave_value argx = args(0);
06423 
06424       int dim = -1;
06425       if (nargin == 3)
06426         {
06427           dim = args(2).int_value (true) - 1;
06428           if (dim < 0)
06429             error ("nth_element: DIM must be a valid dimension");
06430         }
06431       if (dim < 0)
06432         dim = argx.dims ().first_non_singleton ();
06433 
06434       idx_vector n = args(1).index_vector ();
06435 
06436       if (error_state)
06437         return retval;
06438 
06439       switch (argx.builtin_type ())
06440         {
06441         case btyp_double:
06442           retval = argx.array_value ().nth_element (n, dim);
06443           break;
06444         case btyp_float:
06445           retval = argx.float_array_value ().nth_element (n, dim);
06446           break;
06447         case btyp_complex:
06448           retval = argx.complex_array_value ().nth_element (n, dim);
06449           break;
06450         case btyp_float_complex:
06451           retval = argx.float_complex_array_value ().nth_element (n, dim);
06452           break;
06453 #define MAKE_INT_BRANCH(X) \
06454         case btyp_ ## X: \
06455           retval = argx.X ## _array_value ().nth_element (n, dim); \
06456           break
06457 
06458         MAKE_INT_BRANCH (int8);
06459         MAKE_INT_BRANCH (int16);
06460         MAKE_INT_BRANCH (int32);
06461         MAKE_INT_BRANCH (int64);
06462         MAKE_INT_BRANCH (uint8);
06463         MAKE_INT_BRANCH (uint16);
06464         MAKE_INT_BRANCH (uint32);
06465         MAKE_INT_BRANCH (uint64);
06466 #undef MAKE_INT_BRANCH
06467         default:
06468           if (argx.is_cellstr ())
06469             retval = argx.cellstr_value ().nth_element (n, dim);
06470           else
06471             gripe_wrong_type_arg ("nth_element", argx);
06472         }
06473     }
06474   else
06475     print_usage ();
06476 
06477   return retval;
06478 }
06479 
06480 template <class NDT>
06481 static NDT
06482 do_accumarray_sum (const idx_vector& idx, const NDT& vals,
06483                    octave_idx_type n = -1)
06484 {
06485   typedef typename NDT::element_type T;
06486   if (n < 0)
06487     n = idx.extent (0);
06488   else if (idx.extent (n) > n)
06489     error ("accumarray: index out of range");
06490 
06491   NDT retval (dim_vector (n, 1), T());
06492 
06493   if (vals.numel () == 1)
06494     retval.idx_add (idx, vals (0));
06495   else if (vals.numel () == idx.length (n))
06496     retval.idx_add (idx, vals);
06497   else
06498     error ("accumarray: dimensions mismatch");
06499 
06500   return retval;
06501 }
06502 
06503 DEFUN (__accumarray_sum__, args, ,
06504   "-*- texinfo -*-\n\
06505 @deftypefn {Built-in Function} {} __accumarray_sum__ (@var{idx}, @var{vals}, @var{n})\n\
06506 Undocumented internal function.\n\
06507 @end deftypefn")
06508 {
06509   octave_value retval;
06510   int nargin = args.length ();
06511   if (nargin >= 2 && nargin <= 3 && args(0).is_numeric_type ())
06512     {
06513       idx_vector idx = args(0).index_vector ();
06514       octave_idx_type n = -1;
06515       if (nargin == 3)
06516         n = args(2).idx_type_value (true);
06517 
06518       if (! error_state)
06519         {
06520           octave_value vals = args(1);
06521           if (vals.is_range ())
06522             {
06523               Range r = vals.range_value ();
06524               if (r.inc () == 0)
06525                 vals = r.base ();
06526             }
06527 
06528           if (vals.is_single_type ())
06529             {
06530               if (vals.is_complex_type ())
06531                 retval = do_accumarray_sum (idx, vals.float_complex_array_value (), n);
06532               else
06533                 retval = do_accumarray_sum (idx, vals.float_array_value (), n);
06534             }
06535           else if (vals.is_numeric_type () || vals.is_bool_type ())
06536             {
06537               if (vals.is_complex_type ())
06538                 retval = do_accumarray_sum (idx, vals.complex_array_value (), n);
06539               else
06540                 retval = do_accumarray_sum (idx, vals.array_value (), n);
06541             }
06542           else
06543             gripe_wrong_type_arg ("accumarray", vals);
06544         }
06545     }
06546   else
06547     print_usage ();
06548 
06549   return retval;
06550 }
06551 
06552 template <class NDT>
06553 static NDT
06554 do_accumarray_minmax (const idx_vector& idx, const NDT& vals,
06555                       octave_idx_type n, bool ismin,
06556                       const typename NDT::element_type& zero_val)
06557 {
06558   typedef typename NDT::element_type T;
06559   if (n < 0)
06560     n = idx.extent (0);
06561   else if (idx.extent (n) > n)
06562     error ("accumarray: index out of range");
06563 
06564   NDT retval (dim_vector (n, 1), zero_val);
06565 
06566   // Pick minimizer or maximizer.
06567   void (MArray<T>::*op) (const idx_vector&, const MArray<T>&) =
06568     ismin ? (&MArray<T>::idx_min) : (&MArray<T>::idx_max);
06569 
06570   octave_idx_type l = idx.length (n);
06571   if (vals.numel () == 1)
06572     (retval.*op) (idx, NDT (dim_vector (l, 1), vals(0)));
06573   else if (vals.numel () == l)
06574     (retval.*op) (idx, vals);
06575   else
06576     error ("accumarray: dimensions mismatch");
06577 
06578   return retval;
06579 }
06580 
06581 static octave_value_list
06582 do_accumarray_minmax_fun (const octave_value_list& args,
06583                           bool ismin)
06584 {
06585   octave_value retval;
06586   int nargin = args.length ();
06587   if (nargin >= 3 && nargin <= 4 && args(0).is_numeric_type ())
06588     {
06589       idx_vector idx = args(0).index_vector ();
06590       octave_idx_type n = -1;
06591       if (nargin == 4)
06592         n = args(3).idx_type_value (true);
06593 
06594       if (! error_state)
06595         {
06596           octave_value vals = args(1), zero = args (2);
06597 
06598           switch (vals.builtin_type ())
06599             {
06600             case btyp_double:
06601               retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin,
06602                                              zero.double_value ());
06603               break;
06604             case btyp_float:
06605               retval = do_accumarray_minmax (idx, vals.float_array_value (), n, ismin,
06606                                              zero.float_value ());
06607               break;
06608             case btyp_complex:
06609               retval = do_accumarray_minmax (idx, vals.complex_array_value (), n, ismin,
06610                                              zero.complex_value ());
06611               break;
06612             case btyp_float_complex:
06613               retval = do_accumarray_minmax (idx, vals.float_complex_array_value (), n, ismin,
06614                                              zero.float_complex_value ());
06615               break;
06616 #define MAKE_INT_BRANCH(X) \
06617             case btyp_ ## X: \
06618               retval = do_accumarray_minmax (idx, vals.X ## _array_value (), n, ismin, \
06619                                              zero.X ## _scalar_value ()); \
06620               break
06621 
06622             MAKE_INT_BRANCH (int8);
06623             MAKE_INT_BRANCH (int16);
06624             MAKE_INT_BRANCH (int32);
06625             MAKE_INT_BRANCH (int64);
06626             MAKE_INT_BRANCH (uint8);
06627             MAKE_INT_BRANCH (uint16);
06628             MAKE_INT_BRANCH (uint32);
06629             MAKE_INT_BRANCH (uint64);
06630 #undef MAKE_INT_BRANCH
06631             case btyp_bool:
06632               retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin,
06633                                              zero.bool_value ());
06634               break;
06635             default:
06636               gripe_wrong_type_arg ("accumarray", vals);
06637             }
06638         }
06639     }
06640   else
06641     print_usage ();
06642 
06643   return retval;
06644 }
06645 
06646 DEFUN (__accumarray_min__, args, ,
06647   "-*- texinfo -*-\n\
06648 @deftypefn {Built-in Function} {} __accumarray_min__ (@var{idx}, @var{vals}, @var{zero}, @var{n})\n\
06649 Undocumented internal function.\n\
06650 @end deftypefn")
06651 {
06652   return do_accumarray_minmax_fun (args, true);
06653 }
06654 
06655 DEFUN (__accumarray_max__, args, ,
06656   "-*- texinfo -*-\n\
06657 @deftypefn {Built-in Function} {} __accumarray_max__ (@var{idx}, @var{vals}, @var{zero}, @var{n})\n\
06658 Undocumented internal function.\n\
06659 @end deftypefn")
06660 {
06661   return do_accumarray_minmax_fun (args, false);
06662 }
06663 
06664 template <class NDT>
06665 static NDT
06666 do_accumdim_sum (const idx_vector& idx, const NDT& vals,
06667                  int dim = -1, octave_idx_type n = -1)
06668 {
06669   typedef typename NDT::element_type T;
06670   if (n < 0)
06671     n = idx.extent (0);
06672   else if (idx.extent (n) > n)
06673     error ("accumdim: index out of range");
06674 
06675   dim_vector vals_dim = vals.dims (), rdv = vals_dim;
06676 
06677   if (dim < 0)
06678     dim = vals.dims ().first_non_singleton ();
06679   else if (dim >= rdv.length ())
06680     rdv.resize (dim+1, 1);
06681 
06682   rdv(dim) = n;
06683 
06684   NDT retval (rdv, T());
06685 
06686   if (idx.length () != vals_dim(dim))
06687     error ("accumdim: dimension mismatch");
06688 
06689   retval.idx_add_nd (idx, vals, dim);
06690 
06691   return retval;
06692 }
06693 
06694 DEFUN (__accumdim_sum__, args, ,
06695   "-*- texinfo -*-\n\
06696 @deftypefn {Built-in Function} {} __accumdim_sum__ (@var{idx}, @var{vals}, @var{dim}, @var{n})\n\
06697 Undocumented internal function.\n\
06698 @end deftypefn")
06699 {
06700   octave_value retval;
06701   int nargin = args.length ();
06702   if (nargin >= 2 && nargin <= 4 && args(0).is_numeric_type ())
06703     {
06704       idx_vector idx = args(0).index_vector ();
06705       int dim = -1;
06706       if (nargin >= 3)
06707         dim = args(2).int_value () - 1;
06708 
06709       octave_idx_type n = -1;
06710       if (nargin == 4)
06711         n = args(3).idx_type_value (true);
06712 
06713       if (! error_state)
06714         {
06715           octave_value vals = args(1);
06716 
06717           if (vals.is_single_type ())
06718             {
06719               if (vals.is_complex_type ())
06720                 retval = do_accumdim_sum (idx, vals.float_complex_array_value (), dim, n);
06721               else
06722                 retval = do_accumdim_sum (idx, vals.float_array_value (), dim, n);
06723             }
06724           else if (vals.is_numeric_type () || vals.is_bool_type ())
06725             {
06726               if (vals.is_complex_type ())
06727                 retval = do_accumdim_sum (idx, vals.complex_array_value (), dim, n);
06728               else
06729                 retval = do_accumdim_sum (idx, vals.array_value (), dim, n);
06730             }
06731           else
06732             gripe_wrong_type_arg ("accumdim", vals);
06733         }
06734     }
06735   else
06736     print_usage ();
06737 
06738   return retval;
06739 }
06740 
06741 template <class NDT>
06742 static NDT
06743 do_merge (const Array<bool>& mask,
06744           const NDT& tval, const NDT& fval)
06745 {
06746   typedef typename NDT::element_type T;
06747   dim_vector dv = mask.dims ();
06748   NDT retval (dv);
06749 
06750   bool tscl = tval.numel () == 1, fscl = fval.numel () == 1;
06751 
06752   if ((! tscl && tval.dims () != dv)
06753       || (! fscl && fval.dims () != dv))
06754     error ("merge: MASK, TVAL, and FVAL dimensions must match");
06755   else
06756     {
06757       T *rv = retval.fortran_vec ();
06758       octave_idx_type n = retval.numel ();
06759 
06760       const T *tv = tval.data (), *fv = fval.data ();
06761       const bool *mv = mask.data ();
06762 
06763       if (tscl)
06764         {
06765           if (fscl)
06766             {
06767               T ts = tv[0], fs = fv[0];
06768               for (octave_idx_type i = 0; i < n; i++)
06769                 rv[i] = mv[i] ? ts : fs;
06770             }
06771           else
06772             {
06773               T ts = tv[0];
06774               for (octave_idx_type i = 0; i < n; i++)
06775                 rv[i] = mv[i] ? ts : fv[i];
06776             }
06777         }
06778       else
06779         {
06780           if (fscl)
06781             {
06782               T fs = fv[0];
06783               for (octave_idx_type i = 0; i < n; i++)
06784                 rv[i] = mv[i] ? tv[i] : fs;
06785             }
06786           else
06787             {
06788               for (octave_idx_type i = 0; i < n; i++)
06789                 rv[i] = mv[i] ? tv[i] : fv[i];
06790             }
06791         }
06792     }
06793 
06794   return retval;
06795 }
06796 
06797 #define MAKE_INT_BRANCH(INTX) \
06798   else if (tval.is_ ## INTX ## _type () && fval.is_ ## INTX ## _type ()) \
06799     { \
06800       retval = do_merge (mask, \
06801                          tval.INTX ## _array_value (), \
06802                          fval.INTX ## _array_value ()); \
06803     }
06804 
06805 DEFUN (merge, args, ,
06806   "-*- texinfo -*-\n\
06807 @deftypefn  {Built-in Function} {} merge (@var{mask}, @var{tval}, @var{fval})\n\
06808 @deftypefnx {Built-in Function} {} ifelse (@var{mask}, @var{tval}, @var{fval})\n\
06809 Merge elements of @var{true_val} and @var{false_val}, depending on the\n\
06810 value of @var{mask}.  If @var{mask} is a logical scalar, the other two\n\
06811 arguments can be arbitrary values.  Otherwise, @var{mask} must be a logical\n\
06812 array, and @var{tval}, @var{fval} should be arrays of matching class, or\n\
06813 cell arrays.  In the scalar mask case, @var{tval} is returned if @var{mask}\n\
06814 is true, otherwise @var{fval} is returned.\n\
06815 \n\
06816 In the array mask case, both @var{tval} and @var{fval} must be either\n\
06817 scalars or arrays with dimensions equal to @var{mask}.  The result is\n\
06818 constructed as follows:\n\
06819 \n\
06820 @example\n\
06821 @group\n\
06822 result(mask) = tval(mask);\n\
06823 result(! mask) = fval(! mask);\n\
06824 @end group\n\
06825 @end example\n\
06826 \n\
06827 @var{mask} can also be arbitrary numeric type, in which case\n\
06828 it is first converted to logical.\n\
06829 @seealso{logical}\n\
06830 @end deftypefn")
06831 {
06832   int nargin = args.length ();
06833   octave_value retval;
06834 
06835   if (nargin == 3 && (args(0).is_bool_type () || args(0).is_numeric_type ()))
06836     {
06837       octave_value mask_val = args(0);
06838 
06839       if (mask_val.is_scalar_type ())
06840         retval = mask_val.is_true () ? args(1) : args(2);
06841       else
06842         {
06843           boolNDArray mask = mask_val.bool_array_value ();
06844           octave_value tval = args(1), fval = args(2);
06845           if (tval.is_double_type () && fval.is_double_type ())
06846             {
06847               if (tval.is_complex_type () || fval.is_complex_type ())
06848                 retval = do_merge (mask,
06849                                    tval.complex_array_value (),
06850                                    fval.complex_array_value ());
06851               else
06852                 retval = do_merge (mask,
06853                                    tval.array_value (),
06854                                    fval.array_value ());
06855             }
06856           else if (tval.is_single_type () && fval.is_single_type ())
06857             {
06858               if (tval.is_complex_type () || fval.is_complex_type ())
06859                 retval = do_merge (mask,
06860                                    tval.float_complex_array_value (),
06861                                    fval.float_complex_array_value ());
06862               else
06863                 retval = do_merge (mask,
06864                                    tval.float_array_value (),
06865                                    fval.float_array_value ());
06866             }
06867           else if (tval.is_string () && fval.is_string ())
06868             {
06869               bool sq_string = tval.is_sq_string () || fval.is_sq_string ();
06870               retval = octave_value (do_merge (mask,
06871                                                tval.char_array_value (),
06872                                                fval.char_array_value ()),
06873                                      sq_string ? '\'' : '"');
06874             }
06875           else if (tval.is_cell () && fval.is_cell ())
06876             {
06877               retval = do_merge (mask,
06878                                  tval.cell_value (),
06879                                  fval.cell_value ());
06880             }
06881 
06882           MAKE_INT_BRANCH (int8)
06883           MAKE_INT_BRANCH (int16)
06884           MAKE_INT_BRANCH (int32)
06885           MAKE_INT_BRANCH (int64)
06886           MAKE_INT_BRANCH (uint8)
06887           MAKE_INT_BRANCH (uint16)
06888           MAKE_INT_BRANCH (uint32)
06889           MAKE_INT_BRANCH (uint64)
06890 
06891           else
06892             error ("merge: cannot merge %s with %s with array mask",
06893                    tval.class_name ().c_str (),
06894                    fval.class_name ().c_str ());
06895         }
06896     }
06897   else
06898     print_usage ();
06899 
06900   return retval;
06901 }
06902 
06903 DEFALIAS (ifelse, merge);
06904 
06905 #undef MAKE_INT_BRANCH
06906 
06907 template <class SparseT>
06908 static SparseT
06909 do_sparse_diff (const SparseT& array, octave_idx_type order,
06910                 int dim)
06911 {
06912   SparseT retval = array;
06913   if (dim == 1)
06914     {
06915       octave_idx_type k = retval.columns ();
06916       while (order > 0 && k > 0)
06917         {
06918           idx_vector col1 (':'), col2 (':'), sl1 (1, k), sl2 (0, k-1);
06919           retval = SparseT (retval.index (col1, sl1)) - SparseT (retval.index (col2, sl2));
06920           assert (retval.columns () == k-1);
06921           order--;
06922           k--;
06923         }
06924     }
06925   else
06926     {
06927       octave_idx_type k = retval.rows ();
06928       while (order > 0 && k > 0)
06929         {
06930           idx_vector col1 (':'), col2 (':'), sl1 (1, k), sl2 (0, k-1);
06931           retval = SparseT (retval.index (sl1, col1)) - SparseT (retval.index (sl2, col2));
06932           assert (retval.rows () == k-1);
06933           order--;
06934           k--;
06935         }
06936     }
06937 
06938   return retval;
06939 }
06940 
06941 static octave_value
06942 do_diff (const octave_value& array, octave_idx_type order,
06943          int dim = -1)
06944 {
06945   octave_value retval;
06946 
06947   const dim_vector& dv = array.dims ();
06948   if (dim == -1)
06949     {
06950       dim = array.dims ().first_non_singleton ();
06951 
06952       // Bother Matlab. This behavior is really wicked.
06953       if (dv(dim) <= order)
06954         {
06955           if (dv(dim) == 1)
06956             retval = array.resize (dim_vector (0, 0));
06957           else
06958             {
06959               retval = array;
06960               while (order > 0)
06961                 {
06962                   if (dim == dv.length ())
06963                     {
06964                       retval = do_diff (array, order, dim - 1);
06965                       order = 0;
06966                     }
06967                   else if (dv(dim) == 1)
06968                     dim++;
06969                   else
06970                     {
06971                       retval = do_diff (array, dv(dim) - 1, dim);
06972                       order -= dv(dim) - 1;
06973                       dim++;
06974                     }
06975                 }
06976             }
06977 
06978           return retval;
06979         }
06980     }
06981 
06982   if (array.is_integer_type ())
06983     {
06984       if (array.is_int8_type ())
06985         retval = array.int8_array_value ().diff (order, dim);
06986       else if (array.is_int16_type ())
06987         retval = array.int16_array_value ().diff (order, dim);
06988       else if (array.is_int32_type ())
06989         retval = array.int32_array_value ().diff (order, dim);
06990       else if (array.is_int64_type ())
06991         retval = array.int64_array_value ().diff (order, dim);
06992       else if (array.is_uint8_type ())
06993         retval = array.uint8_array_value ().diff (order, dim);
06994       else if (array.is_uint16_type ())
06995         retval = array.uint16_array_value ().diff (order, dim);
06996       else if (array.is_uint32_type ())
06997         retval = array.uint32_array_value ().diff (order, dim);
06998       else if (array.is_uint64_type ())
06999         retval = array.uint64_array_value ().diff (order, dim);
07000       else
07001         panic_impossible ();
07002     }
07003   else if (array.is_sparse_type ())
07004     {
07005       if (array.is_complex_type ())
07006         retval = do_sparse_diff (array.sparse_complex_matrix_value (), order, dim);
07007       else
07008         retval = do_sparse_diff (array.sparse_matrix_value (), order, dim);
07009     }
07010   else if (array.is_single_type ())
07011     {
07012       if (array.is_complex_type ())
07013         retval = array.float_complex_array_value ().diff (order, dim);
07014       else
07015         retval = array.float_array_value ().diff (order, dim);
07016     }
07017   else
07018     {
07019       if (array.is_complex_type ())
07020         retval = array.complex_array_value ().diff (order, dim);
07021       else
07022         retval = array.array_value ().diff (order, dim);
07023     }
07024 
07025   return retval;
07026 }
07027 
07028 DEFUN (diff, args, ,
07029   "-*- texinfo -*-\n\
07030 @deftypefn  {Built-in Function} {} diff (@var{x})\n\
07031 @deftypefnx {Built-in Function} {} diff (@var{x}, @var{k})\n\
07032 @deftypefnx {Built-in Function} {} diff (@var{x}, @var{k}, @var{dim})\n\
07033 If @var{x} is a vector of length @math{n}, @code{diff (@var{x})} is the\n\
07034 vector of first differences\n\
07035 @tex\n\
07036  $x_2 - x_1, \\ldots{}, x_n - x_{n-1}$.\n\
07037 @end tex\n\
07038 @ifnottex\n\
07039  @var{x}(2) - @var{x}(1), @dots{}, @var{x}(n) - @var{x}(n-1).\n\
07040 @end ifnottex\n\
07041 \n\
07042 If @var{x} is a matrix, @code{diff (@var{x})} is the matrix of column\n\
07043 differences along the first non-singleton dimension.\n\
07044 \n\
07045 The second argument is optional.  If supplied, @code{diff (@var{x},\n\
07046 @var{k})}, where @var{k} is a non-negative integer, returns the\n\
07047 @var{k}-th differences.  It is possible that @var{k} is larger than\n\
07048 the first non-singleton dimension of the matrix.  In this case,\n\
07049 @code{diff} continues to take the differences along the next\n\
07050 non-singleton dimension.\n\
07051 \n\
07052 The dimension along which to take the difference can be explicitly\n\
07053 stated with the optional variable @var{dim}.  In this case the\n\
07054 @var{k}-th order differences are calculated along this dimension.\n\
07055 In the case where @var{k} exceeds @code{size (@var{x}, @var{dim})}\n\
07056 an empty matrix is returned.\n\
07057 @end deftypefn")
07058 {
07059   int nargin = args.length ();
07060   octave_value retval;
07061 
07062   if (nargin < 1 || nargin > 3)
07063     print_usage ();
07064   else if (! (args(0).is_numeric_type () || args(0).is_bool_type ()))
07065     error ("diff: X must be numeric or logical");
07066 
07067   if (! error_state)
07068     {
07069       int dim = -1;
07070       octave_idx_type order = 1;
07071       if (nargin > 1)
07072         {
07073           if (args(1).is_scalar_type ())
07074             order = args(1).idx_type_value (true, false);
07075           else if (! args(1).is_zero_by_zero ())
07076             error ("order K must be a scalar or []");
07077           if (! error_state && order < 0)
07078             error ("order K must be non-negative");
07079         }
07080 
07081       if (nargin > 2)
07082         {
07083           dim = args(2).int_value (true, false);
07084           if (! error_state && (dim < 1 || dim > args(0).ndims ()))
07085             error ("DIM must be a valid dimension");
07086           else
07087             dim -= 1;
07088         }
07089 
07090       if (! error_state)
07091         retval = do_diff (args(0), order, dim);
07092     }
07093 
07094   return retval;
07095 }
07096 
07097 /*
07098 
07099 %!assert (diff ([1, 2, 3, 4]), [1, 1, 1])
07100 %!assert (diff ([1, 3, 7, 19], 2), [2, 8])
07101 %!assert (diff ([1, 2; 5, 4; 8, 7; 9, 6; 3, 1]), [4, 2; 3, 3; 1, -1; -6, -5])
07102 %!assert (diff ([1, 2; 5, 4; 8, 7; 9, 6; 3, 1], 3), [-1, -5; -5, 0])
07103 %!assert (isempty (diff (1)));
07104 
07105 %!error diff ([1, 2; 3, 4], -1);
07106 
07107 %!error diff ("foo");
07108 
07109 %!error diff ();
07110 
07111 %!error diff (1, 2, 3, 4);
07112 
07113 */
07114 
07115 template <class T>
07116 static Array<T>
07117 do_repelems (const Array<T>& src, const Array<octave_idx_type>& rep)
07118 {
07119   Array<T> retval;
07120 
07121   assert (rep.ndims () == 2 && rep.rows () == 2);
07122 
07123   octave_idx_type n = rep.columns (), l = 0;
07124   for (octave_idx_type i = 0; i < n; i++)
07125     {
07126       octave_idx_type k = rep(1, i);
07127       if (k < 0)
07128         {
07129           error ("repelems: second row must contain non-negative numbers");
07130           return retval;
07131         }
07132 
07133       l += k;
07134     }
07135 
07136   retval.clear (1, l);
07137   T *dest = retval.fortran_vec ();
07138   l = 0;
07139   for (octave_idx_type i = 0; i < n; i++)
07140     {
07141       octave_idx_type k = rep(1, i);
07142       std::fill_n (dest, k, src.checkelem (rep(0, i) - 1));
07143       dest += k;
07144     }
07145 
07146   return retval;
07147 }
07148 
07149 DEFUN (repelems, args, ,
07150   "-*- texinfo -*-\n\
07151 @deftypefn {Built-in Function} {} repelems (@var{x}, @var{r})\n\
07152 Construct a vector of repeated elements from @var{x}.  @var{r}\n\
07153 is a 2x@var{N} integer matrix specifying which elements to repeat and\n\
07154 how often to repeat each element.\n\
07155 \n\
07156 Entries in the first row, @var{r}(1,j), select an element to repeat.\n\
07157 The corresponding entry in the second row, @var{r}(2,j), specifies\n\
07158 the repeat count.  If @var{x} is a matrix then the columns of @var{x} are\n\
07159 imagined to be stacked on top of each other for purposes of the selection\n\
07160 index.  A row vector is always returned.\n\
07161 \n\
07162 Conceptually the result is calculated as follows:\n\
07163 \n\
07164 @example\n\
07165 @group\n\
07166 y = [];\n\
07167 for i = 1:columns (@var{r})\n\
07168   y = [y, @var{x}(@var{r}(1,i)*ones(1, @var{r}(2,i)))];\n\
07169 endfor\n\
07170 @end group\n\
07171 @end example\n\
07172 @seealso{repmat}\n\
07173 @end deftypefn")
07174 {
07175   octave_value retval;
07176 
07177   if (args.length () == 2)
07178     {
07179       octave_value x = args(0);
07180 
07181       const Matrix rm = args(1).matrix_value ();
07182       if (error_state)
07183         return retval;
07184       else if (rm.rows () != 2 || rm.ndims () != 2)
07185         {
07186           error ("repelems: R must be a matrix with two rows");
07187           return retval;
07188         }
07189       else
07190         {
07191           NoAlias< Array<octave_idx_type> > r (rm.dims ());
07192 
07193           for (octave_idx_type i = 0; i < rm.numel (); i++)
07194             {
07195               octave_idx_type rx = rm(i);
07196               if (static_cast<double> (rx) != rm(i))
07197                 {
07198                   error ("repelems: R must be a matrix of integers");
07199                   return retval;
07200                 }
07201 
07202               r(i) = rx;
07203             }
07204 
07205           switch (x.builtin_type ())
07206             {
07207 #define BTYP_BRANCH(X, EX) \
07208             case btyp_ ## X: \
07209               retval = do_repelems (x.EX ## _value (), r); \
07210               break
07211 
07212               BTYP_BRANCH (double, array);
07213               BTYP_BRANCH (float, float_array);
07214               BTYP_BRANCH (complex, complex_array);
07215               BTYP_BRANCH (float_complex, float_complex_array);
07216               BTYP_BRANCH (bool, bool_array);
07217               BTYP_BRANCH (char, char_array);
07218 
07219               BTYP_BRANCH (int8,  int8_array);
07220               BTYP_BRANCH (int16, int16_array);
07221               BTYP_BRANCH (int32, int32_array);
07222               BTYP_BRANCH (int64, int64_array);
07223               BTYP_BRANCH (uint8,  uint8_array);
07224               BTYP_BRANCH (uint16, uint16_array);
07225               BTYP_BRANCH (uint32, uint32_array);
07226               BTYP_BRANCH (uint64, uint64_array);
07227 
07228               BTYP_BRANCH (cell, cell);
07229               //BTYP_BRANCH (struct, map);//FIXME
07230 #undef BTYP_BRANCH
07231 
07232             default:
07233               gripe_wrong_type_arg ("repelems", x);
07234             }
07235         }
07236     }
07237   else
07238     print_usage ();
07239 
07240   return retval;
07241 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines