00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
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
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
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
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
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
00396
00397
00398
00399
00400
00401
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
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
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
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
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
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
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
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
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
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
01824 error ("cat: dimension mismatch");
01825 return retval;
01826 }
01827 }
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
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
01855
01856
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
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
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
02112
02113
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
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
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
02339
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
02467
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
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
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
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
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
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
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
03022
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
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384
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
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
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
03494
03495
03496
03497
03498
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));
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
03620
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
03700
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
03781
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
03848
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
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
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
03936
03937
03938
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
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
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
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
04056
04057
04058
04059
04060
04061
04062
04063
04064
04065
04066
04067
04068
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
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212
04213
04214
04215
04216
04217
04218
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
04399
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
04488
04489
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
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
04654
04655
04656
04657
04658
04659
04660
04661
04662
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
04775
04776
04777
04778
04779
04780
04781
04782
04783
04784
04785
04786
04787
04788
04789
04790
04791
04792
04793
04794
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
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
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
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
05078
05079
05080
05081
05082
05083
05084
05085
05086
05087
05088
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
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
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
05253
05254
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267
05268
05269
05270
05271
05272
05273
05274
05275
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
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
05359
05360
05361
05362
05363
05364
05365
05366
05367
05368
05369
05370
05371
05372
05373
05374
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
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402
05403
05404
05405
05406
05407
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
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));
06023 }
06024 else
06025 retval(0) = arg.sort (dim, smode);
06026
06027 return retval;
06028 }
06029
06030
06031
06032
06033
06034
06035
06036
06037
06038
06039
06040
06041
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051
06052
06053
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063
06064
06065
06066
06067
06068
06069
06070
06071
06072
06073
06074
06075
06076
06077
06078
06079
06080
06081
06082
06083
06084
06085
06086
06087
06088
06089
06090
06091
06092
06093
06094
06095
06096
06097
06098
06099
06100
06101
06102
06103
06104
06105
06106
06107
06108
06109
06110
06111
06112
06113
06114
06115
06116
06117
06118
06119
06120
06121
06122
06123
06124
06125
06126
06127
06128
06129
06130
06131
06132
06133
06134
06135
06136
06137
06138
06139
06140
06141
06142
06143
06144
06145
06146
06147
06148
06149
06150
06151
06152
06153
06154
06155
06156
06157
06158
06159
06160
06161
06162
06163
06164
06165
06166
06167
06168
06169
06170
06171
06172
06173
06174
06175
06176
06177
06178
06179
06180
06181
06182
06183
06184
06185
06186
06187
06188
06189
06190
06191
06192
06193
06194
06195
06196
06197
06198
06199
06200
06201
06202
06203
06204
06205
06206
06207
06208
06209
06210
06211
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
06264
06265
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
06363
06364
06365
06366
06367
06368
06369
06370
06371
06372
06373
06374
06375
06376
06377
06378
06379
06380
06381
06382
06383
06384
06385
06386
06387
06388
06389
06390
06391
06392
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
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
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
07100
07101
07102
07103
07104
07105
07106
07107
07108
07109
07110
07111
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
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 }