00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include "lo-ieee.h"
00029 #include "lo-mappers.h"
00030 #include "lo-math.h"
00031 #include "dNDArray.h"
00032 #include "CNDArray.h"
00033 #include "quit.h"
00034
00035 #include "defun-dld.h"
00036 #include "error.h"
00037 #include "gripes.h"
00038 #include "oct-obj.h"
00039
00040 #include "ov-cx-mat.h"
00041 #include "ov-re-sparse.h"
00042 #include "ov-cx-sparse.h"
00043
00044 template <class ArrayType>
00045 static octave_value_list
00046 do_minmax_red_op (const octave_value& arg,
00047 int nargout, int dim, bool ismin)
00048 {
00049 octave_value_list retval;
00050 ArrayType array = octave_value_extract<ArrayType> (arg);
00051
00052 if (error_state)
00053 return retval;
00054
00055 if (nargout == 2)
00056 {
00057 retval.resize (2);
00058 Array<octave_idx_type> idx;
00059 if (ismin)
00060 retval(0) = array.min (idx, dim);
00061 else
00062 retval(0) = array.max (idx, dim);
00063
00064 retval(1) = octave_value (idx, true, true);
00065 }
00066 else
00067 {
00068 if (ismin)
00069 retval(0) = array.min (dim);
00070 else
00071 retval(0) = array.max (dim);
00072 }
00073
00074 return retval;
00075 }
00076
00077
00078 template <>
00079 octave_value_list
00080 do_minmax_red_op<boolNDArray> (const octave_value& arg,
00081 int nargout, int dim, bool ismin)
00082 {
00083 octave_value_list retval;
00084
00085 if (nargout <= 1)
00086 {
00087
00088 boolNDArray array = arg.bool_array_value ();
00089
00090 if (array.is_empty ())
00091 retval(0) = array;
00092 else if (ismin)
00093 retval(0) = array.all (dim);
00094 else
00095 retval(0) = array.any (dim);
00096 }
00097 else
00098 {
00099
00100 retval = do_minmax_red_op<int8NDArray> (arg, nargout, dim, ismin);
00101 if (! error_state)
00102 retval(0) = retval(0).bool_array_value ();
00103 }
00104
00105 return retval;
00106 }
00107
00108 template <class ArrayType>
00109 static octave_value
00110 do_minmax_bin_op (const octave_value& argx, const octave_value& argy,
00111 bool ismin)
00112 {
00113 typedef typename ArrayType::element_type ScalarType;
00114
00115 octave_value retval;
00116
00117 if (argx.is_scalar_type () == 1)
00118 {
00119 ScalarType x = octave_value_extract<ScalarType> (argx);
00120 ArrayType y = octave_value_extract<ArrayType> (argy);
00121
00122 if (error_state)
00123 ;
00124 else if (ismin)
00125 retval = min (x, y);
00126 else
00127 retval = max (x, y);
00128 }
00129 else if (argy.is_scalar_type () == 1)
00130 {
00131 ArrayType x = octave_value_extract<ArrayType> (argx);
00132 ScalarType y = octave_value_extract<ScalarType> (argy);
00133
00134 if (error_state)
00135 ;
00136 else if (ismin)
00137 retval = min (x, y);
00138 else
00139 retval = max (x, y);
00140 }
00141 else
00142 {
00143 ArrayType x = octave_value_extract<ArrayType> (argx);
00144 ArrayType y = octave_value_extract<ArrayType> (argy);
00145
00146 if (error_state)
00147 ;
00148 else if (ismin)
00149 retval = min (x, y);
00150 else
00151 retval = max (x, y);
00152 }
00153
00154 return retval;
00155 }
00156
00157 static octave_value_list
00158 do_minmax_body (const octave_value_list& args,
00159 int nargout, bool ismin)
00160 {
00161 octave_value_list retval;
00162
00163 const char *func = ismin ? "min" : "max";
00164
00165 int nargin = args.length ();
00166
00167 if (nargin == 3 || nargin == 1)
00168 {
00169 octave_value arg = args(0);
00170 int dim = -1;
00171 if (nargin == 3)
00172 {
00173 dim = args(2).int_value (true) - 1;
00174 if (error_state || dim < 0)
00175 {
00176 error ("%s: DIM must be a valid dimension", func);
00177 return retval;
00178 }
00179
00180 if (! args(1).is_empty ())
00181 warning ("%s: second argument is ignored", func);
00182 }
00183
00184 switch (arg.builtin_type ())
00185 {
00186 case btyp_double:
00187 {
00188 if (arg.is_range () && (dim == -1 || dim == 1))
00189 {
00190 Range range = arg.range_value ();
00191 if (range.nelem () == 0)
00192 {
00193 retval(0) = arg;
00194 if (nargout > 1)
00195 retval(1) = arg;
00196 }
00197 else if (ismin)
00198 {
00199 retval(0) = range.min ();
00200 if (nargout > 1)
00201 retval(1) = static_cast<double> (range.inc () < 0 ? range.nelem () : 1);
00202 }
00203 else
00204 {
00205 retval(0) = range.max ();
00206 if (nargout > 1)
00207 retval(1) = static_cast<double> (range.inc () >= 0 ? range.nelem () : 1);
00208 }
00209 }
00210 else if (arg.is_sparse_type ())
00211 retval = do_minmax_red_op<SparseMatrix> (arg, nargout, dim, ismin);
00212 else
00213 retval = do_minmax_red_op<NDArray> (arg, nargout, dim, ismin);
00214 break;
00215 }
00216 case btyp_complex:
00217 {
00218 if (arg.is_sparse_type ())
00219 retval = do_minmax_red_op<SparseComplexMatrix> (arg, nargout, dim, ismin);
00220 else
00221 retval = do_minmax_red_op<ComplexNDArray> (arg, nargout, dim, ismin);
00222 break;
00223 }
00224 case btyp_float:
00225 retval = do_minmax_red_op<FloatNDArray> (arg, nargout, dim, ismin);
00226 break;
00227 case btyp_float_complex:
00228 retval = do_minmax_red_op<FloatComplexNDArray> (arg, nargout, dim, ismin);
00229 break;
00230 #define MAKE_INT_BRANCH(X) \
00231 case btyp_ ## X: \
00232 retval = do_minmax_red_op<X ## NDArray> (arg, nargout, dim, ismin); \
00233 break;
00234 MAKE_INT_BRANCH (int8);
00235 MAKE_INT_BRANCH (int16);
00236 MAKE_INT_BRANCH (int32);
00237 MAKE_INT_BRANCH (int64);
00238 MAKE_INT_BRANCH (uint8);
00239 MAKE_INT_BRANCH (uint16);
00240 MAKE_INT_BRANCH (uint32);
00241 MAKE_INT_BRANCH (uint64);
00242 #undef MAKE_INT_BRANCH
00243 case btyp_bool:
00244 retval = do_minmax_red_op<boolNDArray> (arg, nargout, dim, ismin);
00245 break;
00246 default:
00247 gripe_wrong_type_arg (func, arg);
00248 }
00249 }
00250 else if (nargin == 2)
00251 {
00252 octave_value argx = args(0), argy = args(1);
00253 builtin_type_t xtyp = argx.builtin_type (), ytyp = argy.builtin_type ();
00254 builtin_type_t rtyp = btyp_mixed_numeric (xtyp, ytyp);
00255
00256 switch (rtyp)
00257 {
00258 case btyp_double:
00259 {
00260 if ((argx.is_sparse_type ()
00261 && (argy.is_sparse_type () || argy.is_scalar_type ()))
00262 || (argy.is_sparse_type () && argx.is_scalar_type ()))
00263 retval = do_minmax_bin_op<SparseMatrix> (argx, argy, ismin);
00264 else
00265 retval = do_minmax_bin_op<NDArray> (argx, argy, ismin);
00266 break;
00267 }
00268 case btyp_complex:
00269 {
00270 if ((argx.is_sparse_type ()
00271 && (argy.is_sparse_type () || argy.is_scalar_type ()))
00272 || (argy.is_sparse_type () && argx.is_scalar_type ()))
00273 retval = do_minmax_bin_op<SparseComplexMatrix> (argx, argy, ismin);
00274 else
00275 retval = do_minmax_bin_op<ComplexNDArray> (argx, argy, ismin);
00276 break;
00277 }
00278 case btyp_float:
00279 retval = do_minmax_bin_op<FloatNDArray> (argx, argy, ismin);
00280 break;
00281 case btyp_float_complex:
00282 retval = do_minmax_bin_op<FloatComplexNDArray> (argx, argy, ismin);
00283 break;
00284 #define MAKE_INT_BRANCH(X) \
00285 case btyp_ ## X: \
00286 retval = do_minmax_bin_op<X ## NDArray> (argx, argy, ismin); \
00287 break;
00288 MAKE_INT_BRANCH (int8);
00289 MAKE_INT_BRANCH (int16);
00290 MAKE_INT_BRANCH (int32);
00291 MAKE_INT_BRANCH (int64);
00292 MAKE_INT_BRANCH (uint8);
00293 MAKE_INT_BRANCH (uint16);
00294 MAKE_INT_BRANCH (uint32);
00295 MAKE_INT_BRANCH (uint64);
00296 #undef MAKE_INT_BRANCH
00297 default:
00298 error ("%s: cannot compute %s (%s, %s)", func, func,
00299 argx.type_name ().c_str (), argy.type_name ().c_str ());
00300 }
00301 }
00302 else
00303 print_usage ();
00304
00305 return retval;
00306 }
00307
00308 DEFUN_DLD (min, args, nargout,
00309 "-*- texinfo -*-\n\
00310 @deftypefn {Loadable Function} {} min (@var{x})\n\
00311 @deftypefnx {Loadable Function} {} min (@var{x}, @var{y})\n\
00312 @deftypefnx {Loadable Function} {} min (@var{x}, [], @var{dim})\n\
00313 @deftypefnx {Loadable Function} {} min (@var{x}, @var{y}, @var{dim})\n\
00314 @deftypefnx {Loadable Function} {[@var{w}, @var{iw}] =} min (@var{x})\n\
00315 For a vector argument, return the minimum value. For a matrix\n\
00316 argument, return the minimum value from each column, as a row\n\
00317 vector, or over the dimension @var{dim} if defined, in which case @var{y} \n\
00318 should be set to the empty matrix (it's ignored otherwise). For two matrices\n\
00319 (or a matrix and scalar), return the pair-wise minimum.\n\
00320 Thus,\n\
00321 \n\
00322 @example\n\
00323 min (min (@var{x}))\n\
00324 @end example\n\
00325 \n\
00326 @noindent\n\
00327 returns the smallest element of @var{x}, and\n\
00328 \n\
00329 @example\n\
00330 @group\n\
00331 min (2:5, pi)\n\
00332 @result{} 2.0000 3.0000 3.1416 3.1416\n\
00333 @end group\n\
00334 @end example\n\
00335 \n\
00336 @noindent\n\
00337 compares each element of the range @code{2:5} with @code{pi}, and\n\
00338 returns a row vector of the minimum values.\n\
00339 \n\
00340 For complex arguments, the magnitude of the elements are used for\n\
00341 comparison.\n\
00342 \n\
00343 If called with one input and two output arguments,\n\
00344 @code{min} also returns the first index of the\n\
00345 minimum value(s). Thus,\n\
00346 \n\
00347 @example\n\
00348 @group\n\
00349 [x, ix] = min ([1, 3, 0, 2, 0])\n\
00350 @result{} x = 0\n\
00351 ix = 3\n\
00352 @end group\n\
00353 @end example\n\
00354 @seealso{max, cummin, cummax}\n\
00355 @end deftypefn")
00356 {
00357 return do_minmax_body (args, nargout, true);
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 DEFUN_DLD (max, args, nargout,
00388 "-*- texinfo -*-\n\
00389 @deftypefn {Loadable Function} {} max (@var{x})\n\
00390 @deftypefnx {Loadable Function} {} max (@var{x}, @var{y})\n\
00391 @deftypefnx {Loadable Function} {} max (@var{x}, [], @var{dim})\n\
00392 @deftypefnx {Loadable Function} {} max (@var{x}, @var{y}, @var{dim})\n\
00393 @deftypefnx {Loadable Function} {[@var{w}, @var{iw}] =} max (@var{x})\n\
00394 For a vector argument, return the maximum value. For a matrix\n\
00395 argument, return the maximum value from each column, as a row\n\
00396 vector, or over the dimension @var{dim} if defined, in which case @var{y} \n\
00397 should be set to the empty matrix (it's ignored otherwise). For two matrices\n\
00398 (or a matrix and scalar), return the pair-wise maximum.\n\
00399 Thus,\n\
00400 \n\
00401 @example\n\
00402 max (max (@var{x}))\n\
00403 @end example\n\
00404 \n\
00405 @noindent\n\
00406 returns the largest element of the matrix @var{x}, and\n\
00407 \n\
00408 @example\n\
00409 @group\n\
00410 max (2:5, pi)\n\
00411 @result{} 3.1416 3.1416 4.0000 5.0000\n\
00412 @end group\n\
00413 @end example\n\
00414 \n\
00415 @noindent\n\
00416 compares each element of the range @code{2:5} with @code{pi}, and\n\
00417 returns a row vector of the maximum values.\n\
00418 \n\
00419 For complex arguments, the magnitude of the elements are used for\n\
00420 comparison.\n\
00421 \n\
00422 If called with one input and two output arguments,\n\
00423 @code{max} also returns the first index of the\n\
00424 maximum value(s). Thus,\n\
00425 \n\
00426 @example\n\
00427 @group\n\
00428 [x, ix] = max ([1, 3, 5, 2, 5])\n\
00429 @result{} x = 5\n\
00430 ix = 3\n\
00431 @end group\n\
00432 @end example\n\
00433 @seealso{min, cummax, cummin}\n\
00434 @end deftypefn")
00435 {
00436 return do_minmax_body (args, nargout, false);
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 template <class ArrayType>
00468 static octave_value_list
00469 do_cumminmax_red_op (const octave_value& arg,
00470 int nargout, int dim, bool ismin)
00471 {
00472 octave_value_list retval;
00473 ArrayType array = octave_value_extract<ArrayType> (arg);
00474
00475 if (error_state)
00476 return retval;
00477
00478 if (nargout == 2)
00479 {
00480 retval.resize (2);
00481 Array<octave_idx_type> idx;
00482 if (ismin)
00483 retval(0) = array.cummin (idx, dim);
00484 else
00485 retval(0) = array.cummax (idx, dim);
00486
00487 retval(1) = octave_value (idx, true, true);
00488 }
00489 else
00490 {
00491 if (ismin)
00492 retval(0) = array.cummin (dim);
00493 else
00494 retval(0) = array.cummax (dim);
00495 }
00496
00497 return retval;
00498 }
00499
00500 static octave_value_list
00501 do_cumminmax_body (const octave_value_list& args,
00502 int nargout, bool ismin)
00503 {
00504 octave_value_list retval;
00505
00506 const char *func = ismin ? "cummin" : "cummax";
00507
00508 int nargin = args.length ();
00509
00510 if (nargin == 1 || nargin == 2)
00511 {
00512 octave_value arg = args(0);
00513 int dim = -1;
00514 if (nargin == 2)
00515 {
00516 dim = args(1).int_value (true) - 1;
00517 if (error_state || dim < 0)
00518 {
00519 error ("%s: DIM must be a valid dimension", func);
00520 return retval;
00521 }
00522 }
00523
00524 switch (arg.builtin_type ())
00525 {
00526 case btyp_double:
00527 retval = do_cumminmax_red_op<NDArray> (arg, nargout, dim, ismin);
00528 break;
00529 case btyp_complex:
00530 retval = do_cumminmax_red_op<ComplexNDArray> (arg, nargout, dim, ismin);
00531 break;
00532 case btyp_float:
00533 retval = do_cumminmax_red_op<FloatNDArray> (arg, nargout, dim, ismin);
00534 break;
00535 case btyp_float_complex:
00536 retval = do_cumminmax_red_op<FloatComplexNDArray> (arg, nargout, dim, ismin);
00537 break;
00538 #define MAKE_INT_BRANCH(X) \
00539 case btyp_ ## X: \
00540 retval = do_cumminmax_red_op<X ## NDArray> (arg, nargout, dim, ismin); \
00541 break;
00542 MAKE_INT_BRANCH (int8);
00543 MAKE_INT_BRANCH (int16);
00544 MAKE_INT_BRANCH (int32);
00545 MAKE_INT_BRANCH (int64);
00546 MAKE_INT_BRANCH (uint8);
00547 MAKE_INT_BRANCH (uint16);
00548 MAKE_INT_BRANCH (uint32);
00549 MAKE_INT_BRANCH (uint64);
00550 #undef MAKE_INT_BRANCH
00551 case btyp_bool:
00552 {
00553 retval = do_cumminmax_red_op<int8NDArray> (arg, nargout, dim, ismin);
00554 if (retval.length () > 0)
00555 retval(0) = retval(0).bool_array_value ();
00556 break;
00557 }
00558 default:
00559 gripe_wrong_type_arg (func, arg);
00560 }
00561 }
00562 else
00563 print_usage ();
00564
00565 return retval;
00566 }
00567
00568 DEFUN_DLD (cummin, args, nargout,
00569 "-*- texinfo -*-\n\
00570 @deftypefn {Loadable Function} {} cummin (@var{x})\n\
00571 @deftypefnx {Loadable Function} {} cummin (@var{x}, @var{dim})\n\
00572 @deftypefnx {Loadable Function} {[@var{w}, @var{iw}] =} cummin (@var{x})\n\
00573 Return the cumulative minimum values along dimension @var{dim}. If @var{dim}\n\
00574 is unspecified it defaults to column-wise operation. For example:\n\
00575 \n\
00576 @example\n\
00577 @group\n\
00578 cummin ([5 4 6 2 3 1])\n\
00579 @result{} 5 4 4 2 2 1\n\
00580 @end group\n\
00581 @end example\n\
00582 \n\
00583 \n\
00584 The call\n\
00585 \n\
00586 @example\n\
00587 [w, iw] = cummin (x)\n\
00588 @end example\n\
00589 \n\
00590 @noindent\n\
00591 with @code{x} a vector, is equivalent to the following code:\n\
00592 \n\
00593 @example\n\
00594 @group\n\
00595 w = iw = zeros (size (x));\n\
00596 for i = 1:length (x)\n\
00597 [w(i), iw(i)] = max (x(1:i));\n\
00598 endfor\n\
00599 @end group\n\
00600 @end example\n\
00601 \n\
00602 @noindent\n\
00603 but computed in a much faster manner.\n\
00604 @seealso{cummax, min, max}\n\
00605 @end deftypefn")
00606 {
00607 return do_cumminmax_body (args, nargout, true);
00608 }
00609
00610 DEFUN_DLD (cummax, args, nargout,
00611 "-*- texinfo -*-\n\
00612 @deftypefn {Loadable Function} {} cummax (@var{x})\n\
00613 @deftypefnx {Loadable Function} {} cummax (@var{x}, @var{dim})\n\
00614 @deftypefnx {Loadable Function} {[@var{w}, @var{iw}] =} cummax (@var{x})\n\
00615 Return the cumulative maximum values along dimension @var{dim}. If @var{dim}\n\
00616 is unspecified it defaults to column-wise operation. For example:\n\
00617 \n\
00618 @example\n\
00619 @group\n\
00620 cummax ([1 3 2 6 4 5])\n\
00621 @result{} 1 3 3 6 6 6\n\
00622 @end group\n\
00623 @end example\n\
00624 \n\
00625 The call\n\
00626 \n\
00627 @example\n\
00628 [w, iw] = cummax (x, dim)\n\
00629 @end example\n\
00630 \n\
00631 @noindent\n\
00632 with @code{x} a vector, is equivalent to the following code:\n\
00633 \n\
00634 @example\n\
00635 @group\n\
00636 w = iw = zeros (size (x));\n\
00637 for i = 1:length (x)\n\
00638 [w(i), iw(i)] = max (x(1:i));\n\
00639 endfor\n\
00640 @end group\n\
00641 @end example\n\
00642 \n\
00643 @noindent\n\
00644 but computed in a much faster manner.\n\
00645 @seealso{cummin, max, min}\n\
00646 @end deftypefn")
00647 {
00648 return do_cumminmax_body (args, nargout, false);
00649 }